diff --git a/apps/web/.source/browser.ts b/apps/web/.source/browser.ts index d240fbb..244cffc 100644 --- a/apps/web/.source/browser.ts +++ b/apps/web/.source/browser.ts @@ -7,6 +7,6 @@ const create = browser(); const browserCollections = { - docs: create.doc("docs", {"conditional-logic.mdx": () => import("../content/docs/conditional-logic.mdx?collection=docs"), "configuration.mdx": () => import("../content/docs/configuration.mdx?collection=docs"), "custom-rendering.mdx": () => import("../content/docs/custom-rendering.mdx?collection=docs"), "form-component.mdx": () => import("../content/docs/form-component.mdx?collection=docs"), "index.mdx": () => import("../content/docs/index.mdx?collection=docs"), "installation.mdx": () => import("../content/docs/installation.mdx?collection=docs"), "quick-start.mdx": () => import("../content/docs/quick-start.mdx?collection=docs"), "schema.mdx": () => import("../content/docs/schema.mdx?collection=docs"), "validation.mdx": () => import("../content/docs/validation.mdx?collection=docs"), "your-first-form.mdx": () => import("../content/docs/your-first-form.mdx?collection=docs"), "fields/types.mdx": () => import("../content/docs/fields/types.mdx?collection=docs"), "fields/data/checkbox.mdx": () => import("../content/docs/fields/data/checkbox.mdx?collection=docs"), "fields/data/date.mdx": () => import("../content/docs/fields/data/date.mdx?collection=docs"), "fields/data/number.mdx": () => import("../content/docs/fields/data/number.mdx?collection=docs"), "fields/data/password.mdx": () => import("../content/docs/fields/data/password.mdx?collection=docs"), "fields/data/radio.mdx": () => import("../content/docs/fields/data/radio.mdx?collection=docs"), "fields/data/select.mdx": () => import("../content/docs/fields/data/select.mdx?collection=docs"), "fields/data/switch.mdx": () => import("../content/docs/fields/data/switch.mdx?collection=docs"), "fields/data/tags.mdx": () => import("../content/docs/fields/data/tags.mdx?collection=docs"), "fields/data/text.mdx": () => import("../content/docs/fields/data/text.mdx?collection=docs"), "fields/data/textarea.mdx": () => import("../content/docs/fields/data/textarea.mdx?collection=docs"), "fields/data/upload.mdx": () => import("../content/docs/fields/data/upload.mdx?collection=docs"), "fields/layout/array.mdx": () => import("../content/docs/fields/layout/array.mdx?collection=docs"), "fields/layout/collapsible.mdx": () => import("../content/docs/fields/layout/collapsible.mdx?collection=docs"), "fields/layout/group.mdx": () => import("../content/docs/fields/layout/group.mdx?collection=docs"), "fields/layout/row.mdx": () => import("../content/docs/fields/layout/row.mdx?collection=docs"), "fields/layout/tabs.mdx": () => import("../content/docs/fields/layout/tabs.mdx?collection=docs"), }), + docs: create.doc("docs", {"conditional-logic.mdx": () => import("../content/docs/conditional-logic.mdx?collection=docs"), "configuration.mdx": () => import("../content/docs/configuration.mdx?collection=docs"), "custom-rendering.mdx": () => import("../content/docs/custom-rendering.mdx?collection=docs"), "form-component.mdx": () => import("../content/docs/form-component.mdx?collection=docs"), "index.mdx": () => import("../content/docs/index.mdx?collection=docs"), "installation.mdx": () => import("../content/docs/installation.mdx?collection=docs"), "quick-start.mdx": () => import("../content/docs/quick-start.mdx?collection=docs"), "schema.mdx": () => import("../content/docs/schema.mdx?collection=docs"), "validation.mdx": () => import("../content/docs/validation.mdx?collection=docs"), "your-first-form.mdx": () => import("../content/docs/your-first-form.mdx?collection=docs"), "fields/types.mdx": () => import("../content/docs/fields/types.mdx?collection=docs"), "fields/layout/array.mdx": () => import("../content/docs/fields/layout/array.mdx?collection=docs"), "fields/layout/collapsible.mdx": () => import("../content/docs/fields/layout/collapsible.mdx?collection=docs"), "fields/layout/group.mdx": () => import("../content/docs/fields/layout/group.mdx?collection=docs"), "fields/layout/row.mdx": () => import("../content/docs/fields/layout/row.mdx?collection=docs"), "fields/layout/tabs.mdx": () => import("../content/docs/fields/layout/tabs.mdx?collection=docs"), "fields/data/checkbox.mdx": () => import("../content/docs/fields/data/checkbox.mdx?collection=docs"), "fields/data/date.mdx": () => import("../content/docs/fields/data/date.mdx?collection=docs"), "fields/data/number.mdx": () => import("../content/docs/fields/data/number.mdx?collection=docs"), "fields/data/password.mdx": () => import("../content/docs/fields/data/password.mdx?collection=docs"), "fields/data/radio.mdx": () => import("../content/docs/fields/data/radio.mdx?collection=docs"), "fields/data/select.mdx": () => import("../content/docs/fields/data/select.mdx?collection=docs"), "fields/data/switch.mdx": () => import("../content/docs/fields/data/switch.mdx?collection=docs"), "fields/data/tags.mdx": () => import("../content/docs/fields/data/tags.mdx?collection=docs"), "fields/data/text.mdx": () => import("../content/docs/fields/data/text.mdx?collection=docs"), "fields/data/textarea.mdx": () => import("../content/docs/fields/data/textarea.mdx?collection=docs"), "fields/data/upload.mdx": () => import("../content/docs/fields/data/upload.mdx?collection=docs"), }), }; export default browserCollections; \ No newline at end of file diff --git a/apps/web/.source/server.ts b/apps/web/.source/server.ts index 61a3044..45c6b33 100644 --- a/apps/web/.source/server.ts +++ b/apps/web/.source/server.ts @@ -1,20 +1,20 @@ // @ts-nocheck -import * as __fd_glob_30 from "../content/docs/fields/layout/tabs.mdx?collection=docs" -import * as __fd_glob_29 from "../content/docs/fields/layout/row.mdx?collection=docs" -import * as __fd_glob_28 from "../content/docs/fields/layout/group.mdx?collection=docs" -import * as __fd_glob_27 from "../content/docs/fields/layout/collapsible.mdx?collection=docs" -import * as __fd_glob_26 from "../content/docs/fields/layout/array.mdx?collection=docs" -import * as __fd_glob_25 from "../content/docs/fields/data/upload.mdx?collection=docs" -import * as __fd_glob_24 from "../content/docs/fields/data/textarea.mdx?collection=docs" -import * as __fd_glob_23 from "../content/docs/fields/data/text.mdx?collection=docs" -import * as __fd_glob_22 from "../content/docs/fields/data/tags.mdx?collection=docs" -import * as __fd_glob_21 from "../content/docs/fields/data/switch.mdx?collection=docs" -import * as __fd_glob_20 from "../content/docs/fields/data/select.mdx?collection=docs" -import * as __fd_glob_19 from "../content/docs/fields/data/radio.mdx?collection=docs" -import * as __fd_glob_18 from "../content/docs/fields/data/password.mdx?collection=docs" -import * as __fd_glob_17 from "../content/docs/fields/data/number.mdx?collection=docs" -import * as __fd_glob_16 from "../content/docs/fields/data/date.mdx?collection=docs" -import * as __fd_glob_15 from "../content/docs/fields/data/checkbox.mdx?collection=docs" +import * as __fd_glob_30 from "../content/docs/fields/data/upload.mdx?collection=docs" +import * as __fd_glob_29 from "../content/docs/fields/data/textarea.mdx?collection=docs" +import * as __fd_glob_28 from "../content/docs/fields/data/text.mdx?collection=docs" +import * as __fd_glob_27 from "../content/docs/fields/data/tags.mdx?collection=docs" +import * as __fd_glob_26 from "../content/docs/fields/data/switch.mdx?collection=docs" +import * as __fd_glob_25 from "../content/docs/fields/data/select.mdx?collection=docs" +import * as __fd_glob_24 from "../content/docs/fields/data/radio.mdx?collection=docs" +import * as __fd_glob_23 from "../content/docs/fields/data/password.mdx?collection=docs" +import * as __fd_glob_22 from "../content/docs/fields/data/number.mdx?collection=docs" +import * as __fd_glob_21 from "../content/docs/fields/data/date.mdx?collection=docs" +import * as __fd_glob_20 from "../content/docs/fields/data/checkbox.mdx?collection=docs" +import * as __fd_glob_19 from "../content/docs/fields/layout/tabs.mdx?collection=docs" +import * as __fd_glob_18 from "../content/docs/fields/layout/row.mdx?collection=docs" +import * as __fd_glob_17 from "../content/docs/fields/layout/group.mdx?collection=docs" +import * as __fd_glob_16 from "../content/docs/fields/layout/collapsible.mdx?collection=docs" +import * as __fd_glob_15 from "../content/docs/fields/layout/array.mdx?collection=docs" import * as __fd_glob_14 from "../content/docs/fields/types.mdx?collection=docs" import * as __fd_glob_13 from "../content/docs/your-first-form.mdx?collection=docs" import * as __fd_glob_12 from "../content/docs/validation.mdx?collection=docs" @@ -26,8 +26,8 @@ import * as __fd_glob_7 from "../content/docs/form-component.mdx?collection=docs import * as __fd_glob_6 from "../content/docs/custom-rendering.mdx?collection=docs" import * as __fd_glob_5 from "../content/docs/configuration.mdx?collection=docs" import * as __fd_glob_4 from "../content/docs/conditional-logic.mdx?collection=docs" -import { default as __fd_glob_3 } from "../content/docs/fields/data/meta.json?collection=docs" -import { default as __fd_glob_2 } from "../content/docs/fields/layout/meta.json?collection=docs" +import { default as __fd_glob_3 } from "../content/docs/fields/layout/meta.json?collection=docs" +import { default as __fd_glob_2 } from "../content/docs/fields/data/meta.json?collection=docs" import { default as __fd_glob_1 } from "../content/docs/fields/meta.json?collection=docs" import { default as __fd_glob_0 } from "../content/docs/meta.json?collection=docs" import { server } from 'fumadocs-mdx/runtime/server'; @@ -38,4 +38,4 @@ const create = server({"doc":{"passthroughs":["extractedReferences"]}}); -export const docs = await create.docs("docs", "content/docs", {"meta.json": __fd_glob_0, "fields/meta.json": __fd_glob_1, "fields/layout/meta.json": __fd_glob_2, "fields/data/meta.json": __fd_glob_3, }, {"conditional-logic.mdx": __fd_glob_4, "configuration.mdx": __fd_glob_5, "custom-rendering.mdx": __fd_glob_6, "form-component.mdx": __fd_glob_7, "index.mdx": __fd_glob_8, "installation.mdx": __fd_glob_9, "quick-start.mdx": __fd_glob_10, "schema.mdx": __fd_glob_11, "validation.mdx": __fd_glob_12, "your-first-form.mdx": __fd_glob_13, "fields/types.mdx": __fd_glob_14, "fields/data/checkbox.mdx": __fd_glob_15, "fields/data/date.mdx": __fd_glob_16, "fields/data/number.mdx": __fd_glob_17, "fields/data/password.mdx": __fd_glob_18, "fields/data/radio.mdx": __fd_glob_19, "fields/data/select.mdx": __fd_glob_20, "fields/data/switch.mdx": __fd_glob_21, "fields/data/tags.mdx": __fd_glob_22, "fields/data/text.mdx": __fd_glob_23, "fields/data/textarea.mdx": __fd_glob_24, "fields/data/upload.mdx": __fd_glob_25, "fields/layout/array.mdx": __fd_glob_26, "fields/layout/collapsible.mdx": __fd_glob_27, "fields/layout/group.mdx": __fd_glob_28, "fields/layout/row.mdx": __fd_glob_29, "fields/layout/tabs.mdx": __fd_glob_30, }); \ No newline at end of file +export const docs = await create.docs("docs", "content/docs", {"meta.json": __fd_glob_0, "fields/meta.json": __fd_glob_1, "fields/data/meta.json": __fd_glob_2, "fields/layout/meta.json": __fd_glob_3, }, {"conditional-logic.mdx": __fd_glob_4, "configuration.mdx": __fd_glob_5, "custom-rendering.mdx": __fd_glob_6, "form-component.mdx": __fd_glob_7, "index.mdx": __fd_glob_8, "installation.mdx": __fd_glob_9, "quick-start.mdx": __fd_glob_10, "schema.mdx": __fd_glob_11, "validation.mdx": __fd_glob_12, "your-first-form.mdx": __fd_glob_13, "fields/types.mdx": __fd_glob_14, "fields/layout/array.mdx": __fd_glob_15, "fields/layout/collapsible.mdx": __fd_glob_16, "fields/layout/group.mdx": __fd_glob_17, "fields/layout/row.mdx": __fd_glob_18, "fields/layout/tabs.mdx": __fd_glob_19, "fields/data/checkbox.mdx": __fd_glob_20, "fields/data/date.mdx": __fd_glob_21, "fields/data/number.mdx": __fd_glob_22, "fields/data/password.mdx": __fd_glob_23, "fields/data/radio.mdx": __fd_glob_24, "fields/data/select.mdx": __fd_glob_25, "fields/data/switch.mdx": __fd_glob_26, "fields/data/tags.mdx": __fd_glob_27, "fields/data/text.mdx": __fd_glob_28, "fields/data/textarea.mdx": __fd_glob_29, "fields/data/upload.mdx": __fd_glob_30, }); \ No newline at end of file diff --git a/apps/web/app/(builder)/components/properties/default-value-select.tsx b/apps/web/app/(builder)/components/properties/default-value-select.tsx new file mode 100644 index 0000000..8727595 --- /dev/null +++ b/apps/web/app/(builder)/components/properties/default-value-select.tsx @@ -0,0 +1,64 @@ +"use client"; + +import type { + Field, + FieldComponentProps, + SelectField as SelectFieldType, +} from "@buildnbuzz/buzzform"; +import { getNestedValue } from "@buildnbuzz/buzzform"; +import { SelectField } from "@/components/buzzform/fields/select"; + +function getSiblingData( + formValues: Record, + path: string, +): Record { + const pathParts = path.split("."); + const parentParts = pathParts.slice(0, -1); + if (parentParts.length === 0) return formValues; + const parent = getNestedValue(formValues, parentParts.join(".")); + return (parent as Record) ?? formValues; +} + +export function DefaultValueSelect( + props: FieldComponentProps< + NonNullable, + Field + >, +) { + const { field, path, form, autoFocus, id, disabled, readOnly, error } = props; + + if (field.type !== "select") { + return null; + } + + const hasMany = !!form.watch("hasMany"); + const options = form.watch("options"); + + const selectField: SelectFieldType = { + ...(field as SelectFieldType), + options: Array.isArray(options) ? options : [], + hasMany, + }; + + const formValues = form.getValues() as Record; + const siblingData = getSiblingData(formValues, path); + + const label = + field.label === false ? null : (field.label ?? field.name ?? null); + + return ( + + ); +} diff --git a/apps/web/app/(builder)/components/provider.tsx b/apps/web/app/(builder)/components/provider.tsx index a3494fb..cdff332 100644 --- a/apps/web/app/(builder)/components/provider.tsx +++ b/apps/web/app/(builder)/components/provider.tsx @@ -282,12 +282,13 @@ function DragOverlayItem({ id }: { id: string }) { return (
{/* Icon container */} @@ -307,13 +308,25 @@ function DragOverlayItem({ id }: { id: string }) {
{isFromSidebar ? `New ${label}` : (fieldName ?? label)}
-
+
- {isFromSidebar ? "Adding new field" : "Moving field"} + + {isFromSidebar + ? ( + <> + Adding new field, press + + Esc + + to cancel + + ) + : "Moving field"} +
diff --git a/apps/web/app/(builder)/lib/properties.ts b/apps/web/app/(builder)/lib/properties.ts index dcb3a61..262bee4 100644 --- a/apps/web/app/(builder)/lib/properties.ts +++ b/apps/web/app/(builder)/lib/properties.ts @@ -112,6 +112,45 @@ export function sanitizeFieldConstraints>(fiel return result; } +/** + * Ensure defaultValue stays in sync with options for option-based fields. + * Clears invalid defaults when options are removed/changed. + */ +export function sanitizeFieldDefaults>(field: T): T { + const options = (field as Record).options; + if (!Array.isArray(options)) return field; + + const optionValues = options + .map((opt) => (typeof opt === "string" ? opt : (opt as { value?: unknown }).value)) + .filter((val) => val !== undefined && val !== null && val !== ""); + + if (optionValues.length === 0) { + if ("defaultValue" in field) { + (field as Record).defaultValue = undefined; + } + return field; + } + + const defaultValue = (field as Record).defaultValue; + if (defaultValue === undefined || defaultValue === null || defaultValue === "") return field; + + if (Array.isArray(defaultValue)) { + const filtered = defaultValue.filter((val) => + optionValues.some((opt) => opt === val), + ); + (field as Record).defaultValue = + filtered.length > 0 ? filtered : undefined; + return field; + } + + const isValid = optionValues.some((opt) => opt === defaultValue); + if (!isValid) { + (field as Record).defaultValue = undefined; + } + + return field; +} + /** * Flattens field props to form values for the properties editor. * Excludes structural props like children, fields, and type. diff --git a/apps/web/app/(builder)/lib/properties/radio.ts b/apps/web/app/(builder)/lib/properties/radio.ts index 2949ecc..8a93443 100644 --- a/apps/web/app/(builder)/lib/properties/radio.ts +++ b/apps/web/app/(builder)/lib/properties/radio.ts @@ -70,6 +70,17 @@ export const radioFieldProperties: Field[] = [ }, ], }, + { + type: "select", + name: "defaultValue", + label: "Default Value", + description: "Preselect an option (optional)", + options: async (context) => + Array.isArray(context?.data?.options) + ? context.data.options + : [], + dependencies: ["options"], + }, { type: "switch", name: "hidden", diff --git a/apps/web/app/(builder)/lib/properties/select.ts b/apps/web/app/(builder)/lib/properties/select.ts index 7999216..250e032 100644 --- a/apps/web/app/(builder)/lib/properties/select.ts +++ b/apps/web/app/(builder)/lib/properties/select.ts @@ -1,4 +1,15 @@ +import { z } from "zod"; import type { Field } from "@buildnbuzz/buzzform"; +import { DefaultValueSelect } from "../../components/properties/default-value-select"; + +const selectDefaultValueSchema = z + .union([ + z.string(), + z.number(), + z.boolean(), + z.array(z.union([z.string(), z.number(), z.boolean()])), + ]) + .optional(); export const selectFieldProperties: Field[] = [ { @@ -75,6 +86,20 @@ export const selectFieldProperties: Field[] = [ }, ], }, + { + type: "select", + name: "defaultValue", + label: "Default Value", + description: "Preselect a value", + component: DefaultValueSelect, + // @ts-expect-error: schema allows undefined but SelectField["defaultValue"] doesn't (will be fixed in package) + schema: selectDefaultValueSchema, + options: async (context) => + Array.isArray(context?.data?.options) + ? context.data.options + : [], + dependencies: ["options"], + }, { type: "switch", name: "hasMany", diff --git a/apps/web/app/(builder)/lib/registry.ts b/apps/web/app/(builder)/lib/registry.ts index 54f8d36..be2b127 100644 --- a/apps/web/app/(builder)/lib/registry.ts +++ b/apps/web/app/(builder)/lib/registry.ts @@ -116,6 +116,7 @@ export const builderFieldRegistry: BuilderFieldRegistry = { defaultProps: { type: 'radio', label: 'Radio', + defaultValue: 'option1', options: [ { label: 'Option 1', value: 'option1' }, { label: 'Option 2', value: 'option2' }, @@ -131,8 +132,10 @@ export const builderFieldRegistry: BuilderFieldRegistry = { }, switch: { kind: 'data', - sidebar: { label: 'Switch', icon: ToggleOnIcon, category: 'selection' }, - defaultProps: { type: 'switch', label: 'Switch' }, + sidebar: { label: 'Switch', icon: ToggleOnIcon, category: 'selection', }, + defaultProps: { + type: 'switch', label: 'Switch', defaultValue: false, + }, properties: switchFieldProperties, }, diff --git a/apps/web/app/(builder)/lib/store.ts b/apps/web/app/(builder)/lib/store.ts index 1d49512..c239a9c 100644 --- a/apps/web/app/(builder)/lib/store.ts +++ b/apps/web/app/(builder)/lib/store.ts @@ -7,6 +7,7 @@ import type { TemporalState } from 'zundo'; import { nanoid } from 'nanoid'; import type { Node, FieldType, Viewport, BuilderMode } from './types'; import { builderFieldRegistry } from './registry'; +import { sanitizeFieldDefaults } from './properties'; type SaveStatus = 'idle' | 'saving' | 'saved'; @@ -152,6 +153,7 @@ export const useBuilderStore = create()( const node = state.nodes[id]; if (node) { mergeUpdates(node.field, updates); + sanitizeFieldDefaults(node.field as unknown as Record); } }); }, diff --git a/apps/web/package.json b/apps/web/package.json index b966d37..976eb2d 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -51,7 +51,7 @@ "tailwind-merge": "^3.4.0", "tw-animate-css": "^1.4.0", "vaul": "^1.1.2", - "zod": "^3.25.0", + "zod": "^4.0.0", "zundo": "^2.3.0", "zustand": "^5.0.10" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0020f00..733a11b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -89,13 +89,13 @@ importers: version: 8.6.0(react@19.2.3) fumadocs-core: specifier: ^16.4.1 - version: 16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.25.76) + version: 16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@4.3.4) fumadocs-mdx: specifier: ^14.2.3 - version: 14.2.3(@types/react@19.2.2)(fumadocs-core@16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.25.76))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3) + version: 14.2.3(@types/react@19.2.2)(fumadocs-core@16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@4.3.4))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3) fumadocs-ui: specifier: ^16.4.1 - version: 16.4.1(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18)(zod@3.25.76) + version: 16.4.1(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18)(zod@4.3.4) immer: specifier: ^11.1.3 version: 11.1.3 @@ -148,8 +148,8 @@ importers: specifier: ^1.1.2 version: 1.1.2(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) zod: - specifier: ^3.25.0 - version: 3.25.76 + specifier: ^4.0.0 + version: 4.3.4 zundo: specifier: ^2.3.0 version: 2.3.0(zustand@5.0.10(@types/react@19.2.2)(immer@11.1.3)(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3))) @@ -5905,9 +5905,9 @@ snapshots: '@formatjs/fast-memoize': 3.0.1 tslib: 2.8.1 - '@fumadocs/ui@16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18)(zod@3.25.76)': + '@fumadocs/ui@16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18)(zod@4.3.4)': dependencies: - fumadocs-core: 16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.25.76) + fumadocs-core: 16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@4.3.4) lodash.merge: 4.6.2 next-themes: 0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) postcss-selector-parser: 7.1.1 @@ -8253,7 +8253,7 @@ snapshots: fsevents@2.3.3: optional: true - fumadocs-core@16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.25.76): + fumadocs-core@16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@4.3.4): dependencies: '@formatjs/intl-localematcher': 0.7.3 '@orama/orama': 3.1.18 @@ -8279,18 +8279,18 @@ snapshots: next: 16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - zod: 3.25.76 + zod: 4.3.4 transitivePeerDependencies: - supports-color - fumadocs-mdx@14.2.3(@types/react@19.2.2)(fumadocs-core@16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.25.76))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3): + fumadocs-mdx@14.2.3(@types/react@19.2.2)(fumadocs-core@16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@4.3.4))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3): dependencies: '@mdx-js/mdx': 3.1.1 '@standard-schema/spec': 1.1.0 chokidar: 5.0.0 esbuild: 0.27.2 estree-util-value-to-estree: 3.5.0 - fumadocs-core: 16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.25.76) + fumadocs-core: 16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@4.3.4) js-yaml: 4.1.1 mdast-util-to-markdown: 2.1.2 picocolors: 1.1.1 @@ -8310,9 +8310,9 @@ snapshots: transitivePeerDependencies: - supports-color - fumadocs-ui@16.4.1(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18)(zod@3.25.76): + fumadocs-ui@16.4.1(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18)(zod@4.3.4): dependencies: - '@fumadocs/ui': 16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18)(zod@3.25.76) + '@fumadocs/ui': 16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tailwindcss@4.1.18)(zod@4.3.4) '@radix-ui/react-accordion': 1.2.12(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -8324,7 +8324,7 @@ snapshots: '@radix-ui/react-slot': 1.2.4(@types/react@19.2.2)(react@19.2.3) '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) class-variance-authority: 0.7.1 - fumadocs-core: 16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.25.76) + fumadocs-core: 16.4.1(@types/react@19.2.2)(lucide-react@0.562.0(react@19.2.3))(next@16.1.1(@babel/core@7.28.6)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@4.3.4) next-themes: 0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) react: 19.2.3 react-dom: 19.2.3(react@19.2.3)