@delmaredigital/payload-experiments 0.1.0-rc.7 → 0.2.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 (207) hide show
  1. package/README.md +28 -0
  2. package/dist/admin/LayerUsage.d.ts +1 -1
  3. package/dist/admin/LayerUsage.js +23 -11
  4. package/dist/admin/MetricSourceSelect.js +2 -1
  5. package/dist/admin/TestsNavLink.d.ts +1 -0
  6. package/dist/admin/TestsNavLink.js +30 -0
  7. package/dist/admin/allocation.model.js +1 -1
  8. package/dist/admin/copy/actions.d.ts +0 -2
  9. package/dist/admin/copy/actions.js +0 -2
  10. package/dist/admin/copy/advanced.d.ts +55 -0
  11. package/dist/admin/copy/advanced.js +55 -0
  12. package/dist/admin/copy/armSelect.js +1 -1
  13. package/dist/admin/copy/arms.d.ts +0 -13
  14. package/dist/admin/copy/arms.js +0 -13
  15. package/dist/admin/copy/{who.d.ts → audience.d.ts} +1 -9
  16. package/dist/admin/copy/{who.js → audience.js} +1 -9
  17. package/dist/admin/copy/history.d.ts +0 -4
  18. package/dist/admin/copy/history.js +3 -7
  19. package/dist/admin/copy/metrics.d.ts +2 -2
  20. package/dist/admin/copy/metrics.js +2 -2
  21. package/dist/admin/copy/newTest.d.ts +32 -0
  22. package/dist/admin/copy/newTest.js +32 -0
  23. package/dist/admin/copy/readiness.d.ts +45 -0
  24. package/dist/admin/copy/readiness.js +50 -0
  25. package/dist/admin/copy/recommendation.d.ts +26 -0
  26. package/dist/admin/copy/recommendation.js +25 -0
  27. package/dist/admin/copy/results.d.ts +0 -1
  28. package/dist/admin/copy/results.js +0 -1
  29. package/dist/admin/copy/review.d.ts +0 -17
  30. package/dist/admin/copy/review.js +1 -112
  31. package/dist/admin/copy/setting.d.ts +10 -0
  32. package/dist/admin/copy/setting.js +10 -0
  33. package/dist/admin/copy/surface.d.ts +36 -0
  34. package/dist/admin/copy/surface.js +47 -0
  35. package/dist/admin/copy/testPage.d.ts +88 -0
  36. package/dist/admin/copy/testPage.js +88 -0
  37. package/dist/admin/paths.d.ts +5 -13
  38. package/dist/admin/paths.js +5 -13
  39. package/dist/admin/review/review.model.d.ts +3 -26
  40. package/dist/admin/review/review.model.js +3 -30
  41. package/dist/admin/surface/ResultsRoute.d.ts +7 -0
  42. package/dist/admin/surface/ResultsRoute.js +58 -0
  43. package/dist/admin/surface/SurfaceShell.d.ts +6 -0
  44. package/dist/admin/surface/SurfaceShell.js +35 -0
  45. package/dist/admin/surface/TestsHome.d.ts +4 -0
  46. package/dist/admin/surface/TestsHome.js +212 -0
  47. package/dist/admin/surface/TestsSurface.d.ts +2 -0
  48. package/dist/admin/surface/TestsSurface.js +36 -0
  49. package/dist/admin/surface/contracts.d.ts +48 -0
  50. package/dist/admin/surface/contracts.js +8 -0
  51. package/dist/admin/surface/home.model.d.ts +41 -0
  52. package/dist/admin/surface/home.model.js +59 -0
  53. package/dist/admin/surface/newTest/NewTest.d.ts +7 -0
  54. package/dist/admin/surface/newTest/NewTest.js +355 -0
  55. package/dist/admin/surface/newTest/newTest.css +9 -0
  56. package/dist/admin/surface/pageBlock/pageBlock.model.d.ts +6 -0
  57. package/dist/admin/surface/pageBlock/pageBlock.model.js +8 -0
  58. package/dist/admin/surface/pageBlock/parts.d.ts +2 -0
  59. package/dist/admin/surface/pageBlock/parts.js +64 -0
  60. package/dist/admin/surface/readiness/ActionDialogs.d.ts +15 -0
  61. package/dist/admin/surface/readiness/ActionDialogs.js +274 -0
  62. package/dist/admin/surface/readiness/Banner.d.ts +2 -0
  63. package/dist/admin/surface/readiness/Banner.js +138 -0
  64. package/dist/admin/surface/readiness/SaveStatus.d.ts +4 -0
  65. package/dist/admin/surface/readiness/SaveStatus.js +50 -0
  66. package/dist/admin/surface/readiness/parts.d.ts +2 -0
  67. package/dist/admin/surface/readiness/parts.js +9 -0
  68. package/dist/admin/surface/readiness/readiness.model.d.ts +22 -0
  69. package/dist/admin/surface/readiness/readiness.model.js +107 -0
  70. package/dist/admin/surface/readiness/useTransition.d.ts +10 -0
  71. package/dist/admin/surface/readiness/useTransition.js +34 -0
  72. package/dist/admin/surface/results/ResultsBody.d.ts +7 -0
  73. package/dist/admin/surface/results/ResultsBody.js +262 -0
  74. package/dist/admin/surface/results/recommendation.model.d.ts +12 -0
  75. package/dist/admin/surface/results/recommendation.model.js +59 -0
  76. package/dist/admin/surface/results/useResults.d.ts +56 -0
  77. package/dist/admin/surface/results/useResults.js +183 -0
  78. package/dist/admin/surface/setting/parts.d.ts +3 -0
  79. package/dist/admin/surface/setting/parts.js +263 -0
  80. package/dist/admin/surface/setting/setting.css +29 -0
  81. package/dist/admin/surface/setting/setting.model.d.ts +8 -0
  82. package/dist/admin/surface/setting/setting.model.js +25 -0
  83. package/dist/admin/surface/surface.css +50 -0
  84. package/dist/admin/surface/test/AdvancedSection.d.ts +2 -0
  85. package/dist/admin/surface/test/AdvancedSection.js +153 -0
  86. package/dist/admin/surface/test/GoalSection.d.ts +2 -0
  87. package/dist/admin/surface/test/GoalSection.js +198 -0
  88. package/dist/admin/surface/test/LengthSection.d.ts +2 -0
  89. package/dist/admin/surface/test/LengthSection.js +87 -0
  90. package/dist/admin/surface/test/Section.d.ts +7 -0
  91. package/dist/admin/surface/test/Section.js +27 -0
  92. package/dist/admin/surface/test/TargetingSection.d.ts +2 -0
  93. package/dist/admin/surface/test/TargetingSection.js +164 -0
  94. package/dist/admin/surface/test/TestHeader.d.ts +4 -0
  95. package/dist/admin/surface/test/TestHeader.js +69 -0
  96. package/dist/admin/surface/test/TestPage.d.ts +7 -0
  97. package/dist/admin/surface/test/TestPage.js +84 -0
  98. package/dist/admin/surface/test/VersionsSection.d.ts +4 -0
  99. package/dist/admin/surface/test/VersionsSection.js +208 -0
  100. package/dist/admin/surface/test/fields.d.ts +55 -0
  101. package/dist/admin/surface/test/fields.js +185 -0
  102. package/dist/admin/surface/test/pageParts.d.ts +2 -0
  103. package/dist/admin/surface/test/pageParts.js +39 -0
  104. package/dist/admin/surface/test/testPage.css +23 -0
  105. package/dist/admin/surface/test/testPage.model.d.ts +17 -0
  106. package/dist/admin/surface/test/testPage.model.js +53 -0
  107. package/dist/admin/surface/testDocument.model.d.ts +39 -0
  108. package/dist/admin/surface/testDocument.model.js +61 -0
  109. package/dist/admin/surface/useTestDocument.d.ts +22 -0
  110. package/dist/admin/surface/useTestDocument.js +345 -0
  111. package/dist/admin/targeting/targeting.model.js +2 -2
  112. package/dist/admin/useLayerUsage.d.ts +0 -5
  113. package/dist/admin/useLayerUsage.js +1 -39
  114. package/dist/admin/views/CollectionEditRedirect.d.ts +4 -0
  115. package/dist/admin/views/CollectionEditRedirect.js +14 -0
  116. package/dist/admin/views/CollectionListRedirect.d.ts +2 -0
  117. package/dist/admin/views/CollectionListRedirect.js +8 -0
  118. package/dist/admin/views/ExperimentsRootView.d.ts +2 -0
  119. package/dist/admin/views/ExperimentsRootView.js +175 -0
  120. package/dist/admin/views/access.model.d.ts +7 -0
  121. package/dist/admin/views/access.model.js +5 -0
  122. package/dist/collections/experiments/config.js +18 -125
  123. package/dist/collections/experiments/createDefaults.js +6 -0
  124. package/dist/collections/layers.js +43 -12
  125. package/dist/collections/metrics.js +70 -14
  126. package/dist/collections/serialize.js +4 -1
  127. package/dist/db/snapshots.d.ts +2 -1
  128. package/dist/db/snapshots.js +2 -2
  129. package/dist/endpoints/results.js +7 -0
  130. package/dist/endpoints/summary.d.ts +1 -1
  131. package/dist/endpoints/summary.js +37 -1
  132. package/dist/exports/adminClient.d.ts +2 -13
  133. package/dist/exports/adminClient.js +2 -13
  134. package/dist/exports/adminRsc.d.ts +3 -0
  135. package/dist/exports/adminRsc.js +3 -0
  136. package/dist/exports/index.d.ts +1 -1
  137. package/dist/options.js +29 -0
  138. package/dist/plugin.js +25 -0
  139. package/dist/puck/editor/CreateExperimentDrawer.d.ts +2 -1
  140. package/dist/puck/editor/CreateExperimentDrawer.js +17 -57
  141. package/dist/puck/editor/ExperimentSlotEditor.js +6 -0
  142. package/dist/puck/editor/copy.d.ts +10 -9
  143. package/dist/puck/editor/copy.js +11 -10
  144. package/dist/puck/editor/createTest.d.ts +7 -0
  145. package/dist/puck/editor/createTest.js +50 -0
  146. package/dist/puck/editor/editor.model.d.ts +28 -1
  147. package/dist/puck/editor/editor.model.js +61 -0
  148. package/dist/results/analyse.js +4 -1
  149. package/dist/results/verdict.d.ts +1 -0
  150. package/dist/results/verdict.js +7 -4
  151. package/dist/transitions/checkStart.d.ts +1 -0
  152. package/dist/transitions/placements.d.ts +5 -1
  153. package/dist/transitions/placements.js +14 -7
  154. package/dist/transitions/preflightData.d.ts +7 -1
  155. package/dist/transitions/preflightData.js +199 -148
  156. package/dist/transitions/start.js +2 -2
  157. package/dist/types/admin.d.ts +1 -0
  158. package/dist/types/contracts.d.ts +17 -0
  159. package/dist/types/endpoints.d.ts +11 -1
  160. package/dist/types/snapshot.d.ts +1 -0
  161. package/dist/types/surface.d.ts +29 -0
  162. package/dist/types/surface.js +1 -0
  163. package/package.json +7 -1
  164. package/dist/access.d.ts +0 -1
  165. package/dist/access.js +0 -2
  166. package/dist/admin/AllocationField.d.ts +0 -2
  167. package/dist/admin/AllocationField.js +0 -80
  168. package/dist/admin/FlagPointSelect.d.ts +0 -2
  169. package/dist/admin/FlagPointSelect.js +0 -54
  170. package/dist/admin/LockedFieldNotice.d.ts +0 -2
  171. package/dist/admin/LockedFieldNotice.js +0 -26
  172. package/dist/admin/PhaseHistory.d.ts +0 -2
  173. package/dist/admin/PhaseHistory.js +0 -76
  174. package/dist/admin/StatusCell.d.ts +0 -3
  175. package/dist/admin/StatusCell.js +0 -19
  176. package/dist/admin/SummaryCell.d.ts +0 -2
  177. package/dist/admin/SummaryCell.js +0 -32
  178. package/dist/admin/actions/AddMetricDialog.d.ts +0 -6
  179. package/dist/admin/actions/AddMetricDialog.js +0 -138
  180. package/dist/admin/actions/AllocateDialog.d.ts +0 -6
  181. package/dist/admin/actions/AllocateDialog.js +0 -81
  182. package/dist/admin/actions/ExperimentActions.d.ts +0 -3
  183. package/dist/admin/actions/ExperimentActions.js +0 -110
  184. package/dist/admin/arms/ArmsField.d.ts +0 -2
  185. package/dist/admin/arms/ArmsField.js +0 -310
  186. package/dist/admin/arms/ParamsEditor.d.ts +0 -16
  187. package/dist/admin/arms/ParamsEditor.js +0 -79
  188. package/dist/admin/copy/tabs.d.ts +0 -7
  189. package/dist/admin/copy/tabs.js +0 -7
  190. package/dist/admin/permissions.model.d.ts +0 -10
  191. package/dist/admin/permissions.model.js +0 -4
  192. package/dist/admin/phaseHistory.model.d.ts +0 -19
  193. package/dist/admin/phaseHistory.model.js +0 -19
  194. package/dist/admin/results/ResultsView.d.ts +0 -3
  195. package/dist/admin/results/ResultsView.js +0 -312
  196. package/dist/admin/review/ReviewPanel.d.ts +0 -2
  197. package/dist/admin/review/ReviewPanel.js +0 -268
  198. package/dist/admin/summaryBatcher.d.ts +0 -8
  199. package/dist/admin/summaryBatcher.js +0 -33
  200. package/dist/admin/targeting/TargetingAttributeField.d.ts +0 -2
  201. package/dist/admin/targeting/TargetingAttributeField.js +0 -31
  202. package/dist/admin/targeting/TargetingOpField.d.ts +0 -2
  203. package/dist/admin/targeting/TargetingOpField.js +0 -45
  204. package/dist/admin/targeting/TargetingValueField.d.ts +0 -2
  205. package/dist/admin/targeting/TargetingValueField.js +0 -142
  206. package/dist/index.d.ts +0 -1
  207. package/dist/index.js +0 -4
