@delmaredigital/payload-experiments 0.2.0-rc.7 → 0.3.0-rc.1
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.
- package/README.md +129 -11
- package/dist/admin/PreviewLinks.d.ts +2 -1
- package/dist/admin/PreviewLinks.js +24 -16
- package/dist/admin/actions/ConfirmDialog.d.ts +7 -4
- package/dist/admin/actions/ConfirmDialog.js +37 -82
- package/dist/admin/actions/DecideDialog.d.ts +3 -1
- package/dist/admin/actions/DecideDialog.js +30 -13
- package/dist/admin/actions/MakeContentResult.d.ts +13 -2
- package/dist/admin/actions/MakeContentResult.js +115 -16
- package/dist/admin/actions/actions.model.d.ts +2 -4
- package/dist/admin/actions/actions.model.js +2 -3
- package/dist/admin/allocation.model.js +3 -5
- package/dist/admin/api.d.ts +10 -4
- package/dist/admin/api.js +11 -7
- package/dist/admin/copy/actions.d.ts +39 -3
- package/dist/admin/copy/actions.js +40 -4
- package/dist/admin/copy/armSelect.js +5 -5
- package/dist/admin/copy/audience.d.ts +2 -1
- package/dist/admin/copy/audience.js +3 -2
- package/dist/admin/copy/common.d.ts +13 -6
- package/dist/admin/copy/common.js +14 -8
- package/dist/admin/copy/goals.d.ts +21 -6
- package/dist/admin/copy/goals.js +27 -6
- package/dist/admin/copy/readiness.d.ts +19 -0
- package/dist/admin/copy/readiness.js +19 -0
- package/dist/admin/copy/recommendation.d.ts +0 -3
- package/dist/admin/copy/recommendation.js +0 -3
- package/dist/admin/copy/results.d.ts +41 -2
- package/dist/admin/copy/results.js +42 -3
- package/dist/admin/copy/review.d.ts +1 -1
- package/dist/admin/copy/review.js +1 -1
- package/dist/admin/copy/setting.d.ts +2 -0
- package/dist/admin/copy/setting.js +2 -0
- package/dist/admin/copy/surface.d.ts +7 -4
- package/dist/admin/copy/surface.js +9 -4
- package/dist/admin/copy/testPage.d.ts +10 -0
- package/dist/admin/copy/testPage.js +10 -0
- package/dist/admin/format/date.d.ts +2 -0
- package/dist/admin/format/date.js +10 -0
- package/dist/admin/previewLinks.model.d.ts +2 -2
- package/dist/admin/previewLinks.model.js +5 -7
- package/dist/admin/results/CiChart.js +11 -21
- package/dist/admin/results/DataQualityPanel.d.ts +4 -2
- package/dist/admin/results/DataQualityPanel.js +30 -17
- package/dist/admin/results/DataTable.d.ts +16 -0
- package/dist/admin/results/DataTable.js +152 -0
- package/dist/admin/results/StatTile.d.ts +7 -0
- package/dist/admin/results/StatTile.js +22 -0
- package/dist/admin/results/VerdictHero.d.ts +13 -0
- package/dist/admin/results/{VerdictCard.js → VerdictHero.js} +15 -12
- package/dist/admin/results/releasePages.model.d.ts +17 -0
- package/dist/admin/results/releasePages.model.js +10 -0
- package/dist/admin/results/results.css +64 -0
- package/dist/admin/results/results.model.d.ts +5 -1
- package/dist/admin/results/results.model.js +10 -2
- package/dist/admin/surface/ResultsRoute.d.ts +1 -1
- package/dist/admin/surface/ResultsRoute.js +59 -34
- package/dist/admin/surface/SurfaceShell.d.ts +11 -2
- package/dist/admin/surface/SurfaceShell.js +49 -14
- package/dist/admin/surface/TestsHome.d.ts +6 -1
- package/dist/admin/surface/TestsHome.js +183 -112
- package/dist/admin/surface/TestsSurface.js +56 -16
- package/dist/admin/surface/goals/GoalForm.js +341 -308
- package/dist/admin/surface/goals/GoalsList.js +123 -89
- package/dist/admin/surface/goals/data.d.ts +8 -2
- package/dist/admin/surface/goals/data.js +11 -3
- package/dist/admin/surface/goals/goals.css +10 -13
- package/dist/admin/surface/home.model.d.ts +7 -8
- package/dist/admin/surface/home.model.js +23 -12
- package/dist/admin/surface/newTest/NewTest.js +5 -5
- package/dist/admin/surface/pageBlock/parts.js +31 -26
- package/dist/admin/surface/readiness/ActionDialogs.js +43 -14
- package/dist/admin/surface/readiness/Banner.d.ts +3 -0
- package/dist/admin/surface/readiness/Banner.js +58 -33
- package/dist/admin/surface/readiness/SaveStatus.d.ts +1 -0
- package/dist/admin/surface/readiness/SaveStatus.js +6 -3
- package/dist/admin/surface/readiness/readiness.model.d.ts +2 -0
- package/dist/admin/surface/readiness/readiness.model.js +18 -9
- package/dist/admin/surface/readiness/useTransition.d.ts +1 -0
- package/dist/admin/surface/readiness/useTransition.js +2 -1
- package/dist/admin/surface/results/ReleasePages.d.ts +14 -0
- package/dist/admin/surface/results/ReleasePages.js +116 -0
- package/dist/admin/surface/results/ResultsBody.d.ts +11 -1
- package/dist/admin/surface/results/ResultsBody.js +276 -105
- package/dist/admin/surface/results/ResultsHeader.d.ts +10 -0
- package/dist/admin/surface/results/ResultsHeader.js +177 -0
- package/dist/admin/surface/results/recommendation.model.js +2 -6
- package/dist/admin/surface/results/useResults.d.ts +21 -3
- package/dist/admin/surface/results/useResults.js +2 -1
- package/dist/admin/surface/setting/parts.js +75 -88
- package/dist/admin/surface/setting/setting.css +3 -15
- package/dist/admin/surface/surface.css +62 -47
- package/dist/admin/surface/test/AdvancedSection.js +55 -48
- package/dist/admin/surface/test/GoalSection.js +39 -32
- package/dist/admin/surface/test/LengthSection.js +46 -34
- package/dist/admin/surface/test/Rail.d.ts +4 -0
- package/dist/admin/surface/test/Rail.js +83 -0
- package/dist/admin/surface/test/ReadinessBar.d.ts +5 -0
- package/dist/admin/surface/test/ReadinessBar.js +33 -0
- package/dist/admin/surface/test/Section.d.ts +1 -1
- package/dist/admin/surface/test/Section.js +36 -16
- package/dist/admin/surface/test/TargetingSection.js +168 -142
- package/dist/admin/surface/test/TestPage.d.ts +2 -1
- package/dist/admin/surface/test/TestPage.js +146 -68
- package/dist/admin/surface/test/VersionsSection.js +151 -120
- package/dist/admin/surface/test/fields.d.ts +11 -4
- package/dist/admin/surface/test/fields.js +84 -85
- package/dist/admin/surface/test/jumpToSection.d.ts +3 -0
- package/dist/admin/surface/test/jumpToSection.js +10 -0
- package/dist/admin/surface/test/pageParts.js +9 -3
- package/dist/admin/surface/test/testPage.css +81 -14
- package/dist/admin/surface/useTestDocument.js +10 -4
- package/dist/admin/targeting/targeting.model.d.ts +1 -3
- package/dist/admin/targeting/targeting.model.js +3 -8
- package/dist/admin/theme.css +115 -36
- package/dist/admin/theme.d.ts +38 -0
- package/dist/admin/theme.js +38 -1
- package/dist/admin/useApi.d.ts +17 -2
- package/dist/admin/views/ExperimentsRootView.js +12 -2
- package/dist/collections/experiments/config.js +25 -0
- package/dist/collections/experiments/lockHook.js +3 -1
- package/dist/collections/identities.js +6 -1
- package/dist/collections/metrics.js +7 -0
- package/dist/collections/metricsGuards.d.ts +9 -0
- package/dist/collections/metricsGuards.js +33 -0
- package/dist/contentDone.d.ts +4 -0
- package/dist/contentDone.js +5 -0
- package/dist/db/identities.d.ts +8 -7
- package/dist/db/identities.js +9 -6
- package/dist/db/metricUsage.d.ts +19 -0
- package/dist/db/metricUsage.js +54 -0
- package/dist/db/names.d.ts +5 -0
- package/dist/db/names.js +5 -0
- package/dist/db/publishedContent.d.ts +10 -0
- package/dist/db/publishedContent.js +43 -0
- package/dist/db/results.d.ts +2 -0
- package/dist/db/results.js +6 -2
- package/dist/db/snapshots.d.ts +18 -6
- package/dist/db/snapshots.js +23 -7
- package/dist/db/sweep.js +11 -6
- package/dist/endpoints/index.js +19 -1
- package/dist/endpoints/results.js +5 -0
- package/dist/endpoints/sanitizeReadinessDetail.d.ts +1 -0
- package/dist/endpoints/sanitizeReadinessDetail.js +2 -0
- package/dist/endpoints/summary.js +20 -2
- package/dist/endpoints/transitions.d.ts +15 -0
- package/dist/endpoints/transitions.js +36 -0
- package/dist/errors.d.ts +8 -0
- package/dist/errors.js +28 -0
- package/dist/exports/index.d.ts +2 -1
- package/dist/exports/index.js +1 -0
- package/dist/exports/puckEditor.d.ts +1 -0
- package/dist/exports/puckEditor.js +1 -0
- package/dist/exports/rsc.d.ts +5 -1
- package/dist/exports/rsc.js +2 -0
- package/dist/hooks/pageGuard.d.ts +5 -0
- package/dist/hooks/pageGuard.js +121 -0
- package/dist/log.js +6 -3
- package/dist/manifest/compile.d.ts +5 -0
- package/dist/manifest/compile.js +5 -1
- package/dist/options.js +23 -0
- package/dist/plugin.js +26 -2
- package/dist/puck/copy.d.ts +1 -1
- package/dist/puck/copy.js +1 -1
- package/dist/puck/editor/editor.chrome.css +235 -0
- package/dist/puck/editor/editor.css +241 -43
- package/dist/results/aggregate.js +4 -3
- package/dist/results/analyse.d.ts +4 -1
- package/dist/results/analyse.js +27 -11
- package/dist/results/cuped.js +3 -2
- package/dist/results/identityCredit.d.ts +15 -7
- package/dist/results/identityCredit.js +32 -33
- package/dist/results/rolloutUnits.js +2 -1
- package/dist/results/snapshot.js +8 -2
- package/dist/results/srm.js +2 -1
- package/dist/sanitizeReadinessDetail.d.ts +7 -0
- package/dist/sanitizeReadinessDetail.js +54 -0
- package/dist/server/linkIdentity.d.ts +10 -1
- package/dist/server/linkIdentity.js +17 -15
- package/dist/server/metadata.d.ts +5 -0
- package/dist/server/metadata.js +9 -1
- package/dist/server/runResults.d.ts +3 -2
- package/dist/server/runResults.js +121 -31
- package/dist/targeting/values.d.ts +4 -0
- package/dist/targeting/values.js +10 -0
- package/dist/transitions/addMetric.js +8 -0
- package/dist/transitions/archive.js +2 -3
- package/dist/transitions/checkStart.d.ts +6 -3
- package/dist/transitions/checkStart.js +15 -0
- package/dist/transitions/contentFields.d.ts +7 -0
- package/dist/transitions/contentFields.js +20 -0
- package/dist/transitions/decide.js +6 -1
- package/dist/transitions/dismissContentEntry.d.ts +8 -0
- package/dist/transitions/dismissContentEntry.js +45 -0
- package/dist/transitions/makeContent.d.ts +5 -2
- package/dist/transitions/makeContent.js +217 -118
- package/dist/transitions/phaseRecord.d.ts +8 -2
- package/dist/transitions/placements.d.ts +1 -0
- package/dist/transitions/placements.js +4 -0
- package/dist/transitions/preflightData.d.ts +1 -1
- package/dist/transitions/preflightData.js +42 -4
- package/dist/transitions/releasePages.d.ts +8 -0
- package/dist/transitions/releasePages.js +26 -0
- package/dist/transitions/restoreContentEntry.d.ts +8 -0
- package/dist/transitions/restoreContentEntry.js +47 -0
- package/dist/transitions/start.js +30 -5
- package/dist/types/contracts.d.ts +14 -0
- package/dist/types/endpoints.d.ts +34 -3
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/reasons.d.ts +3 -0
- package/dist/types/reasons.js +1 -0
- package/dist/types/snapshot.d.ts +6 -1
- package/dist/ui/Banner.d.ts +2 -0
- package/dist/ui/Banner.js +2 -0
- package/dist/ui/Breadcrumb.d.ts +7 -0
- package/dist/ui/Breadcrumb.js +25 -0
- package/dist/ui/Button.d.ts +15 -0
- package/dist/ui/Button.js +32 -0
- package/dist/ui/Card.d.ts +12 -0
- package/dist/ui/Card.js +40 -0
- package/dist/ui/Checkbox.d.ts +2 -0
- package/dist/ui/Checkbox.js +2 -0
- package/dist/{admin/components → ui}/ChipsInput.d.ts +4 -3
- package/dist/{admin/components → ui}/ChipsInput.js +20 -12
- package/dist/ui/Dialog.d.ts +13 -0
- package/dist/ui/Dialog.js +85 -0
- package/dist/ui/EmptyState.d.ts +2 -0
- package/dist/ui/EmptyState.js +2 -0
- package/dist/ui/Feedback.d.ts +24 -0
- package/dist/ui/Feedback.js +40 -0
- package/dist/ui/Inputs.d.ts +34 -0
- package/dist/ui/Inputs.js +225 -0
- package/dist/ui/NumberInput.d.ts +2 -0
- package/dist/ui/NumberInput.js +2 -0
- package/dist/ui/Range.d.ts +2 -0
- package/dist/ui/Range.js +2 -0
- package/dist/ui/SearchInput.d.ts +2 -0
- package/dist/ui/SearchInput.js +2 -0
- package/dist/ui/SectionCard.d.ts +2 -0
- package/dist/ui/SectionCard.js +2 -0
- package/dist/ui/Select.d.ts +2 -0
- package/dist/ui/Select.js +2 -0
- package/dist/ui/StatusChip.d.ts +2 -0
- package/dist/ui/StatusChip.js +2 -0
- package/dist/ui/Tabs.d.ts +14 -0
- package/dist/ui/Tabs.js +54 -0
- package/dist/ui/TextInput.d.ts +2 -0
- package/dist/ui/TextInput.js +2 -0
- package/dist/ui/Textarea.d.ts +2 -0
- package/dist/ui/Textarea.js +2 -0
- package/dist/ui/Toggle.d.ts +2 -0
- package/dist/ui/Toggle.js +2 -0
- package/dist/ui/accent.d.ts +21 -0
- package/dist/ui/accent.js +81 -0
- package/dist/ui/index.d.ts +9 -0
- package/dist/ui/index.js +9 -0
- package/dist/ui/ui.css +92 -0
- package/package.json +1 -1
- package/dist/admin/components/chipsInput.css +0 -11
- package/dist/admin/results/ArmTable.d.ts +0 -8
- package/dist/admin/results/ArmTable.js +0 -113
- package/dist/admin/results/VerdictCard.d.ts +0 -9
- package/dist/admin/surface/goals/GoalsBreadcrumb.d.ts +0 -5
- package/dist/admin/surface/goals/GoalsBreadcrumb.js +0 -47
- package/dist/admin/surface/test/TestHeader.d.ts +0 -4
- package/dist/admin/surface/test/TestHeader.js +0 -70
|
@@ -1,23 +1,90 @@
|
|
|
1
1
|
.xp-test-page { color: var(--xp-text); background: var(--xp-bg); max-width: 90rem; margin: 0 auto; padding: 1.5rem; }
|
|
2
|
+
.xp-test-page--setup { min-width: 0; padding: 0 0 160px; }
|
|
2
3
|
.xp-test-header { position: sticky; top: 0; z-index: 10; background: var(--xp-bg); padding: 1rem 0; border-bottom: 1px solid var(--xp-border); }
|
|
3
4
|
.xp-header-meta, .xp-section-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; margin-block: 1rem; }
|
|
4
|
-
.xp-kind-chip, .xp-status-pill { border: 1px solid var(--xp-border-
|
|
5
|
+
.xp-kind-chip, .xp-status-pill { border: 1px solid var(--xp-border-strong); border-radius: 1rem; padding: .25rem .75rem; }
|
|
5
6
|
.xp-status-pill--success, .xp-content-ready, .xp-section-check--done { color: var(--xp-success-text); }
|
|
6
7
|
.xp-content-empty, .xp-status-pill--warning { color: var(--xp-warning-text); }
|
|
7
|
-
.xp-test-section
|
|
8
|
-
.xp-version-rows { display: grid;
|
|
9
|
-
.xp-version-row {
|
|
10
|
-
.xp-version-
|
|
11
|
-
.xp-
|
|
8
|
+
.xp-test-section, .xp-test-advanced { scroll-margin-top: var(--xp-space-6); }
|
|
9
|
+
.xp-version-rows { display: grid; grid-template-columns: minmax(0, 1.3fr) var(--xp-version-share-width) minmax(var(--xp-version-state-width), 1fr) var(--xp-version-remove-width); gap: var(--xp-space-3); align-items: center; }
|
|
10
|
+
.xp-version-row, .xp-version-grid-head { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; gap: var(--xp-space-3); align-items: center; }
|
|
11
|
+
.xp-version-grid-head { margin-bottom: var(--xp-space-2); font: var(--xp-text-small); color: var(--xp-text-2); }
|
|
12
|
+
.xp-version-row > .xp-field-error, .xp-version-row > [role=alert] { grid-column: 1 / -1; }
|
|
13
|
+
.xp-version-remove { grid-column: 4; }
|
|
14
|
+
.xp-grid-field .xp-ui-field { margin: 0; }
|
|
15
|
+
.xp-grid-field .xp-ui-field > label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
|
|
16
|
+
.xp-version-content { display: flex; flex-wrap: nowrap; gap: var(--xp-space-2); align-items: center; min-width: 0; }
|
|
17
|
+
.xp-version-content .xp-ui-button { white-space: nowrap; }
|
|
18
|
+
.xp-content-chip { flex-shrink: 0; display: inline-flex; width: fit-content; border-radius: var(--xp-radius-chip); padding: var(--xp-space-half) var(--xp-space-2); font: var(--xp-text-small); background: var(--xp-surface-2); color: var(--xp-text-2); }
|
|
19
|
+
.xp-content-chip.xp-content-ready { background: var(--xp-success-bg); color: var(--xp-success); }
|
|
20
|
+
.xp-content-chip.xp-content-empty { background: var(--xp-warning-bg); color: var(--xp-warning); }
|
|
21
|
+
.xp-traffic-bar { display: flex; height: var(--xp-space-2); gap: var(--xp-space-half); margin-block: var(--xp-space-5) var(--xp-space-3); overflow: hidden; border-radius: var(--xp-space-1); }
|
|
12
22
|
.xp-traffic-bar > span { display: block; }
|
|
13
|
-
.xp-
|
|
14
|
-
.xp-
|
|
15
|
-
.xp-field
|
|
16
|
-
.xp-field
|
|
23
|
+
.xp-split-legend { display: flex; flex-wrap: wrap; gap: var(--xp-space-4); font: var(--xp-text-small); color: var(--xp-text-2); }
|
|
24
|
+
.xp-split-legend i { display: inline-block; width: var(--xp-legend-key-size); height: var(--xp-legend-key-size); border-radius: var(--xp-legend-key-radius); margin-right: var(--xp-space-one-half); }
|
|
25
|
+
.xp-field-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--xp-space-4); }
|
|
26
|
+
.xp-test-advanced .xp-field-grid { padding-top: var(--xp-space-4); }
|
|
27
|
+
.xp-field-grid > div { min-width: 0; }
|
|
28
|
+
.xp-field-grid p, .xp-page-binding p { color: var(--xp-text-2); font: var(--xp-text-small); }
|
|
29
|
+
.xp-read-only code { font-family: var(--xp-mono); overflow-wrap: anywhere; }
|
|
30
|
+
.xp-ui-checkbox-list { display: flex; flex-wrap: wrap; gap: var(--xp-space-2) var(--xp-space-4); }
|
|
31
|
+
.xp-duration-suggestion { align-items: center; margin-top: var(--xp-space-4); }
|
|
17
32
|
.xp-read-only { padding-block: .5rem; }
|
|
18
33
|
.xp-read-only p { margin-block: .5rem; }
|
|
19
34
|
.xp-field-error { color: var(--xp-error-text); }
|
|
20
|
-
|
|
21
|
-
.xp-
|
|
22
|
-
.xp-
|
|
23
|
-
|
|
35
|
+
|
|
36
|
+
.xp-targeting-row { display: grid; grid-template-columns: var(--xp-targeting-attribute-width) var(--xp-targeting-comparison-width) minmax(0, 1fr); align-items: start; gap: var(--xp-space-3); border: 1px solid var(--xp-border); border-radius: var(--xp-radius-control); padding: var(--xp-space-4); margin-bottom: var(--xp-space-4); }
|
|
37
|
+
.xp-targeting-row > .xp-ui-button-group, .xp-targeting-row > p { grid-column: 1 / -1; }
|
|
38
|
+
@media (max-width: 720px) {
|
|
39
|
+
.xp-version-rows { grid-template-columns: minmax(0, 1fr) var(--xp-version-share-width-mobile); }
|
|
40
|
+
.xp-version-content { flex-wrap: wrap; }
|
|
41
|
+
.xp-version-remove:empty { display: none; }
|
|
42
|
+
.xp-version-content, .xp-setting-values, .xp-version-remove { grid-column: 1 / -1; }
|
|
43
|
+
.xp-version-grid-head > :nth-child(n+3) { display: none; }
|
|
44
|
+
.xp-targeting-row, .xp-field-grid { grid-template-columns: 1fr; }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.xp-test-layout { display: grid; grid-template-columns: 220px minmax(0, 1fr); align-items: start; gap: var(--xp-space-8); }
|
|
48
|
+
.xp-test-content { display: grid; gap: var(--xp-space-8); min-width: 0; max-width: 760px; }
|
|
49
|
+
.xp-test-rail { position: sticky; top: var(--xp-space-6); min-width: 0; }
|
|
50
|
+
.xp-test-rail-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: var(--xp-space-1); }
|
|
51
|
+
.xp-test-rail-item { display: flex; align-items: center; gap: var(--xp-space-2); padding: var(--xp-space-2); border-radius: var(--xp-radius-control); color: var(--xp-text-2); text-decoration: none; font: var(--xp-text-small); }
|
|
52
|
+
.xp-test-rail-item:hover, .xp-test-rail-item.is-active { background: var(--xp-surface-2); color: var(--xp-text); }
|
|
53
|
+
.xp-test-rail-item.is-active { font-weight: 600; }
|
|
54
|
+
.xp-test-rail-item--advanced { margin-top: var(--xp-space-3); color: var(--xp-text-3); }
|
|
55
|
+
.xp-test-rail-mark { flex: none; color: var(--xp-text-3); }
|
|
56
|
+
.xp-test-rail-mark--done { color: var(--xp-success); }
|
|
57
|
+
.xp-test-sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
|
|
58
|
+
.xp-test-rail-item:focus-visible, .xp-test-advanced > summary:focus-visible, .xp-test-content h2:focus { outline: 2px solid var(--xp-focus); outline-offset: 2px; }
|
|
59
|
+
.xp-test-advanced { border: 1px solid var(--xp-border); border-radius: var(--xp-radius-card); background: var(--xp-surface); }
|
|
60
|
+
.xp-test-advanced > summary { cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: var(--xp-space-3); padding: var(--xp-space-4) var(--xp-space-5); color: var(--xp-text-2); }
|
|
61
|
+
.xp-test-advanced > summary h2 { margin: 0; font: var(--xp-text-body); }
|
|
62
|
+
.xp-test-advanced[open] > summary { border-bottom: 1px solid var(--xp-border); }
|
|
63
|
+
.xp-test-readiness-bar { position: fixed; bottom: 0; inset-inline: 0; z-index: 20; background: var(--xp-surface); border-top: 1px solid var(--xp-border); }
|
|
64
|
+
.xp-readiness { color: var(--xp-text); background: var(--xp-surface); padding: var(--xp-space-4); border: 1px solid var(--xp-border-strong); border-radius: var(--xp-radius-control); }
|
|
65
|
+
.xp-readiness--ready:not(.xp-readiness--bar) { background: var(--xp-success-bg); }
|
|
66
|
+
.xp-readiness--bar { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--xp-space-2) var(--xp-space-4); padding-block: var(--xp-space-3); min-height: 64px; border: 0; border-radius: 0; }
|
|
67
|
+
.xp-readiness__state { display: flex; align-items: center; flex-wrap: wrap; gap: var(--xp-space-2); min-width: 0; }
|
|
68
|
+
.xp-readiness__state p, .xp-readiness--bar > p { margin: 0; }
|
|
69
|
+
.xp-readiness__state > p { font-weight: 500; }
|
|
70
|
+
.xp-readiness--bar .xp-save-status, .xp-readiness__separator { color: var(--xp-text-3); font: var(--xp-text-small); }
|
|
71
|
+
.xp-readiness__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--xp-space-2); }
|
|
72
|
+
.xp-readiness--bar > .xp-readiness__actions { grid-column: 2; grid-row: 1 / span 3; justify-content: flex-end; }
|
|
73
|
+
@media (max-width: 960px) {
|
|
74
|
+
.xp-test-layout { grid-template-columns: minmax(0, 1fr); gap: var(--xp-space-5); }
|
|
75
|
+
.xp-test-rail { top: 0; z-index: 2; background: var(--xp-bg); padding-block: var(--xp-space-2); border-bottom: 1px solid var(--xp-border); }
|
|
76
|
+
.xp-test-rail-list { flex-direction: row; overflow-x: auto; }
|
|
77
|
+
.xp-test-rail-item { white-space: nowrap; }
|
|
78
|
+
.xp-test-rail-item--advanced { margin-top: 0; }
|
|
79
|
+
.xp-test-content { max-width: none; }
|
|
80
|
+
.xp-test-section, .xp-test-advanced { scroll-margin-top: 64px; }
|
|
81
|
+
}
|
|
82
|
+
@media (max-width: 720px) {
|
|
83
|
+
.xp-readiness--bar { grid-template-columns: minmax(0, 1fr); }
|
|
84
|
+
/* The sentence wraps under the save state here, so a trailing separator would dangle. */
|
|
85
|
+
.xp-readiness--bar .xp-readiness__separator { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
|
|
86
|
+
.xp-readiness--bar > .xp-readiness__actions { grid-column: 1; grid-row: auto; justify-content: flex-start; }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.xp-ui-checkbox-list > .xp-ui-field:has(input[type="search"]) { flex-basis: 100%; }
|
|
90
|
+
.xp-targeting-row .xp-ui-chips { margin-block: 0; }
|
|
@@ -155,11 +155,13 @@ function stage(session, partial) {
|
|
|
155
155
|
}
|
|
156
156
|
session.publish();
|
|
157
157
|
}
|
|
158
|
-
async function readDocument() {
|
|
158
|
+
async function readDocument(forSave = false) {
|
|
159
159
|
const response = await fetch(url, {
|
|
160
160
|
method: 'GET',
|
|
161
161
|
credentials: 'include',
|
|
162
|
-
|
|
162
|
+
...forSave ? {} : {
|
|
163
|
+
signal: controller.signal
|
|
164
|
+
}
|
|
163
165
|
});
|
|
164
166
|
if (!response.ok) throw new Error(API_MESSAGES.unreadable);
|
|
165
167
|
const doc = await response.json();
|
|
@@ -181,6 +183,10 @@ function stage(session, partial) {
|
|
|
181
183
|
let failed = false;
|
|
182
184
|
try {
|
|
183
185
|
if (!session.saved) return;
|
|
186
|
+
if (typeof session.saved.updatedAt !== 'string' || !session.saved.updatedAt) {
|
|
187
|
+
session.saved = await readDocument(true);
|
|
188
|
+
if (typeof session.saved.updatedAt !== 'string' || !session.saved.updatedAt) throw new Error(API_MESSAGES.unreadable);
|
|
189
|
+
}
|
|
184
190
|
const patch = changedPatch(session.saved, queued);
|
|
185
191
|
changed = Object.keys(patch).length > 0;
|
|
186
192
|
if (changed) {
|
|
@@ -221,8 +227,8 @@ function stage(session, partial) {
|
|
|
221
227
|
const doc = body?.doc;
|
|
222
228
|
const readable = doc && doc.id != null && doc.status;
|
|
223
229
|
// A 2xx has applied even if its response body was lost. Preserve it while re-reading.
|
|
224
|
-
// The old timestamp is no longer a valid baseline.
|
|
225
|
-
//
|
|
230
|
+
// The old timestamp is no longer a valid baseline. The next queued save
|
|
231
|
+
// must recover it with a GET before sending another PATCH.
|
|
226
232
|
session.saved = readable ? doc : {
|
|
227
233
|
...session.saved,
|
|
228
234
|
...patch,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { TargetingRule } from '../../types/contracts.js';
|
|
2
2
|
import type { SerializedAttributeKeys } from '../../types/admin.js';
|
|
3
3
|
import type { TargetingOp } from '../../targeting/ops.js';
|
|
4
|
+
export { readListValue } from '../../targeting/values.js';
|
|
4
5
|
type Attribute = SerializedAttributeKeys[string];
|
|
5
6
|
export type AttributeType = Attribute['type'];
|
|
6
7
|
export declare function opsFor(type?: AttributeType): readonly TargetingOp[];
|
|
@@ -13,11 +14,8 @@ export declare function valueInput(attribute?: Attribute, op?: TargetingOp): {
|
|
|
13
14
|
}[];
|
|
14
15
|
};
|
|
15
16
|
export declare function coerceValue(type: AttributeType, op: TargetingOp, raw: unknown): string | number | boolean | string[] | null;
|
|
16
|
-
/** Only the read boundary accepts legacy comma-separated document values. */
|
|
17
|
-
export declare function readListValue(raw: unknown): string[];
|
|
18
17
|
/** Normalize the read boundary before any whole-group edit. */
|
|
19
18
|
export declare function readTargetingRules(rules: TargetingRule[]): TargetingRule[];
|
|
20
19
|
export declare function rowPath(path: string): string;
|
|
21
20
|
export declare function emptyListHint(op: TargetingOp, value: unknown): string | undefined;
|
|
22
21
|
export declare function humaniseAttribute(key: string): string;
|
|
23
|
-
export {};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { TARGETING_OPS, isOpValid } from '../../targeting/ops.js';
|
|
2
|
+
import { coerceListValue, readListValue } from '../../targeting/values.js';
|
|
2
3
|
import { NUMBER_OP_LABELS, STRING_OP_LABELS, AUDIENCE_COPY } from '../copy/audience.js';
|
|
4
|
+
export { readListValue } from '../../targeting/values.js';
|
|
3
5
|
export function opsFor(type) {
|
|
4
6
|
return type ? TARGETING_OPS[type] : [];
|
|
5
7
|
}
|
|
@@ -27,11 +29,7 @@ export function valueInput(attribute, op = 'eq') {
|
|
|
27
29
|
export function coerceValue(type, op, raw) {
|
|
28
30
|
if (!isOpValid(type, op)) return null;
|
|
29
31
|
if (type === 'string') {
|
|
30
|
-
if (op === 'in' || op === 'nin') return
|
|
31
|
-
...new Set((Array.isArray(raw) ? raw.map(String) : [
|
|
32
|
-
String(raw ?? '')
|
|
33
|
-
]).map((value)=>value.trim()).filter(Boolean))
|
|
34
|
-
];
|
|
32
|
+
if (op === 'in' || op === 'nin') return coerceListValue(raw);
|
|
35
33
|
return raw == null ? '' : String(raw);
|
|
36
34
|
}
|
|
37
35
|
if (type === 'number') {
|
|
@@ -41,9 +39,6 @@ export function coerceValue(type, op, raw) {
|
|
|
41
39
|
}
|
|
42
40
|
return raw === true || raw === 'true' ? true : raw === false || raw === 'false' ? false : null;
|
|
43
41
|
}
|
|
44
|
-
/** Only the read boundary accepts legacy comma-separated document values. */ export function readListValue(raw) {
|
|
45
|
-
return coerceValue('string', 'in', typeof raw === 'string' ? raw.split(',') : raw);
|
|
46
|
-
}
|
|
47
42
|
/** Normalize the read boundary before any whole-group edit. */ export function readTargetingRules(rules) {
|
|
48
43
|
return rules.map((rule)=>rule.op === 'in' || rule.op === 'nin' ? {
|
|
49
44
|
...rule,
|
package/dist/admin/theme.css
CHANGED
|
@@ -1,44 +1,123 @@
|
|
|
1
|
-
/* The Payload token boundary.
|
|
1
|
+
/* The only Payload token boundary. Reference: Payload 3.90.2; nearest neutral
|
|
2
|
+
elevation by RGB distance to the approved mockup, advancing toward the mockup
|
|
3
|
+
on collision so all five surface steps stay distinct (light / dark):
|
|
4
|
+
bg 50/0; surface 0/50; surface-2 100/100; surface-3 150/150;
|
|
5
|
+
accent-subtle 200/200;
|
|
6
|
+
border 100/100; border-strong 250/200; text 850/800;
|
|
7
|
+
text-2 650/550; text-3 450/350; accent 800/800; hover 900/900;
|
|
8
|
+
accent-fg 0/0; focus 800/800; series-muted 300/250.
|
|
9
|
+
Semantic and series hues are fixed mockup literals; only neutrals use Payload. */
|
|
2
10
|
:root, [data-theme] {
|
|
3
|
-
--xp-bg: var(--theme-
|
|
4
|
-
--xp-
|
|
5
|
-
--xp-surface: var(--theme-elevation-
|
|
6
|
-
--xp-surface-
|
|
7
|
-
--xp-border: var(--theme-elevation-
|
|
8
|
-
--xp-border-strong: var(--theme-elevation-
|
|
11
|
+
--xp-bg: var(--theme-elevation-50);
|
|
12
|
+
--xp-surface: var(--theme-elevation-0);
|
|
13
|
+
--xp-surface-2: var(--theme-elevation-100);
|
|
14
|
+
--xp-surface-3: var(--theme-elevation-150);
|
|
15
|
+
--xp-border: var(--theme-elevation-100);
|
|
16
|
+
--xp-border-strong: var(--theme-elevation-250);
|
|
17
|
+
--xp-text: var(--theme-elevation-850);
|
|
18
|
+
--xp-text-2: var(--theme-elevation-650);
|
|
19
|
+
--xp-text-3: var(--theme-elevation-450);
|
|
20
|
+
--xp-accent: var(--theme-elevation-800);
|
|
21
|
+
--xp-accent-hover: var(--theme-elevation-900);
|
|
22
|
+
--xp-accent-active: var(--theme-elevation-950);
|
|
23
|
+
--xp-accent-subtle: var(--theme-elevation-200);
|
|
24
|
+
--xp-accent-fg: var(--theme-elevation-0);
|
|
25
|
+
--xp-accent-text: var(--xp-text);
|
|
26
|
+
--xp-accent-text-decoration: none;
|
|
27
|
+
--xp-focus: var(--theme-elevation-800);
|
|
28
|
+
--xp-series-muted: var(--theme-elevation-300);
|
|
29
|
+
--xp-success: #1a6a3a;
|
|
30
|
+
--xp-success-bg: #e8f4ec;
|
|
31
|
+
--xp-success-border: #bddfc9;
|
|
32
|
+
--xp-warning: #8a5a0b;
|
|
33
|
+
--xp-warning-bg: #fbf3e1;
|
|
34
|
+
--xp-warning-border: #ecd6a2;
|
|
35
|
+
--xp-error: #a63030;
|
|
36
|
+
--xp-error-bg: #fbeaea;
|
|
37
|
+
--xp-error-border: #efc3c3;
|
|
38
|
+
--xp-series-a: #2a78d6;
|
|
39
|
+
--xp-series-b: #eb6834;
|
|
40
|
+
--xp-series-c: #8056b3;
|
|
41
|
+
--xp-radius-control: 8px;
|
|
42
|
+
--xp-radius-card: 12px;
|
|
43
|
+
--xp-radius-chip: 6px;
|
|
44
|
+
--xp-font: var(--font-body);
|
|
45
|
+
--xp-mono: var(--font-mono);
|
|
46
|
+
--xp-text-display: 600 28px/32px var(--xp-font);
|
|
47
|
+
--xp-text-title: 600 20px/28px var(--xp-font);
|
|
48
|
+
--xp-text-body: 400 15px/22px var(--xp-font);
|
|
49
|
+
--xp-text-small: 400 13px/18px var(--xp-font);
|
|
50
|
+
--xp-motion: 120ms;
|
|
51
|
+
--xp-space-half: 2px;
|
|
52
|
+
--xp-space-one-half: 6px;
|
|
53
|
+
--xp-version-share-width: 96px;
|
|
54
|
+
--xp-version-share-width-mobile: 84px;
|
|
55
|
+
--xp-version-state-width: 192px;
|
|
56
|
+
--xp-version-remove-width: 128px;
|
|
57
|
+
--xp-targeting-attribute-width: 150px;
|
|
58
|
+
--xp-targeting-comparison-width: 140px;
|
|
59
|
+
--xp-legend-key-size: 10px;
|
|
60
|
+
--xp-legend-key-radius: 3px;
|
|
61
|
+
--xp-space-1: 4px;
|
|
62
|
+
--xp-space-2: 8px;
|
|
63
|
+
--xp-space-3: 12px;
|
|
64
|
+
--xp-space-4: 16px;
|
|
65
|
+
--xp-space-5: 20px;
|
|
66
|
+
--xp-space-6: 24px;
|
|
67
|
+
--xp-space-7: 28px;
|
|
68
|
+
--xp-space-8: 32px;
|
|
69
|
+
--xp-surface-raised: var(--xp-surface-2);
|
|
9
70
|
--xp-border-control: var(--theme-elevation-250);
|
|
10
71
|
--xp-input-border: var(--theme-elevation-300);
|
|
11
72
|
--xp-border-accent: var(--theme-elevation-400);
|
|
12
|
-
--xp-
|
|
13
|
-
--xp-text-
|
|
14
|
-
--xp-text-
|
|
15
|
-
--xp-text-emphasis: var(--theme-elevation-900);
|
|
73
|
+
--xp-text-muted: var(--xp-text-2);
|
|
74
|
+
--xp-text-strong: var(--xp-text);
|
|
75
|
+
--xp-text-emphasis: var(--xp-text);
|
|
16
76
|
--xp-input-bg: var(--theme-input-bg);
|
|
17
77
|
--xp-overlay: var(--theme-overlay);
|
|
18
|
-
--xp-success-surface: var(--
|
|
19
|
-
--xp-success-
|
|
20
|
-
--xp-success: var(--
|
|
21
|
-
--xp-
|
|
22
|
-
--xp-
|
|
23
|
-
--xp-warning-
|
|
24
|
-
--xp-
|
|
25
|
-
--xp-
|
|
26
|
-
--xp-
|
|
27
|
-
--xp-
|
|
28
|
-
--xp-error-surface: var(--theme-error-100);
|
|
29
|
-
--xp-error: var(--theme-error-500);
|
|
30
|
-
--xp-error-text: var(--theme-error-600);
|
|
31
|
-
--xp-radius: var(--style-radius-s);
|
|
32
|
-
--xp-radius-large: var(--style-radius-m);
|
|
33
|
-
--xp-space-1: calc(var(--base) * 0.25);
|
|
34
|
-
--xp-space-2: calc(var(--base) * 0.5);
|
|
35
|
-
--xp-space-3: calc(var(--base) * 0.75);
|
|
36
|
-
--xp-space-4: calc(var(--base) * 1);
|
|
37
|
-
--xp-space-5: calc(var(--base) * 1.5);
|
|
38
|
-
--xp-space-6: calc(var(--base) * 2);
|
|
78
|
+
--xp-success-surface: var(--xp-success-bg);
|
|
79
|
+
--xp-success-text: var(--xp-success);
|
|
80
|
+
--xp-success-text-strong: var(--xp-success);
|
|
81
|
+
--xp-warning-surface: var(--xp-warning-bg);
|
|
82
|
+
--xp-warning-text: var(--xp-warning);
|
|
83
|
+
--xp-warning-text-strong: var(--xp-warning);
|
|
84
|
+
--xp-error-surface: var(--xp-error-bg);
|
|
85
|
+
--xp-error-text: var(--xp-error);
|
|
86
|
+
--xp-radius: var(--xp-radius-control);
|
|
87
|
+
--xp-radius-large: var(--xp-radius-card);
|
|
39
88
|
--xp-dash-card-gap: 12px;
|
|
40
|
-
--xp-dash-card-gap-small:
|
|
41
|
-
--xp-font-body: var(--font
|
|
42
|
-
--xp-font-size-small:
|
|
43
|
-
--xp-font-size-body:
|
|
89
|
+
--xp-dash-card-gap-small: 8px;
|
|
90
|
+
--xp-font-body: var(--xp-font);
|
|
91
|
+
--xp-font-size-small: 13px;
|
|
92
|
+
--xp-font-size-body: 15px;
|
|
93
|
+
}
|
|
94
|
+
[data-theme="dark"] {
|
|
95
|
+
--xp-bg: var(--theme-elevation-0);
|
|
96
|
+
--xp-surface: var(--theme-elevation-50);
|
|
97
|
+
--xp-surface-2: var(--theme-elevation-100);
|
|
98
|
+
--xp-surface-3: var(--theme-elevation-150);
|
|
99
|
+
--xp-border: var(--theme-elevation-100);
|
|
100
|
+
--xp-border-strong: var(--theme-elevation-200);
|
|
101
|
+
--xp-text: var(--theme-elevation-800);
|
|
102
|
+
--xp-text-2: var(--theme-elevation-550);
|
|
103
|
+
--xp-text-3: var(--theme-elevation-350);
|
|
104
|
+
--xp-accent: var(--theme-elevation-800);
|
|
105
|
+
--xp-accent-hover: var(--theme-elevation-900);
|
|
106
|
+
--xp-accent-active: var(--theme-elevation-1000);
|
|
107
|
+
--xp-accent-subtle: var(--theme-elevation-200);
|
|
108
|
+
--xp-accent-fg: var(--theme-elevation-0);
|
|
109
|
+
--xp-focus: var(--theme-elevation-800);
|
|
110
|
+
--xp-series-muted: var(--theme-elevation-250);
|
|
111
|
+
--xp-success: #7fd49c;
|
|
112
|
+
--xp-success-bg: #142b1d;
|
|
113
|
+
--xp-success-border: #23492f;
|
|
114
|
+
--xp-warning: #e7bd5c;
|
|
115
|
+
--xp-warning-bg: #2b2312;
|
|
116
|
+
--xp-warning-border: #4d3d17;
|
|
117
|
+
--xp-error: #f09494;
|
|
118
|
+
--xp-error-bg: #2f1717;
|
|
119
|
+
--xp-error-border: #5a2626;
|
|
120
|
+
--xp-series-a: #3987e5;
|
|
121
|
+
--xp-series-b: #d95926;
|
|
122
|
+
--xp-series-c: #b48ade;
|
|
44
123
|
}
|
package/dist/admin/theme.d.ts
CHANGED
|
@@ -1,9 +1,33 @@
|
|
|
1
|
+
/** Host accent rules (reference surfaces are defined by theme.css):
|
|
2
|
+
* (i) Foreground on accent, hover and active fills reaches 4.5:1 in both themes.
|
|
3
|
+
* (ii) Accent text moves toward the surface's opposite to reach 4.5:1; if the
|
|
4
|
+
* bounded search fails, use the neutral text token and underline it.
|
|
5
|
+
* (iii) Focus reaches 3:1 against the surface: darken on light, lighten on dark.
|
|
6
|
+
*/
|
|
7
|
+
export { deriveAccent } from '../ui/accent.js';
|
|
1
8
|
/** every Payload token reference lives in theme.css; porting to Payload 4 edits that file only */
|
|
2
9
|
export declare const theme: {
|
|
3
10
|
readonly color: {
|
|
4
11
|
readonly bg: "var(--xp-bg)";
|
|
5
12
|
readonly text: "var(--xp-text)";
|
|
6
13
|
readonly surface: "var(--xp-surface)";
|
|
14
|
+
readonly surface2: "var(--xp-surface-2)";
|
|
15
|
+
readonly surface3: "var(--xp-surface-3)";
|
|
16
|
+
readonly text2: "var(--xp-text-2)";
|
|
17
|
+
readonly text3: "var(--xp-text-3)";
|
|
18
|
+
readonly accentHover: "var(--xp-accent-hover)";
|
|
19
|
+
readonly accentActive: "var(--xp-accent-active)";
|
|
20
|
+
readonly accentText: "var(--xp-accent-text)";
|
|
21
|
+
readonly accentSubtle: "var(--xp-accent-subtle)";
|
|
22
|
+
readonly accentFg: "var(--xp-accent-fg)";
|
|
23
|
+
readonly focus: "var(--xp-focus)";
|
|
24
|
+
readonly successBorder: "var(--xp-success-border)";
|
|
25
|
+
readonly warningBorder: "var(--xp-warning-border)";
|
|
26
|
+
readonly errorBg: "var(--xp-error-bg)";
|
|
27
|
+
readonly errorBorder: "var(--xp-error-border)";
|
|
28
|
+
readonly seriesA: "var(--xp-series-a)";
|
|
29
|
+
readonly seriesB: "var(--xp-series-b)";
|
|
30
|
+
readonly seriesMuted: "var(--xp-series-muted)";
|
|
7
31
|
readonly surfaceRaised: "var(--xp-surface-raised)";
|
|
8
32
|
readonly border: "var(--xp-border)";
|
|
9
33
|
readonly borderStrong: "var(--xp-border-strong)";
|
|
@@ -30,7 +54,17 @@ export declare const theme: {
|
|
|
30
54
|
readonly error: "var(--xp-error)";
|
|
31
55
|
readonly errorText: "var(--xp-error-text)";
|
|
32
56
|
};
|
|
57
|
+
readonly motion: "var(--xp-motion)";
|
|
58
|
+
readonly type: {
|
|
59
|
+
readonly display: "var(--xp-text-display)";
|
|
60
|
+
readonly title: "var(--xp-text-title)";
|
|
61
|
+
readonly body: "var(--xp-text-body)";
|
|
62
|
+
readonly small: "var(--xp-text-small)";
|
|
63
|
+
};
|
|
33
64
|
readonly radius: {
|
|
65
|
+
readonly control: "var(--xp-radius-control)";
|
|
66
|
+
readonly card: "var(--xp-radius-card)";
|
|
67
|
+
readonly chip: "var(--xp-radius-chip)";
|
|
34
68
|
readonly small: "var(--xp-radius)";
|
|
35
69
|
readonly large: "var(--xp-radius-large)";
|
|
36
70
|
};
|
|
@@ -41,8 +75,12 @@ export declare const theme: {
|
|
|
41
75
|
readonly 4: "var(--xp-space-4)";
|
|
42
76
|
readonly 5: "var(--xp-space-5)";
|
|
43
77
|
readonly 6: "var(--xp-space-6)";
|
|
78
|
+
readonly 7: "var(--xp-space-7)";
|
|
79
|
+
readonly 8: "var(--xp-space-8)";
|
|
44
80
|
};
|
|
45
81
|
readonly font: {
|
|
82
|
+
readonly mono: "var(--xp-mono)";
|
|
83
|
+
readonly family: "var(--xp-font)";
|
|
46
84
|
readonly body: "var(--xp-font-body)";
|
|
47
85
|
readonly small: "var(--xp-font-size-small)";
|
|
48
86
|
readonly size: "var(--xp-font-size-body)";
|
package/dist/admin/theme.js
CHANGED
|
@@ -1,8 +1,31 @@
|
|
|
1
|
+
/** Host accent rules (reference surfaces are defined by theme.css):
|
|
2
|
+
* (i) Foreground on accent, hover and active fills reaches 4.5:1 in both themes.
|
|
3
|
+
* (ii) Accent text moves toward the surface's opposite to reach 4.5:1; if the
|
|
4
|
+
* bounded search fails, use the neutral text token and underline it.
|
|
5
|
+
* (iii) Focus reaches 3:1 against the surface: darken on light, lighten on dark.
|
|
6
|
+
*/ export { deriveAccent } from '../ui/accent.js';
|
|
1
7
|
/** every Payload token reference lives in theme.css; porting to Payload 4 edits that file only */ export const theme = {
|
|
2
8
|
color: {
|
|
3
9
|
bg: 'var(--xp-bg)',
|
|
4
10
|
text: 'var(--xp-text)',
|
|
5
11
|
surface: 'var(--xp-surface)',
|
|
12
|
+
surface2: 'var(--xp-surface-2)',
|
|
13
|
+
surface3: 'var(--xp-surface-3)',
|
|
14
|
+
text2: 'var(--xp-text-2)',
|
|
15
|
+
text3: 'var(--xp-text-3)',
|
|
16
|
+
accentHover: 'var(--xp-accent-hover)',
|
|
17
|
+
accentActive: 'var(--xp-accent-active)',
|
|
18
|
+
accentText: 'var(--xp-accent-text)',
|
|
19
|
+
accentSubtle: 'var(--xp-accent-subtle)',
|
|
20
|
+
accentFg: 'var(--xp-accent-fg)',
|
|
21
|
+
focus: 'var(--xp-focus)',
|
|
22
|
+
successBorder: 'var(--xp-success-border)',
|
|
23
|
+
warningBorder: 'var(--xp-warning-border)',
|
|
24
|
+
errorBg: 'var(--xp-error-bg)',
|
|
25
|
+
errorBorder: 'var(--xp-error-border)',
|
|
26
|
+
seriesA: 'var(--xp-series-a)',
|
|
27
|
+
seriesB: 'var(--xp-series-b)',
|
|
28
|
+
seriesMuted: 'var(--xp-series-muted)',
|
|
6
29
|
surfaceRaised: 'var(--xp-surface-raised)',
|
|
7
30
|
border: 'var(--xp-border)',
|
|
8
31
|
borderStrong: 'var(--xp-border-strong)',
|
|
@@ -29,7 +52,17 @@
|
|
|
29
52
|
error: 'var(--xp-error)',
|
|
30
53
|
errorText: 'var(--xp-error-text)'
|
|
31
54
|
},
|
|
55
|
+
motion: 'var(--xp-motion)',
|
|
56
|
+
type: {
|
|
57
|
+
display: 'var(--xp-text-display)',
|
|
58
|
+
title: 'var(--xp-text-title)',
|
|
59
|
+
body: 'var(--xp-text-body)',
|
|
60
|
+
small: 'var(--xp-text-small)'
|
|
61
|
+
},
|
|
32
62
|
radius: {
|
|
63
|
+
control: 'var(--xp-radius-control)',
|
|
64
|
+
card: 'var(--xp-radius-card)',
|
|
65
|
+
chip: 'var(--xp-radius-chip)',
|
|
33
66
|
small: 'var(--xp-radius)',
|
|
34
67
|
large: 'var(--xp-radius-large)'
|
|
35
68
|
},
|
|
@@ -39,9 +72,13 @@
|
|
|
39
72
|
3: 'var(--xp-space-3)',
|
|
40
73
|
4: 'var(--xp-space-4)',
|
|
41
74
|
5: 'var(--xp-space-5)',
|
|
42
|
-
6: 'var(--xp-space-6)'
|
|
75
|
+
6: 'var(--xp-space-6)',
|
|
76
|
+
7: 'var(--xp-space-7)',
|
|
77
|
+
8: 'var(--xp-space-8)'
|
|
43
78
|
},
|
|
44
79
|
font: {
|
|
80
|
+
mono: 'var(--xp-mono)',
|
|
81
|
+
family: 'var(--xp-font)',
|
|
45
82
|
body: 'var(--xp-font-body)',
|
|
46
83
|
small: 'var(--xp-font-size-small)',
|
|
47
84
|
size: 'var(--xp-font-size-body)'
|
package/dist/admin/useApi.d.ts
CHANGED
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
export declare function useApi(): {
|
|
2
2
|
start: (id: import("../types/contracts.js").DocId) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").TransitionSuccess>>;
|
|
3
|
-
allocate: (id: import("../types/contracts.js").DocId, body: import("../types/endpoints.js").AllocateBody
|
|
4
|
-
|
|
3
|
+
allocate: (id: import("../types/contracts.js").DocId, body: import("../types/endpoints.js").AllocateBody, options?: {
|
|
4
|
+
notFound?: string;
|
|
5
|
+
codes?: Readonly<Record<string, string>>;
|
|
6
|
+
fallback?: string;
|
|
7
|
+
}) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").TransitionSuccess>>;
|
|
8
|
+
addMetric: (id: import("../types/contracts.js").DocId, body: import("../types/endpoints.js").AddMetricBody, options?: {
|
|
9
|
+
notFound?: string;
|
|
10
|
+
codes?: Readonly<Record<string, string>>;
|
|
11
|
+
fallback?: string;
|
|
12
|
+
}) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").TransitionSuccess>>;
|
|
5
13
|
stop: (id: import("../types/contracts.js").DocId) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").TransitionSuccess>>;
|
|
6
14
|
decide: (id: import("../types/contracts.js").DocId, body: import("../types/endpoints.js").DecideBody) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").TransitionSuccess>>;
|
|
7
15
|
releaseHoldout: (id: import("../types/contracts.js").DocId) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").TransitionSuccess>>;
|
|
16
|
+
releasePages: (id: import("../types/contracts.js").DocId) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").TransitionSuccess>>;
|
|
8
17
|
makeContent: (id: import("../types/contracts.js").DocId) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").MakeContentResult>>;
|
|
18
|
+
dismissContentEntry: (id: import("../types/contracts.js").DocId, body: import("../types/endpoints.js").DismissContentEntryBody) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").DismissContentEntryResult>>;
|
|
19
|
+
restoreContentEntry: (id: import("../types/contracts.js").DocId, body: import("../types/endpoints.js").RestoreContentEntryBody) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").RestoreContentEntryResult>>;
|
|
9
20
|
archive: (id: import("../types/contracts.js").DocId, body: import("../types/endpoints.js").ArchiveBody) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").TransitionSuccess>>;
|
|
10
21
|
preflight: (id: import("../types/contracts.js").DocId) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").PreflightResult>>;
|
|
11
22
|
previewToken: (id: import("../types/contracts.js").DocId, arm: string) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").PreviewTokenResult>>;
|
|
12
23
|
results: (id: import("../types/contracts.js").DocId, options?: {
|
|
13
24
|
phase?: number;
|
|
14
25
|
series?: boolean;
|
|
26
|
+
} & {
|
|
27
|
+
notFound?: string;
|
|
28
|
+
codes?: Readonly<Record<string, string>>;
|
|
29
|
+
fallback?: string;
|
|
15
30
|
}) => Promise<import("./api.js").ApiResult<import("../types/endpoints.js").ResultsResponse>>;
|
|
16
31
|
recompute: (id: import("../types/contracts.js").DocId) => Promise<import("./api.js").ApiResult<{
|
|
17
32
|
snapshotId: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { accentStyles } from '../../ui/accent.js';
|
|
2
3
|
import { formatAdminURL } from 'payload/shared';
|
|
3
4
|
import { notFound, redirect } from 'next/navigation.js';
|
|
4
5
|
import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent';
|
|
@@ -166,10 +167,19 @@ export async function ExperimentsRootView({ initPageResult, params, searchParams
|
|
|
166
167
|
children: SURFACE_COPY.notInstalled
|
|
167
168
|
});
|
|
168
169
|
}
|
|
169
|
-
|
|
170
|
+
const css = accentStyles(options.theme?.accent);
|
|
171
|
+
const surface = RenderServerComponent({
|
|
170
172
|
Component: XP_TESTS_SURFACE,
|
|
171
173
|
Fallback: TestsSurfaceFallback,
|
|
172
174
|
importMap: req.payload.importMap,
|
|
173
175
|
clientProps
|
|
174
176
|
});
|
|
177
|
+
return css ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
178
|
+
children: [
|
|
179
|
+
/*#__PURE__*/ _jsx("style", {
|
|
180
|
+
children: css
|
|
181
|
+
}),
|
|
182
|
+
surface
|
|
183
|
+
]
|
|
184
|
+
}) : surface;
|
|
175
185
|
}
|
|
@@ -2,12 +2,14 @@ import * as paths from '../../admin/paths.js';
|
|
|
2
2
|
import { managedAccess } from '../access.js';
|
|
3
3
|
import { serializeAttributeKeys, serializeFlagPoints } from '../serialize.js';
|
|
4
4
|
import { TARGETING_OPS, isOpValid } from '../../targeting/ops.js';
|
|
5
|
+
import { readListValue } from '../../targeting/values.js';
|
|
5
6
|
import { createDefaults } from './createDefaults.js';
|
|
6
7
|
import { flagControlParams } from './flagControlParams.js';
|
|
7
8
|
import { lockHook } from './lockHook.js';
|
|
8
9
|
import { deleteGuard, deleteGuardAfter } from './deleteGuard.js';
|
|
9
10
|
import { checkArms } from './armInvariants.js';
|
|
10
11
|
import { XpNotImplemented, XpRefusal } from '../../errors.js';
|
|
12
|
+
const targetingValue = (rule)=>rule.op === 'in' || rule.op === 'nin' ? readListValue(rule.value) : rule.value;
|
|
11
13
|
const positiveInteger = (value)=>value != null && Number.isInteger(value) && value > 0 || 'Enter a positive whole number.';
|
|
12
14
|
export function experimentsCollection(options) {
|
|
13
15
|
const flagPoints = serializeFlagPoints(options);
|
|
@@ -224,6 +226,21 @@ export function experimentsCollection(options) {
|
|
|
224
226
|
{
|
|
225
227
|
name: 'targeting',
|
|
226
228
|
type: 'array',
|
|
229
|
+
validate: (value, { data, previousValue })=>{
|
|
230
|
+
// Payload 3.90.2 beforeChange/promise.js passes merged document data
|
|
231
|
+
// and this document's stored array as previousValue, including in bulk updates.
|
|
232
|
+
const status = data?.status ?? 'draft';
|
|
233
|
+
if (data?.kind === 'block' && (status === 'draft' || status === 'stopped')) {
|
|
234
|
+
for (const rule of value ?? []){
|
|
235
|
+
if (rule.attribute !== 'path') continue;
|
|
236
|
+
const previous = rule.id == null ? undefined : previousValue?.find((stored)=>stored.id != null && String(stored.id) === String(rule.id));
|
|
237
|
+
if (!previous || previous.attribute !== rule.attribute || previous.op !== rule.op || JSON.stringify(targetingValue(previous)) !== JSON.stringify(targetingValue(rule))) {
|
|
238
|
+
return 'Page block tests run on their page; remove the page-path rule.';
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return true;
|
|
243
|
+
},
|
|
227
244
|
fields: [
|
|
228
245
|
{
|
|
229
246
|
name: 'attribute',
|
|
@@ -477,6 +494,14 @@ export function experimentsCollection(options) {
|
|
|
477
494
|
{
|
|
478
495
|
name: 'holdoutReleasedAt',
|
|
479
496
|
type: 'date'
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
name: 'pagesReleasedAt',
|
|
500
|
+
type: 'date'
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
name: 'pagesReleasedBy',
|
|
504
|
+
type: 'text'
|
|
480
505
|
}
|
|
481
506
|
]
|
|
482
507
|
}
|
|
@@ -12,6 +12,7 @@ const relationships = new Set([
|
|
|
12
12
|
'metrics.secondary',
|
|
13
13
|
'metrics.guardrails',
|
|
14
14
|
'decision.decidedBy',
|
|
15
|
+
'decision.pagesReleasedBy',
|
|
15
16
|
'decision.snapshotId'
|
|
16
17
|
]);
|
|
17
18
|
const dates = new Set([
|
|
@@ -20,7 +21,8 @@ const dates = new Set([
|
|
|
20
21
|
'decidedAt',
|
|
21
22
|
'archivedAt',
|
|
22
23
|
'decision.discardedAt',
|
|
23
|
-
'decision.holdoutReleasedAt'
|
|
24
|
+
'decision.holdoutReleasedAt',
|
|
25
|
+
'decision.pagesReleasedAt'
|
|
24
26
|
]);
|
|
25
27
|
/** Schema-aware: JSON retains its own ids and date-like strings. */ function normalize(value, path, json = false) {
|
|
26
28
|
json ||= [
|