@delmaredigital/payload-experiments 0.4.0-rc.1 → 0.4.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/README.md +10 -8
  2. package/dist/admin/TestsDashboardCards.d.ts +1 -0
  3. package/dist/admin/TestsDashboardCards.js +4 -8
  4. package/dist/admin/TestsNavLink.d.ts +1 -0
  5. package/dist/admin/TestsNavLink.js +4 -10
  6. package/dist/admin/api.d.ts +7 -0
  7. package/dist/admin/api.js +27 -0
  8. package/dist/admin/blocks/BlockPanel.js +65 -19
  9. package/dist/admin/blocks/formApi.d.ts +3 -0
  10. package/dist/admin/blocks/formApi.js +9 -3
  11. package/dist/admin/blocks/statusCache.d.ts +2 -0
  12. package/dist/admin/blocks/statusCache.js +11 -2
  13. package/dist/admin/copy/blocks.d.ts +16 -0
  14. package/dist/admin/copy/blocks.js +27 -1
  15. package/dist/admin/copy/common.d.ts +1 -0
  16. package/dist/admin/copy/common.js +1 -1
  17. package/dist/admin/copy/pages.d.ts +2 -4
  18. package/dist/admin/copy/pages.js +3 -5
  19. package/dist/admin/copy/readiness.d.ts +1 -0
  20. package/dist/admin/copy/readiness.js +1 -0
  21. package/dist/admin/goals/XpGoalField.d.ts +2 -0
  22. package/dist/admin/goals/XpGoalField.js +51 -35
  23. package/dist/admin/goals/xpGoalField.css +48 -0
  24. package/dist/admin/paths.d.ts +3 -0
  25. package/dist/admin/paths.js +3 -0
  26. package/dist/admin/surface/TestsHome.js +2 -4
  27. package/dist/admin/surface/TestsSurface.js +2 -5
  28. package/dist/admin/surface/goals/GoalForm.js +4 -10
  29. package/dist/admin/surface/goals/GoalsList.js +2 -1
  30. package/dist/admin/surface/home.model.d.ts +2 -2
  31. package/dist/admin/surface/newTest/NewTest.js +2 -4
  32. package/dist/admin/surface/newTest/PageWizard.js +7 -2
  33. package/dist/admin/surface/pagePicker/CopyRoute.d.ts +1 -1
  34. package/dist/admin/surface/pagePicker/{PagePicker.d.ts → PageCombobox.d.ts} +3 -3
  35. package/dist/admin/surface/pagePicker/PageCombobox.js +395 -0
  36. package/dist/admin/surface/pagePicker/pagePicker.css +10 -0
  37. package/dist/admin/surface/pagePicker/pagePicker.model.d.ts +2 -0
  38. package/dist/admin/surface/readiness/readiness.model.js +1 -0
  39. package/dist/admin/surface/results/ResultsHeader.js +3 -8
  40. package/dist/admin/surface/results/useResults.d.ts +10 -0
  41. package/dist/admin/surface/test/GoalSection.js +4 -7
  42. package/dist/admin/surface/test/TestPage.js +3 -8
  43. package/dist/admin/surface/test/pageParts.js +10 -39
  44. package/dist/admin/surface/test/testPage.css +0 -5
  45. package/dist/admin/surface/useTestDocument.d.ts +4 -0
  46. package/dist/admin/surfaceUrls.d.ts +7 -0
  47. package/dist/admin/surfaceUrls.js +19 -0
  48. package/dist/admin/theme.css +2 -0
  49. package/dist/admin/useApi.d.ts +10 -0
  50. package/dist/admin/views/CollectionListRedirect.d.ts +1 -0
  51. package/dist/admin/views/CollectionListRedirect.js +1 -1
  52. package/dist/admin/views/ExperimentsRootView.js +18 -165
  53. package/dist/admin/views/GoalEditRedirect.d.ts +4 -0
  54. package/dist/admin/views/GoalEditRedirect.js +14 -0
  55. package/dist/admin/views/GoalsCollectionListView.d.ts +2 -0
  56. package/dist/admin/views/GoalsCollectionListView.js +4 -0
  57. package/dist/admin/views/TestsCollectionListView.d.ts +2 -0
  58. package/dist/admin/views/TestsCollectionListView.js +4 -0
  59. package/dist/admin/views/TestsNavLinkServer.d.ts +1 -0
  60. package/dist/admin/views/TestsNavLinkServer.js +1 -1
  61. package/dist/admin/views/buildSurfaceProps.d.ts +8 -0
  62. package/dist/admin/views/buildSurfaceProps.js +143 -0
  63. package/dist/admin/views/renderCollectionList.d.ts +2 -0
  64. package/dist/admin/views/renderCollectionList.js +34 -0
  65. package/dist/admin/views/renderTestsSurface.d.ts +3 -0
  66. package/dist/admin/views/renderTestsSurface.js +34 -0
  67. package/dist/collections/experiments/config.js +9 -5
  68. package/dist/collections/metrics.js +16 -4
  69. package/dist/exports/adminRsc.d.ts +3 -0
  70. package/dist/exports/adminRsc.js +3 -0
  71. package/dist/fields/xpGoal.js +2 -14
  72. package/dist/goals/validate.d.ts +3 -0
  73. package/dist/goals/validate.js +14 -0
  74. package/dist/hooks/puckGoals.d.ts +3 -0
  75. package/dist/hooks/puckGoals.js +38 -0
  76. package/dist/plugin.js +12 -18
  77. package/dist/puck/editor/editor.chrome.css +13 -0
  78. package/dist/puck/editor/editor.css +105 -0
  79. package/dist/puck/editor/xpGoalPuckEditorField.js +28 -20
  80. package/dist/sanitizeReadinessDetail.js +2 -0
  81. package/dist/transitions/checkStart.d.ts +2 -1
  82. package/dist/transitions/checkStart.js +3 -1
  83. package/dist/transitions/decide.js +1 -0
  84. package/dist/transitions/start.js +2 -1
  85. package/dist/types/endpoints.d.ts +1 -1
  86. package/dist/ui/ui.css +4 -0
  87. package/package.json +1 -1
  88. package/dist/admin/surface/pagePicker/PagePicker.js +0 -172
