@delmaredigital/payload-experiments 0.2.0-rc.7 → 0.3.0-rc.4

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 (336) hide show
  1. package/README.md +202 -26
  2. package/dist/admin/PreviewLinks.d.ts +2 -1
  3. package/dist/admin/PreviewLinks.js +50 -21
  4. package/dist/admin/TestsNavLink.d.ts +3 -1
  5. package/dist/admin/TestsNavLink.js +2 -2
  6. package/dist/admin/actions/ConfirmDialog.d.ts +7 -4
  7. package/dist/admin/actions/ConfirmDialog.js +37 -82
  8. package/dist/admin/actions/DecideDialog.d.ts +3 -1
  9. package/dist/admin/actions/DecideDialog.js +30 -13
  10. package/dist/admin/actions/MakeContentResult.d.ts +13 -2
  11. package/dist/admin/actions/MakeContentResult.js +115 -16
  12. package/dist/admin/actions/actions.model.d.ts +2 -4
  13. package/dist/admin/actions/actions.model.js +2 -3
  14. package/dist/admin/allocation.model.js +3 -5
  15. package/dist/admin/api.d.ts +10 -4
  16. package/dist/admin/api.js +11 -7
  17. package/dist/admin/armSelect/ArmSelectField.js +14 -22
  18. package/dist/admin/arms/arms.model.d.ts +1 -21
  19. package/dist/admin/arms/arms.model.js +1 -153
  20. package/dist/admin/copy/actions.d.ts +39 -3
  21. package/dist/admin/copy/actions.js +40 -4
  22. package/dist/admin/copy/armSelect.js +5 -5
  23. package/dist/admin/copy/arms.d.ts +1 -6
  24. package/dist/admin/copy/arms.js +1 -16
  25. package/dist/admin/copy/audience.d.ts +2 -1
  26. package/dist/admin/copy/audience.js +3 -2
  27. package/dist/admin/copy/common.d.ts +13 -6
  28. package/dist/admin/copy/common.js +14 -8
  29. package/dist/admin/copy/goals.d.ts +21 -6
  30. package/dist/admin/copy/goals.js +27 -6
  31. package/dist/admin/copy/readiness.d.ts +22 -0
  32. package/dist/admin/copy/readiness.js +21 -0
  33. package/dist/admin/copy/recommendation.d.ts +0 -3
  34. package/dist/admin/copy/recommendation.js +0 -3
  35. package/dist/admin/copy/results.d.ts +43 -2
  36. package/dist/admin/copy/results.js +44 -3
  37. package/dist/admin/copy/review.d.ts +2 -2
  38. package/dist/admin/copy/review.js +2 -2
  39. package/dist/admin/copy/setting.d.ts +2 -0
  40. package/dist/admin/copy/setting.js +2 -0
  41. package/dist/admin/copy/surface.d.ts +7 -5
  42. package/dist/admin/copy/surface.js +9 -5
  43. package/dist/admin/copy/testPage.d.ts +10 -0
  44. package/dist/admin/copy/testPage.js +10 -0
  45. package/dist/admin/format/date.d.ts +2 -0
  46. package/dist/admin/format/date.js +10 -0
  47. package/dist/admin/paths.d.ts +2 -1
  48. package/dist/admin/paths.js +2 -1
  49. package/dist/admin/previewLinks.model.d.ts +4 -2
  50. package/dist/admin/previewLinks.model.js +8 -7
  51. package/dist/admin/results/CiChart.js +11 -21
  52. package/dist/admin/results/DataQualityPanel.d.ts +4 -2
  53. package/dist/admin/results/DataQualityPanel.js +30 -17
  54. package/dist/admin/results/DataTable.d.ts +16 -0
  55. package/dist/admin/results/DataTable.js +152 -0
  56. package/dist/admin/results/StatTile.d.ts +7 -0
  57. package/dist/admin/results/StatTile.js +22 -0
  58. package/dist/admin/results/VerdictHero.d.ts +13 -0
  59. package/dist/admin/results/{VerdictCard.js → VerdictHero.js} +15 -12
  60. package/dist/admin/results/legacy.d.ts +16 -0
  61. package/dist/admin/results/legacy.js +27 -0
  62. package/dist/admin/results/releasePages.model.d.ts +17 -0
  63. package/dist/admin/results/releasePages.model.js +10 -0
  64. package/dist/admin/results/results.css +64 -0
  65. package/dist/admin/results/results.model.d.ts +11 -7
  66. package/dist/admin/results/results.model.js +24 -7
  67. package/dist/admin/results/snapshot.d.ts +14 -0
  68. package/dist/admin/results/snapshot.js +3 -0
  69. package/dist/admin/surface/ResultsRoute.d.ts +1 -1
  70. package/dist/admin/surface/ResultsRoute.js +59 -34
  71. package/dist/admin/surface/SurfaceShell.d.ts +11 -2
  72. package/dist/admin/surface/SurfaceShell.js +49 -14
  73. package/dist/admin/surface/TestsHome.d.ts +6 -1
  74. package/dist/admin/surface/TestsHome.js +182 -114
  75. package/dist/admin/surface/TestsSurface.js +56 -16
  76. package/dist/admin/surface/goals/GoalForm.js +341 -308
  77. package/dist/admin/surface/goals/GoalsList.js +123 -89
  78. package/dist/admin/surface/goals/data.d.ts +8 -2
  79. package/dist/admin/surface/goals/data.js +24 -16
  80. package/dist/admin/surface/goals/goals.css +10 -13
  81. package/dist/admin/surface/home.model.d.ts +8 -8
  82. package/dist/admin/surface/home.model.js +23 -12
  83. package/dist/admin/surface/newTest/NewTest.js +9 -9
  84. package/dist/admin/surface/pageBlock/parts.js +31 -26
  85. package/dist/admin/surface/readiness/ActionDialogs.js +47 -19
  86. package/dist/admin/surface/readiness/Banner.d.ts +3 -0
  87. package/dist/admin/surface/readiness/Banner.js +58 -33
  88. package/dist/admin/surface/readiness/SaveStatus.d.ts +1 -0
  89. package/dist/admin/surface/readiness/SaveStatus.js +6 -3
  90. package/dist/admin/surface/readiness/readiness.model.d.ts +2 -0
  91. package/dist/admin/surface/readiness/readiness.model.js +25 -9
  92. package/dist/admin/surface/readiness/useTransition.d.ts +1 -0
  93. package/dist/admin/surface/readiness/useTransition.js +2 -1
  94. package/dist/admin/surface/results/ReleasePages.d.ts +14 -0
  95. package/dist/admin/surface/results/ReleasePages.js +116 -0
  96. package/dist/admin/surface/results/ResultsBody.d.ts +11 -1
  97. package/dist/admin/surface/results/ResultsBody.js +277 -105
  98. package/dist/admin/surface/results/ResultsHeader.d.ts +10 -0
  99. package/dist/admin/surface/results/ResultsHeader.js +177 -0
  100. package/dist/admin/surface/results/recommendation.model.d.ts +3 -2
  101. package/dist/admin/surface/results/recommendation.model.js +12 -9
  102. package/dist/admin/surface/results/useResults.d.ts +21 -3
  103. package/dist/admin/surface/results/useResults.js +2 -1
  104. package/dist/admin/surface/setting/parts.js +75 -88
  105. package/dist/admin/surface/setting/setting.css +3 -15
  106. package/dist/admin/surface/surface.css +61 -47
  107. package/dist/admin/surface/test/AdvancedSection.js +55 -48
  108. package/dist/admin/surface/test/GoalSection.js +46 -47
  109. package/dist/admin/surface/test/LengthSection.js +46 -34
  110. package/dist/admin/surface/test/Rail.d.ts +4 -0
  111. package/dist/admin/surface/test/Rail.js +83 -0
  112. package/dist/admin/surface/test/ReadinessBar.d.ts +5 -0
  113. package/dist/admin/surface/test/ReadinessBar.js +33 -0
  114. package/dist/admin/surface/test/Section.d.ts +1 -1
  115. package/dist/admin/surface/test/Section.js +36 -16
  116. package/dist/admin/surface/test/TargetingSection.js +168 -142
  117. package/dist/admin/surface/test/TestPage.d.ts +2 -1
  118. package/dist/admin/surface/test/TestPage.js +146 -68
  119. package/dist/admin/surface/test/VersionsSection.js +151 -120
  120. package/dist/admin/surface/test/fields.d.ts +11 -4
  121. package/dist/admin/surface/test/fields.js +84 -85
  122. package/dist/admin/surface/test/jumpToSection.d.ts +3 -0
  123. package/dist/admin/surface/test/jumpToSection.js +10 -0
  124. package/dist/admin/surface/test/pageParts.js +9 -3
  125. package/dist/admin/surface/test/testPage.css +81 -14
  126. package/dist/admin/surface/test/testPage.model.d.ts +2 -3
  127. package/dist/admin/surface/test/testPage.model.js +1 -21
  128. package/dist/admin/surface/useTestDocument.js +12 -5
  129. package/dist/admin/targeting/targeting.model.d.ts +1 -3
  130. package/dist/admin/targeting/targeting.model.js +3 -8
  131. package/dist/admin/theme.css +115 -36
  132. package/dist/admin/theme.d.ts +38 -0
  133. package/dist/admin/theme.js +38 -1
  134. package/dist/admin/useApi.d.ts +17 -2
  135. package/dist/admin/useLayerUsage.js +14 -23
  136. package/dist/admin/views/ExperimentsRootView.js +12 -2
  137. package/dist/admin/views/TestsNavLinkServer.d.ts +2 -0
  138. package/dist/admin/views/TestsNavLinkServer.js +43 -0
  139. package/dist/arms/copy.d.ts +6 -0
  140. package/dist/arms/copy.js +16 -0
  141. package/dist/arms/model.d.ts +23 -0
  142. package/dist/arms/model.js +173 -0
  143. package/dist/collections/experiments/config.js +25 -0
  144. package/dist/collections/experiments/lockHook.js +3 -1
  145. package/dist/collections/identities.js +6 -1
  146. package/dist/collections/metrics.js +7 -0
  147. package/dist/collections/metricsGuards.d.ts +9 -0
  148. package/dist/collections/metricsGuards.js +33 -0
  149. package/dist/contentDone.d.ts +4 -0
  150. package/dist/contentDone.js +5 -0
  151. package/dist/db/appends.d.ts +6 -2
  152. package/dist/db/appends.js +10 -4
  153. package/dist/db/identities.d.ts +8 -7
  154. package/dist/db/identities.js +9 -6
  155. package/dist/db/locks.d.ts +6 -0
  156. package/dist/db/locks.js +13 -1
  157. package/dist/db/metricUsage.d.ts +19 -0
  158. package/dist/db/metricUsage.js +54 -0
  159. package/dist/db/names.d.ts +5 -0
  160. package/dist/db/names.js +5 -0
  161. package/dist/db/pageOccupancy.d.ts +12 -0
  162. package/dist/db/pageOccupancy.js +45 -0
  163. package/dist/db/publishedContent.d.ts +10 -0
  164. package/dist/db/publishedContent.js +43 -0
  165. package/dist/db/results.d.ts +2 -0
  166. package/dist/db/results.js +6 -2
  167. package/dist/db/snapshots.d.ts +18 -6
  168. package/dist/db/snapshots.js +25 -8
  169. package/dist/db/sweep.js +11 -6
  170. package/dist/endpoints/index.js +19 -1
  171. package/dist/endpoints/results.js +5 -0
  172. package/dist/endpoints/sanitizeReadinessDetail.d.ts +1 -0
  173. package/dist/endpoints/sanitizeReadinessDetail.js +2 -0
  174. package/dist/endpoints/summary.js +20 -2
  175. package/dist/endpoints/transitions.d.ts +15 -0
  176. package/dist/endpoints/transitions.js +36 -0
  177. package/dist/errors.d.ts +8 -0
  178. package/dist/errors.js +28 -0
  179. package/dist/exports/adminRsc.d.ts +1 -0
  180. package/dist/exports/adminRsc.js +1 -0
  181. package/dist/exports/index.d.ts +2 -1
  182. package/dist/exports/index.js +1 -0
  183. package/dist/exports/puck.d.ts +2 -1
  184. package/dist/exports/puck.js +1 -1
  185. package/dist/exports/puckEditor.d.ts +4 -1
  186. package/dist/exports/puckEditor.js +3 -1
  187. package/dist/exports/rsc.d.ts +6 -1
  188. package/dist/exports/rsc.js +2 -0
  189. package/dist/hooks/pageGuard.d.ts +5 -0
  190. package/dist/hooks/pageGuard.js +139 -0
  191. package/dist/lib/fetchAllDocs.d.ts +16 -0
  192. package/dist/lib/fetchAllDocs.js +56 -0
  193. package/dist/log.js +6 -3
  194. package/dist/manifest/compile.d.ts +5 -0
  195. package/dist/manifest/compile.js +5 -1
  196. package/dist/options.js +16 -0
  197. package/dist/plugin.js +30 -2
  198. package/dist/puck/ExperimentPicker.js +47 -16
  199. package/dist/puck/ExperimentSlot.d.ts +51 -1
  200. package/dist/puck/ExperimentSlot.js +23 -12
  201. package/dist/puck/copy.d.ts +6 -5
  202. package/dist/puck/copy.js +6 -5
  203. package/dist/puck/editor/CreateExperimentDrawer.js +46 -56
  204. package/dist/puck/editor/ExperimentSlotEditor.d.ts +52 -1
  205. package/dist/puck/editor/ExperimentSlotEditor.js +292 -137
  206. package/dist/puck/editor/ResultsReadout.d.ts +6 -0
  207. package/dist/puck/editor/ResultsReadout.js +99 -0
  208. package/dist/puck/editor/VersionBuilder.d.ts +34 -0
  209. package/dist/puck/editor/VersionBuilder.js +317 -0
  210. package/dist/puck/editor/armWrites.d.ts +7 -0
  211. package/dist/puck/editor/armWrites.js +71 -0
  212. package/dist/puck/editor/armsCache.d.ts +14 -0
  213. package/dist/puck/editor/armsCache.js +78 -0
  214. package/dist/puck/editor/copy.d.ts +33 -1
  215. package/dist/puck/editor/copy.js +45 -8
  216. package/dist/puck/editor/createTest.d.ts +1 -1
  217. package/dist/puck/editor/createTest.js +25 -14
  218. package/dist/puck/editor/editor.chrome.css +121 -0
  219. package/dist/puck/editor/editor.css +288 -204
  220. package/dist/puck/editor/editor.model.d.ts +4 -1
  221. package/dist/puck/editor/editor.model.js +10 -7
  222. package/dist/puck/editor/experimentOutlinePlugin.d.ts +3 -0
  223. package/dist/puck/editor/experimentOutlinePlugin.js +89 -0
  224. package/dist/puck/experimentSlotField.d.ts +2 -0
  225. package/dist/puck/experimentSlotField.js +11 -3
  226. package/dist/puck/hostContext.d.ts +10 -0
  227. package/dist/puck/hostContext.js +12 -0
  228. package/dist/puck/routes.d.ts +12 -0
  229. package/dist/puck/routes.js +11 -0
  230. package/dist/puck/slotConfig.d.ts +1 -1
  231. package/dist/puck/slotConfig.js +2 -2
  232. package/dist/results/aggregate.js +4 -3
  233. package/dist/results/analyse.d.ts +4 -1
  234. package/dist/results/analyse.js +27 -11
  235. package/dist/results/cuped.js +3 -2
  236. package/dist/results/identityCredit.d.ts +15 -7
  237. package/dist/results/identityCredit.js +32 -33
  238. package/dist/results/rolloutUnits.js +2 -1
  239. package/dist/results/snapshot.js +8 -2
  240. package/dist/results/srm.js +2 -1
  241. package/dist/sanitizeReadinessDetail.d.ts +7 -0
  242. package/dist/sanitizeReadinessDetail.js +63 -0
  243. package/dist/server/linkIdentity.d.ts +10 -1
  244. package/dist/server/linkIdentity.js +17 -15
  245. package/dist/server/metadata.d.ts +5 -0
  246. package/dist/server/metadata.js +18 -3
  247. package/dist/server/normaliseContentRelationships.d.ts +7 -0
  248. package/dist/server/normaliseContentRelationships.js +62 -0
  249. package/dist/server/recordContentChange.d.ts +1 -1
  250. package/dist/server/recordContentChange.js +17 -8
  251. package/dist/server/runResults.d.ts +3 -2
  252. package/dist/server/runResults.js +157 -35
  253. package/dist/targeting/values.d.ts +4 -0
  254. package/dist/targeting/values.js +10 -0
  255. package/dist/transitions/addMetric.js +8 -0
  256. package/dist/transitions/archive.js +2 -3
  257. package/dist/transitions/checkStart.d.ts +10 -3
  258. package/dist/transitions/checkStart.js +25 -0
  259. package/dist/transitions/contentFields.d.ts +7 -0
  260. package/dist/transitions/contentFields.js +20 -0
  261. package/dist/transitions/decide.js +22 -2
  262. package/dist/transitions/dismissContentEntry.d.ts +8 -0
  263. package/dist/transitions/dismissContentEntry.js +45 -0
  264. package/dist/transitions/makeContent.d.ts +5 -2
  265. package/dist/transitions/makeContent.js +217 -118
  266. package/dist/transitions/phaseRecord.d.ts +8 -2
  267. package/dist/transitions/placements.d.ts +3 -6
  268. package/dist/transitions/placements.js +12 -1
  269. package/dist/transitions/preflightData.d.ts +9 -1
  270. package/dist/transitions/preflightData.js +138 -20
  271. package/dist/transitions/releasePages.d.ts +8 -0
  272. package/dist/transitions/releasePages.js +26 -0
  273. package/dist/transitions/restoreContentEntry.d.ts +8 -0
  274. package/dist/transitions/restoreContentEntry.js +47 -0
  275. package/dist/transitions/start.js +62 -7
  276. package/dist/types/contracts.d.ts +24 -4
  277. package/dist/types/endpoints.d.ts +34 -3
  278. package/dist/types/index.d.ts +1 -0
  279. package/dist/types/index.js +1 -0
  280. package/dist/types/reasons.d.ts +3 -0
  281. package/dist/types/reasons.js +1 -0
  282. package/dist/types/snapshot.d.ts +6 -1
  283. package/dist/ui/Banner.d.ts +2 -0
  284. package/dist/ui/Banner.js +2 -0
  285. package/dist/ui/Breadcrumb.d.ts +7 -0
  286. package/dist/ui/Breadcrumb.js +25 -0
  287. package/dist/ui/Button.d.ts +15 -0
  288. package/dist/ui/Button.js +32 -0
  289. package/dist/ui/Card.d.ts +12 -0
  290. package/dist/ui/Card.js +40 -0
  291. package/dist/ui/Checkbox.d.ts +2 -0
  292. package/dist/ui/Checkbox.js +2 -0
  293. package/dist/{admin/components → ui}/ChipsInput.d.ts +4 -3
  294. package/dist/{admin/components → ui}/ChipsInput.js +20 -12
  295. package/dist/ui/Dialog.d.ts +13 -0
  296. package/dist/ui/Dialog.js +85 -0
  297. package/dist/ui/EmptyState.d.ts +2 -0
  298. package/dist/ui/EmptyState.js +2 -0
  299. package/dist/ui/Feedback.d.ts +24 -0
  300. package/dist/ui/Feedback.js +40 -0
  301. package/dist/ui/Inputs.d.ts +34 -0
  302. package/dist/ui/Inputs.js +225 -0
  303. package/dist/ui/NumberInput.d.ts +2 -0
  304. package/dist/ui/NumberInput.js +2 -0
  305. package/dist/ui/Range.d.ts +2 -0
  306. package/dist/ui/Range.js +2 -0
  307. package/dist/ui/SearchInput.d.ts +2 -0
  308. package/dist/ui/SearchInput.js +2 -0
  309. package/dist/ui/SectionCard.d.ts +2 -0
  310. package/dist/ui/SectionCard.js +2 -0
  311. package/dist/ui/Select.d.ts +2 -0
  312. package/dist/ui/Select.js +2 -0
  313. package/dist/ui/StatusChip.d.ts +2 -0
  314. package/dist/ui/StatusChip.js +2 -0
  315. package/dist/ui/Tabs.d.ts +16 -0
  316. package/dist/ui/Tabs.js +61 -0
  317. package/dist/ui/TextInput.d.ts +2 -0
  318. package/dist/ui/TextInput.js +2 -0
  319. package/dist/ui/Textarea.d.ts +2 -0
  320. package/dist/ui/Textarea.js +2 -0
  321. package/dist/ui/Toggle.d.ts +2 -0
  322. package/dist/ui/Toggle.js +2 -0
  323. package/dist/ui/accent.d.ts +40 -0
  324. package/dist/ui/accent.js +139 -0
  325. package/dist/ui/index.d.ts +9 -0
  326. package/dist/ui/index.js +9 -0
  327. package/dist/ui/ui.css +92 -0
  328. package/package.json +5 -2
  329. package/dist/admin/components/chipsInput.css +0 -11
  330. package/dist/admin/results/ArmTable.d.ts +0 -8
  331. package/dist/admin/results/ArmTable.js +0 -113
  332. package/dist/admin/results/VerdictCard.d.ts +0 -9
  333. package/dist/admin/surface/goals/GoalsBreadcrumb.d.ts +0 -5
  334. package/dist/admin/surface/goals/GoalsBreadcrumb.js +0 -47
  335. package/dist/admin/surface/test/TestHeader.d.ts +0 -4
  336. package/dist/admin/surface/test/TestHeader.js +0 -70
