formanitor 0.0.27 → 0.0.28
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.
- package/dist/index.cjs +175 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -3
- package/dist/index.d.ts +35 -3
- package/dist/index.mjs +175 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -430,6 +430,11 @@ var FormStore = class {
|
|
|
430
430
|
result[field.id] = raw?.text ?? null;
|
|
431
431
|
return;
|
|
432
432
|
}
|
|
433
|
+
if (field.type === "diagnosis_textarea") {
|
|
434
|
+
const raw = values[field.id];
|
|
435
|
+
result[field.id] = typeof raw === "string" ? raw : raw && typeof raw === "object" ? raw.text ?? null : null;
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
433
438
|
if (field.type === "ophthal_diagnosis") {
|
|
434
439
|
const raw = values[field.id];
|
|
435
440
|
const formatEye = (eyeData, eyeLabel) => {
|
|
@@ -4794,6 +4799,174 @@ var SmartTextareaWidget = ({ fieldId }) => {
|
|
|
4794
4799
|
showError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
|
|
4795
4800
|
] });
|
|
4796
4801
|
};
|
|
4802
|
+
function normalizeDiagnosisGrades(payload) {
|
|
4803
|
+
const result = [];
|
|
4804
|
+
const pushGroup = (conditionRaw, gradesRaw) => {
|
|
4805
|
+
const condition = typeof conditionRaw === "string" ? conditionRaw.trim() : "";
|
|
4806
|
+
if (!condition) return;
|
|
4807
|
+
if (!Array.isArray(gradesRaw)) return;
|
|
4808
|
+
const grades = Array.from(
|
|
4809
|
+
new Set(
|
|
4810
|
+
gradesRaw.map((grade) => typeof grade === "string" ? grade.trim() : "").filter(Boolean)
|
|
4811
|
+
)
|
|
4812
|
+
);
|
|
4813
|
+
if (grades.length === 0) return;
|
|
4814
|
+
result.push({ condition, grades });
|
|
4815
|
+
};
|
|
4816
|
+
const asArrayResponse = payload;
|
|
4817
|
+
if (Array.isArray(asArrayResponse?.diagnosisGrades)) {
|
|
4818
|
+
asArrayResponse.diagnosisGrades.forEach((item) => {
|
|
4819
|
+
pushGroup(item?.condition, item?.grades);
|
|
4820
|
+
});
|
|
4821
|
+
return result;
|
|
4822
|
+
}
|
|
4823
|
+
const asMapResponse = payload;
|
|
4824
|
+
const mapLike = asMapResponse?.field === "diagnosisgrade" && asMapResponse?.value && typeof asMapResponse.value === "object" ? asMapResponse.value : null;
|
|
4825
|
+
if (mapLike) {
|
|
4826
|
+
Object.entries(mapLike).forEach(([condition, grades]) => {
|
|
4827
|
+
pushGroup(condition, grades);
|
|
4828
|
+
});
|
|
4829
|
+
}
|
|
4830
|
+
return result;
|
|
4831
|
+
}
|
|
4832
|
+
var DiagnosisTextareaWidget = ({ fieldId }) => {
|
|
4833
|
+
const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
|
|
4834
|
+
const { state } = useForm();
|
|
4835
|
+
const handler = useFieldHandlers(fieldId);
|
|
4836
|
+
const def = fieldDef;
|
|
4837
|
+
const [gradeGroups, setGradeGroups] = React13__namespace.default.useState([]);
|
|
4838
|
+
const [isLoadingGrades, setIsLoadingGrades] = React13__namespace.default.useState(false);
|
|
4839
|
+
const normalized = React13__namespace.default.useMemo(() => {
|
|
4840
|
+
const raw = value;
|
|
4841
|
+
if (typeof raw === "string") {
|
|
4842
|
+
return { text: raw, selectedGradesByCondition: {} };
|
|
4843
|
+
}
|
|
4844
|
+
if (!raw || typeof raw !== "object") {
|
|
4845
|
+
return { text: "", selectedGradesByCondition: {} };
|
|
4846
|
+
}
|
|
4847
|
+
const text = typeof raw.text === "string" ? raw.text : "";
|
|
4848
|
+
const mapRaw = raw.selectedGradesByCondition;
|
|
4849
|
+
let selectedGradesByCondition = {};
|
|
4850
|
+
if (mapRaw && typeof mapRaw === "object" && !Array.isArray(mapRaw)) {
|
|
4851
|
+
const entries = Object.entries(mapRaw);
|
|
4852
|
+
for (const [condition, gradeRaw] of entries) {
|
|
4853
|
+
if (typeof condition !== "string") continue;
|
|
4854
|
+
if (typeof gradeRaw === "string" && gradeRaw.trim()) {
|
|
4855
|
+
selectedGradesByCondition[condition] = gradeRaw;
|
|
4856
|
+
}
|
|
4857
|
+
}
|
|
4858
|
+
}
|
|
4859
|
+
const sg = raw.selectedGrade;
|
|
4860
|
+
if (sg && typeof sg === "object" && typeof sg.condition === "string" && typeof sg.grade === "string") {
|
|
4861
|
+
const condition = sg.condition.trim();
|
|
4862
|
+
const grade = sg.grade.trim();
|
|
4863
|
+
if (condition && grade && !selectedGradesByCondition[condition]) {
|
|
4864
|
+
selectedGradesByCondition = { ...selectedGradesByCondition, [condition]: grade };
|
|
4865
|
+
}
|
|
4866
|
+
}
|
|
4867
|
+
return { text, selectedGradesByCondition };
|
|
4868
|
+
}, [value]);
|
|
4869
|
+
const textValue = normalized.text;
|
|
4870
|
+
const showError = !!error && (touched || state.submitAttempted);
|
|
4871
|
+
React13__namespace.default.useEffect(() => {
|
|
4872
|
+
const query = textValue.trim();
|
|
4873
|
+
const fetchGrades = handler.onFetchDiagnosisGrades;
|
|
4874
|
+
const debounceMs = def?.debounceDelay ?? 1e3;
|
|
4875
|
+
if (!query || !fetchGrades) {
|
|
4876
|
+
setGradeGroups([]);
|
|
4877
|
+
setIsLoadingGrades(false);
|
|
4878
|
+
return;
|
|
4879
|
+
}
|
|
4880
|
+
let isActive = true;
|
|
4881
|
+
const timer = window.setTimeout(async () => {
|
|
4882
|
+
setIsLoadingGrades(true);
|
|
4883
|
+
try {
|
|
4884
|
+
const response = await fetchGrades(query);
|
|
4885
|
+
if (!isActive) return;
|
|
4886
|
+
setGradeGroups(normalizeDiagnosisGrades(response));
|
|
4887
|
+
} catch {
|
|
4888
|
+
if (!isActive) return;
|
|
4889
|
+
setGradeGroups([]);
|
|
4890
|
+
} finally {
|
|
4891
|
+
if (isActive) setIsLoadingGrades(false);
|
|
4892
|
+
}
|
|
4893
|
+
}, debounceMs);
|
|
4894
|
+
return () => {
|
|
4895
|
+
isActive = false;
|
|
4896
|
+
window.clearTimeout(timer);
|
|
4897
|
+
};
|
|
4898
|
+
}, [textValue, handler.onFetchDiagnosisGrades, def?.debounceDelay]);
|
|
4899
|
+
if (!def) return null;
|
|
4900
|
+
const theme = getThemeConfig("textarea", def.theme);
|
|
4901
|
+
const wrapperClass = theme?.wrapperClassName ?? "space-y-2";
|
|
4902
|
+
const labelClass = theme?.labelClassName;
|
|
4903
|
+
const inputClass = cn(theme?.inputClassName, showError && "border-red-500");
|
|
4904
|
+
const toggleSelectedGrade = (condition, grade) => {
|
|
4905
|
+
if (disabled) return;
|
|
4906
|
+
const current = normalized.selectedGradesByCondition[condition];
|
|
4907
|
+
const nextForCondition = current === grade ? "" : grade;
|
|
4908
|
+
const nextMap = { ...normalized.selectedGradesByCondition };
|
|
4909
|
+
if (!nextForCondition) {
|
|
4910
|
+
delete nextMap[condition];
|
|
4911
|
+
} else {
|
|
4912
|
+
nextMap[condition] = nextForCondition;
|
|
4913
|
+
}
|
|
4914
|
+
setValue({ text: normalized.text, selectedGradesByCondition: nextMap });
|
|
4915
|
+
setTouched();
|
|
4916
|
+
};
|
|
4917
|
+
const labelContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4918
|
+
def.label,
|
|
4919
|
+
" ",
|
|
4920
|
+
def.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" })
|
|
4921
|
+
] });
|
|
4922
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: wrapperClass, children: [
|
|
4923
|
+
theme ? /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: fieldId, className: labelClass, children: labelContent }) : /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: fieldId, children: labelContent }),
|
|
4924
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4925
|
+
Textarea,
|
|
4926
|
+
{
|
|
4927
|
+
id: fieldId,
|
|
4928
|
+
value: textValue,
|
|
4929
|
+
onChange: (e) => setValue({ text: e.target.value, selectedGradesByCondition: normalized.selectedGradesByCondition }),
|
|
4930
|
+
onBlur: setTouched,
|
|
4931
|
+
disabled,
|
|
4932
|
+
placeholder: def.placeholder,
|
|
4933
|
+
className: inputClass,
|
|
4934
|
+
...def.height != null ? { height: def.height } : {}
|
|
4935
|
+
}
|
|
4936
|
+
),
|
|
4937
|
+
isLoadingGrades && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-xs text-muted-foreground", children: "Checking diagnosis grades..." }),
|
|
4938
|
+
!isLoadingGrades && gradeGroups.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4939
|
+
"div",
|
|
4940
|
+
{
|
|
4941
|
+
className: "mt-2 space-y-3 rounded-lg border border-border bg-muted/30 p-3",
|
|
4942
|
+
role: "group",
|
|
4943
|
+
"aria-label": "Diagnosis grade options",
|
|
4944
|
+
children: gradeGroups.map((group) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
4945
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium leading-none text-muted-foreground", children: [
|
|
4946
|
+
group.condition,
|
|
4947
|
+
":"
|
|
4948
|
+
] }),
|
|
4949
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: group.grades.map((grade) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4950
|
+
"button",
|
|
4951
|
+
{
|
|
4952
|
+
type: "button",
|
|
4953
|
+
onClick: () => toggleSelectedGrade(group.condition, grade),
|
|
4954
|
+
disabled,
|
|
4955
|
+
className: cn(
|
|
4956
|
+
"inline-flex min-h-8 items-center rounded-full border px-3 py-1 text-xs font-medium leading-none transition-colors",
|
|
4957
|
+
normalized.selectedGradesByCondition[group.condition] === grade ? "border-primary bg-primary/15 text-primary shadow-sm" : "border-border/80 bg-background text-foreground hover:bg-muted/80",
|
|
4958
|
+
disabled && "cursor-not-allowed opacity-60"
|
|
4959
|
+
),
|
|
4960
|
+
children: grade
|
|
4961
|
+
},
|
|
4962
|
+
`${group.condition}-${grade}`
|
|
4963
|
+
)) })
|
|
4964
|
+
] }, group.condition))
|
|
4965
|
+
}
|
|
4966
|
+
),
|
|
4967
|
+
showError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
|
|
4968
|
+
] });
|
|
4969
|
+
};
|
|
4797
4970
|
var DEFAULT_DRAFT = {
|
|
4798
4971
|
gpal: { G: 0, P: 0, A: 0, L: 0 },
|
|
4799
4972
|
lmp: "",
|
|
@@ -7147,6 +7320,8 @@ var FieldRenderer = ({ fieldId }) => {
|
|
|
7147
7320
|
return /* @__PURE__ */ jsxRuntime.jsx(FollowupWidget, { fieldId });
|
|
7148
7321
|
case "smart_textarea":
|
|
7149
7322
|
return /* @__PURE__ */ jsxRuntime.jsx(SmartTextareaWidget, { fieldId });
|
|
7323
|
+
case "diagnosis_textarea":
|
|
7324
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DiagnosisTextareaWidget, { fieldId });
|
|
7150
7325
|
case "obstetric_history":
|
|
7151
7326
|
return /* @__PURE__ */ jsxRuntime.jsx(ObstetricHistoryWidget, { fieldId });
|
|
7152
7327
|
case "eye_prescription":
|