{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "plugin-forms", "title": "Form Yönetimi (Formik + Yup)", "description": "Formik + Yup form altyapısı. TRA UI Kit bileşenlerine bağlı TextField, Select, Checkbox, DatePicker, RadioButtons ve ortak Validations sabitleri.", "dependencies": [ "formik@2.4.9", "yup@1.7.1" ], "registryDependencies": [ "@tra-kit/text-field", "@tra-kit/select", "@tra-kit/checkbox", "@tra-kit/date-picker", "@tra-kit/radio-buttons", "@tra-kit/switch" ], "files": [ { "path": "registry/tra-plugins/forms/components/formik/formik-text-field.tsx", "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport Label from \"@/components/ui/label\";\nimport Input from \"@/components/ui/input\";\nimport { FormikErrorText } from \"./formik-error-text\";\nimport { getNestedValue } from \"./utils\";\n\ninterface FormikTextFieldProps {\n id: string;\n formik: any;\n label?: string;\n placeholder?: string;\n type?: string;\n disabled?: boolean;\n className?: string;\n containerClassName?: string;\n maxLength?: number;\n startIcon?: React.ReactNode;\n endIcon?: React.ReactNode;\n textarea?: boolean;\n showRequiredIcon?: boolean;\n onChange?: (value: string) => void;\n onKeyDown?: (e: React.KeyboardEvent) => void;\n autoFocus?: boolean;\n defaultValue?: string | number;\n}\n\nexport const FormikTextField: React.FC = ({\n id,\n formik,\n label,\n placeholder,\n type = \"text\",\n disabled,\n className,\n containerClassName,\n maxLength,\n startIcon,\n endIcon,\n textarea,\n showRequiredIcon,\n onChange,\n onKeyDown,\n autoFocus,\n defaultValue,\n}) => (\n
\n {label && (\n \n )}\n {\n if (!disabled) {\n formik.setFieldValue(id, e.target.value);\n onChange?.(e.target.value);\n }\n }}\n onBlur={formik.handleBlur}\n type={type}\n placeholder={placeholder}\n disabled={disabled}\n maxLength={maxLength}\n startIcon={startIcon}\n endIcon={endIcon}\n textarea={textarea}\n autoFocus={autoFocus}\n error={Boolean(getNestedValue(formik.touched, id) && getNestedValue(formik.errors, id))}\n className={cn(className)}\n onKeyDown={onKeyDown}\n />\n \n
\n);\n", "type": "registry:file", "target": "src/components/formik/formik-text-field.tsx" }, { "path": "registry/tra-plugins/forms/components/formik/formik-select.tsx", "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport Select from \"@/components/ui/select\";\nimport { FormikErrorText } from \"./formik-error-text\";\nimport { getNestedValue } from \"./utils\";\n\ninterface ISelectOption {\n content: string | React.ReactNode;\n value: number | string | boolean;\n}\n\ninterface FormikSelectProps {\n id: string;\n formik: any;\n label?: string;\n options: ISelectOption[];\n placeholder?: string;\n disabled?: boolean;\n className?: string;\n selectClassName?: string;\n isMulti?: boolean;\n isSearchable?: boolean;\n showRequiredIcon?: boolean;\n onChange?: (value: any) => void;\n onlyParentOnChange?: boolean;\n hideErrorText?: boolean;\n defaultValue?: string | number | string[] | number[];\n}\n\nexport const FormikSelect: React.FC = ({\n id,\n formik,\n label,\n options,\n placeholder = \"Seçiniz...\",\n disabled,\n className,\n selectClassName,\n isMulti = false,\n isSearchable = false,\n showRequiredIcon,\n onChange,\n onlyParentOnChange,\n hideErrorText,\n defaultValue,\n}) => (\n
\n {\n if (onlyParentOnChange) {\n onChange?.(value);\n } else {\n if (!disabled) formik.setFieldValue(id, value);\n onChange?.(value);\n }\n }}\n defaultValue={defaultValue}\n placeholder={placeholder}\n options={options}\n isMulti={isMulti}\n isSearchable={isSearchable}\n disabled={disabled}\n error={Boolean(getNestedValue(formik.touched, id) && getNestedValue(formik.errors, id))}\n className={selectClassName}\n />\n {!hideErrorText && }\n
\n);\n", "type": "registry:file", "target": "src/components/formik/formik-select.tsx" }, { "path": "registry/tra-plugins/forms/components/formik/formik-checkbox.tsx", "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport Checkbox from \"@/components/ui/checkbox\";\nimport { FormikErrorText } from \"./formik-error-text\";\nimport { getNestedValue } from \"./utils\";\n\ninterface FormikCheckboxProps {\n id: string;\n formik: any;\n label?: string;\n disabled?: boolean;\n className?: string;\n containerClassName?: string;\n labelClassName?: string;\n labelSide?: \"left\" | \"right\";\n onChange?: (value: any) => void;\n onlyParentOnChange?: boolean;\n}\n\nexport const FormikCheckbox: React.FC = ({\n id,\n formik,\n label,\n disabled,\n className,\n containerClassName,\n labelClassName,\n labelSide = \"right\",\n onChange,\n onlyParentOnChange,\n}) => (\n
\n {\n onChange?.(checked);\n if (!onlyParentOnChange) {\n formik.setFieldValue(id, checked);\n }\n }}\n disabled={disabled}\n className={cn(\"peer\", className)}\n containerClassName={cn(containerClassName)}\n labelClassName={cn(labelClassName)}\n label={label}\n labelSide={labelSide}\n />\n \n
\n);\n", "type": "registry:file", "target": "src/components/formik/formik-checkbox.tsx" }, { "path": "registry/tra-plugins/forms/components/formik/formik-date-picker.tsx", "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport DatePicker from \"@/components/ui/date-picker\";\nimport Label from \"@/components/ui/label\";\nimport type { DayPickerProps } from \"react-day-picker\";\nimport { FormikErrorText } from \"./formik-error-text\";\nimport { getNestedValue } from \"./utils\";\n\ninterface FormikDatePickerProps {\n id: string;\n formik: any;\n label?: string;\n disabled?: boolean;\n minDate?: Date;\n maxDate?: Date;\n containerClassName?: string;\n mode?: DayPickerProps[\"mode\"];\n showRequiredIcon?: boolean;\n showCompleteButton?: boolean;\n showClearButton?: boolean;\n onBlur?: () => void;\n}\n\nexport const FormikDatePicker: React.FC = ({\n id,\n formik,\n label,\n disabled,\n minDate,\n maxDate,\n containerClassName,\n mode = \"single\",\n showRequiredIcon,\n showCompleteButton,\n showClearButton = false,\n onBlur,\n}) => (\n
\n {label && (\n \n )}\n {\n if (!disabled) {\n if (mode === \"range\") {\n formik.setFieldValue(id, e);\n return;\n }\n const cleanedDate =\n e instanceof Date && !Number.isNaN(e.getTime())\n ? new Date(Date.UTC(e.getFullYear(), e.getMonth(), e.getDate()))\n : null;\n formik.setFieldValue(id, cleanedDate);\n }\n }}\n error={Boolean(getNestedValue(formik.touched, id) && getNestedValue(formik.errors, id))}\n showCompleteButton={showCompleteButton}\n showClearButton={showClearButton}\n onBlur={onBlur}\n />\n \n
\n);\n", "type": "registry:file", "target": "src/components/formik/formik-date-picker.tsx" }, { "path": "registry/tra-plugins/forms/components/formik/formik-radio-buttons.tsx", "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { RadioGroup, RadioGroupItem } from \"@/components/ui/radio-buttons\";\nimport Label from \"@/components/ui/label\";\nimport { FormikErrorText } from \"./formik-error-text\";\n\ninterface FormikRadioButtonsProps {\n id: string;\n formik: any;\n options: { value: string | boolean; label?: string; disabled?: boolean }[];\n defaultValue?: string | boolean;\n disabled?: boolean;\n className?: string;\n onChange?: (value: any) => void;\n onlyParentOnChange?: boolean;\n hideErrorText?: boolean;\n}\n\nexport const FormikRadioButtons: React.FC = ({\n id,\n formik,\n options,\n defaultValue,\n className,\n onChange,\n onlyParentOnChange,\n hideErrorText = false,\n}) => (\n
\n {\n if (onlyParentOnChange) {\n onChange?.(selected);\n } else {\n onChange?.(selected);\n formik.setFieldValue(id, selected);\n }\n }}\n >\n {options?.map((option) => (\n
\n \n {option?.label && }\n
\n ))}\n \n {!hideErrorText && }\n
\n);\n", "type": "registry:file", "target": "src/components/formik/formik-radio-buttons.tsx" }, { "path": "registry/tra-plugins/forms/components/formik/formik-switch.tsx", "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport Switch from \"@/components/ui/switch\";\nimport Label from \"@/components/ui/label\";\nimport { FormikErrorText } from \"./formik-error-text\";\nimport { getNestedValue } from \"./utils\";\n\ninterface FormikSwitchProps {\n id: string;\n formik: any;\n label?: string | React.ReactNode;\n disabled?: boolean;\n className?: string;\n containerClassName?: string;\n labelClassName?: string;\n labelSide?: \"left\" | \"right\";\n onChange?: (checked: boolean) => void;\n}\n\nexport const FormikSwitch: React.FC = ({\n id,\n formik,\n label,\n disabled,\n className,\n containerClassName,\n labelClassName,\n labelSide = \"left\",\n onChange,\n}) => (\n
\n {label && labelSide === \"left\" && (\n \n )}\n
\n {\n formik.setFieldValue(id, checked);\n onChange?.(checked);\n }}\n disabled={disabled}\n className={cn(className)}\n />\n {label && labelSide === \"right\" && (\n \n )}\n
\n \n
\n);\n", "type": "registry:file", "target": "src/components/formik/formik-switch.tsx" }, { "path": "registry/tra-plugins/forms/components/formik/formik-error-text.tsx", "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport React from \"react\";\nimport { formikErrorCheck } from \"./utils\";\n\ninterface FormikErrorTextProps {\n id: string;\n formik: any;\n}\n\nexport const FormikErrorText: React.FC = ({ id, formik }) => {\n const errorMessage = formikErrorCheck(formik, id);\n\n return errorMessage ? (\n {errorMessage}\n ) : (\n  \n );\n};\n", "type": "registry:file", "target": "src/components/formik/formik-error-text.tsx" }, { "path": "registry/tra-plugins/forms/components/formik/utils.ts", "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport function getNestedValue(obj: any, path: string): any {\n if (!obj || !path) return undefined;\n return path.split(\".\").reduce((acc, key) => acc?.[key], obj);\n}\n\nexport function formikErrorCheck(formik: any, id: string): string | undefined {\n const touched = getNestedValue(formik.touched, id);\n const error = getNestedValue(formik.errors, id);\n if (touched && error) {\n return typeof error === \"object\" && error.text ? error.text : error;\n }\n return undefined;\n}\n", "type": "registry:file", "target": "src/components/formik/utils.ts" }, { "path": "registry/tra-plugins/forms/components/formik/index.ts", "content": "export { FormikTextField } from \"./formik-text-field\";\nexport { FormikSelect } from \"./formik-select\";\nexport { FormikCheckbox } from \"./formik-checkbox\";\nexport { FormikDatePicker } from \"./formik-date-picker\";\nexport { FormikRadioButtons } from \"./formik-radio-buttons\";\nexport { FormikSwitch } from \"./formik-switch\";\nexport { FormikErrorText } from \"./formik-error-text\";\nexport { getNestedValue } from \"./utils\";\n", "type": "registry:file", "target": "src/components/formik/index.ts" }, { "path": "registry/tra-plugins/forms/constants/Validations.ts", "content": "import * as Yup from \"yup\";\n\nconst requiredErrorMessage = \"Bu alan zorunludur.\";\n\nexport const exampleSchema = Yup.object().shape({\n email: Yup.string().email(\"Geçerli bir e-posta giriniz\").required(requiredErrorMessage),\n name: Yup.string().required(\"Geçerli bir isim giriniz\"),\n password: Yup.string().min(8, \"Şifre en az 8 karakter olmalıdır\").required(requiredErrorMessage),\n age: Yup.number().min(18, \"Yaşınız en az 18 olmalıdır\").required(requiredErrorMessage),\n beginDate: Yup.date().nullable().required(requiredErrorMessage),\n endDate: Yup.date()\n .nullable()\n .required(requiredErrorMessage)\n .when(\"beginDate\", ([beginDate], schema) =>\n beginDate\n ? schema.min(beginDate, \"Bitiş tarihi başlangıç tarihinden büyük olmalıdır\")\n : schema\n ),\n});\n", "type": "registry:file", "target": "src/constants/Validations.ts" } ], "type": "registry:block" }