@@ -0,0 +1,355 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import { useRouter } from 'next/navigation.js';
5
+ import { formatAdminURL } from 'payload/shared';
6
+ import { NEW_TEST_COPY as C } from '../../copy/newTest.js';
7
+ import { CreateRefused, createTest } from '../../../puck/editor/createTest.js';
8
+ import './newTest.css';
9
+ export function NewTest({ surface, pages }) {
10
+ const router = useRouter();
11
+ const [step, setStep] = useState('kind');
12
+ const [pointId, setPointId] = useState('');
13
+ const point = surface.flagPoints.find((item)=>item.id === pointId);
14
+ const [unitType, setUnitType] = useState('visitor');
15
+ const [name, setName] = useState('');
16
+ const [hypothesis, setHypothesis] = useState('');
17
+ const [advanced, setAdvanced] = useState(false);
18
+ const [layers, setLayers] = useState([]);
19
+ const [layer, setLayer] = useState();
20
+ const [layerState, setLayerState] = useState('loading');
21
+ const [layerRetry, setLayerRetry] = useState(0);
22
+ const [pending, setPending] = useState(false);
23
+ const [error, setError] = useState('');
24
+ const inFlight = useRef(false);
25
+ useEffect(()=>{
26
+ if (step !== 'setting' || !advanced) return;
27
+ const controller = new AbortController();
28
+ setLayerState('loading');
29
+ void (async ()=>{
30
+ try {
31
+ const response = await fetch(`${surface.apiRoute.replace(/\/$/, '')}/xp-layers?depth=0&limit=100`, {
32
+ credentials: 'include',
33
+ signal: controller.signal
34
+ });
35
+ const body = await response.json();
36
+ if (!response.ok || !Array.isArray(body?.docs)) throw new Error('groups');
37
+ if (!controller.signal.aborted) {
38
+ setLayers(body.docs);
39
+ setLayerState('ready');
40
+ }
41
+ } catch {
42
+ if (!controller.signal.aborted) setLayerState('error');
43
+ }
44
+ })();
45
+ return ()=>controller.abort();
46
+ }, [
47
+ step,
48
+ advanced,
49
+ surface.apiRoute,
50
+ layerRetry
51
+ ]);
52
+ async function submit() {
53
+ if (inFlight.current || !point || !name.trim()) return;
54
+ inFlight.current = true;
55
+ setPending(true);
56
+ setError('');
57
+ try {
58
+ const { id } = await createTest(surface.apiRoute, {
59
+ kind: 'flag',
60
+ unitType,
61
+ name,
62
+ flagPoint: point.id,
63
+ ...layer === undefined ? {} : {
64
+ layer
65
+ },
66
+ ...hypothesis.trim() ? {
67
+ hypothesis
68
+ } : {}
69
+ });
70
+ router.push(formatAdminURL({
71
+ adminRoute: surface.adminRoute,
72
+ path: `/experiments/${encodeURIComponent(String(id))}`
73
+ }));
74
+ } catch (cause) {
75
+ setError(cause instanceof CreateRefused ? cause.message : C.createError);
76
+ inFlight.current = false;
77
+ setPending(false);
78
+ }
79
+ }
80
+ const collections = [
81
+ ...new Set(pages?.map((page)=>page.collection))
82
+ ];
83
+ return /*#__PURE__*/ _jsxs("main", {
84
+ className: "xp-new-test",
85
+ children: [
86
+ step === 'kind' ? /*#__PURE__*/ _jsxs(_Fragment, {
87
+ children: [
88
+ /*#__PURE__*/ _jsx("h1", {
89
+ children: C.question
90
+ }),
91
+ /*#__PURE__*/ _jsxs("div", {
92
+ className: "xp-new-test-cards",
93
+ children: [
94
+ pages !== undefined ? /*#__PURE__*/ _jsxs("button", {
95
+ type: "button",
96
+ className: "xp-new-test-card",
97
+ onClick: ()=>setStep('block'),
98
+ children: [
99
+ /*#__PURE__*/ _jsx("strong", {
100
+ children: C.block
101
+ }),
102
+ /*#__PURE__*/ _jsx("span", {
103
+ children: C.blockMeaning
104
+ }),
105
+ surface.descriptions?.block ? /*#__PURE__*/ _jsx("span", {
106
+ children: surface.descriptions.block
107
+ }) : null
108
+ ]
109
+ }) : null,
110
+ surface.flagPoints.length > 0 ? /*#__PURE__*/ _jsxs("button", {
111
+ type: "button",
112
+ className: "xp-new-test-card",
113
+ onClick: ()=>setStep('setting'),
114
+ children: [
115
+ /*#__PURE__*/ _jsx("strong", {
116
+ children: C.setting
117
+ }),
118
+ /*#__PURE__*/ _jsx("span", {
119
+ children: C.settingMeaning
120
+ }),
121
+ surface.descriptions?.setting ? /*#__PURE__*/ _jsx("span", {
122
+ children: surface.descriptions.setting
123
+ }) : null
124
+ ]
125
+ }) : null
126
+ ]
127
+ }),
128
+ pages === undefined && !surface.flagPoints.length ? /*#__PURE__*/ _jsx("p", {
129
+ children: C.unavailable
130
+ }) : null
131
+ ]
132
+ }) : step === 'block' ? /*#__PURE__*/ _jsxs(_Fragment, {
133
+ children: [
134
+ /*#__PURE__*/ _jsx("h1", {
135
+ children: C.block
136
+ }),
137
+ /*#__PURE__*/ _jsx("p", {
138
+ children: C.handoff
139
+ }),
140
+ !pages?.length ? /*#__PURE__*/ _jsx("p", {
141
+ children: C.noPages
142
+ }) : collections.map((collection)=>{
143
+ const group = pages.filter((page)=>page.collection === collection);
144
+ return /*#__PURE__*/ _jsxs("section", {
145
+ children: [
146
+ /*#__PURE__*/ _jsx("h2", {
147
+ children: group[0].collectionLabel
148
+ }),
149
+ /*#__PURE__*/ _jsx("ul", {
150
+ children: group.map((page)=>/*#__PURE__*/ _jsxs("li", {
151
+ children: [
152
+ /*#__PURE__*/ _jsx("span", {
153
+ children: page.title
154
+ }),
155
+ ' ',
156
+ /*#__PURE__*/ _jsx("a", {
157
+ href: page.editorUrl,
158
+ children: C.open
159
+ })
160
+ ]
161
+ }, `${typeof page.id}:${page.id}`))
162
+ }),
163
+ group.length === 50 ? /*#__PURE__*/ _jsx("p", {
164
+ children: C.recentPages
165
+ }) : null
166
+ ]
167
+ }, collection);
168
+ })
169
+ ]
170
+ }) : step === 'setting' ? /*#__PURE__*/ _jsxs(_Fragment, {
171
+ children: [
172
+ /*#__PURE__*/ _jsx("h1", {
173
+ children: C.chooseSetting
174
+ }),
175
+ /*#__PURE__*/ _jsxs("fieldset", {
176
+ children: [
177
+ /*#__PURE__*/ _jsx("legend", {
178
+ children: C.setting
179
+ }),
180
+ surface.flagPoints.map((setting)=>/*#__PURE__*/ _jsxs("label", {
181
+ className: "xp-new-test-choice",
182
+ children: [
183
+ /*#__PURE__*/ _jsx("input", {
184
+ type: "radio",
185
+ name: "setting",
186
+ checked: pointId === setting.id,
187
+ onChange: ()=>{
188
+ if (pointId !== setting.id) {
189
+ setPointId(setting.id);
190
+ setName(setting.label);
191
+ }
192
+ }
193
+ }),
194
+ setting.label,
195
+ setting.description ? /*#__PURE__*/ _jsx("span", {
196
+ children: setting.description
197
+ }) : null
198
+ ]
199
+ }, setting.id))
200
+ ]
201
+ }),
202
+ /*#__PURE__*/ _jsxs("fieldset", {
203
+ "aria-describedby": "xp-new-people-help",
204
+ children: [
205
+ /*#__PURE__*/ _jsx("legend", {
206
+ children: C.people
207
+ }),
208
+ /*#__PURE__*/ _jsxs("label", {
209
+ children: [
210
+ /*#__PURE__*/ _jsx("input", {
211
+ type: "radio",
212
+ name: "people",
213
+ checked: unitType === 'visitor',
214
+ onChange: ()=>setUnitType('visitor')
215
+ }),
216
+ C.visitors
217
+ ]
218
+ }),
219
+ /*#__PURE__*/ _jsxs("label", {
220
+ children: [
221
+ /*#__PURE__*/ _jsx("input", {
222
+ type: "radio",
223
+ name: "people",
224
+ checked: unitType === 'user',
225
+ onChange: ()=>setUnitType('user')
226
+ }),
227
+ C.users
228
+ ]
229
+ })
230
+ ]
231
+ }),
232
+ /*#__PURE__*/ _jsx("p", {
233
+ id: "xp-new-people-help",
234
+ children: C.peopleHelp
235
+ }),
236
+ /*#__PURE__*/ _jsxs("details", {
237
+ open: advanced,
238
+ onToggle: (event)=>setAdvanced(event.currentTarget.open),
239
+ children: [
240
+ /*#__PURE__*/ _jsx("summary", {
241
+ children: C.advanced
242
+ }),
243
+ /*#__PURE__*/ _jsxs("label", {
244
+ children: [
245
+ C.group,
246
+ /*#__PURE__*/ _jsxs("select", {
247
+ "aria-describedby": "xp-new-group-help",
248
+ disabled: layerState !== 'ready',
249
+ value: layer === undefined ? '' : layers.findIndex((item)=>item.id === layer),
250
+ onChange: (event)=>setLayer(event.currentTarget.value === '' ? undefined : layers[Number(event.currentTarget.value)]?.id),
251
+ children: [
252
+ /*#__PURE__*/ _jsx("option", {
253
+ value: "",
254
+ children: C.noGroup
255
+ }),
256
+ layers.map((item, index)=>/*#__PURE__*/ _jsx("option", {
257
+ value: index,
258
+ children: item.name
259
+ }, index))
260
+ ]
261
+ })
262
+ ]
263
+ }),
264
+ /*#__PURE__*/ _jsx("p", {
265
+ id: "xp-new-group-help",
266
+ children: C.groupHelp
267
+ }),
268
+ layerState === 'loading' ? /*#__PURE__*/ _jsx("p", {
269
+ role: "status",
270
+ children: C.groupsLoading
271
+ }) : layerState === 'error' ? /*#__PURE__*/ _jsxs("p", {
272
+ role: "alert",
273
+ children: [
274
+ C.groupsError,
275
+ ' ',
276
+ /*#__PURE__*/ _jsx("button", {
277
+ type: "button",
278
+ onClick: ()=>setLayerRetry((value)=>value + 1),
279
+ children: C.retry
280
+ })
281
+ ]
282
+ }) : null
283
+ ]
284
+ })
285
+ ]
286
+ }) : /*#__PURE__*/ _jsxs("form", {
287
+ onSubmit: (event)=>{
288
+ event.preventDefault();
289
+ void submit();
290
+ },
291
+ children: [
292
+ /*#__PURE__*/ _jsx("h1", {
293
+ children: C.nameQuestion
294
+ }),
295
+ /*#__PURE__*/ _jsxs("label", {
296
+ children: [
297
+ C.name,
298
+ /*#__PURE__*/ _jsx("input", {
299
+ required: true,
300
+ value: name,
301
+ disabled: pending,
302
+ onChange: (event)=>setName(event.currentTarget.value)
303
+ })
304
+ ]
305
+ }),
306
+ /*#__PURE__*/ _jsxs("label", {
307
+ children: [
308
+ C.hypothesis,
309
+ /*#__PURE__*/ _jsx("textarea", {
310
+ value: hypothesis,
311
+ disabled: pending,
312
+ onChange: (event)=>setHypothesis(event.currentTarget.value)
313
+ })
314
+ ]
315
+ }),
316
+ error ? /*#__PURE__*/ _jsx("p", {
317
+ role: "alert",
318
+ children: error
319
+ }) : null,
320
+ /*#__PURE__*/ _jsx("button", {
321
+ type: "submit",
322
+ disabled: pending || !name.trim(),
323
+ children: pending ? C.creating : C.createTest
324
+ })
325
+ ]
326
+ }),
327
+ /*#__PURE__*/ _jsxs("div", {
328
+ className: "xp-new-test-actions",
329
+ children: [
330
+ /*#__PURE__*/ _jsx("button", {
331
+ type: "button",
332
+ disabled: pending,
333
+ onClick: ()=>{
334
+ if (step === 'kind') router.push(formatAdminURL({
335
+ adminRoute: surface.adminRoute,
336
+ path: '/experiments'
337
+ }));
338
+ else {
339
+ setError('');
340
+ setStep(step === 'name' ? 'setting' : 'kind');
341
+ }
342
+ },
343
+ children: C.back
344
+ }),
345
+ step === 'setting' ? /*#__PURE__*/ _jsx("button", {
346
+ type: "button",
347
+ disabled: !point,
348
+ onClick: ()=>setStep('name'),
349
+ children: C.next
350
+ }) : null
351
+ ]
352
+ })
353
+ ]
354
+ });
355
+ }
@@ -0,0 +1,9 @@
1
+ .xp-new-test { max-width: 60rem; padding: var(--base); color: var(--theme-text); }
2
+ .xp-new-test-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: var(--base); }
3
+ .xp-new-test-card { display: flex; flex-direction: column; gap: .75rem; padding: 1.5rem; border: 1px solid var(--theme-elevation-200); border-radius: .5rem; background: var(--theme-elevation-50); color: var(--theme-text); text-align: left; cursor: pointer; font: inherit; }
4
+ .xp-new-test-card strong { font-size: 1.25rem; }
5
+ .xp-new-test-card:hover { background: var(--theme-elevation-100); }
6
+ .xp-new-test label { display: block; margin-block: .75rem; }
7
+ .xp-new-test input:not([type=radio]), .xp-new-test textarea, .xp-new-test select { display: block; width: 100%; max-width: 36rem; padding: .5rem; color: var(--theme-text); background: var(--theme-input-bg); border: 1px solid var(--theme-elevation-300); font: inherit; }
8
+ .xp-new-test-choice span { display: block; margin-left: 1.5rem; }
9
+ .xp-new-test-actions { display: flex; gap: 1rem; margin-top: var(--base); }
@@ -0,0 +1,6 @@
1
+ import type { Arm } from '../../../types/contracts.js';
2
+ import type { PreflightResult } from '../../../types/endpoints.js';
3
+ type Placement = PreflightResult['placements'][number];
4
+ export declare function placementLine(placement: Placement): string;
5
+ export declare function slotReady(placement: Placement, arm: Arm): boolean;
6
+ export {};
@@ -0,0 +1,8 @@
1
+ import { TEST_PAGE as C } from '../../copy/testPage.js';
2
+ export function placementLine(placement) {
3
+ return `${C.onPage} ${placement.title} (${placement.detail === 'Published' ? 'Published' : 'Draft'})`;
4
+ }
5
+ export function slotReady(placement, arm) {
6
+ const slot = arm.kind === 'holdout' ? 'control' : arm.slot;
7
+ return Boolean(slot && (placement.slots?.[slot] ?? 0) > 0);
8
+ }
@@ -0,0 +1,2 @@
1
+ import type { KindParts } from '../contracts.js';
2
+ export declare const pageBlockParts: KindParts;
@@ -0,0 +1,64 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { TEST_PAGE as C } from '../../copy/testPage.js';
4
+ import { placementLine, slotReady } from './pageBlock.model.js';
5
+ function Binding({ test }) {
6
+ const placements = test.preflight?.placements ?? [];
7
+ return /*#__PURE__*/ _jsx("div", {
8
+ className: "xp-page-binding",
9
+ children: placements.length ? /*#__PURE__*/ _jsxs(_Fragment, {
10
+ children: [
11
+ placements.map((placement, index)=>/*#__PURE__*/ _jsxs("p", {
12
+ children: [
13
+ placementLine(placement),
14
+ ' ',
15
+ placement.editorUrl ? /*#__PURE__*/ _jsx("a", {
16
+ href: placement.editorUrl,
17
+ children: C.openPage
18
+ }) : null
19
+ ]
20
+ }, index)),
21
+ /*#__PURE__*/ _jsx("p", {
22
+ children: C.editedOnPage
23
+ })
24
+ ]
25
+ }) : /*#__PURE__*/ _jsx("p", {
26
+ children: C.notPlaced
27
+ })
28
+ });
29
+ }
30
+ function VersionContent({ test, armIndex }) {
31
+ const arm = test.doc?.arms[armIndex];
32
+ if (!arm) return null;
33
+ if (arm.kind === 'holdout') return /*#__PURE__*/ _jsx("p", {
34
+ children: C.holdoutContent
35
+ });
36
+ const placements = test.preflight?.placements ?? [];
37
+ return /*#__PURE__*/ _jsx("div", {
38
+ children: placements.length ? placements.map((placement, index)=>/*#__PURE__*/ _jsxs("p", {
39
+ children: [
40
+ /*#__PURE__*/ _jsxs("span", {
41
+ children: [
42
+ placement.title,
43
+ ": "
44
+ ]
45
+ }),
46
+ /*#__PURE__*/ _jsx("span", {
47
+ className: slotReady(placement, arm) ? 'xp-content-ready' : 'xp-content-empty',
48
+ children: slotReady(placement, arm) ? C.ready : C.emptySlot
49
+ }),
50
+ ' ',
51
+ placement.editorUrl ? /*#__PURE__*/ _jsx("a", {
52
+ href: placement.editorUrl,
53
+ children: C.editOnPage
54
+ }) : null
55
+ ]
56
+ }, index)) : /*#__PURE__*/ _jsx("p", {
57
+ children: C.emptySlot
58
+ })
59
+ });
60
+ }
61
+ export const pageBlockParts = {
62
+ Binding,
63
+ VersionContent
64
+ };
@@ -0,0 +1,15 @@
1
+ import type { SectionProps } from '../contracts.js';
2
+ import type { ExperimentAction } from '../../actions/actions.model.js';
3
+ type Props = SectionProps & {
4
+ onClose(): void;
5
+ };
6
+ /** Prop-driven ConfirmDialog adapter: same model/copy, section reload instead of a page reload. */
7
+ export declare function ConfirmAction({ test, surface, action, winnerLabel, onClose }: Props & {
8
+ action: ExperimentAction;
9
+ winnerLabel: string;
10
+ }): import("react").JSX.Element;
11
+ /** AllocateDialog's validation and copy, with data supplied by the test document. */
12
+ export declare function AllocateAction({ test, surface, onClose }: Props): import("react").JSX.Element;
13
+ /** AddMetricDialog adapter; the primary goal is deliberately absent from the role picker. */
14
+ export declare function AddMetricAction({ test, surface, onClose }: Props): import("react").JSX.Element;
15
+ export {};