@carlonicora/nextjs-jsonapi 6.17.0 → 6.18.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 (33) hide show
  1. package/dist/{BlockNoteEditor-FAUTV5FW.js → BlockNoteEditor-HHTAZKRO.js} +9 -9
  2. package/dist/{BlockNoteEditor-FAUTV5FW.js.map → BlockNoteEditor-HHTAZKRO.js.map} +1 -1
  3. package/dist/{BlockNoteEditor-IGUHTERQ.mjs → BlockNoteEditor-KSOVYIOL.mjs} +2 -2
  4. package/dist/billing/index.js +378 -378
  5. package/dist/billing/index.mjs +1 -1
  6. package/dist/{chunk-4OCBNCKH.js → chunk-B6WMZXRY.js} +18 -3
  7. package/dist/chunk-B6WMZXRY.js.map +1 -0
  8. package/dist/{chunk-RINMQQZH.mjs → chunk-MBLF236G.mjs} +18 -3
  9. package/dist/chunk-MBLF236G.mjs.map +1 -0
  10. package/dist/client/index.js +2 -2
  11. package/dist/client/index.mjs +1 -1
  12. package/dist/components/index.d.mts +6 -1
  13. package/dist/components/index.d.ts +6 -1
  14. package/dist/components/index.js +2 -2
  15. package/dist/components/index.mjs +1 -1
  16. package/dist/contexts/index.js +2 -2
  17. package/dist/contexts/index.mjs +1 -1
  18. package/dist/email-automations/index.js +78 -78
  19. package/dist/email-automations/index.mjs +1 -1
  20. package/dist/features/analytics/index.js +96 -96
  21. package/dist/features/analytics/index.mjs +1 -1
  22. package/dist/features/blog/index.js +93 -93
  23. package/dist/features/blog/index.mjs +1 -1
  24. package/dist/features/help/index.js +31 -31
  25. package/dist/features/help/index.mjs +1 -1
  26. package/dist/features/tokenusage/index.js +102 -102
  27. package/dist/features/tokenusage/index.mjs +1 -1
  28. package/package.json +1 -1
  29. package/src/components/forms/EditorSheet.tsx +21 -1
  30. package/src/components/forms/__tests__/EditorSheet.spec.tsx +40 -1
  31. package/dist/chunk-4OCBNCKH.js.map +0 -1
  32. package/dist/chunk-RINMQQZH.mjs.map +0 -1
  33. /package/dist/{BlockNoteEditor-IGUHTERQ.mjs.map → BlockNoteEditor-KSOVYIOL.mjs.map} +0 -0
