@stapel/forms-react 0.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 (203) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/MODULE.md +172 -0
  3. package/README.md +207 -0
  4. package/dist/api/export.d.ts +66 -0
  5. package/dist/api/export.d.ts.map +1 -0
  6. package/dist/api/export.js +138 -0
  7. package/dist/api/export.js.map +1 -0
  8. package/dist/api/extensions.d.ts +8 -0
  9. package/dist/api/extensions.d.ts.map +1 -0
  10. package/dist/api/extensions.js +8 -0
  11. package/dist/api/extensions.js.map +1 -0
  12. package/dist/api/formsApi.d.ts +113 -0
  13. package/dist/api/formsApi.d.ts.map +1 -0
  14. package/dist/api/formsApi.js +81 -0
  15. package/dist/api/formsApi.js.map +1 -0
  16. package/dist/api/generated/schema.d.ts +987 -0
  17. package/dist/api/generated/schema.d.ts.map +1 -0
  18. package/dist/api/generated/schema.js +2 -0
  19. package/dist/api/generated/schema.js.map +1 -0
  20. package/dist/api/types.d.ts +222 -0
  21. package/dist/api/types.d.ts.map +1 -0
  22. package/dist/api/types.js +14 -0
  23. package/dist/api/types.js.map +1 -0
  24. package/dist/default/ConfigField.d.ts +32 -0
  25. package/dist/default/ConfigField.d.ts.map +1 -0
  26. package/dist/default/ConfigField.js +101 -0
  27. package/dist/default/ConfigField.js.map +1 -0
  28. package/dist/default/ErrorAlert.d.ts +9 -0
  29. package/dist/default/ErrorAlert.d.ts.map +1 -0
  30. package/dist/default/ErrorAlert.js +27 -0
  31. package/dist/default/ErrorAlert.js.map +1 -0
  32. package/dist/default/FormBuilderPane.d.ts +36 -0
  33. package/dist/default/FormBuilderPane.d.ts.map +1 -0
  34. package/dist/default/FormBuilderPane.js +70 -0
  35. package/dist/default/FormBuilderPane.js.map +1 -0
  36. package/dist/default/FormsListPane.d.ts +18 -0
  37. package/dist/default/FormsListPane.d.ts.map +1 -0
  38. package/dist/default/FormsListPane.js +28 -0
  39. package/dist/default/FormsListPane.js.map +1 -0
  40. package/dist/default/ResponsesPane.d.ts +21 -0
  41. package/dist/default/ResponsesPane.d.ts.map +1 -0
  42. package/dist/default/ResponsesPane.js +118 -0
  43. package/dist/default/ResponsesPane.js.map +1 -0
  44. package/dist/default/StapelForm.d.ts +76 -0
  45. package/dist/default/StapelForm.d.ts.map +1 -0
  46. package/dist/default/StapelForm.js +118 -0
  47. package/dist/default/StapelForm.js.map +1 -0
  48. package/dist/default/fields.d.ts +11 -0
  49. package/dist/default/fields.d.ts.map +1 -0
  50. package/dist/default/fields.js +273 -0
  51. package/dist/default/fields.js.map +1 -0
  52. package/dist/default/index.d.ts +42 -0
  53. package/dist/default/index.d.ts.map +1 -0
  54. package/dist/default/index.js +37 -0
  55. package/dist/default/index.js.map +1 -0
  56. package/dist/default/slots.d.ts +59 -0
  57. package/dist/default/slots.d.ts.map +1 -0
  58. package/dist/default/slots.js +25 -0
  59. package/dist/default/slots.js.map +1 -0
  60. package/dist/default/theme.d.ts +23 -0
  61. package/dist/default/theme.d.ts.map +1 -0
  62. package/dist/default/theme.js +38 -0
  63. package/dist/default/theme.js.map +1 -0
  64. package/dist/default/types.d.ts +12 -0
  65. package/dist/default/types.d.ts.map +1 -0
  66. package/dist/default/types.js +2 -0
  67. package/dist/default/types.js.map +1 -0
  68. package/dist/flows/errors.d.ts +12 -0
  69. package/dist/flows/errors.d.ts.map +1 -0
  70. package/dist/flows/errors.js +13 -0
  71. package/dist/flows/errors.js.map +1 -0
  72. package/dist/flows/registry.d.ts +22 -0
  73. package/dist/flows/registry.d.ts.map +1 -0
  74. package/dist/flows/registry.js +20 -0
  75. package/dist/flows/registry.js.map +1 -0
  76. package/dist/headless/FormBuilder.d.ts +100 -0
  77. package/dist/headless/FormBuilder.d.ts.map +1 -0
  78. package/dist/headless/FormBuilder.js +278 -0
  79. package/dist/headless/FormBuilder.js.map +1 -0
  80. package/dist/headless/FormFill.d.ts +88 -0
  81. package/dist/headless/FormFill.d.ts.map +1 -0
  82. package/dist/headless/FormFill.js +279 -0
  83. package/dist/headless/FormFill.js.map +1 -0
  84. package/dist/headless/FormList.d.ts +34 -0
  85. package/dist/headless/FormList.d.ts.map +1 -0
  86. package/dist/headless/FormList.js +37 -0
  87. package/dist/headless/FormList.js.map +1 -0
  88. package/dist/headless/FormsProvider.d.ts +19 -0
  89. package/dist/headless/FormsProvider.d.ts.map +1 -0
  90. package/dist/headless/FormsProvider.js +15 -0
  91. package/dist/headless/FormsProvider.js.map +1 -0
  92. package/dist/headless/ResponsesTable.d.ts +82 -0
  93. package/dist/headless/ResponsesTable.d.ts.map +1 -0
  94. package/dist/headless/ResponsesTable.js +195 -0
  95. package/dist/headless/ResponsesTable.js.map +1 -0
  96. package/dist/i18n/errorsMap.d.ts +10 -0
  97. package/dist/i18n/errorsMap.d.ts.map +1 -0
  98. package/dist/i18n/errorsMap.js +20 -0
  99. package/dist/i18n/errorsMap.js.map +1 -0
  100. package/dist/i18n/es.d.ts +7 -0
  101. package/dist/i18n/es.d.ts.map +1 -0
  102. package/dist/i18n/es.js +118 -0
  103. package/dist/i18n/es.js.map +1 -0
  104. package/dist/i18n/generated/errors.es.gen.d.ts +16 -0
  105. package/dist/i18n/generated/errors.es.gen.d.ts.map +1 -0
  106. package/dist/i18n/generated/errors.es.gen.js +79 -0
  107. package/dist/i18n/generated/errors.es.gen.js.map +1 -0
  108. package/dist/i18n/generated/errors.gen.d.ts +485 -0
  109. package/dist/i18n/generated/errors.gen.d.ts.map +1 -0
  110. package/dist/i18n/generated/errors.gen.js +246 -0
  111. package/dist/i18n/generated/errors.gen.js.map +1 -0
  112. package/dist/i18n/generated/errors.ru.gen.d.ts +16 -0
  113. package/dist/i18n/generated/errors.ru.gen.d.ts.map +1 -0
  114. package/dist/i18n/generated/errors.ru.gen.js +79 -0
  115. package/dist/i18n/generated/errors.ru.gen.js.map +1 -0
  116. package/dist/i18n/keys.d.ts +141 -0
  117. package/dist/i18n/keys.d.ts.map +1 -0
  118. package/dist/i18n/keys.js +233 -0
  119. package/dist/i18n/keys.js.map +1 -0
  120. package/dist/i18n/ru.d.ts +7 -0
  121. package/dist/i18n/ru.d.ts.map +1 -0
  122. package/dist/i18n/ru.js +127 -0
  123. package/dist/i18n/ru.js.map +1 -0
  124. package/dist/index.d.ts +61 -0
  125. package/dist/index.d.ts.map +1 -0
  126. package/dist/index.js +55 -0
  127. package/dist/index.js.map +1 -0
  128. package/dist/model/context.d.ts +11 -0
  129. package/dist/model/context.d.ts.map +1 -0
  130. package/dist/model/context.js +16 -0
  131. package/dist/model/context.js.map +1 -0
  132. package/dist/model/mutations.d.ts +135 -0
  133. package/dist/model/mutations.d.ts.map +1 -0
  134. package/dist/model/mutations.js +223 -0
  135. package/dist/model/mutations.js.map +1 -0
  136. package/dist/model/queries.d.ts +59 -0
  137. package/dist/model/queries.d.ts.map +1 -0
  138. package/dist/model/queries.js +117 -0
  139. package/dist/model/queries.js.map +1 -0
  140. package/dist/model/queryKeys.d.ts +28 -0
  141. package/dist/model/queryKeys.d.ts.map +1 -0
  142. package/dist/model/queryKeys.js +23 -0
  143. package/dist/model/queryKeys.js.map +1 -0
  144. package/dist/model/runtime.d.ts +28 -0
  145. package/dist/model/runtime.d.ts.map +1 -0
  146. package/dist/model/runtime.js +14 -0
  147. package/dist/model/runtime.js.map +1 -0
  148. package/dist/widgets/configForms.d.ts +112 -0
  149. package/dist/widgets/configForms.d.ts.map +1 -0
  150. package/dist/widgets/configForms.js +211 -0
  151. package/dist/widgets/configForms.js.map +1 -0
  152. package/dist/widgets/registry.d.ts +83 -0
  153. package/dist/widgets/registry.d.ts.map +1 -0
  154. package/dist/widgets/registry.js +27 -0
  155. package/dist/widgets/registry.js.map +1 -0
  156. package/dist/widgets/validate.d.ts +57 -0
  157. package/dist/widgets/validate.d.ts.map +1 -0
  158. package/dist/widgets/validate.js +173 -0
  159. package/dist/widgets/validate.js.map +1 -0
  160. package/llms.txt +124 -0
  161. package/manifest.json +1038 -0
  162. package/package.json +108 -0
  163. package/src/analytics/generated/events.json +7 -0
  164. package/src/api/export.ts +195 -0
  165. package/src/api/extensions.ts +7 -0
  166. package/src/api/formsApi.ts +329 -0
  167. package/src/api/generated/schema.ts +989 -0
  168. package/src/api/types.ts +276 -0
  169. package/src/default/ConfigField.tsx +227 -0
  170. package/src/default/ErrorAlert.tsx +46 -0
  171. package/src/default/FormBuilderPane.tsx +414 -0
  172. package/src/default/FormsListPane.tsx +144 -0
  173. package/src/default/ResponsesPane.tsx +332 -0
  174. package/src/default/StapelForm.tsx +377 -0
  175. package/src/default/fields.tsx +454 -0
  176. package/src/default/index.ts +71 -0
  177. package/src/default/slots.ts +78 -0
  178. package/src/default/theme.tsx +65 -0
  179. package/src/default/types.ts +12 -0
  180. package/src/flows/errors.ts +16 -0
  181. package/src/flows/registry.ts +32 -0
  182. package/src/headless/FormBuilder.tsx +453 -0
  183. package/src/headless/FormFill.tsx +396 -0
  184. package/src/headless/FormList.tsx +74 -0
  185. package/src/headless/FormsProvider.tsx +20 -0
  186. package/src/headless/ResponsesTable.tsx +341 -0
  187. package/src/i18n/errorsMap.ts +31 -0
  188. package/src/i18n/es.ts +140 -0
  189. package/src/i18n/generated/errors.es.gen.ts +85 -0
  190. package/src/i18n/generated/errors.gen.ts +277 -0
  191. package/src/i18n/generated/errors.json +583 -0
  192. package/src/i18n/generated/errors.ru.gen.ts +85 -0
  193. package/src/i18n/keys.ts +264 -0
  194. package/src/i18n/ru.ts +150 -0
  195. package/src/index.ts +184 -0
  196. package/src/model/context.tsx +28 -0
  197. package/src/model/mutations.ts +387 -0
  198. package/src/model/queries.ts +154 -0
  199. package/src/model/queryKeys.ts +61 -0
  200. package/src/model/runtime.ts +48 -0
  201. package/src/widgets/registry.ts +101 -0
  202. package/src/widgets/validate.ts +224 -0
  203. package/tsconfig.json +26 -0
