@questpie/admin 3.0.8 → 3.1.0

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 (53) hide show
  1. package/dist/augmentation.d.mts +39 -0
  2. package/dist/client/blocks/block-renderer.d.mts +2 -2
  3. package/dist/client/builder/types/field-types.d.mts +10 -14
  4. package/dist/client/components/actions/action-button.mjs +2 -1
  5. package/dist/client/components/admin-link.d.mts +2 -2
  6. package/dist/client/components/fields/relation-picker.mjs +2 -2
  7. package/dist/client/components/fields/relation-select.mjs +3 -3
  8. package/dist/client/hooks/use-reactive-prop.mjs +308 -0
  9. package/dist/client/hooks/use-server-actions.mjs +2 -1
  10. package/dist/client/preview/block-scope-context.d.mts +2 -2
  11. package/dist/client/preview/preview-banner.d.mts +2 -2
  12. package/dist/client/preview/preview-field.d.mts +4 -4
  13. package/dist/client/scope/picker.d.mts +2 -2
  14. package/dist/client/scope/provider.d.mts +2 -2
  15. package/dist/client/views/auth/accept-invite-form.d.mts +2 -2
  16. package/dist/client/views/auth/auth-layout.d.mts +3 -3
  17. package/dist/client/views/auth/forgot-password-form.d.mts +2 -2
  18. package/dist/client/views/auth/login-form.d.mts +2 -2
  19. package/dist/client/views/auth/reset-password-form.d.mts +2 -2
  20. package/dist/client/views/collection/field-renderer.mjs +59 -134
  21. package/dist/client/views/collection/form-view.mjs +34 -6
  22. package/dist/client/views/pages/accept-invite-page.d.mts +2 -2
  23. package/dist/client/views/pages/dashboard-page.d.mts +2 -2
  24. package/dist/client/views/pages/forgot-password-page.d.mts +2 -2
  25. package/dist/client/views/pages/reset-password-page.d.mts +2 -2
  26. package/dist/client/views/pages/setup-page.d.mts +2 -2
  27. package/dist/components/rich-text/rich-text-renderer.d.mts +2 -2
  28. package/dist/server/augmentation/form-layout.d.mts +48 -4
  29. package/dist/server/augmentation/index.d.mts +1 -1
  30. package/dist/server/augmentation.d.mts +1 -1
  31. package/dist/server/modules/admin/collections/account.d.mts +30 -30
  32. package/dist/server/modules/admin/collections/admin-locks.d.mts +54 -54
  33. package/dist/server/modules/admin/collections/admin-preferences.d.mts +39 -39
  34. package/dist/server/modules/admin/collections/admin-saved-views.d.mts +47 -47
  35. package/dist/server/modules/admin/collections/apikey.d.mts +68 -68
  36. package/dist/server/modules/admin/collections/assets.d.mts +8 -8
  37. package/dist/server/modules/admin/collections/session.d.mts +42 -42
  38. package/dist/server/modules/admin/collections/user.d.mts +32 -32
  39. package/dist/server/modules/admin/collections/verification.d.mts +23 -23
  40. package/dist/server/modules/admin/routes/admin-config.d.mts +2 -2
  41. package/dist/server/modules/admin/routes/execute-action.d.mts +9 -9
  42. package/dist/server/modules/admin/routes/locales.d.mts +2 -2
  43. package/dist/server/modules/admin/routes/preview.d.mts +11 -11
  44. package/dist/server/modules/admin/routes/reactive.d.mts +13 -11
  45. package/dist/server/modules/admin/routes/reactive.mjs +75 -11
  46. package/dist/server/modules/admin/routes/setup.d.mts +7 -7
  47. package/dist/server/modules/admin/routes/translations.d.mts +4 -4
  48. package/dist/server/modules/admin/routes/widget-data.d.mts +5 -5
  49. package/dist/server/modules/admin-preferences/collections/saved-views.d.mts +45 -45
  50. package/dist/server/modules/audit/.generated/module.d.mts +6 -6
  51. package/dist/server/modules/audit/collections/audit-log.d.mts +78 -78
  52. package/dist/server/modules/audit/jobs/audit-cleanup.d.mts +2 -2
  53. package/package.json +3 -3
@@ -6,12 +6,19 @@ import { Skeleton } from "../../components/ui/skeleton.mjs";
6
6
  import { scopeDependencies, trackDependencies } from "../../utils/dependency-tracker.mjs";
7
7
  import { buildComponentProps, getFieldContext, getFieldOptions, getFullFieldName } from "./field-context.mjs";
8
8
  import { useFieldHooks } from "../../hooks/use-field-hooks.mjs";
9
+ import { useReactiveProps } from "../../hooks/use-reactive-prop.mjs";
9
10
  import { c } from "react/compiler-runtime";
10
- import "react";
11
+ import * as React from "react";
11
12
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
13
  import { useFormContext, useWatch } from "react-hook-form";
13
14
 
14
15
  //#region src/client/views/collection/field-renderer.tsx