@@ -0,0 +1,177 @@
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 { formatAdminURL } from 'payload/shared';
5
+ import { SurfaceShell } from '../SurfaceShell.js';
6
+ import { Button } from '../../../ui/Button.js';
7
+ import { Banner, StatusChip } from '../../../ui/Feedback.js';
8
+ import { createApi } from '../../api.js';
9
+ import { availableActions, actionGroupLabel } from '../../actions/actions.model.js';
10
+ import { AllocateAction, ConfirmAction } from '../readiness/ActionDialogs.js';
11
+ import { READINESS, daysRemaining, displayDate, nextStep } from '../readiness/readiness.model.js';
12
+ import { READINESS_COPY as R, runningCopy, stoppedCopy, decidedCopy } from '../../copy/readiness.js';
13
+ import { RESULTS_COPY as C } from '../../copy/results.js';
14
+ import { TEST_PAGE } from '../../copy/testPage.js';
15
+ export function ResultsHeader({ test, surface, resultsVersion, children, actions, released }) {
16
+ const doc = test.doc;
17
+ const [selected, setSelected] = useState(null);
18
+ const [people, setPeople] = useState(null);
19
+ useEffect(()=>{
20
+ let active = true;
21
+ if (surface.canReadResults && doc.status === 'running') {
22
+ void createApi(surface.apiRoute).summary([
23
+ doc.id
24
+ ]).then((result)=>{
25
+ const count = result.ok ? result.data?.[doc.id]?.exposures : undefined;
26
+ if (active && typeof count === 'number' && Number.isFinite(count)) setPeople(count);
27
+ }).catch(()=>{});
28
+ }
29
+ return ()=>{
30
+ active = false;
31
+ };
32
+ }, [
33
+ doc.id,
34
+ doc.status,
35
+ surface.apiRoute,
36
+ surface.canReadResults,
37
+ resultsVersion
38
+ ]);
39
+ const decision = doc.decision;
40
+ const winner = actionGroupLabel(decision?.winnerArm ?? 'control', doc.arms.find((item)=>item.key === decision?.winnerArm)?.label);
41
+ const available = availableActions({
42
+ status: doc.status,
43
+ kind: doc.kind,
44
+ arms: doc.arms,
45
+ decision,
46
+ canManage: surface.canManage
47
+ }).filter((action)=>doc.status === 'running' ? [
48
+ 'allocate',
49
+ 'stop'
50
+ ].includes(action.id) : action.id !== 'decide').sort((a, b)=>doc.status === 'running' ? [
51
+ 'allocate',
52
+ 'stop'
53
+ ].indexOf(a.id) - [
54
+ 'allocate',
55
+ 'stop'
56
+ ].indexOf(b.id) : 0);
57
+ const next = nextStep(test.preflight, {
58
+ ...doc,
59
+ flagPoints: surface.flagPoints
60
+ });
61
+ const ready = Boolean(test.preflight && !test.preflightPending && !test.preflightError && test.preflight.checks.every((check)=>check.ok));
62
+ const startReason = next?.sentence ?? (!ready ? test.preflightError ? R.checkError : R.checking : undefined);
63
+ const action = available.find((item)=>item.id === selected);
64
+ const sentence = doc.status === 'running' ? runningCopy(displayDate(doc.startedAt), people, daysRemaining(doc, Date.now())) : doc.status === 'stopped' ? stoppedCopy(displayDate(doc.stoppedAt)) : doc.status === 'decided' ? decidedCopy(displayDate(doc.decidedAt), winner) : doc.status === 'archived' ? R.archived : null;
65
+ const testURL = formatAdminURL({
66
+ adminRoute: surface.adminRoute,
67
+ path: `/experiments/${encodeURIComponent(String(doc.id))}`
68
+ });
69
+ return /*#__PURE__*/ _jsxs(SurfaceShell, {
70
+ adminRoute: surface.adminRoute,
71
+ title: doc.name,
72
+ crumbs: [
73
+ {
74
+ label: C.tests,
75
+ href: formatAdminURL({
76
+ adminRoute: surface.adminRoute,
77
+ path: '/experiments'
78
+ })
79
+ },
80
+ {
81
+ label: doc.name,
82
+ href: testURL
83
+ },
84
+ {
85
+ label: C.results
86
+ }
87
+ ],
88
+ status: /*#__PURE__*/ _jsxs(_Fragment, {
89
+ children: [
90
+ /*#__PURE__*/ _jsx("span", {
91
+ className: "xp-tests-kind",
92
+ children: TEST_PAGE.kinds[doc.kind]
93
+ }),
94
+ /*#__PURE__*/ _jsx(StatusChip, {
95
+ status: doc.status
96
+ })
97
+ ]
98
+ }),
99
+ subtitle: /*#__PURE__*/ _jsxs(_Fragment, {
100
+ children: [
101
+ sentence ? /*#__PURE__*/ _jsx("p", {
102
+ role: "status",
103
+ children: sentence
104
+ }) : null,
105
+ released,
106
+ surface.canManage ? test.preflight?.checks.filter((check)=>check.code === 'make-content-unsupported' && check.warning).map((check, index)=>/*#__PURE__*/ _jsx(Banner, {
107
+ tone: "warning",
108
+ children: READINESS[check.code].next(check.detail, doc)
109
+ }, `${check.code}/${index}`)) : null
110
+ ]
111
+ }),
112
+ actions: /*#__PURE__*/ _jsxs("div", {
113
+ className: "xp-ui-button-group",
114
+ children: [
115
+ /*#__PURE__*/ _jsx(Button, {
116
+ variant: "quiet",
117
+ href: testURL,
118
+ children: C.backToSetup
119
+ }),
120
+ available.map((item)=>/*#__PURE__*/ _jsx(Button, {
121
+ variant: item.tone === 'danger' ? 'danger' : 'secondary',
122
+ disabled: item.id === 'start' && !!startReason || !!selected || test.hasUnsaved || test.saving === 'saving' || item.id === 'allocate' && doc.allocation >= 100,
123
+ title: item.id === 'start' ? startReason : item.id === 'allocate' && doc.allocation >= 100 ? R.everyone : undefined,
124
+ onClick: ()=>setSelected(item.id),
125
+ children: item.id === 'allocate' ? R.allocate : item.label
126
+ }, item.id)),
127
+ actions
128
+ ]
129
+ }),
130
+ children: [
131
+ test.errors._section ? /*#__PURE__*/ _jsx(Banner, {
132
+ tone: "error",
133
+ children: test.errors._section
134
+ }) : null,
135
+ test.preflightError ? /*#__PURE__*/ _jsx(Banner, {
136
+ tone: "error",
137
+ children: test.preflightError
138
+ }) : null,
139
+ children,
140
+ action?.id === 'allocate' ? /*#__PURE__*/ _jsx(AllocateAction, {
141
+ test: test,
142
+ surface: surface,
143
+ onClose: ()=>setSelected(null)
144
+ }) : action ? /*#__PURE__*/ _jsx(ConfirmAction, {
145
+ test: test,
146
+ surface: surface,
147
+ action: action,
148
+ winnerLabel: winner,
149
+ onClose: ()=>setSelected(null)
150
+ }) : null
151
+ ]
152
+ });
153
+ }
154
+ export function ReaderResultsShell({ surface, children, data }) {
155
+ // CORE-48 sends a missing name as an empty string.
156
+ const title = data?.experiment?.name?.trim() || C.test;
157
+ return /*#__PURE__*/ _jsx(SurfaceShell, {
158
+ adminRoute: surface.adminRoute,
159
+ title: title,
160
+ crumbs: [
161
+ {
162
+ label: C.tests,
163
+ href: formatAdminURL({
164
+ adminRoute: surface.adminRoute,
165
+ path: '/experiments'
166
+ })
167
+ },
168
+ {
169
+ label: title
170
+ },
171
+ {
172
+ label: C.results
173
+ }
174
+ ],
175
+ children: children
176
+ });
177
+ }
@@ -1,8 +1,9 @@
1
1
  import type { PhaseSummary } from '../../../types/endpoints.js';
