+
+
+ updateForm((current) => ({ ...current, title: title || undefined }))
+ }
+ className={classes.inlineTitle}
+ ariaLabel={t("Form title")}
+ placeholder={pageTitle?.trim() || t("Untitled form")}
+ maxLength={300}
+ singleLine
+ />
+
+ updateForm((current) => ({
+ ...current,
+ description: description || undefined,
+ }))
+ }
+ className={classes.inlineDescription}
+ ariaLabel={t("Form description")}
+ placeholder={t("Add a description")}
+ maxLength={5000}
+ />
+
+
+ {visibleFields.length === 0 ? (
+
+ {t("Add your first question")}
+
+ {t(
+ "Each question fills a property of this base, and every response becomes a new row.",
+ )}
+
+ {addQuestion}
+
+ ) : (
+
+ {visibleFields.map((field, index) => (
+ handleChange(field.propertyId, patch)}
+ onRemove={() => handleRemove(field.propertyId)}
+ onMove={(offset) => handleMove(field.propertyId, offset)}
+ onReorder={handleReorder}
+ />
+ ))}
+
+ )}
+
+
+ {visibleFields.length > 0 && addQuestion}
+
+
+
+
+
+ );
+}
diff --git a/apps/client/src/ee/base/components/form/form-definition.ts b/apps/client/src/ee/base/components/form/form-definition.ts
new file mode 100644
index 000000000..d7225fad1
--- /dev/null
+++ b/apps/client/src/ee/base/components/form/form-definition.ts
@@ -0,0 +1,357 @@
+import type { TFunction } from "i18next";
+import {
+ BasePropertyType,
+ FormConfig,
+ FormFieldConfig,
+ FormFieldError,
+ FormFieldType,
+ IBaseProperty,
+ NumberTypeOptions,
+ PersonTypeOptions,
+ PublicForm,
+ PublicFormChoice,
+ PublicFormField,
+ SelectTypeOptions,
+} from "@/ee/base/types/base.types";
+
+export type FormAnswers = Record