16
+ /**
17
+ * FieldRenderer Component
18
+ *
19
+ * Renders a single form field using FieldDefinition.
20
+ * Shared between AutoFormFields and BlockEditor.
21
+ */
15
22
  function renderConfigError(message) {
16
23
  return /* @__PURE__ */ jsx("div", {
17
24
  className: "border-destructive/40 bg-destructive/5 text-destructive rounded border p-3 text-sm",
@@ -88,23 +95,19 @@ function computeDynamicDependencyPaths({ fieldOptions, form, fieldPrefix }) {
88
95
  /**
89
96
  * Render field using FieldDefinition.field.component
90
97
  *
91
- * This is the primary rendering method. Field components receive:
92
- * - Base props (name, value, onChange, label, etc.) from componentProps
93
- * - Field-specific options from FieldDefinition["~options"]
98
+ * The caller has already merged field-instance options + layout `extraProps`
99
+ * + base props (label/value/onChange/…) into `componentProps` and resolved
100
+ * any `ReactivePropPlaceholder`s via `useReactiveProps`. The component just
101
+ * receives the final flat record.
94
102
  */
95
103
  function renderDefinitionComponent({ context, componentProps, blocks }) {
96
104
  const Component = context.component;
97
105
  if (!Component) return null;
98
- const options = stripFieldUiOptions(getFieldOptions(context.fieldDef));
99
106
  if (context.type === "blocks" && blocks) return /* @__PURE__ */ jsx(Component, {
100
107
  ...componentProps,
101
- ...options,
102
108
  blocks
103
109
  });
104
- return /* @__PURE__ */ jsx(Component, {
105
- ...componentProps,
106
- ...options
107
- });
110
+ return /* @__PURE__ */ jsx(Component, { ...componentProps });
108
111
  }
109
112
  /**
110
113
  * Render embedded collection field
@@ -115,15 +118,13 @@ function renderDefinitionComponent({ context, componentProps, blocks }) {
115
118
  */
116
119
  function renderEmbeddedField({ context, registry, allCollectionsConfig, componentProps, renderEmbeddedFields }) {
117
120
  if (context.type !== "embedded") return null;
118
- const options = stripFieldUiOptions(getFieldOptions(context.fieldDef));
119
- const embeddedCollection = options.collection;
121
+ const embeddedCollection = componentProps.collection;
120
122
  if (!embeddedCollection) return renderConfigError(`Missing collection for embedded field "${context.fieldName}".`);
121
123
  const embeddedCollectionConfig = allCollectionsConfig?.[embeddedCollection];
122
124
  const EmbeddedComponent = context.component || registry?.fields?.embedded;
123
125
  if (!EmbeddedComponent) return renderConfigError(`No component found for embedded field "${context.fieldName}".`);
124
126
  return /* @__PURE__ */ jsx(EmbeddedComponent, {
125
127
  ...componentProps,
126
- ...options,
127
128
  value: context.fieldValue || [],
128
129
  collection: embeddedCollection,
129
130
  renderFields: (index) => renderEmbeddedFields?.({
@@ -142,90 +143,38 @@ function renderEmbeddedField({ context, registry, allCollectionsConfig, componen
142
143
  * 2. FieldDefinition.field.component (registry-first approach)
143
144
  * 3. Error message if no component registered
144
145
  */
145
- function FieldRenderer(t0) {
146
- const $ = c(31);
147
- const { fieldName, fieldDef, collection, mode: t1, registry, fieldPrefix, allCollectionsConfig, renderEmbeddedFields, className, entityMeta: entityMetaProp, extraProps } = t0;
148
- const mode = t1 === void 0 ? "collection" : t1;
146
+ function FieldRenderer({ fieldName, fieldDef, collection, mode = "collection", registry, fieldPrefix, allCollectionsConfig, renderEmbeddedFields, className, entityMeta: entityMetaProp, extraProps }) {
149
147
  const form = useFormContext();
150
148
  const { locale } = useScopedLocale();
151
149
  const resolveText = useResolveText();
152
150
  const { data: adminConfig } = useAdminConfig();
153
- let t2;
154
- if ($[0] !== fieldName || $[1] !== fieldPrefix) {
155
- t2 = getFullFieldName(fieldName, fieldPrefix);
156
- $[0] = fieldName;
157
- $[1] = fieldPrefix;
158
- $[2] = t2;
159
- } else t2 = $[2];
160
- const fullFieldName = t2;
161
- let t3;
162
- if ($[3] !== fieldDef) {
163
- t3 = getFieldOptions(fieldDef);
164
- $[3] = fieldDef;
165
- $[4] = t3;
166
- } else t3 = $[4];
167
- const fieldOptions = t3;
168
- let t4;
169
- if ($[5] !== fieldOptions || $[6] !== fieldPrefix || $[7] !== form) {
170
- t4 = computeDynamicDependencyPaths({
171
- fieldOptions,
172
- form,
173
- fieldPrefix
174
- });
175
- $[5] = fieldOptions;
176
- $[6] = fieldPrefix;
177
- $[7] = form;
178
- $[8] = t4;
179
- } else t4 = $[8];
180
- const dynamicDependencyPaths = t4;
181
- let t5;
182
- if ($[9] !== dynamicDependencyPaths || $[10] !== fullFieldName) {
183
- t5 = new Set([fullFieldName, ...dynamicDependencyPaths]);
184
- $[9] = dynamicDependencyPaths;
185
- $[10] = fullFieldName;
186
- $[11] = t5;
187
- } else t5 = $[11];
188
- let t6;
189
- if ($[12] !== t5) {
190
- t6 = [...t5];
191
- $[12] = t5;
192
- $[13] = t6;
193
- } else t6 = $[13];
194
- const t7 = t6;
195
- let t8;
196
- if ($[14] !== form.control || $[15] !== t7) {
197
- t8 = {
198
- control: form.control,
199
- name: t7
200
- };
201
- $[14] = form.control;
202
- $[15] = t7;
203
- $[16] = t8;
204
- } else t8 = $[16];
205
- const watchedDependencyValues = useWatch(t8);
151
+ const fullFieldName = getFullFieldName(fieldName, fieldPrefix);
152
+ const fieldOptions = React.useMemo(() => getFieldOptions(fieldDef), [fieldDef]);
153
+ const dynamicDependencyPaths = React.useMemo(() => computeDynamicDependencyPaths({
154
+ fieldOptions,
155
+ form,
156
+ fieldPrefix
157
+ }), [
158
+ fieldOptions,
159
+ form,
160
+ fieldPrefix
161
+ ]);
162
+ const watchNames = React.useMemo(() => {
163
+ return [...new Set([fullFieldName, ...dynamicDependencyPaths])];
164
+ }, [fullFieldName, dynamicDependencyPaths]);
165
+ const watchedDependencyValues = useWatch({
166
+ control: form.control,
167
+ name: watchNames
168
+ });
206
169
  const watchedFieldValue = Array.isArray(watchedDependencyValues) ? watchedDependencyValues[0] : watchedDependencyValues;
207
- let t9;
208
- bb0: {
209
- if (!fieldPrefix) {
210
- let t10$2;
211
- if ($[17] !== form) {
212
- t10$2 = form.getValues() ?? {};
213
- $[17] = form;
214
- $[18] = t10$2;
215
- } else t10$2 = $[18];
216
- t9 = t10$2;
217
- break bb0;
218
- }
219
- let t10$1;
220
- if ($[19] !== fieldPrefix || $[20] !== form) {
221
- t10$1 = form.getValues(fieldPrefix) ?? {};
222
- $[19] = fieldPrefix;
223
- $[20] = form;
224
- $[21] = t10$1;
225
- } else t10$1 = $[21];
226
- t9 = t10$1;
227
- }
228
- const formValues = t9;
170
+ const formValues = React.useMemo(() => {
171
+ if (!fieldPrefix) return form.getValues() ?? {};
172
+ return form.getValues(fieldPrefix) ?? {};
173
+ }, [
174
+ form,
175
+ fieldPrefix,
176
+ watchedDependencyValues
177
+ ]);
229
178
  const context = getFieldContext({
230
179
  fieldName,
231
180
  fieldDef,
@@ -249,21 +198,22 @@ function FieldRenderer(t0) {
249
198
  staticOptions: context.options
250
199
  });
251
200
  if (context.isHidden) return null;
252
- if (!fieldDef) {
253
- const t10$1 = `Field "${fieldName}" not found in ${mode === "global" ? "global" : "collection"} "${collection}" config.`;
254
- let t11;
255
- if ($[22] !== t10$1) {
256
- t11 = renderConfigError(t10$1);
257
- $[22] = t10$1;
258
- $[23] = t11;
259
- } else t11 = $[23];
260
- return t11;
261
- }
201
+ if (!fieldDef) return renderConfigError(`Field "${fieldName}" not found in ${mode === "global" ? "global" : "collection"} "${collection}" config.`);
262
202
  const resolvedOptions = hookOptions ?? context.options;
263
203
  const rawComponentProps = buildComponentProps(context);
204
+ const { props: resolvedFieldProps } = useReactiveProps({
205
+ entity: collection,
206
+ entityType: mode,
207
+ field: fullFieldName,
208
+ props: React.useMemo(() => ({
209
+ ...stripFieldUiOptions(getFieldOptions(fieldDef)),
210
+ ...extraProps ?? {}
211
+ }), [fieldDef, extraProps])
212
+ });
264
213
  const fieldValue = isComputed ? computedValue : watchedFieldValue === void 0 ? rawComponentProps.value : watchedFieldValue;
265
214
  const componentProps = {
266
215
  ...rawComponentProps,
216
+ ...resolvedFieldProps,
267
217
  value: fieldValue,
268
218
  onChange: handleChange,
269
219
  options: resolvedOptions,
@@ -271,8 +221,7 @@ function FieldRenderer(t0) {
271
221
  readOnly: rawComponentProps.readOnly || isComputed,
272
222
  label: resolveText(rawComponentProps.label, "", formValues),
273
223
  description: resolveText(rawComponentProps.description, "", formValues),
274
- placeholder: resolveText(rawComponentProps.placeholder, "", formValues),
275
- ...extraProps ?? {}
224
+ placeholder: resolveText(rawComponentProps.placeholder, "", formValues)
276
225
  };
277
226
  let content = null;
278
227
  if (context.type === "embedded") content = renderEmbeddedField({
@@ -294,36 +243,12 @@ function FieldRenderer(t0) {
294
243
  componentProps,
295
244
  blocks: adminConfig?.blocks
296
245
  });
297
- if (!content) {
298
- const t10$1 = `No component registered for field type "${context.type}" (field: "${context.fieldName}").`;
299
- let t11;
300
- if ($[24] !== t10$1) {
301
- t11 = renderConfigError(t10$1);
302
- $[24] = t10$1;
303
- $[25] = t11;
304
- } else t11 = $[25];
305
- content = t11;
306
- }
307
- if (className) {
308
- let t10$1;
309
- if ($[26] !== className || $[27] !== content) {
310
- t10$1 = /* @__PURE__ */ jsx("div", {
311
- className,
312
- children: content
313
- });
314
- $[26] = className;
315
- $[27] = content;
316
- $[28] = t10$1;
317
- } else t10$1 = $[28];
318
- return t10$1;
319
- }
320
- let t10;
321
- if ($[29] !== content) {
322
- t10 = /* @__PURE__ */ jsx(Fragment, { children: content });
323
- $[29] = content;
324
- $[30] = t10;
325
- } else t10 = $[30];
326
- return t10;
246
+ if (!content) content = renderConfigError(`No component registered for field type "${context.type}" (field: "${context.fieldName}").`);
247
+ if (className) return /* @__PURE__ */ jsx("div", {
248
+ className,
249
+ children: content
250
+ });
251
+ return /* @__PURE__ */ jsx(Fragment, { children: content });
327
252
  }
328
253
 
329
254
  //#endregion
@@ -979,15 +979,15 @@ function FormView({ collection, id, config, viewConfig, navigate, basePath = "/a
979
979
  setActionLoading(true);
980
980
  const apiPromise = async () => {
981
981
  const url = `${storeBasePath}/${collection}/${endpoint}`;
982
- const response = await fetch(url, {
982
+ const response_0 = await fetch(url, {
983
983
  method,
984
984
  headers: { "Content-Type": "application/json" },
985
985
  body
986
986
  });
987
- if (!response.ok) {
987
+ if (!response_0.ok) {
988
988
  let errorBody = {};
989
989
  try {
990
- errorBody = await response.json();
990
+ errorBody = await response_0.json();
991
991
  } catch (_parseErr) {}
992
992
  let errorMessage;
993
993
  if (errorBody.message) if (typeof errorBody.message === "string") errorMessage = errorBody.message;
@@ -995,7 +995,7 @@ function FormView({ collection, id, config, viewConfig, navigate, basePath = "/a
995
995
  else errorMessage = t("toast.actionFailed");
996
996
  throw new Error(errorMessage);
997
997
  }
998
- return response.json();
998
+ return response_0.json();
999
999
  };
1000
1000
  const p = apiPromise();
1001
1001
  p.then(() => setActionLoading(false), () => setActionLoading(false));
@@ -1021,6 +1021,34 @@ function FormView({ collection, id, config, viewConfig, navigate, basePath = "/a
1021
1021
  }
1022
1022
  break;
1023
1023
  }
1024
+ case "server": {
1025
+ const serverHandler = handler;
1026
+ setActionLoading(true);
1027
+ try {
1028
+ const routes = client?.routes;
1029
+ if (!routes?.executeAction) throw new Error(t("error.serverActionFailed"));
1030
+ const response = await routes.executeAction({
1031
+ collection: serverHandler.collection,
1032
+ actionId: serverHandler.actionId,
1033
+ itemId: transformedItem?.id || id
1034
+ });
1035
+ if (!response?.success || response.result?.type === "error") throw new Error(response?.error ?? response?.result?.toast?.message ?? t("error.serverActionFailed"));
1036
+ const result_2 = response.result;
1037
+ if (result_2?.toast?.message) toast.success(result_2.toast.message);
1038
+ else toast.success(t("toast.actionSuccess"));
1039
+ if (result_2?.effects?.invalidate === true) await actionHelpers.invalidateAll();
1040
+ else if (Array.isArray(result_2?.effects?.invalidate)) for (const col_1 of result_2.effects.invalidate) await actionHelpers.invalidateCollection(col_1);
1041
+ if (result_2?.effects?.redirect) storeNavigate(result_2.effects.redirect);
1042
+ if (result_2?.type === "redirect" && result_2.url) if (result_2.external) window.open(result_2.url, "_blank");
1043
+ else storeNavigate(result_2.url);
1044
+ if (result_2?.effects?.closeModal) actionHelpers.closeDialog();
1045
+ } catch (error_0) {
1046
+ toast.error(error_0 instanceof Error ? error_0.message : t("error.actionFailed"));
1047
+ } finally {
1048
+ setActionLoading(false);
1049
+ }
1050
+ break;
1051
+ }
1024
1052
  }
1025
1053
  setConfirmAction(null);
1026
1054
  };
@@ -1032,8 +1060,8 @@ function FormView({ collection, id, config, viewConfig, navigate, basePath = "/a
1032
1060
  const payload = { id };
1033
1061
  if (typeof pendingRevertVersion.versionId === "string") payload.versionId = pendingRevertVersion.versionId;
1034
1062
  else if (typeof pendingRevertVersion.versionNumber === "number") payload.version = pendingRevertVersion.versionNumber;
1035
- const result_2 = await revertVersionMutation.mutateAsync(payload);
1036
- form.reset(result_2);
1063
+ const result_3 = await revertVersionMutation.mutateAsync(payload);
1064
+ form.reset(result_3);
1037
1065
  triggerPreviewRefresh();
1038
1066
  toast.success(t("version.revertSuccess"));
1039
1067
  setPendingRevertVersion(null);
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import * as react_jsx_runtime7 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime9 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/client/views/pages/accept-invite-page.d.ts
5
5
 
@@ -61,6 +61,6 @@ declare function AcceptInvitePage({
61
61
  redirectTo,
62
62
  loginPath,
63
63
  minPasswordLength
64
- }: AcceptInvitePageProps): react_jsx_runtime7.JSX.Element;
64
+ }: AcceptInvitePageProps): react_jsx_runtime9.JSX.Element;
65
65
  //#endregion
66
66
  export { AcceptInvitePage };
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime8 from "react/jsx-runtime";
1
+ import * as react_jsx_runtime7 from "react/jsx-runtime";
2
2
 
3
3
  //#region src/client/views/pages/dashboard-page.d.ts
4
4
 
@@ -38,6 +38,6 @@ declare function DashboardPage({
38
38
  title,
39
39
  description,
40
40
  className
41
- }: DashboardPageProps): react_jsx_runtime8.JSX.Element;
41
+ }: DashboardPageProps): react_jsx_runtime7.JSX.Element;
42
42
  //#endregion
43
43
  export { DashboardPage };
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import * as react_jsx_runtime9 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime8 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/client/views/pages/forgot-password-page.d.ts
5
5
 
@@ -51,6 +51,6 @@ declare function ForgotPasswordPage({
51
51
  logo,
52
52
  loginPath,
53
53
  resetPasswordRedirectUrl
54
- }: ForgotPasswordPageProps): react_jsx_runtime9.JSX.Element;
54
+ }: ForgotPasswordPageProps): react_jsx_runtime8.JSX.Element;
55
55
  //#endregion
56
56
  export { ForgotPasswordPage };
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import * as react_jsx_runtime14 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime12 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/client/views/pages/reset-password-page.d.ts
5
5
 
@@ -58,6 +58,6 @@ declare function ResetPasswordPage({
58
58
  loginPath,
59
59
  minPasswordLength,
60
60
  getToken
61
- }: ResetPasswordPageProps): react_jsx_runtime14.JSX.Element;
61
+ }: ResetPasswordPageProps): react_jsx_runtime12.JSX.Element;
62
62
  //#endregion
63
63
  export { ResetPasswordPage };
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import * as react_jsx_runtime15 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime13 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/client/views/pages/setup-page.d.ts
5
5
 
@@ -56,6 +56,6 @@ declare function SetupPage({
56
56
  redirectTo,
57
57
  loginPath,
58
58
  showLoginLink
59
- }: SetupPageProps): react_jsx_runtime15.JSX.Element;
59
+ }: SetupPageProps): react_jsx_runtime13.JSX.Element;
60
60
  //#endregion
61
61
  export { SetupPage, SetupPageProps };
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime25 from "react/jsx-runtime";
1
+ import * as react_jsx_runtime20 from "react/jsx-runtime";
2
2
 
3
3
  //#region src/components/rich-text/rich-text-renderer.d.ts
4
4
  /**
@@ -98,6 +98,6 @@ declare function RichTextRenderer({
98
98
  content,
99
99
  styles: customStyles,
100
100
  className
101
- }: RichTextRendererProps): react_jsx_runtime25.JSX.Element | null;
101
+ }: RichTextRendererProps): react_jsx_runtime20.JSX.Element | null;
102
102
  //#endregion
103
103
  export { RichTextRenderer, RichTextStyles, TipTapDoc, TipTapNode };
@@ -219,6 +219,20 @@ interface FormTabsLayout {
219
219
  type: "tabs";
220
220
  tabs: FormTabConfig[];
221
221
  }
222
+ /**
223
+ * Per-prop value type for `FormFieldLayoutItem.props` — accepts JSON, a
224
+ * handler function, or a `{ handler, deps?, debounce? }` config.
225
+ *
226
+ * Functions / config objects are resolved server-side via the
227
+ * `/admin/reactive` `prop` endpoint; static JSON is shipped through
228
+ * introspection unchanged. See `FormFieldLayoutItem.props` for the
229
+ * full description.
230
+ */
231
+ type FormReactivePropValue<TData = any> = unknown | ((ctx: FormReactiveContext<TData>) => unknown | Promise<unknown>) | {
232
+ handler: (ctx: FormReactiveContext<TData>) => unknown | Promise<unknown>;
233
+ deps?: string[] | ((ctx: FormReactiveContext<TData>) => any[]);
234
+ debounce?: number;
235
+ };
222
236
  /**
223
237
  * Field entry with optional reactive form behavior.
224
238
  */
@@ -233,12 +247,42 @@ interface FormFieldLayoutItem<TData = any> {
233
247
  * Extra props forwarded to the field component (escape hatch for
234
248
  * component-specific config like relation `filter`).
235
249
  *
236
- * @example
250
+ * Each prop value can be:
251
+ * - **Static JSON** (string, number, boolean, array, object) — passed
252
+ * through introspection unchanged and given to the field component
253
+ * as-is. Use this when the value doesn't depend on form state.
254
+ * - **A function** `(ctx) => T` — stays on the server. Introspection
255
+ * emits a `ReactivePropPlaceholder` in its place; the client resolves
256
+ * the value via `/admin/reactive` (type `"prop"`) whenever the
257
+ * tracked dependencies change.
258
+ * - **A `{ handler, deps?, debounce? }` config** — same as a function
259
+ * but with explicit dependency control + debouncing.
260
+ *
261
+ * @example Static
262
+ * ```ts
263
+ * { field: f.counselorId, props: { filter: { role: "admin" } } }
264
+ * ```
265
+ *
266
+ * @example Reactive (deps inferred from handler)
267
+ * ```ts
268
+ * { field: f.author, props: { filter: ({ data }) => ({ team: data.team }) } }
269
+ * ```
270
+ *
271
+ * @example Reactive with explicit deps + debounce
237
272
  * ```ts
238
- * { field: f.counselorId, props: { filter: () => ({ role: "admin" }) } }
273
+ * {
274
+ * field: f.author,
275
+ * props: {
276
+ * filter: {
277
+ * handler: ({ data }) => ({ team: data.team }),
278
+ * deps: ["team"],
279
+ * debounce: 200,
280
+ * },
281
+ * },
282
+ * }
239
283
  * ```
240
284
  */
241
- props?: Record<string, any>;
285
+ props?: Record<string, FormReactivePropValue<TData>>;
242
286
  }
243
287
  /**
244
288
  * Field layout item - union of field reference or layout container.
@@ -331,4 +375,4 @@ interface AdminGlobalConfig {
331
375
  audit?: boolean;
332
376
  }
333
377
  //#endregion
334
- export { AdminBlockConfig, AdminCollectionConfig, AdminGlobalConfig, BlockCategoryConfig, FieldLayoutItem, FormFieldLayoutItem, FormReactiveConfig, FormReactiveContext, FormSectionLayout, FormSidebarConfig, FormTabConfig, FormTabsLayout, FormViewConfig, ListViewConfig, PreviewConfig };
378
+ export { AdminBlockConfig, AdminCollectionConfig, AdminGlobalConfig, BlockCategoryConfig, FieldLayoutItem, FormFieldLayoutItem, FormReactiveConfig, FormReactiveContext, FormReactivePropValue, FormSectionLayout, FormSidebarConfig, FormTabConfig, FormTabsLayout, FormViewConfig, ListViewConfig, PreviewConfig };
@@ -1,5 +1,5 @@
1
1
  import { ActionReference, AdminLocaleConfig, ComponentReference, ComponentType, ComponentTypeRegistry } from "./common.mjs";
2
- import { AdminBlockConfig, AdminCollectionConfig, AdminGlobalConfig, BlockCategoryConfig, FieldLayoutItem, FormFieldLayoutItem, FormReactiveConfig, FormReactiveContext, FormSectionLayout, FormSidebarConfig, FormTabConfig, FormTabsLayout, FormViewConfig, ListViewConfig, PreviewConfig } from "./form-layout.mjs";
2
+ import { AdminBlockConfig, AdminCollectionConfig, AdminGlobalConfig, BlockCategoryConfig, FieldLayoutItem, FormFieldLayoutItem, FormReactiveConfig, FormReactiveContext, FormReactivePropValue, FormSectionLayout, FormSidebarConfig, FormTabConfig, FormTabsLayout, FormViewConfig, ListViewConfig, PreviewConfig } from "./form-layout.mjs";
3
3
  import { AdminConfigContext, ComponentDefinition, ComponentFactory, EditViewDefinition, EditViewFactory, FilterViewsByKind, FormViewConfigContext, ListViewConfigContext, ListViewDefinition, ListViewFactory, ViewDefinition, ViewKind, ViewKindRegistry } from "./views.mjs";
4
4
  import { BrandLogo, DashboardActionFactory, DashboardActionProxy, DashboardCallback, DashboardCallbackContext, DashboardConfigContext, DashboardContribution, DashboardItemDef, DashboardProxy, DashboardSectionDef, ServerBrandingConfig, ServerChartWidget, ServerCustomWidget, ServerDashboardAction, ServerDashboardConfig, ServerDashboardItem, ServerDashboardSection, ServerDashboardTab, ServerDashboardTabs, ServerDashboardWidget, ServerProgressWidget, ServerQuickAction, ServerQuickActionsWidget, ServerRecentItemsWidget, ServerStatsWidget, ServerTableWidget, ServerTimelineWidget, ServerValueWidget, WidgetAccessRule, WidgetFetchContext } from "./dashboard.mjs";
5
5
  import { ServerSidebarCollectionItem, ServerSidebarConfig, ServerSidebarDividerItem, ServerSidebarGlobalItem, ServerSidebarItem, ServerSidebarLinkItem, ServerSidebarPageItem, ServerSidebarSection, SidebarCallback, SidebarCallbackContext, SidebarConfigContext, SidebarContribution, SidebarItemDef, SidebarProxy, SidebarSectionDef } from "./sidebar.mjs";
@@ -1,5 +1,5 @@
1
1
  import { ActionReference, AdminLocaleConfig, ComponentReference, ComponentType, ComponentTypeRegistry } from "./augmentation/common.mjs";
2
- import { AdminBlockConfig, AdminCollectionConfig, AdminGlobalConfig, BlockCategoryConfig, FieldLayoutItem, FormFieldLayoutItem, FormReactiveConfig, FormReactiveContext, FormSectionLayout, FormSidebarConfig, FormTabConfig, FormTabsLayout, FormViewConfig, ListViewConfig, PreviewConfig } from "./augmentation/form-layout.mjs";
2
+ import { AdminBlockConfig, AdminCollectionConfig, AdminGlobalConfig, BlockCategoryConfig, FieldLayoutItem, FormFieldLayoutItem, FormReactiveConfig, FormReactiveContext, FormReactivePropValue, FormSectionLayout, FormSidebarConfig, FormTabConfig, FormTabsLayout, FormViewConfig, ListViewConfig, PreviewConfig } from "./augmentation/form-layout.mjs";
3
3
  import { AdminConfigContext, ComponentDefinition, ComponentFactory, EditViewDefinition, EditViewFactory, FilterViewsByKind, FormViewConfigContext, ListViewConfigContext, ListViewDefinition, ListViewFactory, ViewDefinition, ViewKind, ViewKindRegistry } from "./augmentation/views.mjs";
4
4
  import { BrandLogo, DashboardActionFactory, DashboardActionProxy, DashboardCallback, DashboardCallbackContext, DashboardConfigContext, DashboardContribution, DashboardItemDef, DashboardProxy, DashboardSectionDef, ServerBrandingConfig, ServerChartWidget, ServerCustomWidget, ServerDashboardAction, ServerDashboardConfig, ServerDashboardItem, ServerDashboardSection, ServerDashboardTab, ServerDashboardTabs, ServerDashboardWidget, ServerProgressWidget, ServerQuickAction, ServerQuickActionsWidget, ServerRecentItemsWidget, ServerStatsWidget, ServerTableWidget, ServerTimelineWidget, ServerValueWidget, WidgetAccessRule, WidgetFetchContext } from "./augmentation/dashboard.mjs";
5
5
  import { ServerSidebarCollectionItem, ServerSidebarConfig, ServerSidebarDividerItem, ServerSidebarGlobalItem, ServerSidebarItem, ServerSidebarLinkItem, ServerSidebarPageItem, ServerSidebarSection, SidebarCallback, SidebarCallbackContext, SidebarConfigContext, SidebarContribution, SidebarItemDef, SidebarProxy, SidebarSectionDef } from "./augmentation/sidebar.mjs";
@@ -1,27 +1,27 @@
1
1
  import * as questpie_shared22 from "questpie/shared";
2
- import * as questpie151 from "questpie";
2
+ import * as questpie152 from "questpie";
3
3
  import * as questpie_src_server_modules_core_fields_email_js3 from "questpie/src/server/modules/core/fields/email.js";
4
4
  import * as questpie_src_server_modules_core_fields_json_js3 from "questpie/src/server/modules/core/fields/json.js";
5
5
  import * as drizzle_orm_pg_core32 from "drizzle-orm/pg-core";
6
6
  import * as drizzle_orm15 from "drizzle-orm";
7
7
 
8
8
  //#region src/server/modules/admin/collections/account.d.ts
9
- declare const _default: questpie151.CollectionBuilder<questpie_shared22.Override<questpie151.EmptyCollectionState<"account", undefined, {
10
- readonly text: typeof questpie151.text;
11
- readonly textarea: typeof questpie151.textarea;
9
+ declare const _default: questpie152.CollectionBuilder<questpie_shared22.Override<questpie152.EmptyCollectionState<"account", undefined, {
10
+ readonly text: typeof questpie152.text;
11
+ readonly textarea: typeof questpie152.textarea;
12
12
  readonly email: typeof questpie_src_server_modules_core_fields_email_js3.email;
13
- readonly url: typeof questpie151.url;
14
- readonly number: typeof questpie151.number;
15
- readonly boolean: typeof questpie151.boolean;
16
- readonly date: typeof questpie151.date;
17
- readonly datetime: typeof questpie151.datetime;
18
- readonly time: typeof questpie151.time;
19
- readonly select: typeof questpie151.select;
20
- readonly upload: typeof questpie151.upload;
21
- readonly relation: typeof questpie151.relation;
22
- readonly object: typeof questpie151.object;
13
+ readonly url: typeof questpie152.url;
14
+ readonly number: typeof questpie152.number;
15
+ readonly boolean: typeof questpie152.boolean;
16
+ readonly date: typeof questpie152.date;
17
+ readonly datetime: typeof questpie152.datetime;
18
+ readonly time: typeof questpie152.time;
19
+ readonly select: typeof questpie152.select;
20
+ readonly upload: typeof questpie152.upload;
21
+ readonly relation: typeof questpie152.relation;
22
+ readonly object: typeof questpie152.object;
23
23
  readonly json: typeof questpie_src_server_modules_core_fields_json_js3.json;
24
- readonly from: typeof questpie151.from;
24
+ readonly from: typeof questpie152.from;
25
25
  }>, {
26
26
  name: "account";
27
27
  fields: Record<string, any> & {
@@ -37,35 +37,35 @@ declare const _default: questpie151.CollectionBuilder<questpie_shared22.Override
37
37
  readonly password: drizzle_orm_pg_core32.PgVarcharBuilder<[string, ...string[]]>;
38
38
  };
39
39
  virtuals: undefined;
40
- relations: Record<string, questpie151.RelationConfig>;
40
+ relations: Record<string, questpie152.RelationConfig>;
41
41
  indexes: Record<string, any>;
42
42
  title: "providerId";
43
- options: questpie151.CollectionOptions & {
43
+ options: questpie152.CollectionOptions & {
44
44
  timestamps: true;
45
45
  };
46
46
  hooks: Record<string, any>;
47
47
  access: Record<string, any>;
48
48
  searchable: undefined;
49
49
  fieldDefinitions: {
50
- readonly userId: questpie151.FieldWithMethods<Omit<questpie151.TextFieldState, "notNull" | "column"> & {
50
+ readonly userId: questpie152.FieldWithMethods<Omit<questpie152.TextFieldState, "notNull" | "column"> & {
51
51
  notNull: true;
52
52
  column: drizzle_orm15.NotNull<drizzle_orm_pg_core32.PgVarcharBuilder<[string, ...string[]]>>;
53
- }, questpie151.TextFieldMethods>;
54
- readonly accountId: questpie151.FieldWithMethods<Omit<questpie151.TextFieldState, "notNull" | "column"> & {
53
+ }, questpie152.TextFieldMethods>;
54
+ readonly accountId: questpie152.FieldWithMethods<Omit<questpie152.TextFieldState, "notNull" | "column"> & {
55
55
  notNull: true;
56
56
  column: drizzle_orm15.NotNull<drizzle_orm_pg_core32.PgVarcharBuilder<[string, ...string[]]>>;
57
- }, questpie151.TextFieldMethods>;
58
- readonly providerId: questpie151.FieldWithMethods<Omit<questpie151.TextFieldState, "notNull" | "column"> & {
57
+ }, questpie152.TextFieldMethods>;
58
+ readonly providerId: questpie152.FieldWithMethods<Omit<questpie152.TextFieldState, "notNull" | "column"> & {
59
59
  notNull: true;
60
60
  column: drizzle_orm15.NotNull<drizzle_orm_pg_core32.PgVarcharBuilder<[string, ...string[]]>>;
61
- }, questpie151.TextFieldMethods>;
62
- readonly accessToken: questpie151.FieldWithMethods<questpie151.TextFieldState, questpie151.TextFieldMethods>;
63
- readonly refreshToken: questpie151.FieldWithMethods<questpie151.TextFieldState, questpie151.TextFieldMethods>;
64
- readonly accessTokenExpiresAt: questpie151.FieldWithMethods<questpie151.DatetimeFieldState, questpie151.DatetimeFieldMethods>;
65
- readonly refreshTokenExpiresAt: questpie151.FieldWithMethods<questpie151.DatetimeFieldState, questpie151.DatetimeFieldMethods>;
66
- readonly scope: questpie151.FieldWithMethods<questpie151.TextFieldState, questpie151.TextFieldMethods>;
67
- readonly idToken: questpie151.FieldWithMethods<questpie151.TextFieldState, questpie151.TextFieldMethods>;
68
- readonly password: questpie151.FieldWithMethods<questpie151.TextFieldState, questpie151.TextFieldMethods>;
61
+ }, questpie152.TextFieldMethods>;
62
+ readonly accessToken: questpie152.FieldWithMethods<questpie152.TextFieldState, questpie152.TextFieldMethods>;
63
+ readonly refreshToken: questpie152.FieldWithMethods<questpie152.TextFieldState, questpie152.TextFieldMethods>;
64
+ readonly accessTokenExpiresAt: questpie152.FieldWithMethods<questpie152.DatetimeFieldState, questpie152.DatetimeFieldMethods>;
65
+ readonly refreshTokenExpiresAt: questpie152.FieldWithMethods<questpie152.DatetimeFieldState, questpie152.DatetimeFieldMethods>;
66
+ readonly scope: questpie152.FieldWithMethods<questpie152.TextFieldState, questpie152.TextFieldMethods>;
67
+ readonly idToken: questpie152.FieldWithMethods<questpie152.TextFieldState, questpie152.TextFieldMethods>;
68
+ readonly password: questpie152.FieldWithMethods<questpie152.TextFieldState, questpie152.TextFieldMethods>;
69
69
  };
70
70
  upload: undefined;
71
71
  output: {};