@@ -1,9 +1,11 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { Button, FieldError, FieldLabel, TextInput, useAuth, useConfig, useField } from '@payloadcms/ui';
3
+ import { Button, FieldError, FieldLabel, SelectInput, TextInput, useAuth, useConfig, useField } from '@payloadcms/ui';
4
4
  import { useId } from 'react';
5
5
  import { useClickGoalPicker } from '../../goals/picker/useClickGoalPicker.js';
6
6
  import { CLICK_GOAL_COPY as C } from '../../goals/picker/copy.js';
7
+ import '../theme.css';
8
+ import './xpGoalField.css';
7
9
  export function XpGoalField({ path, field, readOnly }) {
8
10
  const { value, setValue, showError } = useField({
9
11
  path
@@ -24,6 +26,7 @@ export function XpGoalField({ path, field, readOnly }) {
24
26
  }
25
27
  };
26
28
  return /*#__PURE__*/ _jsxs("div", {
29
+ className: "field-type xp-goal-field",
27
30
  children: [
28
31
  /*#__PURE__*/ _jsx(TextInput, {
29
32
  path: path,
@@ -43,36 +46,40 @@ export function XpGoalField({ path, field, readOnly }) {
43
46
  }),
44
47
  picker.canManage && !locked ? /*#__PURE__*/ _jsxs(_Fragment, {
45
48
  children: [
46
- /*#__PURE__*/ _jsx("label", {
47
- htmlFor: `${id}-picker`,
48
- children: C.choose
49
- }),
50
- /*#__PURE__*/ _jsxs("select", {
51
- id: `${id}-picker`,
52
- value: picker.goals.some((goal)=>goal.slug === value) ? value : '',
53
- onChange: (event)=>{
54
- if (event.currentTarget.value) setValue(event.currentTarget.value);
55
- },
49
+ /*#__PURE__*/ _jsxs("div", {
50
+ className: "xp-goal-field__row",
56
51
  children: [
57
- /*#__PURE__*/ _jsx("option", {
58
- value: "",
59
- children: C.choose
52
+ /*#__PURE__*/ _jsx(SelectInput, {
53
+ name: `${path}__xpGoalPicker`,
54
+ path: `${path}__xpGoalPicker`,
55
+ className: "xp-goal-field__select",
56
+ value: picker.goals.some((goal)=>goal.slug === value) ? value : undefined,
57
+ options: picker.goals.map((goal)=>({
58
+ value: goal.slug,
59
+ label: goal.name
60
+ })),
61
+ placeholder: C.choose,
62
+ isClearable: false,
63
+ label: C.choose,
64
+ onChange: (option)=>{
65
+ if (option && !Array.isArray(option)) setValue(String(option.value));
66
+ }
60
67
  }),
61
- picker.goals.map((goal)=>/*#__PURE__*/ _jsx("option", {
62
- value: goal.slug,
63
- children: goal.name
64
- }, goal.id))
68
+ !picker.panel.open ? /*#__PURE__*/ _jsx(Button, {
69
+ type: "button",
70
+ margin: false,
71
+ buttonStyle: "secondary",
72
+ onClick: picker.open,
73
+ children: C.newGoal
74
+ }) : null
65
75
  ]
66
76
  }),
67
77
  picker.undefinedKey(value ?? '') ? /*#__PURE__*/ _jsx("p", {
68
78
  role: "status",
69
79
  children: C.undefinedKey
70
80
  }) : null,
71
- !picker.panel.open ? /*#__PURE__*/ _jsx(Button, {
72
- type: "button",
73
- onClick: picker.open,
74
- children: C.newGoal
75
- }) : /*#__PURE__*/ _jsxs("section", {
81
+ picker.panel.open ? /*#__PURE__*/ _jsxs("section", {
82
+ className: "xp-goal-field__panel",
76
83
  "aria-labelledby": `${id}-title`,
77
84
  children: [
78
85
  /*#__PURE__*/ _jsx("h3", {
@@ -131,20 +138,29 @@ export function XpGoalField({ path, field, readOnly }) {
131
138
  role: "alert",
132
139
  children: picker.panel.errors.general
133
140
  }) : null,
134
- /*#__PURE__*/ _jsx(Button, {
135
- type: "button",
136
- disabled: picker.panel.pending || !picker.panel.name.trim(),
137
- onClick: ()=>void picker.create(),
138
- children: C.createGoal
139
- }),
140
- /*#__PURE__*/ _jsx(Button, {
141
- type: "button",
142
- disabled: picker.panel.pending,
143
- onClick: picker.cancel,
144
- children: C.cancel
141
+ /*#__PURE__*/ _jsxs("div", {
142
+ className: "xp-goal-field__actions",
143
+ children: [
144
+ /*#__PURE__*/ _jsx(Button, {
145
+ type: "button",
146
+ margin: false,
147
+ buttonStyle: "primary",
148
+ disabled: picker.panel.pending || !picker.panel.name.trim(),
149
+ onClick: ()=>void picker.create(),
150
+ children: C.createGoal
151
+ }),
152
+ /*#__PURE__*/ _jsx(Button, {
153
+ type: "button",
154
+ margin: false,
155
+ buttonStyle: "secondary",
156
+ disabled: picker.panel.pending,
157
+ onClick: picker.cancel,
158
+ children: C.cancel
159
+ })
160
+ ]
145
161
  })
146
162
  ]
147
- })
163
+ }) : null
148
164
  ]
149
165
  }) : null
150
166
  ]
@@ -0,0 +1,48 @@
1
+ .xp-goal-field {
2
+ display: grid;
3
+ gap: var(--xp-field-gap);
4
+ }
5
+
6
+ .xp-goal-field__row {
7
+ display: flex;
8
+ flex-wrap: wrap;
9
+ align-items: end;
10
+ gap: var(--xp-space-2);
11
+ }
12
+
13
+ .xp-goal-field__select {
14
+ flex: 1 1 auto;
15
+ min-width: 0;
16
+ }
17
+
18
+ .xp-goal-field__panel {
19
+ display: grid;
20
+ gap: var(--xp-field-gap);
21
+ border: 1px solid var(--xp-border);
22
+ border-radius: var(--xp-radius-control);
23
+ padding: var(--xp-space-4);
24
+ }
25
+
26
+ .xp-goal-field > p,
27
+ .xp-goal-field__panel > h3,
28
+ .xp-goal-field__panel > p {
29
+ margin: 0;
30
+ }
31
+
32
+ .xp-goal-field__panel details[open] > summary {
33
+ margin-bottom: var(--xp-field-gap);
34
+ }
35
+
36
+ .xp-goal-field__actions {
37
+ display: flex;
38
+ flex-wrap: wrap;
39
+ gap: var(--xp-space-2);
40
+ }
41
+
42
+ /* Payload halves the gap between fields below 768px; match it inside the field. */
43
+ @media (max-width: 768px) {
44
+ .xp-goal-field,
45
+ .xp-goal-field__panel {
46
+ gap: calc(var(--xp-field-gap) / 2);
47
+ }
48
+ }
@@ -14,3 +14,6 @@ export declare const XP_BLOCK_STATUS = "@delmaredigital/payload-experiments/admi
14
14
  export declare const XP_BLOCK_ROW_LABEL = "@delmaredigital/payload-experiments/admin/client#BlockSlotRowLabel";
15
15
  export declare const XP_COPY_ORIGINAL = "@delmaredigital/payload-experiments/admin/client#CopyOriginalField";
16
16
  export declare const XP_GOAL_FIELD = "@delmaredigital/payload-experiments/admin/client#XpGoalField";
17
+ export declare const XP_TESTS_COLLECTION_LIST = "@delmaredigital/payload-experiments/admin/rsc#TestsCollectionListView";
18
+ export declare const XP_GOALS_COLLECTION_LIST = "@delmaredigital/payload-experiments/admin/rsc#GoalsCollectionListView";
19
+ export declare const XP_GOAL_EDIT_REDIRECT = "@delmaredigital/payload-experiments/admin/rsc#GoalEditRedirect";
@@ -14,3 +14,6 @@ export const XP_BLOCK_STATUS = '@delmaredigital/payload-experiments/admin/client
14
14
  export const XP_BLOCK_ROW_LABEL = '@delmaredigital/payload-experiments/admin/client#BlockSlotRowLabel';
15
15
  export const XP_COPY_ORIGINAL = '@delmaredigital/payload-experiments/admin/client#CopyOriginalField';
16
16
  export const XP_GOAL_FIELD = '@delmaredigital/payload-experiments/admin/client#XpGoalField';
17
+ export const XP_TESTS_COLLECTION_LIST = '@delmaredigital/payload-experiments/admin/rsc#TestsCollectionListView';
18
+ export const XP_GOALS_COLLECTION_LIST = '@delmaredigital/payload-experiments/admin/rsc#GoalsCollectionListView';
19
+ export const XP_GOAL_EDIT_REDIRECT = '@delmaredigital/payload-experiments/admin/rsc#GoalEditRedirect';
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { surfaceUrls } from '../surfaceUrls.js';
3
4
  import { useEffect, useMemo, useState } from 'react';
4
5
  import { formatAdminURL } from 'payload/shared';
5
6
  import { fetchAllDocs } from '../../lib/fetchAllDocs.js';
@@ -154,10 +155,7 @@ export function TestsHome({ adminRoute, apiRoute, canManage = false, crumbs, fla
154
155
  ]
155
156
  }),
156
157
  canManage ? /*#__PURE__*/ _jsx(Button, {
157
- href: formatAdminURL({
158
- adminRoute,
159
- path: '/experiments/goals'
160
- }),
158
+ href: surfaceUrls.goals(adminRoute),
161
159
  children: SURFACE_COPY.goals
162
160
  }) : null,
163
161
  newTest
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { surfaceUrls } from '../surfaceUrls.js';
3
4
  import { useState } from 'react';
4
- import { formatAdminURL } from 'payload/shared';
5
5
  import { SURFACE_COPY } from '../copy/surface.js';
6
6
  import { NewTest } from './newTest/NewTest.js';
7
7
  import { TestPage } from './test/TestPage.js';
@@ -40,10 +40,7 @@ function SurfacePage(props) {
40
40
  }
41
41
  ];
42
42
  if (props.route !== 'home') {
43
- crumbs[0].href = formatAdminURL({
44
- adminRoute: props.adminRoute,
45
- path: '/experiments'
46
- });
43
+ crumbs[0].href = props.canManage ? surfaceUrls.home(props.adminRoute) : undefined;
47
44
  crumbs.push({
48
45
  label: props.route === 'new' ? SURFACE_COPY.newTest : props.route === 'results' ? SURFACE_COPY.resultsTitle : SURFACE_COPY.test
49
46
  });
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { surfaceUrls } from '../../surfaceUrls.js';
3
4
  import { useEffect, useRef, useState } from 'react';
4
5
  import { useRouter } from 'next/navigation.js';
5
6
  import { formatAdminURL } from 'payload/shared';
@@ -61,13 +62,9 @@ export function GoalForm({ surface, id, returnToTest }) {
61
62
  }, [
62
63
  fieldErrors
63
64
  ]);
64
- const returnQuery = returnToTest ? `?${new URLSearchParams({
65
+ const listUrl = surfaceUrls.goals(surface.adminRoute, returnToTest ? {
65
66
  return: returnToTest
66
- })}` : '';
67
- const listUrl = formatAdminURL({
68
- adminRoute: surface.adminRoute,
69
- path: `/experiments/goals${returnQuery}`
70
- });
67
+ } : undefined);
71
68
  useEffect(()=>{
72
69
  const controller = new AbortController();
73
70
  setReady(false);
@@ -215,10 +212,7 @@ export function GoalForm({ surface, id, returnToTest }) {
215
212
  crumbs: [
216
213
  {
217
214
  label: SURFACE_COPY.title,
218
- href: formatAdminURL({
219
- adminRoute: surface.adminRoute,
220
- path: '/experiments'
221
- })
215
+ href: surfaceUrls.home(surface.adminRoute)
222
216
  },
223
217
  {
224
218
  label: C.title,
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { surfaceUrls } from '../../surfaceUrls.js';
3
4
  import { sourceFor } from '../../metricSource.model.js';
4
5
  import { useEffect, useState } from 'react';
5
6
  import { formatAdminURL } from 'payload/shared';
@@ -60,7 +61,7 @@ export function GoalsList({ surface, returnToTest }) {
60
61
  crumbs: [
61
62
  {
62
63
  label: SURFACE_COPY.title,
63
- href: url('/experiments')
64
+ href: surfaceUrls.home(surface.adminRoute)
64
65
  },
65
66
  {
66
67
  label: C.title
@@ -23,11 +23,11 @@ type Summary = SummaryResponse[DocId] | undefined;
23
23
  export type Health = 'red' | 'amber' | 'green';
24
24
  export declare function healthDot(test: HomeTest, summary: Summary): Health | undefined;
25
25
  export declare function groupTests(tests: readonly HomeTest[], summaries: SummaryResponse, search?: string): {
26
- label: "Needs attention" | "Running" | "Decided" | "Draft" | "Archived" | "Ready to start";
26
+ label: "Needs attention" | "Running" | "Decided" | "Ready to start" | "Draft" | "Archived";
27
27
  tests: HomeTest[];
28
28
  }[];
29
29
  export declare function homeCard(test: HomeTest, summary: Summary, adminRoute: string, flagPoints?: ReadinessContext['flagPoints'], goalNames?: Readonly<Record<string, string>>): {
30
- kind: "Whole page" | "Page block" | "Setting";
30
+ kind: "Page block" | "Setting" | "Whole page";
31
31
  pill: {
32
32
  label: string;
33
33
  tone: import("../status.model.js").PillTone;
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { surfaceUrls } from '../../surfaceUrls.js';
3
4
  import { fetchAllDocs } from '../../../lib/fetchAllDocs.js';
4
5
  import { useEffect, useRef, useState } from 'react';
5
6
  import { useRouter } from 'next/navigation.js';
@@ -372,10 +373,7 @@ export function NewTest({ surface, pages }) {
372
373
  type: "button",
373
374
  disabled: pending,
374
375
  onClick: ()=>{
375
- if (step === 'kind') router.push(formatAdminURL({
376
- adminRoute: surface.adminRoute,
377
- path: '/experiments'
378
- }));
376
+ if (step === 'kind') router.push(surfaceUrls.home(surface.adminRoute));
379
377
  else {
380
378
  setError('');
381
379
  setStep(step === 'name' && kind === 'flag' ? 'setting' : 'kind');
@@ -5,7 +5,7 @@ import { useRouter } from 'next/navigation.js';
5
5
  import { formatAdminURL } from 'payload/shared';
6
6
  import { useTestDocument } from '../useTestDocument.js';
7
7
  import { CopyRoute } from '../pagePicker/CopyRoute.js';
8
- import { PagePicker } from '../pagePicker/PagePicker.js';
8
+ import { PageCombobox } from '../pagePicker/PageCombobox.js';
9
9
  import { testPageCollection, controlFirst } from '../pagePicker/pagePicker.model.js';
10
10
  import { NEW_TEST_COPY as C } from '../../copy/newTest.js';
11
11
  import { READINESS_COPY } from '../../copy/readiness.js';
@@ -13,6 +13,7 @@ import { TEST_PAGE } from '../../copy/testPage.js';
13
13
  import { SURFACE_COPY } from '../../copy/surface.js';
14
14
  import { pageStepCopy } from '../../copy/pages.js';
15
15
  import { READINESS, nextStep, pageReadinessContext, readinessArm } from '../readiness/readiness.model.js';
16
+ import { FieldErrors } from '../test/fields.js';
16
17
  import { SaveStatus } from '../readiness/SaveStatus.js';
17
18
  import { createApi } from '../../api.js';
18
19
  import { useTransition } from '../readiness/useTransition.js';
@@ -77,7 +78,7 @@ import { useTransition } from '../readiness/useTransition.js';
77
78
  if (section === 'versions') setStep(key ?? arms.find((item)=>!item.pageTarget)?.key ?? 'control');
78
79
  else router.push(`${testUrl}#section-${section}`);
79
80
  };
80
- const picker = arm && collection ? /*#__PURE__*/ _jsx(PagePicker, {
81
+ const picker = arm && collection ? /*#__PURE__*/ _jsx(PageCombobox, {
81
82
  collection: collection,
82
83
  test: test,
83
84
  armKey: arm.key,
@@ -173,6 +174,10 @@ import { useTransition } from '../readiness/useTransition.js';
173
174
  collection: collection,
174
175
  children: picker
175
176
  }) : null,
177
+ arm ? /*#__PURE__*/ _jsx(FieldErrors, {
178
+ test: test,
179
+ path: `arms.${doc.arms.findIndex((item)=>item.key === arm.key)}.pageTarget`
180
+ }) : null,
176
181
  /*#__PURE__*/ _jsxs("div", {
177
182
  className: "xp-new-test-actions",
178
183
  children: [
@@ -2,5 +2,5 @@ import type { ReactNode } from 'react';
2
2
  import type { PageCollection } from './pagePicker.model.js';
3
3
  export declare function CopyRoute({ collection, children }: {
4
4
  collection: PageCollection;
5
- children: ReactNode;
5
+ children?: ReactNode;
6
6
  }): import("react").JSX.Element;
@@ -1,10 +1,10 @@
1
1
  import type { TestDocApi } from '../contracts.js';
2
2
  import type { PageCollection } from './pagePicker.model.js';
3
- /** Mount on open; every reopen and return from another tab refreshes the current query. */
4
- export declare function PagePicker({ collection, test, armKey, apiRoute, onChoose }: {
3
+ import './pagePicker.css';
4
+ /** One input owns focus; list options are navigated through aria-activedescendant. */
5
+ export declare function PageCombobox({ collection, test, armKey, apiRoute }: {
5
6
  collection: PageCollection;
6
7
  test: TestDocApi;
7
8
  armKey: string;
8
9
  apiRoute: string;
9
- onChoose?: () => void;
10
10
  }): import("react").JSX.Element;