@@ -88,6 +88,11 @@ const sizeClasses: Record<EditorSheetSize, string> = {
88
88
  export type EditorSheetProps<T extends FieldValues> = {
89
89
  form: UseFormReturn<T>;
90
90
  onSubmit: (values: T) => Promise<{ id: string } | void>;
91
+ /** Runs after validation and before `onSubmit`. Return `false` (or a promise
92
+ * resolving to `false`) to abort the submit: `onSubmit` is not called and the
93
+ * sheet stays open with the form unchanged. Use it for a last confirmation
94
+ * (e.g. "this information will be deleted") that must not close the sheet. */
95
+ onBeforeSubmit?: (values: T) => Promise<boolean> | boolean;
91
96
  onReset: () => T;
92
97
  isFormDirty?: () => boolean;
93
98
 
@@ -144,6 +149,7 @@ export type EditorSheetProps<T extends FieldValues> = {
144
149
  export function EditorSheet<T extends FieldValues>({
145
150
  form,
146
151
  onSubmit,
152
+ onBeforeSubmit,
147
153
  onReset,
148
154
  isFormDirty: isFormDirtyProp,
149
155
  entityType,
@@ -222,6 +228,7 @@ export function EditorSheet<T extends FieldValues>({
222
228
  const wrappedOnSubmit = useCallback(
223
229
  async (values: T) => {
224
230
  try {
231
+ if (onBeforeSubmit && !(await onBeforeSubmit(values))) return;
225
232
  const result = await onSubmit(values);
226
233
  setOpen(false);
227
234
  if (result && onSaved) {
@@ -249,7 +256,20 @@ export function EditorSheet<T extends FieldValues>({
249
256
  });
250
257
  }
251
258
  },
252
- [onSubmit, setOpen, onSuccess, onSaved, onRevalidate, onNavigate, generateUrl, module, isEdit, propagateChanges, t],
259
+ [
260
+ onSubmit,
261
+ onBeforeSubmit,
262
+ setOpen,
263
+ onSuccess,
264
+ onSaved,
265
+ onRevalidate,
266
+ onNavigate,
267
+ generateUrl,
268
+ module,
269
+ isEdit,
270
+ propagateChanges,
271
+ t,
272
+ ],
253
273
  );
254
274
 
255
275
  const headerTitle =
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect, vi, beforeEach } from "vitest";
2
- import { act, render, screen } from "@testing-library/react";
2
+ import { act, render, screen, waitFor } from "@testing-library/react";
3
3
  import { Activity } from "react";
4
4
  import userEvent from "@testing-library/user-event";
5
5
  import { useForm } from "react-hook-form";
@@ -234,6 +234,45 @@ describe("EditorSheet", () => {
234
234
  });
235
235
  });
236
236
 
237
+ describe("onBeforeSubmit", () => {
238
+ it("does not call onSubmit and keeps the sheet open when it returns false", async () => {
239
+ const onSubmit = vi.fn().mockResolvedValue({ id: "abc" });
240
+ const onBeforeSubmit = vi.fn().mockResolvedValue(false);
241
+ render(<TestEditor onSubmit={onSubmit} onBeforeSubmit={onBeforeSubmit} />);
242
+
243
+ await userEvent.click(screen.getByText("ui.buttons.create"));
244
+ await userEvent.type(screen.getByTestId("name-input"), "Test Name");
245
+ await userEvent.click(screen.getByTestId("modal-button-create"));
246
+
247
+ expect(onBeforeSubmit).toHaveBeenCalledWith(expect.objectContaining({ name: "Test Name" }));
248
+ expect(onSubmit).not.toHaveBeenCalled();
249
+ expect(screen.getByTestId("name-input")).toHaveValue("Test Name");
250
+ });
251
+
252
+ it("calls onSubmit and closes the sheet when it returns true", async () => {
253
+ const onSubmit = vi.fn().mockResolvedValue({ id: "abc" });
254
+ const onBeforeSubmit = vi.fn().mockReturnValue(true);
255
+ render(<TestEditor onSubmit={onSubmit} onBeforeSubmit={onBeforeSubmit} />);
256
+
257
+ await userEvent.click(screen.getByText("ui.buttons.create"));
258
+ await userEvent.type(screen.getByTestId("name-input"), "Test Name");
259
+ await userEvent.click(screen.getByTestId("modal-button-create"));
260
+
261
+ expect(onBeforeSubmit).toHaveBeenCalledTimes(1);
262
+ expect(onSubmit).toHaveBeenCalledWith(expect.objectContaining({ name: "Test Name" }));
263
+ await waitFor(() => expect(screen.queryByTestId("name-input")).toBeNull());
264
+ });
265
+
266
+ it("is not called when validation fails", async () => {
267
+ const onBeforeSubmit = vi.fn().mockReturnValue(true);
268
+ render(<TestEditor dialogOpen={true} onBeforeSubmit={onBeforeSubmit} />);
269
+
270
+ await userEvent.click(screen.getByTestId("modal-button-create"));
271
+
272
+ expect(onBeforeSubmit).not.toHaveBeenCalled();
273
+ });
274
+ });
275
+
237
276
  describe("onSaved callback", () => {
238
277
  it("calls onSaved on create (no isEdit gate)", async () => {
239
278
  const onSaved = vi.fn();