@@ -0,0 +1,135 @@
1
+ import type { UseMutationResult } from "@tanstack/react-query";
2
+ import type { StapelApiError } from "@stapel/core";
3
+ import type { FormCreateRequest, FormPatchRequest, FormRow, FormSchema, FormState, PublishResult, ResendRequest, ResendResult, SubmitRequest, SubmitResult } from "../api/types.js";
4
+ /** Variables for {@link useSubmitForm}. */
5
+ export interface SubmitVariables {
6
+ readonly publicId: string;
7
+ readonly body: SubmitRequest;
8
+ }
9
+ /**
10
+ * `POST /public/<public_id>/submissions/` — the anonymous submit.
11
+ *
12
+ * Deliberately does NOT invalidate anything: an anonymous respondent holds no
13
+ * admin cache to refresh, and the one read they do hold (the schema) is
14
+ * unchanged by their own submission. The 409-superseded refetch is driven by
15
+ * `<FormFill>`, which knows to preserve the values first.
16
+ *
17
+ * `retry: false` — a resubmit is not idempotent. A retried POST that the
18
+ * server actually received is a duplicate response in somebody's spreadsheet.
19
+ */
20
+ export declare function useSubmitForm(): UseMutationResult<SubmitResult, StapelApiError, SubmitVariables>;
21
+ /** `POST /forms` — create a form (it starts in `draft`). `forms.manage`. */
22
+ export declare function useCreateForm(): UseMutationResult<FormRow, StapelApiError, FormCreateRequest>;
23
+ /** Variables for {@link useUpdateForm}. */
24
+ export interface UpdateFormVariables {
25
+ readonly workspaceId: string;
26
+ readonly formId: string;
27
+ readonly patch: FormPatchRequest;
28
+ }
29
+ /** `PATCH /forms/<id>` — title and notification targets. `forms.manage`. */
30
+ export declare function useUpdateForm(): UseMutationResult<FormRow, StapelApiError, UpdateFormVariables>;
31
+ /** Variables for the form-scoped mutations that take no body. */
32
+ export interface FormRef {
33
+ readonly workspaceId: string;
34
+ readonly formId: string;
35
+ }
36
+ /** `DELETE /forms/<id>` — soft-delete. `forms.manage`. */
37
+ export declare function useDeleteForm(): UseMutationResult<void, StapelApiError, FormRef>;
38
+ /** Variables for {@link useSaveDraft}. */
39
+ export interface SaveDraftVariables extends FormRef {
40
+ readonly schema: FormSchema;
41
+ }
42
+ /**
43
+ * `PUT /forms/<id>/draft` — replace the builder's scratchpad. `forms.manage`.
44
+ *
45
+ * A draft save is NOT a publish: what respondents see does not move until
46
+ * {@link usePublishForm} freezes the draft into the next immutable version.
47
+ * That separation is the whole reason a live form can be edited safely.
48
+ */
49
+ export declare function useSaveDraft(): UseMutationResult<FormRow, StapelApiError, SaveDraftVariables>;
50
+ /**
51
+ * `POST /forms/<id>/publish` — freeze the draft into the next version.
52
+ * `forms.manage`.
53
+ *
54
+ * Refuses a schema the engine will not accept, per-field where it can:
55
+ * `error.400.forms_empty_schema`, `..._duplicate_slug` (`params.slug`),
56
+ * `..._kind_not_allowed` (`params.kind`), `..._too_many_fields`, and
57
+ * `..._invalid_schema` with `params.key` for a config key the type's
58
+ * dataclass does not know — which is a cap that would otherwise silently not
59
+ * exist (backend delta note 1).
60
+ */
61
+ export declare function usePublishForm(): UseMutationResult<PublishResult, StapelApiError, FormRef>;
62
+ /** Variables for {@link useSetFormState}. */
63
+ export interface SetFormStateVariables extends FormRef {
64
+ readonly state: FormState;
65
+ }
66
+ /** `POST /forms/<id>/state` — open / close / back to draft. `forms.manage`. */
67
+ export declare function useSetFormState(): UseMutationResult<FormRow, StapelApiError, SetFormStateVariables>;
68
+ /**
69
+ * `POST /forms/<id>/rotate-link` — mint a new `public_id`. `forms.manage`.
70
+ *
71
+ * The old link stops resolving (a uniform `error.404.forms_not_found`, so a
72
+ * probe cannot tell a rotated link from one that never existed). This is why
73
+ * every admin mutation invalidates the module root: the public read is cached
74
+ * BY the token this call replaces.
75
+ */
76
+ export declare function useRotateLink(): UseMutationResult<FormRow, StapelApiError, FormRef>;
77
+ /** Variables for the submission-scoped mutations. */
78
+ export interface SubmissionRef {
79
+ readonly workspaceId: string;
80
+ readonly submissionId: string;
81
+ }
82
+ /** `DELETE /submissions/<id>` — erase one response.
83
+ * `forms.responses.manage`. */
84
+ export declare function useDeleteSubmission(): UseMutationResult<void, StapelApiError, SubmissionRef>;
85
+ /** Variables for {@link useResendSubmission}. */
86
+ export interface ResendVariables extends SubmissionRef {
87
+ /**
88
+ * Destination override. Given either list, the form's configured targets
89
+ * are **replaced**, not supplemented (backend delta note 7) — "send this one
90
+ * to legal" must not also re-send it to everybody who already received it.
91
+ * Omit to use the form's own targets.
92
+ */
93
+ readonly override?: ResendRequest;
94
+ }
95
+ /**
96
+ * `POST /submissions/<id>/resend` — re-deliver one response.
97
+ * `forms.responses.manage`.
98
+ *
99
+ * Admin-initiated, so it is NOT subject to `NOTIFY_COOLDOWN_SECONDS` (that
100
+ * cooldown suppresses respondent-triggered auto-notifies; a resend is an
101
+ * explicit operator act). Reads no cache and invalidates none — delivery is
102
+ * not state this pair holds.
103
+ */
104
+ export declare function useResendSubmission(): UseMutationResult<ResendResult, StapelApiError, ResendVariables>;
105
+ /** The state of a running CSV export. */
106
+ export interface CsvExportBag {
107
+ /** Drive the export to completion; resolves to the whole CSV text. */
108
+ run(params: {
109
+ readonly workspaceId: string;
110
+ readonly formId: string;
111
+ readonly version?: number;
112
+ }): Promise<string>;
113
+ readonly isExporting: boolean;
114
+ /** Pages fetched so far — a coarse but honest progress signal for a long
115
+ * export (the server never tells us the total). */
116
+ readonly pagesFetched: number;
117
+ readonly error: StapelApiError | null;
118
+ }
119
+ /**
120
+ * The paged CSV export, driven to completion.
121
+ *
122
+ * The server streams a bounded page per request and hands back the
123
+ * continuation cursor in the `X-Forms-Next-Before` response header — never in
124
+ * the body, which is a spreadsheet (backend delta note 6). This hook follows
125
+ * that header until it is absent, concatenates the pages keeping the header
126
+ * row exactly once, and returns the whole CSV as text. The cursor is passed
127
+ * back VERBATIM; re-formatting it is what made the second page a silent 400
128
+ * during the backend build.
129
+ *
130
+ * The result is text, not a download: handing the caller a string keeps this
131
+ * hook usable in a test, in a node script, and in a browser, and leaves the
132
+ * "make it a file" decision (which is a DOM act) to the skin.
133
+ */
134
+ export declare function useCsvExport(): CsvExportBag;
135
+ //# sourceMappingURL=mutations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutations.d.ts","sourceRoot":"","sources":["../../src/model/mutations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,223 @@
1
+ import { useCallback, useState } from "react";
2
+ import { useMutation, useQueryClient } from "@tanstack/react-query";
3
+ import { isStapelApiError } from "@stapel/core";
4
+ import { concatCsvPages } from "../api/export.js";
5
+ import { useFormsApi } from "./context.js";
6
+ import { formsQueryKeys } from "./queryKeys.js";
7
+ /**
8
+ * Write hooks (frontend-standard §2 — mutations invalidate on success).
9
+ *
10
+ * A forms write shifts several cached reads at once — a publish moves the
11
+ * form's `active_version`, adds a version row, AND changes what the public
12
+ * link serves; a rotate-link changes the very key the public read is cached
13
+ * under — so each admin mutation invalidates the module root
14
+ * (`formsQueryKeys.all`) rather than guessing which entries moved. Guessing
15
+ * is how `rotateLink` would leave a stale schema cached under an id that no
16
+ * longer resolves.
17
+ *
18
+ * Options are built as typed `UseMutationOptions` objects (not call-site
19
+ * generics) so `void`/error types stay in reference position.
20
+ */
21
+ function useInvalidateModule() {
22
+ const queryClient = useQueryClient();
23
+ return () => {
24
+ void queryClient.invalidateQueries({ queryKey: formsQueryKeys.all });
25
+ };
26
+ }
27
+ /**
28
+ * `POST /public/<public_id>/submissions/` — the anonymous submit.
29
+ *
30
+ * Deliberately does NOT invalidate anything: an anonymous respondent holds no
31
+ * admin cache to refresh, and the one read they do hold (the schema) is
32
+ * unchanged by their own submission. The 409-superseded refetch is driven by
33
+ * `<FormFill>`, which knows to preserve the values first.
34
+ *
35
+ * `retry: false` — a resubmit is not idempotent. A retried POST that the
36
+ * server actually received is a duplicate response in somebody's spreadsheet.
37
+ */
38
+ export function useSubmitForm() {
39
+ const api = useFormsApi();
40
+ const options = {
41
+ mutationFn: (vars) => api.submit(vars.publicId, vars.body),
42
+ retry: false,
43
+ };
44
+ return useMutation(options);
45
+ }
46
+ // ── admin: the form lifecycle ────────────────────────────────────────────────
47
+ /** `POST /forms` — create a form (it starts in `draft`). `forms.manage`. */
48
+ export function useCreateForm() {
49
+ const api = useFormsApi();
50
+ const invalidate = useInvalidateModule();
51
+ const options = {
52
+ mutationFn: (body) => api.createForm(body),
53
+ onSuccess: invalidate,
54
+ };
55
+ return useMutation(options);
56
+ }
57
+ /** `PATCH /forms/<id>` — title and notification targets. `forms.manage`. */
58
+ export function useUpdateForm() {
59
+ const api = useFormsApi();
60
+ const invalidate = useInvalidateModule();
61
+ const options = {
62
+ mutationFn: (vars) => api.patchForm(vars.workspaceId, vars.formId, vars.patch),
63
+ onSuccess: invalidate,
64
+ };
65
+ return useMutation(options);
66
+ }
67
+ /** `DELETE /forms/<id>` — soft-delete. `forms.manage`. */
68
+ export function useDeleteForm() {
69
+ const api = useFormsApi();
70
+ const invalidate = useInvalidateModule();
71
+ const options = {
72
+ mutationFn: (vars) => api.deleteForm(vars.workspaceId, vars.formId),
73
+ onSuccess: invalidate,
74
+ };
75
+ return useMutation(options);
76
+ }
77
+ /**
78
+ * `PUT /forms/<id>/draft` — replace the builder's scratchpad. `forms.manage`.
79
+ *
80
+ * A draft save is NOT a publish: what respondents see does not move until
81
+ * {@link usePublishForm} freezes the draft into the next immutable version.
82
+ * That separation is the whole reason a live form can be edited safely.
83
+ */
84
+ export function useSaveDraft() {
85
+ const api = useFormsApi();
86
+ const invalidate = useInvalidateModule();
87
+ const options = {
88
+ mutationFn: (vars) => api.putDraft(vars.workspaceId, vars.formId, vars.schema),
89
+ onSuccess: invalidate,
90
+ };
91
+ return useMutation(options);
92
+ }
93
+ /**
94
+ * `POST /forms/<id>/publish` — freeze the draft into the next version.
95
+ * `forms.manage`.
96
+ *
97
+ * Refuses a schema the engine will not accept, per-field where it can:
98
+ * `error.400.forms_empty_schema`, `..._duplicate_slug` (`params.slug`),
99
+ * `..._kind_not_allowed` (`params.kind`), `..._too_many_fields`, and
100
+ * `..._invalid_schema` with `params.key` for a config key the type's
101
+ * dataclass does not know — which is a cap that would otherwise silently not
102
+ * exist (backend delta note 1).
103
+ */
104
+ export function usePublishForm() {
105
+ const api = useFormsApi();
106
+ const invalidate = useInvalidateModule();
107
+ const options = {
108
+ mutationFn: (vars) => api.publish(vars.workspaceId, vars.formId),
109
+ onSuccess: invalidate,
110
+ };
111
+ return useMutation(options);
112
+ }
113
+ /** `POST /forms/<id>/state` — open / close / back to draft. `forms.manage`. */
114
+ export function useSetFormState() {
115
+ const api = useFormsApi();
116
+ const invalidate = useInvalidateModule();
117
+ const options = {
118
+ mutationFn: (vars) => api.setState(vars.workspaceId, vars.formId, vars.state),
119
+ onSuccess: invalidate,
120
+ };
121
+ return useMutation(options);
122
+ }
123
+ /**
124
+ * `POST /forms/<id>/rotate-link` — mint a new `public_id`. `forms.manage`.
125
+ *
126
+ * The old link stops resolving (a uniform `error.404.forms_not_found`, so a
127
+ * probe cannot tell a rotated link from one that never existed). This is why
128
+ * every admin mutation invalidates the module root: the public read is cached
129
+ * BY the token this call replaces.
130
+ */
131
+ export function useRotateLink() {
132
+ const api = useFormsApi();
133
+ const invalidate = useInvalidateModule();
134
+ const options = {
135
+ mutationFn: (vars) => api.rotateLink(vars.workspaceId, vars.formId),
136
+ onSuccess: invalidate,
137
+ };
138
+ return useMutation(options);
139
+ }
140
+ /** `DELETE /submissions/<id>` — erase one response.
141
+ * `forms.responses.manage`. */
142
+ export function useDeleteSubmission() {
143
+ const api = useFormsApi();
144
+ const invalidate = useInvalidateModule();
145
+ const options = {
146
+ mutationFn: (vars) => api.deleteSubmission(vars.workspaceId, vars.submissionId),
147
+ onSuccess: invalidate,
148
+ };
149
+ return useMutation(options);
150
+ }
151
+ /**
152
+ * `POST /submissions/<id>/resend` — re-deliver one response.
153
+ * `forms.responses.manage`.
154
+ *
155
+ * Admin-initiated, so it is NOT subject to `NOTIFY_COOLDOWN_SECONDS` (that
156
+ * cooldown suppresses respondent-triggered auto-notifies; a resend is an
157
+ * explicit operator act). Reads no cache and invalidates none — delivery is
158
+ * not state this pair holds.
159
+ */
160
+ export function useResendSubmission() {
161
+ const api = useFormsApi();
162
+ const options = {
163
+ mutationFn: (vars) => api.resendSubmission(vars.workspaceId, vars.submissionId, vars.override),
164
+ retry: false,
165
+ };
166
+ return useMutation(options);
167
+ }
168
+ /**
169
+ * The paged CSV export, driven to completion.
170
+ *
171
+ * The server streams a bounded page per request and hands back the
172
+ * continuation cursor in the `X-Forms-Next-Before` response header — never in
173
+ * the body, which is a spreadsheet (backend delta note 6). This hook follows
174
+ * that header until it is absent, concatenates the pages keeping the header
175
+ * row exactly once, and returns the whole CSV as text. The cursor is passed
176
+ * back VERBATIM; re-formatting it is what made the second page a silent 400
177
+ * during the backend build.
178
+ *
179
+ * The result is text, not a download: handing the caller a string keeps this
180
+ * hook usable in a test, in a node script, and in a browser, and leaves the
181
+ * "make it a file" decision (which is a DOM act) to the skin.
182
+ */
183
+ export function useCsvExport() {
184
+ const api = useFormsApi();
185
+ const [isExporting, setExporting] = useState(false);
186
+ const [pagesFetched, setPagesFetched] = useState(0);
187
+ const [error, setError] = useState(null);
188
+ const run = useCallback(async (params) => {
189
+ setExporting(true);
190
+ setPagesFetched(0);
191
+ setError(null);
192
+ const pages = [];
193
+ let before;
194
+ try {
195
+ for (;;) {
196
+ const page = await api.exportSubmissions({
197
+ workspaceId: params.workspaceId,
198
+ formId: params.formId,
199
+ ...(params.version !== undefined ? { version: params.version } : {}),
200
+ ...(before !== undefined ? { before } : {}),
201
+ });
202
+ pages.push(page.csv);
203
+ setPagesFetched(pages.length);
204
+ if (page.nextBefore === null)
205
+ break;
206
+ before = page.nextBefore;
207
+ }
208
+ return concatCsvPages(pages);
209
+ }
210
+ catch (caught) {
211
+ // Not `caught as StapelApiError`: a network fault carries neither
212
+ // `.code` nor `.status`, and claiming otherwise makes the skin render
213
+ // `undefined` as a sentence. `null` means "we cannot describe it".
214
+ setError(isStapelApiError(caught) ? caught : null);
215
+ throw caught;
216
+ }
217
+ finally {
218
+ setExporting(false);
219
+ }
220
+ }, [api]);
221
+ return { run, isExporting, pagesFetched, error };
222
+ }
223
+ //# sourceMappingURL=mutations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutations.js","sourceRoot":"","sources":["../../src/model/mutations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import type { UseQueryResult } from "@tanstack/react-query";
2
+ import type { StapelApiError } from "@stapel/core";
3
+ import type { FieldKindCatalogue, FormRow, FormState, FormVersion, PublicForm, Submission, SubmissionListParams } from "../api/types.js";
4
+ /**
5
+ * Read hooks over the forms API (frontend-standard §2 — read hooks). Keys are
6
+ * namespaced (see `formsQueryKeys`).
7
+ *
8
+ * SESSION GATING, and the one hook that is deliberately NOT gated. Every
9
+ * ADMIN read is gated on {@link useActiveSessionReady} (owner-diagnosed live
10
+ * incident, 2026-07-17): a list hook with no natural `enabled` condition is
11
+ * exactly the shape that raced a still-bootstrapping session.
12
+ * {@link usePublicForm} is the documented exception core's own doc comment
13
+ * carves out ("or be unconditionally safe pre-session, e.g. a public GET"):
14
+ * the endpoint is anonymous, and gating it would make an embedded form on a
15
+ * marketing page wait for a login bootstrap it has no stake in — a form that
16
+ * renders late for a visitor who will never sign in.
17
+ */
18
+ /**
19
+ * The active schema behind a public link — the anonymous read `<StapelForm>`
20
+ * and `<FormFill>` are built on.
21
+ *
22
+ * `retry: false`: the refusals here are VERDICTS, not blips
23
+ * (`error.404.forms_not_found`, `error.410.forms_closed`), and retrying a 404
24
+ * three times only delays the moment the skin can say which one it was. A
25
+ * genuine outage is retried by the person, through the bag's `refetch`.
26
+ */
27
+ export declare function usePublicForm(publicId: string): UseQueryResult<PublicForm, StapelApiError>;
28
+ /**
29
+ * The field kinds a form may be built from, with their config forms.
30
+ * `forms.manage`.
31
+ *
32
+ * `staleTime: Infinity`: a deployment's registered feature types change when
33
+ * somebody deploys, not while an admin edits a form, so refetching this on
34
+ * every window focus would be pure noise behind the builder.
35
+ */
36
+ export declare function useFieldKinds(workspaceId: string): UseQueryResult<FieldKindCatalogue, StapelApiError>;
37
+ /** The workspace's forms, optionally filtered by state. `forms.view`. */
38
+ export declare function useForms(workspaceId: string, state?: FormState): UseQueryResult<readonly FormRow[], StapelApiError>;
39
+ /** One form, as its workspace's admins see it. `forms.view`. */
40
+ export declare function useForm(workspaceId: string, formId: string): UseQueryResult<FormRow, StapelApiError>;
41
+ /**
42
+ * Every published version of a form. `forms.view`.
43
+ *
44
+ * This is what makes per-version column sets possible in `<ResponsesTable>`:
45
+ * a submission records WHICH schema it answered, so the reviewer's columns
46
+ * come from that version rather than from today's fields.
47
+ */
48
+ export declare function useFormVersions(workspaceId: string, formId: string): UseQueryResult<readonly FormVersion[], StapelApiError>;
49
+ /**
50
+ * One keyset page of responses. `forms.responses.view`.
51
+ *
52
+ * Keyset, not offset: `before` is the previous page's last `submitted_at`.
53
+ * Each cursor is its own cache entry (see `formsQueryKeys.submissions`), which
54
+ * is what makes paging back instant instead of a re-fetch.
55
+ */
56
+ export declare function useSubmissions(params: SubmissionListParams): UseQueryResult<readonly Submission[], StapelApiError>;
57
+ /** One response in full. `forms.responses.view`. */
58
+ export declare function useSubmission(workspaceId: string, submissionId: string): UseQueryResult<Submission, StapelApiError>;
59
+ //# sourceMappingURL=queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/model/queries.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EACV,kBAAkB,EAClB,OAAO,EACP,SAAS,EACT,WAAW,EACX,UAAU,EACV,UAAU,EACV,oBAAoB,EACrB,MAAM,iBAAiB,CAAC;AAIzB;;;;;;;;;;;;;GAaG;AAEH;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,GACf,cAAc,CAAC,UAAU,EAAE,cAAc,CAAC,CAQ5C;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,GAClB,cAAc,CAAC,kBAAkB,EAAE,cAAc,CAAC,CASpD;AAED,yEAAyE;AACzE,wBAAgB,QAAQ,CACtB,WAAW,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,SAAS,GAChB,cAAc,CAAC,SAAS,OAAO,EAAE,EAAE,cAAc,CAAC,CAQpD;AAED,gEAAgE;AAChE,wBAAgB,OAAO,CACrB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,cAAc,CAAC,OAAO,EAAE,cAAc,CAAC,CAQzC;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,cAAc,CAAC,SAAS,WAAW,EAAE,EAAE,cAAc,CAAC,CAQxD;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,oBAAoB,GAC3B,cAAc,CAAC,SAAS,UAAU,EAAE,EAAE,cAAc,CAAC,CASvD;AAED,oDAAoD;AACpD,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,cAAc,CAAC,UAAU,EAAE,cAAc,CAAC,CAQ5C"}
@@ -0,0 +1,117 @@
1
+ import { useQuery } from "@tanstack/react-query";
2
+ import { useActiveSessionReady } from "@stapel/core";
3
+ import { useFormsApi } from "./context.js";
4
+ import { formsQueryKeys } from "./queryKeys.js";
5
+ /**
6
+ * Read hooks over the forms API (frontend-standard §2 — read hooks). Keys are
7
+ * namespaced (see `formsQueryKeys`).
8
+ *
9
+ * SESSION GATING, and the one hook that is deliberately NOT gated. Every
10
+ * ADMIN read is gated on {@link useActiveSessionReady} (owner-diagnosed live
11
+ * incident, 2026-07-17): a list hook with no natural `enabled` condition is
12
+ * exactly the shape that raced a still-bootstrapping session.
13
+ * {@link usePublicForm} is the documented exception core's own doc comment
14
+ * carves out ("or be unconditionally safe pre-session, e.g. a public GET"):
15
+ * the endpoint is anonymous, and gating it would make an embedded form on a
16
+ * marketing page wait for a login bootstrap it has no stake in — a form that
17
+ * renders late for a visitor who will never sign in.
18
+ */
19
+ /**
20
+ * The active schema behind a public link — the anonymous read `<StapelForm>`
21
+ * and `<FormFill>` are built on.
22
+ *
23
+ * `retry: false`: the refusals here are VERDICTS, not blips
24
+ * (`error.404.forms_not_found`, `error.410.forms_closed`), and retrying a 404
25
+ * three times only delays the moment the skin can say which one it was. A
26
+ * genuine outage is retried by the person, through the bag's `refetch`.
27
+ */
28
+ export function usePublicForm(publicId) {
29
+ const api = useFormsApi();
30
+ return useQuery({
31
+ queryKey: formsQueryKeys.publicForm(publicId),
32
+ queryFn: () => api.getPublicForm(publicId),
33
+ enabled: publicId.length > 0,
34
+ retry: false,
35
+ });
36
+ }
37
+ /**
38
+ * The field kinds a form may be built from, with their config forms.
39
+ * `forms.manage`.
40
+ *
41
+ * `staleTime: Infinity`: a deployment's registered feature types change when
42
+ * somebody deploys, not while an admin edits a form, so refetching this on
43
+ * every window focus would be pure noise behind the builder.
44
+ */
45
+ export function useFieldKinds(workspaceId) {
46
+ const api = useFormsApi();
47
+ const sessionReady = useActiveSessionReady();
48
+ return useQuery({
49
+ queryKey: formsQueryKeys.fieldKinds(workspaceId),
50
+ queryFn: () => api.listFieldKinds(workspaceId),
51
+ enabled: sessionReady && workspaceId.length > 0,
52
+ staleTime: Number.POSITIVE_INFINITY,
53
+ });
54
+ }
55
+ /** The workspace's forms, optionally filtered by state. `forms.view`. */
56
+ export function useForms(workspaceId, state) {
57
+ const api = useFormsApi();
58
+ const sessionReady = useActiveSessionReady();
59
+ return useQuery({
60
+ queryKey: formsQueryKeys.forms(workspaceId, state),
61
+ queryFn: () => api.listForms(workspaceId, state),
62
+ enabled: sessionReady && workspaceId.length > 0,
63
+ });
64
+ }
65
+ /** One form, as its workspace's admins see it. `forms.view`. */
66
+ export function useForm(workspaceId, formId) {
67
+ const api = useFormsApi();
68
+ const sessionReady = useActiveSessionReady();
69
+ return useQuery({
70
+ queryKey: formsQueryKeys.form(workspaceId, formId),
71
+ queryFn: () => api.getForm(workspaceId, formId),
72
+ enabled: sessionReady && workspaceId.length > 0 && formId.length > 0,
73
+ });
74
+ }
75
+ /**
76
+ * Every published version of a form. `forms.view`.
77
+ *
78
+ * This is what makes per-version column sets possible in `<ResponsesTable>`:
79
+ * a submission records WHICH schema it answered, so the reviewer's columns
80
+ * come from that version rather than from today's fields.
81
+ */
82
+ export function useFormVersions(workspaceId, formId) {
83
+ const api = useFormsApi();
84
+ const sessionReady = useActiveSessionReady();
85
+ return useQuery({
86
+ queryKey: formsQueryKeys.versions(workspaceId, formId),
87
+ queryFn: () => api.listVersions(workspaceId, formId),
88
+ enabled: sessionReady && workspaceId.length > 0 && formId.length > 0,
89
+ });
90
+ }
91
+ /**
92
+ * One keyset page of responses. `forms.responses.view`.
93
+ *
94
+ * Keyset, not offset: `before` is the previous page's last `submitted_at`.
95
+ * Each cursor is its own cache entry (see `formsQueryKeys.submissions`), which
96
+ * is what makes paging back instant instead of a re-fetch.
97
+ */
98
+ export function useSubmissions(params) {
99
+ const api = useFormsApi();
100
+ const sessionReady = useActiveSessionReady();
101
+ return useQuery({
102
+ queryKey: formsQueryKeys.submissions(params),
103
+ queryFn: () => api.listSubmissions(params),
104
+ enabled: sessionReady && params.workspaceId.length > 0 && params.formId.length > 0,
105
+ });
106
+ }
107
+ /** One response in full. `forms.responses.view`. */
108
+ export function useSubmission(workspaceId, submissionId) {
109
+ const api = useFormsApi();
110
+ const sessionReady = useActiveSessionReady();
111
+ return useQuery({
112
+ queryKey: formsQueryKeys.submission(workspaceId, submissionId),
113
+ queryFn: () => api.getSubmission(workspaceId, submissionId),
114
+ enabled: sessionReady && workspaceId.length > 0 && submissionId.length > 0,
115
+ });
116
+ }
117
+ //# sourceMappingURL=queries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/model/queries.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Namespaced TanStack Query keys (frontend-standard §2 — namespaced keys).
3
+ * Everything under the `"forms"` root so a host can invalidate the whole
4
+ * module or match a single resource. Explicit tuple return types satisfy
5
+ * `--isolatedDeclarations`. One entry per read-operation.
6
+ *
7
+ * Invalidation shape: a schema-shifting mutation (draft, publish, rotate-link)
8
+ * invalidates the form AND its public read — the public key is keyed by
9
+ * `public_id`, which `rotateLink` changes, so the root is invalidated instead
10
+ * of a stale id. A response mutation (delete, resend) invalidates the
11
+ * submission list, and delete also the form (its `submission_count` moved).
12
+ */
13
+ import type { SubmissionListParams } from "../api/types.js";
14
+ export declare const formsQueryKeys: {
15
+ readonly all: readonly ["forms"];
16
+ /** The anonymous schema read, keyed by the public token — NOT by the row
17
+ * id, which an anonymous respondent never learns. */
18
+ publicForm(publicId: string): readonly ["forms", "public", string];
19
+ /** The builder's field-kind catalogue. Workspace-scoped because the
20
+ * endpoint is — a deployment's registered types are not global knowledge. */
21
+ fieldKinds(workspaceId: string): readonly ["forms", "field-kinds", string];
22
+ forms(workspaceId: string, state?: string): readonly ["forms", "list", string, string | null];
23
+ form(workspaceId: string, formId: string): readonly ["forms", "form", string, string];
24
+ versions(workspaceId: string, formId: string): readonly ["forms", "versions", string, string];
25
+ submissions(params: SubmissionListParams): readonly ["forms", "submissions", SubmissionListParams];
26
+ submission(workspaceId: string, submissionId: string): readonly ["forms", "submission", string, string];
27
+ };
28
+ //# sourceMappingURL=queryKeys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryKeys.d.ts","sourceRoot":"","sources":["../../src/model/queryKeys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAI5D,eAAO,MAAM,cAAc,EAAE;IAC3B,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IACjC;yDACqD;IACrD,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACnE;iFAC6E;IAC7E,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;IAC3E,KAAK,CACH,WAAW,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,MAAM,GACb,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IACrD,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACtF,QAAQ,CACN,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,WAAW,CACT,MAAM,EAAE,oBAAoB,GAC3B,SAAS,CAAC,OAAO,EAAE,aAAa,EAAE,oBAAoB,CAAC,CAAC;IAC3D,UAAU,CACR,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,SAAS,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CAqBrD,CAAC"}
@@ -0,0 +1,23 @@
1
+ const ROOT = "forms";
2
+ export const formsQueryKeys = {
3
+ all: [ROOT],
4
+ publicForm: (publicId) => [ROOT, "public", publicId],
5
+ fieldKinds: (workspaceId) => [ROOT, "field-kinds", workspaceId],
6
+ // `state` is part of the key (a filtered list is a different read surface,
7
+ // not the same list) and normalized to `null` so an absent filter and an
8
+ // explicit `undefined` cannot cache twice.
9
+ forms: (workspaceId, state) => [ROOT, "list", workspaceId, state ?? null],
10
+ form: (workspaceId, formId) => [ROOT, "form", workspaceId, formId],
11
+ versions: (workspaceId, formId) => [ROOT, "versions", workspaceId, formId],
12
+ // The params object rides the key: a version filter and a page size are
13
+ // distinct reads. `before` is deliberately included — keyset pages are
14
+ // cached per cursor, which is what makes "back" instant.
15
+ submissions: (params) => [ROOT, "submissions", params],
16
+ submission: (workspaceId, submissionId) => [
17
+ ROOT,
18
+ "submission",
19
+ workspaceId,
20
+ submissionId,
21
+ ],
22
+ };
23
+ //# sourceMappingURL=queryKeys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryKeys.js","sourceRoot":"","sources":["../../src/model/queryKeys.ts"],"names":[],"mappings":"AAcA,MAAM,IAAI,GAAG,OAAgB,CAAC;AAE9B,MAAM,CAAC,MAAM,cAAc,GAwBvB;IACF,GAAG,EAAE,CAAC,IAAI,CAAC;IACX,UAAU,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC;IACpD,UAAU,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,aAAa,EAAE,WAAW,CAAC;IAC/D,2EAA2E;IAC3E,yEAAyE;IACzE,2CAA2C;IAC3C,KAAK,EAAE,CAAC,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,IAAI,IAAI,CAAC;IACzE,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC;IAClE,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,CAAC;IAC1E,wEAAwE;IACxE,uEAAuE;IACvE,yDAAyD;IACzD,WAAW,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,CAAC;IACtD,UAAU,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,EAAE,CAAC;QACzC,IAAI;QACJ,YAAY;QACZ,WAAW;QACX,YAAY;KACb;CACF,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { CreateModuleRuntimeOptions, ModuleRuntime } from "@stapel/core";
2
+ import type { FormsApi } from "../api/formsApi.js";
3
+ /**
4
+ * The wired forms runtime — core's `ModuleRuntime` bound to this pair's API
5
+ * (slim wave §21/S2: the plumbing lives once in `@stapel/core`'s
6
+ * `createModuleRuntime`/`createModuleContext`; this module only binds the
7
+ * module-prefixed names). The returned `client` is what the host injects into
8
+ * core's `StapelConfigProvider` (as the default or the `"forms"` module
9
+ * client), preserving the client-injection fork seam (frontend-standard §7.2).
10
+ *
11
+ * ANONYMOUS EMBED. The two public routes need no session, so a render-only
12
+ * host page can build this runtime and nothing else:
13
+ *
14
+ * ```tsx
15
+ * const runtime = createFormsRuntime({ baseUrl: "/forms/api/v1/" });
16
+ * <FormsProvider runtime={runtime}><StapelForm publicId="k3J…x9" /></FormsProvider>
17
+ * ```
18
+ *
19
+ * Auth token/refresh and the verification-403 seam are supplied by the host's
20
+ * auth runtime on the shared client when the ADMIN surface is in use — this
21
+ * pair does not re-implement them. The runtime's fetch/credentials/
22
+ * defaultHeaders are ALSO forwarded to the pair's raw CSV surface
23
+ * (`api/export.ts`), which cannot ride the JSON client.
24
+ */
25
+ export type FormsRuntime = ModuleRuntime<FormsApi>;
26
+ export type CreateFormsRuntimeOptions = CreateModuleRuntimeOptions;
27
+ export declare function createFormsRuntime(options: CreateFormsRuntimeOptions): FormsRuntime;
28
+ //# sourceMappingURL=runtime.d.ts.map