2
2
  import type { Status } from '../../../types/contracts.js';
3
- import type { Snapshot, VerdictCode } from '../../../types/snapshot.js';
3
+ import type { VerdictCode } from '../../../types/snapshot.js';
4
+ import { type DisplaySnapshot } from '../../results/snapshot.js';
4
5
  export interface RecommendationContext {
5
- snapshot: Snapshot;
6
+ snapshot: DisplaySnapshot;
6
7
  phase?: PhaseSummary;
7
8
  plannedDurationDays?: number | null;
8
9
  status?: Status;
@@ -1,5 +1,9 @@
1
+ import { formatDate } from '../../format/date.js';
1
2
  import { armLabel } from '../../labels.js';
2
3
  import { formatCount, formatPercent } from '../../results/format.js';
4
+ import { RESULTS_COPY } from '../../copy/results.js';
5
+ import { legacyRecommendationWinner } from '../../results/legacy.js';
6
+ import { isLegacySnapshot } from '../../results/snapshot.js';
3
7
  import { RECOMMENDATION_COPY as C, collectingRecommendation, guardrailRecommendation, mixedRecommendation, rolloutCollectingRecommendation, rolloutReadoutRecommendation, runningRecommendation, winnerRecommendation, worseRecommendation, storedGuardrailFinding } from '../../copy/recommendation.js';
4
8
  function label(ctx, key, fallback = C.group) {
5
9
  const stored = ctx.phase?.arms.find((arm)=>arm.key === key)?.label.trim();
@@ -13,7 +17,10 @@ function label(ctx, key, fallback = C.group) {
13
17
  }
14
18
  const primary = ({ snapshot })=>snapshot.metrics.find((metric)=>metric.role === 'primary');
15
19
  const worse = (ctx)=>primary(ctx)?.comparisons.find((comparison)=>comparison.significant === 'worse' && ctx.phase?.arms.some((arm)=>arm.key === comparison.arm && arm.kind === 'variant'))?.arm;
16
- const winner = (ctx)=>label(ctx, ctx.snapshot.winnerArm ?? ctx.snapshot.verdict.recommendedArm, C.winner);
20
+ const rolloutWinner = (ctx)=>isLegacySnapshot(ctx.snapshot) ? legacyRecommendationWinner(ctx.snapshot, ctx.phase) : {
21
+ key: ctx.snapshot.winnerArm,
22
+ label: label(ctx, ctx.snapshot.winnerArm)
23
+ };
17
24
  /** Select stored findings and format them; never run inference in the admin. */ export const RECOMMENDATION = {
18
25
  unavailable: ()=>C.unavailable,
19
26
  'data-problem': ()=>C.dataProblem,
@@ -42,18 +49,14 @@ const winner = (ctx)=>label(ctx, ctx.snapshot.winnerArm ?? ctx.snapshot.verdict.
42
49
  const days = ctx.plannedDurationDays;
43
50
  const start = Date.parse(ctx.phase?.startedAt ?? '');
44
51
  const end = days != null && Number.isFinite(days) && days > 0 ? start + days * 86_400_000 : NaN;
45
- return Number.isFinite(end) ? runningRecommendation(new Intl.DateTimeFormat('en-US', {
46
- month: 'short',
47
- day: 'numeric',
48
- year: 'numeric',
49
- timeZone: 'UTC'
50
- }).format(end)) : C.keepRunning;
52
+ return Number.isFinite(end) ? runningRecommendation(formatDate(end)) : C.keepRunning;
51
53
  },
52
54
  'no-difference': ()=>C.noDifference,
53
- 'rollout-collecting': (ctx)=>rolloutCollectingRecommendation(winner(ctx)),
54
- 'rollout-readout': (ctx)=>rolloutReadoutRecommendation(winner(ctx), formatPercent(primary(ctx)?.comparisons.find((comparison)=>comparison.arm === (ctx.snapshot.winnerArm ?? ctx.snapshot.verdict.recommendedArm))?.lift, true))
55
+ 'rollout-collecting': (ctx)=>rolloutCollectingRecommendation(rolloutWinner(ctx).label),
56
+ 'rollout-readout': (ctx)=>rolloutReadoutRecommendation(rolloutWinner(ctx).label, formatPercent(primary(ctx)?.comparisons.find((comparison)=>comparison.arm === rolloutWinner(ctx).key)?.lift, true))
55
57
  };
56
58
  export const recommendation = (ctx)=>{
59
+ if (!isLegacySnapshot(ctx.snapshot) && ctx.snapshot.phaseKind === 'rollout' && ctx.snapshot.winnerArm === null) return RESULTS_COPY.missingWinner;
57
60
  const sentence = RECOMMENDATION[ctx.snapshot.verdict.code];
58
61
  return sentence(ctx);
59
62
  };
@@ -1,14 +1,17 @@
1
1
  import type { DocId, Status } from '../../../types/contracts.js';
2
2
  import type { PhaseSummary, ResultsResponse } from '../../../types/endpoints.js';
3
3
  import { type ApiResult } from '../../api.js';
4
+ import type { PageReleaseDecision } from '../../results/releasePages.model.js';
4
5
  export interface ResultsDocument {
6
+ flagPoint?: string;
7
+ kind?: string;
5
8
  status: Status;
6
9
  arms: Array<{
7
10
  key: string;
8
11
  kind?: string;
9
12
  label?: string;
10
13
  }>;
11
- decision?: {
14
+ decision?: PageReleaseDecision & {
12
15
  phase: number;
13
16
  winnerArm?: string;
14
17
  } | null;
@@ -27,18 +30,33 @@ export declare function useResults(id: DocId, { apiRoute, canReadResults, canMan
27
30
  }): {
28
31
  api: {
29
32
  start: (id: DocId) => Promise<ApiResult<import("../../../types/endpoints.js").TransitionSuccess>>;
30
- allocate: (id: DocId, body: import("../../../types/endpoints.js").AllocateBody) => Promise<ApiResult<import("../../../types/endpoints.js").TransitionSuccess>>;
31
- addMetric: (id: DocId, body: import("../../../types/endpoints.js").AddMetricBody) => Promise<ApiResult<import("../../../types/endpoints.js").TransitionSuccess>>;
33
+ allocate: (id: DocId, body: import("../../../types/endpoints.js").AllocateBody, options?: {
34
+ notFound?: string;
35
+ codes?: Readonly<Record<string, string>>;
36
+ fallback?: string;
37
+ }) => Promise<ApiResult<import("../../../types/endpoints.js").TransitionSuccess>>;
38
+ addMetric: (id: DocId, body: import("../../../types/endpoints.js").AddMetricBody, options?: {
39
+ notFound?: string;
40
+ codes?: Readonly<Record<string, string>>;
41
+ fallback?: string;
42
+ }) => Promise<ApiResult<import("../../../types/endpoints.js").TransitionSuccess>>;
32
43
  stop: (id: DocId) => Promise<ApiResult<import("../../../types/endpoints.js").TransitionSuccess>>;
33
44
  decide: (id: DocId, body: import("../../../types/endpoints.js").DecideBody) => Promise<ApiResult<import("../../../types/endpoints.js").TransitionSuccess>>;
34
45
  releaseHoldout: (id: DocId) => Promise<ApiResult<import("../../../types/endpoints.js").TransitionSuccess>>;
46
+ releasePages: (id: DocId) => Promise<ApiResult<import("../../../types/endpoints.js").TransitionSuccess>>;
35
47
  makeContent: (id: DocId) => Promise<ApiResult<import("../../../types/endpoints.js").MakeContentResult>>;
48
+ dismissContentEntry: (id: DocId, body: import("../../../types/endpoints.js").DismissContentEntryBody) => Promise<ApiResult<import("../../../types/endpoints.js").DismissContentEntryResult>>;
49
+ restoreContentEntry: (id: DocId, body: import("../../../types/endpoints.js").RestoreContentEntryBody) => Promise<ApiResult<import("../../../types/endpoints.js").RestoreContentEntryResult>>;
36
50
  archive: (id: DocId, body: import("../../../types/endpoints.js").ArchiveBody) => Promise<ApiResult<import("../../../types/endpoints.js").TransitionSuccess>>;
37
51
  preflight: (id: DocId) => Promise<ApiResult<import("../../../types/endpoints.js").PreflightResult>>;
38
52
  previewToken: (id: DocId, arm: string) => Promise<ApiResult<import("../../../types/endpoints.js").PreviewTokenResult>>;
39
53
  results: (id: DocId, options?: {
40
54
  phase?: number;
41
55
  series?: boolean;
56
+ } & {
57
+ notFound?: string;
58
+ codes?: Readonly<Record<string, string>>;
59
+ fallback?: string;
42
60
  }) => Promise<ApiResult<ResultsResponse>>;
43
61
  recompute: (id: DocId) => Promise<ApiResult<{
44
62
  snapshotId: string;
@@ -85,7 +85,8 @@ export function useResults(id, { apiRoute, canReadResults, canManage = true }) {
85
85
  }),
86
86
  api.results(id, {
87
87
  phase: round ?? undefined,
88
- series: true
88
+ series: true,
89
+ notFound: round === null ? undefined : API_MESSAGES.roundNotFound
89
90
  })
90
91
  ]).then(([document, result])=>{
91
92
  if (signal.aborted) return;
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useId, useState } from 'react';
4
- import { CheckboxInput, TextareaInput, TextInput } from '@payloadcms/ui';
4
+ import { Checkbox, Textarea, TextInput, NumberInput, Select } from '../../../ui/Inputs.js';
5
5
  import { EDITABLE_BY_STATUS, isEditable } from '../../../collections/experiments/editability.js';
6
6
  import { coerceParam, paramIssue, paramsForArm, setParam } from '../../arms/params.model.js';
7
7
  import { SETTING_COPY } from '../../copy/setting.js';
@@ -18,36 +18,31 @@ function Binding({ test, surface }) {
18
18
  return /*#__PURE__*/ _jsxs("div", {
19
19
  className: "xp-setting-binding",
20
20
  children: [
21
- editable ? /*#__PURE__*/ _jsxs("label", {
22
- htmlFor: id,
21
+ editable ? /*#__PURE__*/ _jsxs(Select, {
22
+ id: id,
23
+ label: SETTING_COPY.setting,
24
+ value: point?.id ?? '',
25
+ "aria-describedby": point ? `${id}-description` : undefined,
26
+ onChange: (event)=>{
27
+ const current = test.doc;
28
+ if (!current || !surface.canManage || !isEditable(current.status, 'flagPoint') || event.target.value === current.flagPoint) return;
29
+ const next = surface.flagPoints.find((point)=>point.id === event.target.value);
30
+ if (!next) return;
31
+ test.stage({
32
+ flagPoint: next.id,
33
+ arms: bindSetting(current.arms, next)
34
+ });
35
+ void test.commit();
36
+ },
23
37
  children: [
24
- SETTING_COPY.setting,
25
- /*#__PURE__*/ _jsxs("select", {
26
- id: id,
27
- value: point?.id ?? '',
28
- "aria-describedby": point ? `${id}-description` : undefined,
29
- onChange: (event)=>{
30
- const current = test.doc;
31
- if (!current || !surface.canManage || !isEditable(current.status, 'flagPoint') || event.target.value === current.flagPoint) return;
32
- const next = surface.flagPoints.find((point)=>point.id === event.target.value);
33
- if (!next) return;
34
- test.stage({
35
- flagPoint: next.id,
36
- arms: bindSetting(current.arms, next)
37
- });
38
- void test.commit();
39
- },
40
- children: [
41
- !point ? /*#__PURE__*/ _jsx("option", {
42
- value: "",
43
- children: SETTING_COPY.choose
44
- }) : null,
45
- surface.flagPoints.map((point)=>/*#__PURE__*/ _jsx("option", {
46
- value: point.id,
47
- children: point.label
48
- }, point.id))
49
- ]
50
- })
38
+ !point ? /*#__PURE__*/ _jsx("option", {
39
+ value: "",
40
+ children: SETTING_COPY.choose
41
+ }) : null,
42
+ surface.flagPoints.map((point)=>/*#__PURE__*/ _jsx("option", {
43
+ value: point.id,
44
+ children: point.label
45
+ }, point.id))
51
46
  ]
52
47
  }) : /*#__PURE__*/ _jsxs("p", {
53
48
  title: reason ?? undefined,
@@ -111,7 +106,7 @@ function Parameter({ test, surface, armIndex, paramKey, field }) {
111
106
  };
112
107
  const control = paramControl(field);
113
108
  const shared = {
114
- path: id,
109
+ id,
115
110
  label: field.label,
116
111
  required: field.required
117
112
  };
@@ -146,12 +141,12 @@ function Parameter({ test, surface, armIndex, paramKey, field }) {
146
141
  children: reason
147
142
  }) : null
148
143
  ]
149
- }) : control === 'checkbox' ? /*#__PURE__*/ _jsx(CheckboxInput, {
144
+ }) : control === 'checkbox' ? /*#__PURE__*/ _jsx(Checkbox, {
150
145
  ...shared,
151
- id: id,
146
+ error: issue ?? undefined,
152
147
  name: id,
153
148
  checked: value === true,
154
- onToggle: (event)=>save(event.target.checked)
149
+ onChange: (event)=>save(event.target.checked)
155
150
  }) : control === 'segmented' ? /*#__PURE__*/ _jsxs("fieldset", {
156
151
  "aria-describedby": issue ? `${id}-error` : undefined,
157
152
  children: [
@@ -177,61 +172,45 @@ function Parameter({ test, surface, armIndex, paramKey, field }) {
177
172
  }, option.value))
178
173
  })
179
174
  ]
180
- }) : control === 'select' ? /*#__PURE__*/ _jsxs("label", {
181
- htmlFor: id,
182
- children: [
183
- field.label,
184
- /*#__PURE__*/ _jsxs("select", {
185
- id: id,
186
- value: text,
187
- required: field.required,
188
- "aria-invalid": !!issue,
189
- "aria-describedby": issue ? `${id}-error` : undefined,
190
- onChange: (event)=>save(event.target.value),
191
- children: [
192
- /*#__PURE__*/ _jsx("option", {
193
- value: "",
194
- children: SETTING_COPY.empty
195
- }),
196
- field.options?.map((option)=>/*#__PURE__*/ _jsx("option", {
197
- value: option.value,
198
- children: option.label
199
- }, option.value))
200
- ]
201
- })
202
- ]
203
- }) : control === 'number' ? /*#__PURE__*/ _jsxs("label", {
204
- htmlFor: id,
175
+ }) : control === 'select' ? /*#__PURE__*/ _jsxs(Select, {
176
+ id: id,
177
+ label: field.label,
178
+ value: text,
179
+ required: field.required,
180
+ error: issue ?? undefined,
181
+ onChange: (event)=>save(event.target.value),
205
182
  children: [
206
- field.label,
207
- /*#__PURE__*/ _jsx("input", {
208
- id: id,
209
- type: "number",
210
- min: field.min,
211
- max: field.max,
212
- step: "any",
213
- required: field.required,
214
- value: typeof value === 'number' && Number.isFinite(value) || typeof value === 'string' ? value : '',
215
- "aria-invalid": !!issue,
216
- "aria-describedby": issue ? `${id}-error` : undefined,
217
- onChange: (event)=>editDraft(event.target.value)
218
- })
183
+ /*#__PURE__*/ _jsx("option", {
184
+ value: "",
185
+ children: SETTING_COPY.empty
186
+ }),
187
+ field.options?.map((option)=>/*#__PURE__*/ _jsx("option", {
188
+ value: option.value,
189
+ children: option.label
190
+ }, option.value))
219
191
  ]
220
- }) : control === 'textarea' ? /*#__PURE__*/ _jsx(TextareaInput, {
192
+ }) : control === 'number' ? /*#__PURE__*/ _jsx(NumberInput, {
193
+ id: id,
194
+ label: field.label,
195
+ min: field.min,
196
+ max: field.max,
197
+ step: "any",
198
+ required: field.required,
199
+ value: typeof value === 'number' && Number.isFinite(value) || typeof value === 'string' ? value : '',
200
+ error: issue ?? undefined,
201
+ onChange: (event)=>editDraft(event.target.value)
202
+ }) : control === 'textarea' ? /*#__PURE__*/ _jsx(Textarea, {
221
203
  ...shared,
222
- Error: inlineError,
223
- showError: !!issue,
204
+ error: issue ?? undefined,
224
205
  value: text,
225
206
  onChange: (event)=>editDraft(event.target.value)
226
207
  }) : /*#__PURE__*/ _jsx(TextInput, {
227
208
  ...shared,
228
- Error: inlineError,
229
- showError: !!issue,
230
- hasMany: false,
209
+ error: issue ?? undefined,
231
210
  value: text,
232
211
  onChange: (event)=>editDraft(event.target.value)
233
212
  }),
234
- arm.kind === 'control' || !editable || control !== 'text' && control !== 'textarea' ? inlineError : null
213
+ arm.kind === 'control' || !editable || control === 'segmented' ? inlineError : null
235
214
  ]
236
215
  });
237
216
  }
@@ -239,22 +218,30 @@ function VersionContent({ test, surface, armIndex }) {
239
218
  const doc = test.doc;
240
219
  const arm = doc?.arms[armIndex];
241
220
  if (!doc || !arm) return null;
242
- if (arm.kind === 'holdout') return /*#__PURE__*/ _jsx("p", {
221
+ if (arm.kind === 'holdout') return /*#__PURE__*/ _jsx("span", {
222
+ className: "xp-content-chip",
243
223
  children: SETTING_COPY.holdout
244
224
  });
245
225
  const point = surface.flagPoints.find((point)=>point.id === doc.flagPoint);
246
226
  if (!point) return /*#__PURE__*/ _jsx("p", {
247
227
  children: SETTING_COPY.choose
248
228
  });
249
- return /*#__PURE__*/ _jsx("div", {
229
+ const ready = Object.entries(point.params).every(([key, field])=>!paramIssue(field, paramsForArm(arm, point)[key]));
230
+ return /*#__PURE__*/ _jsxs("div", {
250
231
  className: "xp-setting-values",
251
- children: Object.entries(point.params).map(([key, field])=>/*#__PURE__*/ _jsx(Parameter, {
252
- test: test,
253
- surface: surface,
254
- armIndex: armIndex,
255
- paramKey: key,
256
- field: field
257
- }, `${doc.id}:${point.id}:${arm.key}:${key}:${doc.status}:${surface.canManage}`))
232
+ children: [
233
+ /*#__PURE__*/ _jsx("span", {
234
+ className: `xp-content-chip ${ready ? 'xp-content-ready' : 'xp-content-empty'}`,
235
+ children: ready ? SETTING_COPY.valuesReady : SETTING_COPY.setValues
236
+ }),
237
+ Object.entries(point.params).map(([key, field])=>/*#__PURE__*/ _jsx(Parameter, {
238
+ test: test,
239
+ surface: surface,
240
+ armIndex: armIndex,
241
+ paramKey: key,
242
+ field: field
243
+ }, `${doc.id}:${point.id}:${arm.key}:${key}:${doc.status}:${surface.canManage}`))
244
+ ]
258
245
  });
259
246
  }
260
247
  export const settingParts = {
@@ -1,16 +1,4 @@
1
- .xp-setting-binding select,
2
- .xp-setting-parameter select,
3
- .xp-setting-parameter input[type='number'] {
4
- display: block;
5
- width: 100%;
6
- padding: 0.65rem;
7
- margin-top: 0.4rem;
8
- border: 1px solid var(--xp-border);
9
- border-radius: var(--xp-radius);
10
- background: var(--xp-input-bg);
11
- color: var(--xp-text);
12
- }
13
- .xp-setting-values { display: grid; gap: 1rem; }
1
+ .xp-setting-values { display: grid; gap: var(--xp-space-3); }
14
2
  .xp-setting-value { white-space: pre-wrap; }
15
3
  .xp-setting-lock { color: var(--xp-text-muted); }
16
4
  .xp-setting-parameter fieldset { border: 0; padding: 0; margin: 0; }
@@ -25,5 +13,5 @@
25
13
  background: var(--xp-input-bg);
26
14
  color: var(--xp-text);
27
15
  }
28
- .xp-setting-segments input:checked + span { background: var(--xp-border); border-color: var(--xp-text); }
29
- .xp-setting-segments input:focus-visible + span { outline: 2px solid var(--xp-text); outline-offset: 2px; }
16
+ .xp-setting-segments input:checked + span { background: var(--xp-accent-subtle); border-color: var(--xp-accent); }
17
+ .xp-setting-segments input:focus-visible + span { outline: 2px solid var(--xp-focus); outline-offset: 2px; }