formanitor 0.0.14 → 0.0.16
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 +789 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +59 -3
- package/dist/index.d.ts +59 -3
- package/dist/index.mjs +789 -35
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -634,12 +634,27 @@ var FormStore = class {
|
|
|
634
634
|
}
|
|
635
635
|
};
|
|
636
636
|
var FormContext = createContext(null);
|
|
637
|
+
var emptyFrequentItems = {
|
|
638
|
+
medications: [],
|
|
639
|
+
investigations: [],
|
|
640
|
+
procedures: []
|
|
641
|
+
};
|
|
642
|
+
var FrequentItemsContext = createContext(emptyFrequentItems);
|
|
637
643
|
var FieldHandlersContext = createContext({});
|
|
638
644
|
function useFieldHandlers(fieldId) {
|
|
639
645
|
const map = useContext(FieldHandlersContext);
|
|
640
646
|
return map[fieldId] ?? { onSearch: async () => [], recentlyUsed: [] };
|
|
641
647
|
}
|
|
642
|
-
|
|
648
|
+
function useFrequentItems() {
|
|
649
|
+
return useContext(FrequentItemsContext);
|
|
650
|
+
}
|
|
651
|
+
var FormProvider = ({
|
|
652
|
+
schema,
|
|
653
|
+
config,
|
|
654
|
+
fieldHandlers,
|
|
655
|
+
frequentItems,
|
|
656
|
+
children
|
|
657
|
+
}) => {
|
|
643
658
|
const storeRef = useRef(null);
|
|
644
659
|
if (!storeRef.current) {
|
|
645
660
|
storeRef.current = new FormStore(schema, config);
|
|
@@ -652,7 +667,8 @@ var FormProvider = ({ schema, config, fieldHandlers, children }) => {
|
|
|
652
667
|
useEffect(() => {
|
|
653
668
|
storeRef.current?.load();
|
|
654
669
|
}, []);
|
|
655
|
-
|
|
670
|
+
const frequentItemsValue = frequentItems ?? emptyFrequentItems;
|
|
671
|
+
return /* @__PURE__ */ jsx(FormContext.Provider, { value: storeRef.current, children: /* @__PURE__ */ jsx(FieldHandlersContext.Provider, { value: fieldHandlers ?? {}, children: /* @__PURE__ */ jsx(FrequentItemsContext.Provider, { value: frequentItemsValue, children }) }) });
|
|
656
672
|
};
|
|
657
673
|
function useFormStore() {
|
|
658
674
|
const context = useContext(FormContext);
|
|
@@ -2470,6 +2486,7 @@ var AddEntityDialog = ({
|
|
|
2470
2486
|
onClose,
|
|
2471
2487
|
title,
|
|
2472
2488
|
recentlyUsedSlot,
|
|
2489
|
+
chipSectionLabel = "Recently Used",
|
|
2473
2490
|
children,
|
|
2474
2491
|
actionSlot
|
|
2475
2492
|
}) => {
|
|
@@ -2477,7 +2494,7 @@ var AddEntityDialog = ({
|
|
|
2477
2494
|
/* @__PURE__ */ jsx(DialogHeader, { className: "px-6 pt-6 pb-4 shrink-0", children: /* @__PURE__ */ jsx(DialogTitle, { className: "text-lg font-semibold", children: title }) }),
|
|
2478
2495
|
/* @__PURE__ */ jsxs("div", { className: "px-6 flex flex-col gap-4 overflow-y-auto flex-1 min-h-0 pb-4", children: [
|
|
2479
2496
|
recentlyUsedSlot && /* @__PURE__ */ jsxs("div", { children: [
|
|
2480
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mb-2", children:
|
|
2497
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mb-2", children: chipSectionLabel }),
|
|
2481
2498
|
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: recentlyUsedSlot })
|
|
2482
2499
|
] }),
|
|
2483
2500
|
children
|
|
@@ -2502,9 +2519,9 @@ function mapToMedication(result) {
|
|
|
2502
2519
|
};
|
|
2503
2520
|
}
|
|
2504
2521
|
function mapAIMedicationToMedication(ai) {
|
|
2505
|
-
const id =
|
|
2522
|
+
const id = ai.id != null ? String(ai.id) : "";
|
|
2506
2523
|
return {
|
|
2507
|
-
id
|
|
2524
|
+
id,
|
|
2508
2525
|
brand_name: ai.brand_name ?? "",
|
|
2509
2526
|
generic_name: ai.generic_name ?? "",
|
|
2510
2527
|
frequency: "custom",
|
|
@@ -2520,7 +2537,7 @@ function mapAIMedicationToMedication(ai) {
|
|
|
2520
2537
|
}
|
|
2521
2538
|
function createCustomMedication(name, customId) {
|
|
2522
2539
|
return {
|
|
2523
|
-
id: customId,
|
|
2540
|
+
id: String(customId),
|
|
2524
2541
|
brand_name: name.trim(),
|
|
2525
2542
|
generic_name: "",
|
|
2526
2543
|
frequency: "custom",
|
|
@@ -2534,6 +2551,39 @@ function createCustomMedication(name, customId) {
|
|
|
2534
2551
|
notes: ""
|
|
2535
2552
|
};
|
|
2536
2553
|
}
|
|
2554
|
+
function parseDuration(duration) {
|
|
2555
|
+
if (!duration || !duration.trim()) return { value: "3", unit: "days" };
|
|
2556
|
+
const lower = duration.trim().toLowerCase();
|
|
2557
|
+
const match = lower.match(/^(\d+)\s*(day|days|week|weeks|month|months)?$/);
|
|
2558
|
+
if (!match) return { value: "3", unit: "days" };
|
|
2559
|
+
const value = match[1] ?? "3";
|
|
2560
|
+
const unitWord = match[2] ?? "days";
|
|
2561
|
+
const unit = unitWord.startsWith("month") ? "months" : unitWord.startsWith("week") ? "weeks" : "days";
|
|
2562
|
+
return { value, unit };
|
|
2563
|
+
}
|
|
2564
|
+
function mapFrequentItemToMedication(item) {
|
|
2565
|
+
const parsed = parseDuration(item.duration);
|
|
2566
|
+
const duration_value = item.duration_value ?? parsed.value;
|
|
2567
|
+
const duration_unit = item.duration_unit ?? parsed.unit;
|
|
2568
|
+
const before_after = item.before_after === "BEFORE FOOD" ? "BEFORE FOOD" : "AFTER FOOD";
|
|
2569
|
+
const routeNote = item.route ? `Route: ${item.route}` : "";
|
|
2570
|
+
const baseNotes = item.notes?.trim() || "";
|
|
2571
|
+
const combinedNotes = [baseNotes, routeNote.trim()].filter((part) => part.length > 0).join(" \u2014 ");
|
|
2572
|
+
return {
|
|
2573
|
+
id: item.id,
|
|
2574
|
+
brand_name: item.brand_name ?? item.name,
|
|
2575
|
+
generic_name: item.short_name ?? "",
|
|
2576
|
+
frequency: item.frequency ?? "custom",
|
|
2577
|
+
is_custom: false,
|
|
2578
|
+
duration_value,
|
|
2579
|
+
duration_unit,
|
|
2580
|
+
before_after,
|
|
2581
|
+
morning: item.morning ?? "0",
|
|
2582
|
+
afternoon: item.afternoon ?? "0",
|
|
2583
|
+
night: item.night ?? "0",
|
|
2584
|
+
notes: combinedNotes
|
|
2585
|
+
};
|
|
2586
|
+
}
|
|
2537
2587
|
function Spinner({
|
|
2538
2588
|
value,
|
|
2539
2589
|
onChange
|
|
@@ -2581,11 +2631,14 @@ function MedicationCard({
|
|
|
2581
2631
|
onChange: (e) => set("frequency", e.target.value),
|
|
2582
2632
|
children: [
|
|
2583
2633
|
/* @__PURE__ */ jsx("option", { value: "custom", children: "select frequency" }),
|
|
2584
|
-
/* @__PURE__ */ jsx("option", { value: "
|
|
2585
|
-
/* @__PURE__ */ jsx("option", { value: "
|
|
2586
|
-
/* @__PURE__ */ jsx("option", { value: "
|
|
2587
|
-
/* @__PURE__ */ jsx("option", { value: "
|
|
2588
|
-
/* @__PURE__ */ jsx("option", { value: "
|
|
2634
|
+
/* @__PURE__ */ jsx("option", { value: "qid", children: "4 times a day (QID)" }),
|
|
2635
|
+
/* @__PURE__ */ jsx("option", { value: "alternate_day", children: "Alternate day" }),
|
|
2636
|
+
/* @__PURE__ */ jsx("option", { value: "once_weekly", children: "Once weekly" }),
|
|
2637
|
+
/* @__PURE__ */ jsx("option", { value: "once_monthly", children: "Once monthly" }),
|
|
2638
|
+
/* @__PURE__ */ jsx("option", { value: "as_needed", children: "As needed" }),
|
|
2639
|
+
/* @__PURE__ */ jsx("option", { value: "fort_night", children: "Fort night" }),
|
|
2640
|
+
/* @__PURE__ */ jsx("option", { value: "at_bed_time", children: "At Bed time" }),
|
|
2641
|
+
/* @__PURE__ */ jsx("option", { value: "sos", children: "SOS only" })
|
|
2589
2642
|
]
|
|
2590
2643
|
}
|
|
2591
2644
|
),
|
|
@@ -2724,6 +2777,7 @@ var AddMedicationField = ({
|
|
|
2724
2777
|
onChange,
|
|
2725
2778
|
onSearch,
|
|
2726
2779
|
recentlyUsed = [],
|
|
2780
|
+
frequentItems = [],
|
|
2727
2781
|
suggestedMedications = []
|
|
2728
2782
|
}) => {
|
|
2729
2783
|
const [open, setOpen] = useState(false);
|
|
@@ -2769,6 +2823,13 @@ var AddMedicationField = ({
|
|
|
2769
2823
|
onChange([...safeValue, mapToMedication(result)]);
|
|
2770
2824
|
}
|
|
2771
2825
|
}
|
|
2826
|
+
function handleFrequentItemToggle(item) {
|
|
2827
|
+
if (addedIds.has(String(item.id))) {
|
|
2828
|
+
onChange(safeValue.filter((m) => String(m.id) !== String(item.id)));
|
|
2829
|
+
} else {
|
|
2830
|
+
onChange([...safeValue, mapFrequentItemToMedication(item)]);
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2772
2833
|
function handleResultClick(result) {
|
|
2773
2834
|
if (addedIds.has(String(result.id))) return;
|
|
2774
2835
|
setAddingResultId(result.id);
|
|
@@ -2819,6 +2880,26 @@ var AddMedicationField = ({
|
|
|
2819
2880
|
r.id
|
|
2820
2881
|
);
|
|
2821
2882
|
});
|
|
2883
|
+
const limitedFrequentItems = frequentItems.slice(0, 25);
|
|
2884
|
+
const frequentItemChips = limitedFrequentItems.length > 0 ? limitedFrequentItems.map((item) => {
|
|
2885
|
+
const isAdded = addedIds.has(String(item.id));
|
|
2886
|
+
return /* @__PURE__ */ jsxs(
|
|
2887
|
+
"button",
|
|
2888
|
+
{
|
|
2889
|
+
type: "button",
|
|
2890
|
+
onClick: () => handleFrequentItemToggle(item),
|
|
2891
|
+
className: cn(
|
|
2892
|
+
"rounded-full border text-[11px] px-2 py-0.5 transition-colors cursor-pointer",
|
|
2893
|
+
isAdded ? "border-green-300 bg-green-50 text-green-700" : "border-border bg-white hover:bg-gray-50"
|
|
2894
|
+
),
|
|
2895
|
+
children: [
|
|
2896
|
+
isAdded && /* @__PURE__ */ jsx("span", { className: "mr-1", children: "\u2713" }),
|
|
2897
|
+
item.brand_name ?? item.name
|
|
2898
|
+
]
|
|
2899
|
+
},
|
|
2900
|
+
item.id
|
|
2901
|
+
);
|
|
2902
|
+
}) : [];
|
|
2822
2903
|
return /* @__PURE__ */ jsxs("div", { className: "rounded-md overflow-hidden flex flex-col border bg-white border-[#D0D0D0] space-y-3 p-3 h-fit", children: [
|
|
2823
2904
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2824
2905
|
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold", children: label }),
|
|
@@ -2832,22 +2913,6 @@ var AddMedicationField = ({
|
|
|
2832
2913
|
}
|
|
2833
2914
|
)
|
|
2834
2915
|
] }),
|
|
2835
|
-
suggestedMedications.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1.5 items-center", children: [
|
|
2836
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground mr-1", children: "Suggestions:" }),
|
|
2837
|
-
suggestedMedications.filter((s) => !addedIds.has(String(s.id))).map((s) => /* @__PURE__ */ jsxs(
|
|
2838
|
-
"button",
|
|
2839
|
-
{
|
|
2840
|
-
type: "button",
|
|
2841
|
-
onClick: () => handleAddSuggestion(s),
|
|
2842
|
-
className: "inline-flex items-center gap-1 rounded-full border border-dashed border-purple-300 bg-purple-50/80 text-purple-800 text-xs px-2.5 py-1 hover:bg-purple-100 transition-colors cursor-pointer",
|
|
2843
|
-
children: [
|
|
2844
|
-
/* @__PURE__ */ jsx(Plus, { className: "h-3 w-3" }),
|
|
2845
|
-
s.brand_name || s.generic_name || String(s.id)
|
|
2846
|
-
]
|
|
2847
|
-
},
|
|
2848
|
-
String(s.id)
|
|
2849
|
-
))
|
|
2850
|
-
] }),
|
|
2851
2916
|
/* @__PURE__ */ jsx("div", { className: "space-y-2", children: safeValue.map((med, i) => /* @__PURE__ */ jsx(
|
|
2852
2917
|
MedicationCard,
|
|
2853
2918
|
{
|
|
@@ -2863,7 +2928,8 @@ var AddMedicationField = ({
|
|
|
2863
2928
|
open,
|
|
2864
2929
|
onClose: () => setOpen(false),
|
|
2865
2930
|
title: "Add Medication",
|
|
2866
|
-
recentlyUsedSlot: recentlyUsedChips.length > 0 ? recentlyUsedChips : void 0,
|
|
2931
|
+
recentlyUsedSlot: frequentItemChips.length > 0 ? frequentItemChips : recentlyUsedChips.length > 0 ? recentlyUsedChips : void 0,
|
|
2932
|
+
chipSectionLabel: frequentItemChips.length > 0 ? "Frequently used" : void 0,
|
|
2867
2933
|
actionSlot: /* @__PURE__ */ jsx(
|
|
2868
2934
|
"button",
|
|
2869
2935
|
{
|
|
@@ -2888,6 +2954,22 @@ var AddMedicationField = ({
|
|
|
2888
2954
|
className: "border border-border rounded-md focus-visible:ring-0"
|
|
2889
2955
|
}
|
|
2890
2956
|
),
|
|
2957
|
+
suggestedMedications.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1.5 items-center", children: [
|
|
2958
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground mr-1", children: "Suggestions:" }),
|
|
2959
|
+
suggestedMedications.filter((s) => !addedIds.has(String(s.id))).slice(0, 25).map((s) => /* @__PURE__ */ jsxs(
|
|
2960
|
+
"button",
|
|
2961
|
+
{
|
|
2962
|
+
type: "button",
|
|
2963
|
+
onClick: () => handleAddSuggestion(s),
|
|
2964
|
+
className: "inline-flex items-center gap-1 rounded-full border border-dashed border-purple-300 bg-purple-50/80 text-purple-800 text-[11px] px-2 py-0.5 hover:bg-purple-100 transition-colors cursor-pointer",
|
|
2965
|
+
children: [
|
|
2966
|
+
/* @__PURE__ */ jsx(Plus, { className: "h-3 w-3" }),
|
|
2967
|
+
s.brand_name || s.generic_name || String(s.id)
|
|
2968
|
+
]
|
|
2969
|
+
},
|
|
2970
|
+
String(s.id)
|
|
2971
|
+
))
|
|
2972
|
+
] }),
|
|
2891
2973
|
loading && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground text-center py-2", children: "Searching\u2026" }),
|
|
2892
2974
|
!loading && results.length > 0 && /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2 max-h-64 overflow-y-auto", children: results.map((r) => /* @__PURE__ */ jsx(
|
|
2893
2975
|
SearchResultCard,
|
|
@@ -2907,6 +2989,7 @@ var AddMedicationWidget = ({ fieldId }) => {
|
|
|
2907
2989
|
const { value, setValue } = useField(fieldId);
|
|
2908
2990
|
const handlers = useFieldHandlers(fieldId);
|
|
2909
2991
|
const { medications: suggestedMedications } = useAISuggestions();
|
|
2992
|
+
const { medications: frequentMedications } = useFrequentItems();
|
|
2910
2993
|
const safeValue = Array.isArray(value) ? value : [];
|
|
2911
2994
|
return /* @__PURE__ */ jsx(
|
|
2912
2995
|
AddMedicationField,
|
|
@@ -2915,6 +2998,7 @@ var AddMedicationWidget = ({ fieldId }) => {
|
|
|
2915
2998
|
onChange: setValue,
|
|
2916
2999
|
onSearch: handlers.onSearch,
|
|
2917
3000
|
recentlyUsed: handlers.recentlyUsed,
|
|
3001
|
+
frequentItems: frequentMedications,
|
|
2918
3002
|
suggestedMedications
|
|
2919
3003
|
}
|
|
2920
3004
|
);
|
|
@@ -2928,12 +3012,23 @@ function mapToInvestigation(result) {
|
|
|
2928
3012
|
fromAI: false
|
|
2929
3013
|
};
|
|
2930
3014
|
}
|
|
3015
|
+
function mapFrequentItemToInvestigation(item) {
|
|
3016
|
+
return {
|
|
3017
|
+
id: String(item.id),
|
|
3018
|
+
name: item.name,
|
|
3019
|
+
code: item.code ?? void 0,
|
|
3020
|
+
label: item.name,
|
|
3021
|
+
is_custom: false,
|
|
3022
|
+
fromAI: false
|
|
3023
|
+
};
|
|
3024
|
+
}
|
|
2931
3025
|
var AddInvestigationField = ({
|
|
2932
3026
|
label = "Investigations",
|
|
2933
3027
|
value,
|
|
2934
3028
|
onChange,
|
|
2935
3029
|
onSearch,
|
|
2936
|
-
recentlyUsed = []
|
|
3030
|
+
recentlyUsed = [],
|
|
3031
|
+
frequentItems = []
|
|
2937
3032
|
}) => {
|
|
2938
3033
|
const [open, setOpen] = useState(false);
|
|
2939
3034
|
const [query, setQuery] = useState("");
|
|
@@ -2995,6 +3090,14 @@ var AddInvestigationField = ({
|
|
|
2995
3090
|
addInvestigation(result);
|
|
2996
3091
|
}
|
|
2997
3092
|
}
|
|
3093
|
+
function handleFrequentItemToggle(item) {
|
|
3094
|
+
const id = String(item.id);
|
|
3095
|
+
if (addedIds.has(id)) {
|
|
3096
|
+
removeInvestigation(id);
|
|
3097
|
+
} else {
|
|
3098
|
+
onChange([...valueRef.current, mapFrequentItemToInvestigation(item)]);
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
2998
3101
|
const recentlyUsedChips = recentlyUsed.map((r) => {
|
|
2999
3102
|
const isAdded = addedIds.has(r.id);
|
|
3000
3103
|
return /* @__PURE__ */ jsxs(
|
|
@@ -3014,6 +3117,27 @@ var AddInvestigationField = ({
|
|
|
3014
3117
|
r.id
|
|
3015
3118
|
);
|
|
3016
3119
|
});
|
|
3120
|
+
const limitedFrequentItems = frequentItems.slice(0, 25);
|
|
3121
|
+
const frequentItemChips = limitedFrequentItems.length > 0 ? limitedFrequentItems.map((item) => {
|
|
3122
|
+
const id = String(item.id);
|
|
3123
|
+
const isAdded = addedIds.has(id);
|
|
3124
|
+
return /* @__PURE__ */ jsxs(
|
|
3125
|
+
"button",
|
|
3126
|
+
{
|
|
3127
|
+
type: "button",
|
|
3128
|
+
onClick: () => handleFrequentItemToggle(item),
|
|
3129
|
+
className: cn(
|
|
3130
|
+
"rounded-full border text-xs px-3 py-1 transition-colors",
|
|
3131
|
+
isAdded ? "border-green-300 bg-green-50 text-green-700" : "border-border bg-white hover:bg-gray-50"
|
|
3132
|
+
),
|
|
3133
|
+
children: [
|
|
3134
|
+
isAdded && /* @__PURE__ */ jsx("span", { className: "mr-1", children: "\u2713" }),
|
|
3135
|
+
item.name
|
|
3136
|
+
]
|
|
3137
|
+
},
|
|
3138
|
+
item.id
|
|
3139
|
+
);
|
|
3140
|
+
}) : [];
|
|
3017
3141
|
return /* @__PURE__ */ jsxs("div", { className: "rounded-md overflow-hidden flex flex-col bg-white border border-[#D0D0D0] space-y-3 p-3 h-fit", children: [
|
|
3018
3142
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
|
|
3019
3143
|
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold", children: label }),
|
|
@@ -3052,7 +3176,8 @@ var AddInvestigationField = ({
|
|
|
3052
3176
|
open,
|
|
3053
3177
|
onClose: () => setOpen(false),
|
|
3054
3178
|
title: "Add Investigation",
|
|
3055
|
-
recentlyUsedSlot: recentlyUsedChips.length > 0 ? recentlyUsedChips : void 0,
|
|
3179
|
+
recentlyUsedSlot: frequentItemChips.length > 0 ? frequentItemChips : recentlyUsedChips.length > 0 ? recentlyUsedChips : void 0,
|
|
3180
|
+
chipSectionLabel: frequentItemChips.length > 0 ? "Frequently used" : void 0,
|
|
3056
3181
|
children: /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
3057
3182
|
/* @__PURE__ */ jsx(
|
|
3058
3183
|
Input,
|
|
@@ -3092,13 +3217,15 @@ var AddInvestigationField = ({
|
|
|
3092
3217
|
var AddInvestigationWidget = ({ fieldId }) => {
|
|
3093
3218
|
const { value, setValue } = useField(fieldId);
|
|
3094
3219
|
const handlers = useFieldHandlers(fieldId);
|
|
3220
|
+
const { investigations: frequentInvestigations } = useFrequentItems();
|
|
3095
3221
|
return /* @__PURE__ */ jsx(
|
|
3096
3222
|
AddInvestigationField,
|
|
3097
3223
|
{
|
|
3098
3224
|
value: value ?? [],
|
|
3099
3225
|
onChange: setValue,
|
|
3100
3226
|
onSearch: handlers.onSearch,
|
|
3101
|
-
recentlyUsed: handlers.recentlyUsed
|
|
3227
|
+
recentlyUsed: handlers.recentlyUsed,
|
|
3228
|
+
frequentItems: frequentInvestigations
|
|
3102
3229
|
}
|
|
3103
3230
|
);
|
|
3104
3231
|
};
|
|
@@ -3111,12 +3238,23 @@ function mapToProcedure(result) {
|
|
|
3111
3238
|
fromAI: false
|
|
3112
3239
|
};
|
|
3113
3240
|
}
|
|
3241
|
+
function mapFrequentItemToProcedure(item) {
|
|
3242
|
+
return {
|
|
3243
|
+
id: String(item.id),
|
|
3244
|
+
name: item.name,
|
|
3245
|
+
code: item.code ?? void 0,
|
|
3246
|
+
label: item.name,
|
|
3247
|
+
is_custom: false,
|
|
3248
|
+
fromAI: false
|
|
3249
|
+
};
|
|
3250
|
+
}
|
|
3114
3251
|
var AddProcedureField = ({
|
|
3115
3252
|
label = "Procedures",
|
|
3116
3253
|
value,
|
|
3117
3254
|
onChange,
|
|
3118
3255
|
onSearch,
|
|
3119
|
-
recentlyUsed = []
|
|
3256
|
+
recentlyUsed = [],
|
|
3257
|
+
frequentItems = []
|
|
3120
3258
|
}) => {
|
|
3121
3259
|
const [open, setOpen] = useState(false);
|
|
3122
3260
|
const [query, setQuery] = useState("");
|
|
@@ -3178,6 +3316,14 @@ var AddProcedureField = ({
|
|
|
3178
3316
|
addProcedure(result);
|
|
3179
3317
|
}
|
|
3180
3318
|
}
|
|
3319
|
+
function handleFrequentItemToggle(item) {
|
|
3320
|
+
const id = String(item.id);
|
|
3321
|
+
if (addedIds.has(id)) {
|
|
3322
|
+
removeProcedure(id);
|
|
3323
|
+
} else {
|
|
3324
|
+
onChange([...valueRef.current, mapFrequentItemToProcedure(item)]);
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3181
3327
|
const recentlyUsedChips = recentlyUsed.map((r) => {
|
|
3182
3328
|
const isAdded = addedIds.has(r.id);
|
|
3183
3329
|
return /* @__PURE__ */ jsxs(
|
|
@@ -3197,6 +3343,27 @@ var AddProcedureField = ({
|
|
|
3197
3343
|
r.id
|
|
3198
3344
|
);
|
|
3199
3345
|
});
|
|
3346
|
+
const limitedFrequentItems = frequentItems.slice(0, 25);
|
|
3347
|
+
const frequentItemChips = limitedFrequentItems.length > 0 ? limitedFrequentItems.map((item) => {
|
|
3348
|
+
const id = String(item.id);
|
|
3349
|
+
const isAdded = addedIds.has(id);
|
|
3350
|
+
return /* @__PURE__ */ jsxs(
|
|
3351
|
+
"button",
|
|
3352
|
+
{
|
|
3353
|
+
type: "button",
|
|
3354
|
+
onClick: () => handleFrequentItemToggle(item),
|
|
3355
|
+
className: cn(
|
|
3356
|
+
"rounded-full border text-xs px-3 py-1 transition-colors",
|
|
3357
|
+
isAdded ? "border-green-300 bg-green-50 text-green-700" : "border-border bg-white hover:bg-gray-50"
|
|
3358
|
+
),
|
|
3359
|
+
children: [
|
|
3360
|
+
isAdded && /* @__PURE__ */ jsx("span", { className: "mr-1", children: "\u2713" }),
|
|
3361
|
+
item.name
|
|
3362
|
+
]
|
|
3363
|
+
},
|
|
3364
|
+
item.id
|
|
3365
|
+
);
|
|
3366
|
+
}) : [];
|
|
3200
3367
|
return /* @__PURE__ */ jsxs("div", { className: "rounded-md overflow-hidden flex flex-col bg-white border border-[#D0D0D0] space-y-3 p-3 h-fit", children: [
|
|
3201
3368
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
|
|
3202
3369
|
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold", children: label }),
|
|
@@ -3235,7 +3402,8 @@ var AddProcedureField = ({
|
|
|
3235
3402
|
open,
|
|
3236
3403
|
onClose: () => setOpen(false),
|
|
3237
3404
|
title: "Add Procedure",
|
|
3238
|
-
recentlyUsedSlot: recentlyUsedChips.length > 0 ? recentlyUsedChips : void 0,
|
|
3405
|
+
recentlyUsedSlot: frequentItemChips.length > 0 ? frequentItemChips : recentlyUsedChips.length > 0 ? recentlyUsedChips : void 0,
|
|
3406
|
+
chipSectionLabel: frequentItemChips.length > 0 ? "Frequently used" : void 0,
|
|
3239
3407
|
children: /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
3240
3408
|
/* @__PURE__ */ jsx(
|
|
3241
3409
|
Input,
|
|
@@ -3275,13 +3443,15 @@ var AddProcedureField = ({
|
|
|
3275
3443
|
var AddProcedureWidget = ({ fieldId }) => {
|
|
3276
3444
|
const { value, setValue } = useField(fieldId);
|
|
3277
3445
|
const handlers = useFieldHandlers(fieldId);
|
|
3446
|
+
const { procedures: frequentProcedures } = useFrequentItems();
|
|
3278
3447
|
return /* @__PURE__ */ jsx(
|
|
3279
3448
|
AddProcedureField,
|
|
3280
3449
|
{
|
|
3281
3450
|
value: value ?? [],
|
|
3282
3451
|
onChange: setValue,
|
|
3283
3452
|
onSearch: handlers.onSearch,
|
|
3284
|
-
recentlyUsed: handlers.recentlyUsed
|
|
3453
|
+
recentlyUsed: handlers.recentlyUsed,
|
|
3454
|
+
frequentItems: frequentProcedures
|
|
3285
3455
|
}
|
|
3286
3456
|
);
|
|
3287
3457
|
};
|
|
@@ -4214,6 +4384,588 @@ var SmartTextareaWidget = ({ fieldId }) => {
|
|
|
4214
4384
|
showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
|
|
4215
4385
|
] });
|
|
4216
4386
|
};
|
|
4387
|
+
var DEFAULT_DRAFT = {
|
|
4388
|
+
gpal: { G: 0, P: 0, A: 0, L: 0 },
|
|
4389
|
+
lmp: "",
|
|
4390
|
+
is_pregnant: false,
|
|
4391
|
+
eddUSG: "",
|
|
4392
|
+
primaryEDD: "lmp",
|
|
4393
|
+
complications: "",
|
|
4394
|
+
outcome: null
|
|
4395
|
+
};
|
|
4396
|
+
function pad2(n) {
|
|
4397
|
+
return String(n).padStart(2, "0");
|
|
4398
|
+
}
|
|
4399
|
+
function formatDdMmYyyy(iso) {
|
|
4400
|
+
const [y, m, d] = iso.split("-");
|
|
4401
|
+
if (!y || !m || !d) return iso;
|
|
4402
|
+
return `${pad2(Number(d))}/${pad2(Number(m))}/${y}`;
|
|
4403
|
+
}
|
|
4404
|
+
function todayIso() {
|
|
4405
|
+
const d = /* @__PURE__ */ new Date();
|
|
4406
|
+
const y = d.getFullYear();
|
|
4407
|
+
const m = pad2(d.getMonth() + 1);
|
|
4408
|
+
const day = pad2(d.getDate());
|
|
4409
|
+
return `${y}-${m}-${day}`;
|
|
4410
|
+
}
|
|
4411
|
+
function isValidIsoDate(val) {
|
|
4412
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(val)) return false;
|
|
4413
|
+
const dt = /* @__PURE__ */ new Date(`${val}T00:00:00.000Z`);
|
|
4414
|
+
return !Number.isNaN(dt.getTime());
|
|
4415
|
+
}
|
|
4416
|
+
function safeJsonParse(val) {
|
|
4417
|
+
try {
|
|
4418
|
+
return JSON.parse(val);
|
|
4419
|
+
} catch {
|
|
4420
|
+
return null;
|
|
4421
|
+
}
|
|
4422
|
+
}
|
|
4423
|
+
function clampInt(val, min, max) {
|
|
4424
|
+
if (!Number.isFinite(val)) return min;
|
|
4425
|
+
return Math.max(min, Math.min(max, Math.trunc(val)));
|
|
4426
|
+
}
|
|
4427
|
+
function parseLegacyString(input) {
|
|
4428
|
+
const result = {};
|
|
4429
|
+
const gpalMatch = input.match(/G(\d+)\s*P(\d+)\s*A(\d+)\s*L(\d+)/i);
|
|
4430
|
+
if (gpalMatch) {
|
|
4431
|
+
const [, g, p, a, l] = gpalMatch;
|
|
4432
|
+
result.gpal = {
|
|
4433
|
+
G: clampInt(Number(g), 0, 20),
|
|
4434
|
+
P: clampInt(Number(p), 0, 20),
|
|
4435
|
+
A: clampInt(Number(a), 0, 20),
|
|
4436
|
+
L: clampInt(Number(l), 0, 20)
|
|
4437
|
+
};
|
|
4438
|
+
}
|
|
4439
|
+
const lmpMatch = input.match(/LMP:\s*([^\n]+)/i);
|
|
4440
|
+
if (lmpMatch?.[1]) result.lmp = lmpMatch[1].trim();
|
|
4441
|
+
const eddUsgMatch = input.match(/EDD\s*\(USG\):\s*([^\n]+)/i);
|
|
4442
|
+
if (eddUsgMatch?.[1]) result.eddUSG = eddUsgMatch[1].trim();
|
|
4443
|
+
const primaryMatch = input.match(/Primary\s*EDD:\s*(lmp|usg)/i);
|
|
4444
|
+
if (primaryMatch?.[1]) result.primaryEDD = primaryMatch[1].toLowerCase();
|
|
4445
|
+
const compMatch = input.match(/Complications:\s*([^\n]+)/i);
|
|
4446
|
+
if (compMatch?.[1]) result.complications = compMatch[1].trim();
|
|
4447
|
+
return result;
|
|
4448
|
+
}
|
|
4449
|
+
function normalizeToDraft(value) {
|
|
4450
|
+
if (!value) return { draft: { ...DEFAULT_DRAFT }, isNewEntry: true };
|
|
4451
|
+
let parsed = value;
|
|
4452
|
+
if (typeof value === "string") {
|
|
4453
|
+
const json = safeJsonParse(value);
|
|
4454
|
+
parsed = json ?? value;
|
|
4455
|
+
}
|
|
4456
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed) && "gpal" in parsed && parsed.gpal && typeof parsed.gpal === "object") {
|
|
4457
|
+
const gpal = parsed.gpal ?? {};
|
|
4458
|
+
const edd = parsed.edd ?? null;
|
|
4459
|
+
const eddUSG = (edd && typeof edd === "object" ? edd.usg : void 0) ?? parsed.eddUSG ?? "";
|
|
4460
|
+
const primaryEDD = (edd && typeof edd === "object" ? edd.primary : void 0) ?? parsed.primaryEDD ?? "lmp";
|
|
4461
|
+
const lmp = parsed.lmp ?? "";
|
|
4462
|
+
const complications = parsed.complications ?? "";
|
|
4463
|
+
const outcome = parsed.outcome ?? null;
|
|
4464
|
+
const is_pregnant = !!parsed.is_pregnant;
|
|
4465
|
+
return {
|
|
4466
|
+
isNewEntry: false,
|
|
4467
|
+
draft: {
|
|
4468
|
+
gpal: {
|
|
4469
|
+
G: clampInt(Number(gpal.G ?? 0), 0, 20),
|
|
4470
|
+
P: clampInt(Number(gpal.P ?? 0), 0, 20),
|
|
4471
|
+
A: clampInt(Number(gpal.A ?? 0), 0, 20),
|
|
4472
|
+
L: clampInt(Number(gpal.L ?? 0), 0, 20)
|
|
4473
|
+
},
|
|
4474
|
+
lmp: typeof lmp === "string" ? lmp : "",
|
|
4475
|
+
is_pregnant,
|
|
4476
|
+
eddUSG: typeof eddUSG === "string" ? eddUSG : "",
|
|
4477
|
+
primaryEDD: primaryEDD === "usg" ? "usg" : "lmp",
|
|
4478
|
+
complications: typeof complications === "string" ? complications : "",
|
|
4479
|
+
outcome: outcome && typeof outcome === "object" ? {
|
|
4480
|
+
type: outcome.type ?? "",
|
|
4481
|
+
date: typeof outcome.date === "string" ? outcome.date : "",
|
|
4482
|
+
notes: typeof outcome.notes === "string" ? outcome.notes : "",
|
|
4483
|
+
is_final: !!outcome.is_final
|
|
4484
|
+
} : null
|
|
4485
|
+
}
|
|
4486
|
+
};
|
|
4487
|
+
}
|
|
4488
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
4489
|
+
const gpalFromFlat = {
|
|
4490
|
+
G: clampInt(Number(parsed.G ?? parsed.g ?? 0), 0, 20),
|
|
4491
|
+
P: clampInt(Number(parsed.P ?? parsed.p ?? 0), 0, 20),
|
|
4492
|
+
A: clampInt(Number(parsed.A ?? parsed.a ?? 0), 0, 20),
|
|
4493
|
+
L: clampInt(Number(parsed.L ?? parsed.l ?? 0), 0, 20)
|
|
4494
|
+
};
|
|
4495
|
+
return {
|
|
4496
|
+
isNewEntry: false,
|
|
4497
|
+
draft: {
|
|
4498
|
+
...DEFAULT_DRAFT,
|
|
4499
|
+
gpal: gpalFromFlat,
|
|
4500
|
+
lmp: typeof parsed.lmp === "string" ? parsed.lmp : "",
|
|
4501
|
+
eddUSG: typeof parsed.eddUSG === "string" ? parsed.eddUSG : "",
|
|
4502
|
+
primaryEDD: parsed.primaryEDD === "usg" ? "usg" : "lmp",
|
|
4503
|
+
complications: typeof parsed.complications === "string" ? parsed.complications : "",
|
|
4504
|
+
outcome: parsed.outcome && typeof parsed.outcome === "object" ? {
|
|
4505
|
+
type: parsed.outcome.type ?? "",
|
|
4506
|
+
date: typeof parsed.outcome.date === "string" ? parsed.outcome.date : "",
|
|
4507
|
+
notes: typeof parsed.outcome.notes === "string" ? parsed.outcome.notes : "",
|
|
4508
|
+
is_final: !!parsed.outcome.is_final
|
|
4509
|
+
} : null,
|
|
4510
|
+
is_pregnant: !!parsed.is_pregnant
|
|
4511
|
+
}
|
|
4512
|
+
};
|
|
4513
|
+
}
|
|
4514
|
+
if (typeof parsed === "string") {
|
|
4515
|
+
const legacy = parseLegacyString(parsed);
|
|
4516
|
+
return { isNewEntry: false, draft: { ...DEFAULT_DRAFT, ...legacy } };
|
|
4517
|
+
}
|
|
4518
|
+
return { draft: { ...DEFAULT_DRAFT }, isNewEntry: true };
|
|
4519
|
+
}
|
|
4520
|
+
function computeEddFromLmp(lmpIso) {
|
|
4521
|
+
if (!isValidIsoDate(lmpIso)) return null;
|
|
4522
|
+
const base = /* @__PURE__ */ new Date(`${lmpIso}T00:00:00.000Z`);
|
|
4523
|
+
base.setUTCDate(base.getUTCDate() + 280);
|
|
4524
|
+
const y = base.getUTCFullYear();
|
|
4525
|
+
const m = pad2(base.getUTCMonth() + 1);
|
|
4526
|
+
const d = pad2(base.getUTCDate());
|
|
4527
|
+
return `${y}-${m}-${d}`;
|
|
4528
|
+
}
|
|
4529
|
+
function diffDaysUtc(fromIso, toIso) {
|
|
4530
|
+
if (!isValidIsoDate(fromIso) || !isValidIsoDate(toIso)) return null;
|
|
4531
|
+
const a = (/* @__PURE__ */ new Date(`${fromIso}T00:00:00.000Z`)).getTime();
|
|
4532
|
+
const b = (/* @__PURE__ */ new Date(`${toIso}T00:00:00.000Z`)).getTime();
|
|
4533
|
+
return Math.floor((b - a) / (1e3 * 60 * 60 * 24));
|
|
4534
|
+
}
|
|
4535
|
+
function computeGestationalAgeFromLmp(lmpIso, today) {
|
|
4536
|
+
const days = diffDaysUtc(lmpIso, today);
|
|
4537
|
+
if (days == null || days < 0) return null;
|
|
4538
|
+
const weeks = Math.floor(days / 7);
|
|
4539
|
+
const rem = days % 7;
|
|
4540
|
+
return { weeks, days: rem, totalDays: days, basedOn: "lmp" };
|
|
4541
|
+
}
|
|
4542
|
+
function computeGestationalAgeFromUsgEdd(eddUsgIso, today) {
|
|
4543
|
+
const daysToEdd = diffDaysUtc(today, eddUsgIso);
|
|
4544
|
+
if (daysToEdd == null) return null;
|
|
4545
|
+
const daysElapsed = 280 - daysToEdd;
|
|
4546
|
+
if (daysElapsed < 0) return null;
|
|
4547
|
+
const weeks = Math.floor(daysElapsed / 7);
|
|
4548
|
+
const rem = daysElapsed % 7;
|
|
4549
|
+
return { weeks, days: rem, totalDays: daysElapsed, basedOn: "usg" };
|
|
4550
|
+
}
|
|
4551
|
+
function computeTrimester(ga) {
|
|
4552
|
+
if (!ga) return null;
|
|
4553
|
+
if (ga.weeks < 13) return 1;
|
|
4554
|
+
if (ga.weeks < 27) return 2;
|
|
4555
|
+
if (ga.weeks < 42) return 3;
|
|
4556
|
+
return null;
|
|
4557
|
+
}
|
|
4558
|
+
function buildStored(draft, today) {
|
|
4559
|
+
const lmpIso = isValidIsoDate(draft.lmp) ? draft.lmp : null;
|
|
4560
|
+
const eddUsgIso = isValidIsoDate(draft.eddUSG) ? draft.eddUSG : null;
|
|
4561
|
+
if (!draft.is_pregnant) {
|
|
4562
|
+
return {
|
|
4563
|
+
gpal: draft.gpal,
|
|
4564
|
+
lmp: lmpIso,
|
|
4565
|
+
is_pregnant: false,
|
|
4566
|
+
edd: null,
|
|
4567
|
+
gestationalAge: null,
|
|
4568
|
+
trimester: null,
|
|
4569
|
+
complications: draft.complications.trim() ? draft.complications : null,
|
|
4570
|
+
outcome: draft.outcome
|
|
4571
|
+
};
|
|
4572
|
+
}
|
|
4573
|
+
const eddFromLmp = lmpIso ? computeEddFromLmp(lmpIso) : null;
|
|
4574
|
+
const gaFromLmp = lmpIso ? computeGestationalAgeFromLmp(lmpIso, today) : null;
|
|
4575
|
+
const gaFromUsg = eddUsgIso ? computeGestationalAgeFromUsgEdd(eddUsgIso, today) : null;
|
|
4576
|
+
const primary = draft.primaryEDD;
|
|
4577
|
+
const gaPrimary = primary === "usg" && gaFromUsg ? gaFromUsg : gaFromLmp ? gaFromLmp : null;
|
|
4578
|
+
return {
|
|
4579
|
+
gpal: draft.gpal,
|
|
4580
|
+
lmp: lmpIso,
|
|
4581
|
+
is_pregnant: true,
|
|
4582
|
+
edd: { lmp: eddFromLmp, usg: eddUsgIso, primary },
|
|
4583
|
+
gestationalAge: gaPrimary,
|
|
4584
|
+
trimester: computeTrimester(gaPrimary),
|
|
4585
|
+
complications: draft.complications.trim() ? draft.complications : null,
|
|
4586
|
+
outcome: draft.outcome
|
|
4587
|
+
};
|
|
4588
|
+
}
|
|
4589
|
+
function stripGpalSuffix(label) {
|
|
4590
|
+
return label.replace(/\s*\(G-P-A-L\)\s*$/i, "").trim();
|
|
4591
|
+
}
|
|
4592
|
+
function useDebouncedCommit(commit, delayMs) {
|
|
4593
|
+
const timeoutRef = useRef(null);
|
|
4594
|
+
const latestCommit = useRef(commit);
|
|
4595
|
+
latestCommit.current = commit;
|
|
4596
|
+
useEffect(() => {
|
|
4597
|
+
return () => {
|
|
4598
|
+
if (timeoutRef.current != null) window.clearTimeout(timeoutRef.current);
|
|
4599
|
+
};
|
|
4600
|
+
}, []);
|
|
4601
|
+
return (next) => {
|
|
4602
|
+
if (timeoutRef.current != null) window.clearTimeout(timeoutRef.current);
|
|
4603
|
+
timeoutRef.current = window.setTimeout(() => latestCommit.current(next), delayMs);
|
|
4604
|
+
};
|
|
4605
|
+
}
|
|
4606
|
+
var ObstetricHistoryWidget = ({ fieldId }) => {
|
|
4607
|
+
const { fieldDef, value, setValue, disabled } = useField(fieldId);
|
|
4608
|
+
const [{ draft, isNewEntry }, setDraftState] = useState(() => normalizeToDraft(value));
|
|
4609
|
+
const [lmpError, setLmpError] = useState(null);
|
|
4610
|
+
const [primaryEddError, setPrimaryEddError] = useState(null);
|
|
4611
|
+
const [activeGpalKey, setActiveGpalKey] = useState(null);
|
|
4612
|
+
const refs = {
|
|
4613
|
+
G: useRef(null),
|
|
4614
|
+
P: useRef(null),
|
|
4615
|
+
A: useRef(null),
|
|
4616
|
+
L: useRef(null)
|
|
4617
|
+
};
|
|
4618
|
+
const today = useMemo(() => todayIso(), []);
|
|
4619
|
+
useEffect(() => {
|
|
4620
|
+
const next = normalizeToDraft(value);
|
|
4621
|
+
const currStr = JSON.stringify(buildStored(draft, today));
|
|
4622
|
+
const nextStr = JSON.stringify(buildStored(next.draft, today));
|
|
4623
|
+
if (currStr !== nextStr) setDraftState(next);
|
|
4624
|
+
}, [value]);
|
|
4625
|
+
const commitImmediate = (nextDraft) => {
|
|
4626
|
+
const stored = buildStored(nextDraft, today);
|
|
4627
|
+
setValue(JSON.stringify(stored));
|
|
4628
|
+
};
|
|
4629
|
+
const commitDebounced = useDebouncedCommit(commitImmediate, 500);
|
|
4630
|
+
const storedComputed = useMemo(() => buildStored(draft, today), [draft, today]);
|
|
4631
|
+
const rightPanelEnabled = draft.is_pregnant && (!!storedComputed.lmp || !!storedComputed.edd?.usg);
|
|
4632
|
+
const headerLabel = fieldDef?.label ? stripGpalSuffix(fieldDef.label) : "Obstetric History";
|
|
4633
|
+
const setDraft = (updater, persist) => {
|
|
4634
|
+
setDraftState((prev) => {
|
|
4635
|
+
const nextDraft = updater(prev.draft);
|
|
4636
|
+
const nextState = { ...prev, draft: nextDraft };
|
|
4637
|
+
if (persist === "immediate") commitImmediate(nextDraft);
|
|
4638
|
+
else commitDebounced(nextDraft);
|
|
4639
|
+
return nextState;
|
|
4640
|
+
});
|
|
4641
|
+
};
|
|
4642
|
+
const sanitizeGpalInput = (raw) => {
|
|
4643
|
+
const digits = raw.replace(/[^\d]/g, "").slice(0, 2);
|
|
4644
|
+
if (!digits) return 0;
|
|
4645
|
+
return clampInt(Number(digits), 0, 20);
|
|
4646
|
+
};
|
|
4647
|
+
const handleGpalChange = (key, raw) => {
|
|
4648
|
+
const prevWasEmpty = draft.gpal[key] === 0 && activeGpalKey === key;
|
|
4649
|
+
const val = sanitizeGpalInput(raw);
|
|
4650
|
+
setDraft((prev) => ({ ...prev, gpal: { ...prev.gpal, [key]: val } }), "debounce");
|
|
4651
|
+
const digitsOnly = raw.replace(/[^\d]/g, "");
|
|
4652
|
+
const shouldAutoTab = digitsOnly.length === 1 && (prevWasEmpty || String(draft.gpal[key]).length >= 1);
|
|
4653
|
+
if (shouldAutoTab) {
|
|
4654
|
+
const order = ["G", "P", "A", "L"];
|
|
4655
|
+
const idx = order.indexOf(key);
|
|
4656
|
+
const nextKey = order[idx + 1];
|
|
4657
|
+
if (nextKey) refs[nextKey].current?.focus();
|
|
4658
|
+
}
|
|
4659
|
+
};
|
|
4660
|
+
const handleLmpChange = (nextIso) => {
|
|
4661
|
+
setPrimaryEddError(null);
|
|
4662
|
+
if (nextIso && nextIso > today) {
|
|
4663
|
+
setLmpError("LMP cannot be in the future");
|
|
4664
|
+
return;
|
|
4665
|
+
}
|
|
4666
|
+
setLmpError(null);
|
|
4667
|
+
setDraft((prev) => ({ ...prev, lmp: nextIso }), "debounce");
|
|
4668
|
+
};
|
|
4669
|
+
const handlePregStatus = (isPregnant) => {
|
|
4670
|
+
setLmpError(null);
|
|
4671
|
+
setPrimaryEddError(null);
|
|
4672
|
+
setDraft((prev) => ({ ...prev, is_pregnant: isPregnant }), "immediate");
|
|
4673
|
+
};
|
|
4674
|
+
const handleEddUsgChange = (nextIso) => {
|
|
4675
|
+
setPrimaryEddError(null);
|
|
4676
|
+
setDraft((prev) => ({ ...prev, eddUSG: nextIso }), "debounce");
|
|
4677
|
+
};
|
|
4678
|
+
const handlePrimaryEdd = (next) => {
|
|
4679
|
+
if (next === "usg" && !isValidIsoDate(draft.eddUSG)) {
|
|
4680
|
+
setPrimaryEddError("Please enter EDD from USG first");
|
|
4681
|
+
return;
|
|
4682
|
+
}
|
|
4683
|
+
setPrimaryEddError(null);
|
|
4684
|
+
setDraft((prev) => ({ ...prev, primaryEDD: next }), "immediate");
|
|
4685
|
+
};
|
|
4686
|
+
const ensureOutcome = () => {
|
|
4687
|
+
if (draft.outcome) return;
|
|
4688
|
+
setDraft(
|
|
4689
|
+
(prev) => ({
|
|
4690
|
+
...prev,
|
|
4691
|
+
outcome: { type: "", date: "", notes: "", is_final: false }
|
|
4692
|
+
}),
|
|
4693
|
+
"immediate"
|
|
4694
|
+
);
|
|
4695
|
+
};
|
|
4696
|
+
const clearOutcome = () => {
|
|
4697
|
+
setDraft((prev) => ({ ...prev, outcome: null }), "immediate");
|
|
4698
|
+
};
|
|
4699
|
+
const updateOutcomeImmediate = (updater) => {
|
|
4700
|
+
setDraft(
|
|
4701
|
+
(prev) => {
|
|
4702
|
+
const o = prev.outcome ?? { type: "", date: "", notes: "", is_final: false };
|
|
4703
|
+
return { ...prev, outcome: updater(o) };
|
|
4704
|
+
},
|
|
4705
|
+
"immediate"
|
|
4706
|
+
);
|
|
4707
|
+
};
|
|
4708
|
+
const updateOutcomeNotesDebounced = (notes) => {
|
|
4709
|
+
setDraft(
|
|
4710
|
+
(prev) => {
|
|
4711
|
+
const o = prev.outcome ?? { type: "", date: "", notes: "", is_final: false };
|
|
4712
|
+
return { ...prev, outcome: { ...o, notes } };
|
|
4713
|
+
},
|
|
4714
|
+
"debounce"
|
|
4715
|
+
);
|
|
4716
|
+
};
|
|
4717
|
+
return /* @__PURE__ */ jsxs(Card, { className: cn("w-full", disabled && "opacity-70 pointer-events-none"), children: [
|
|
4718
|
+
/* @__PURE__ */ jsx(CardHeader, { className: "pb-3", children: /* @__PURE__ */ jsx(CardTitle, { className: "text-base font-semibold", children: headerLabel }) }),
|
|
4719
|
+
/* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
|
|
4720
|
+
isNewEntry && /* @__PURE__ */ jsx("div", { className: "rounded-md border border-blue-200 bg-blue-50 px-3 py-2 text-xs text-blue-900", children: "No previous maternity episode found. Please fill obstetric details to start tracking." }),
|
|
4721
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4 items-start", children: [
|
|
4722
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
4723
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-white p-4", children: [
|
|
4724
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs font-medium text-muted-foreground mb-2", children: "G-P-A-L" }),
|
|
4725
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-4 gap-3", children: ["G", "P", "A", "L"].map((k) => /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
4726
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: `${fieldId}-gpal-${k}`, className: "text-[11px] text-muted-foreground", children: k }),
|
|
4727
|
+
/* @__PURE__ */ jsx(
|
|
4728
|
+
Input,
|
|
4729
|
+
{
|
|
4730
|
+
ref: refs[k],
|
|
4731
|
+
id: `${fieldId}-gpal-${k}`,
|
|
4732
|
+
inputMode: "numeric",
|
|
4733
|
+
pattern: "\\d*",
|
|
4734
|
+
maxLength: 2,
|
|
4735
|
+
value: String(draft.gpal[k] ?? 0),
|
|
4736
|
+
onFocus: () => {
|
|
4737
|
+
setActiveGpalKey(k);
|
|
4738
|
+
const el = refs[k].current;
|
|
4739
|
+
if (el) el.select();
|
|
4740
|
+
},
|
|
4741
|
+
onChange: (e) => handleGpalChange(k, e.target.value),
|
|
4742
|
+
onKeyDown: (e) => {
|
|
4743
|
+
const allowed = ["Backspace", "Delete", "ArrowLeft", "ArrowRight", "Tab", "Home", "End"];
|
|
4744
|
+
if (allowed.includes(e.key)) return;
|
|
4745
|
+
if (/^\d$/.test(e.key)) return;
|
|
4746
|
+
e.preventDefault();
|
|
4747
|
+
},
|
|
4748
|
+
className: "text-center text-base"
|
|
4749
|
+
}
|
|
4750
|
+
)
|
|
4751
|
+
] }, k)) })
|
|
4752
|
+
] }),
|
|
4753
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [
|
|
4754
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2 rounded-lg border bg-white p-4", children: [
|
|
4755
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: `${fieldId}-lmp`, className: cn("text-sm", lmpError && "text-red-600"), children: "Last Menstrual Period (LMP)" }),
|
|
4756
|
+
/* @__PURE__ */ jsx(
|
|
4757
|
+
Input,
|
|
4758
|
+
{
|
|
4759
|
+
id: `${fieldId}-lmp`,
|
|
4760
|
+
type: "date",
|
|
4761
|
+
max: today,
|
|
4762
|
+
value: draft.lmp,
|
|
4763
|
+
onChange: (e) => handleLmpChange(e.target.value),
|
|
4764
|
+
className: cn(lmpError && "border-red-500")
|
|
4765
|
+
}
|
|
4766
|
+
),
|
|
4767
|
+
lmpError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-600", children: lmpError })
|
|
4768
|
+
] }),
|
|
4769
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2 rounded-lg border bg-white p-4", children: [
|
|
4770
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium", children: "Pregnancy Status" }),
|
|
4771
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
4772
|
+
/* @__PURE__ */ jsx(
|
|
4773
|
+
"button",
|
|
4774
|
+
{
|
|
4775
|
+
type: "button",
|
|
4776
|
+
onClick: () => handlePregStatus(false),
|
|
4777
|
+
className: cn(
|
|
4778
|
+
"flex-1 rounded-md border px-3 py-2 text-xs",
|
|
4779
|
+
!draft.is_pregnant ? "bg-green-600 text-white border-green-600" : "bg-white"
|
|
4780
|
+
),
|
|
4781
|
+
children: "Not Pregnant"
|
|
4782
|
+
}
|
|
4783
|
+
),
|
|
4784
|
+
/* @__PURE__ */ jsx(
|
|
4785
|
+
"button",
|
|
4786
|
+
{
|
|
4787
|
+
type: "button",
|
|
4788
|
+
onClick: () => handlePregStatus(true),
|
|
4789
|
+
className: cn(
|
|
4790
|
+
"flex-1 rounded-md border px-3 py-2 text-xs",
|
|
4791
|
+
draft.is_pregnant ? "bg-green-600 text-white border-green-600" : "bg-white"
|
|
4792
|
+
),
|
|
4793
|
+
children: "Pregnant"
|
|
4794
|
+
}
|
|
4795
|
+
)
|
|
4796
|
+
] })
|
|
4797
|
+
] })
|
|
4798
|
+
] }),
|
|
4799
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2 rounded-lg border bg-white p-4", children: [
|
|
4800
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: `${fieldId}-complications`, className: "text-sm", children: "Previous Pregnancy Complications" }),
|
|
4801
|
+
/* @__PURE__ */ jsx(
|
|
4802
|
+
Textarea,
|
|
4803
|
+
{
|
|
4804
|
+
id: `${fieldId}-complications`,
|
|
4805
|
+
placeholder: "e.g. Pre-eclampsia, Gestational diabetes, C-section, etc.",
|
|
4806
|
+
value: draft.complications,
|
|
4807
|
+
onChange: (e) => setDraft((prev) => ({ ...prev, complications: e.target.value }), "debounce"),
|
|
4808
|
+
className: "min-h-[140px]"
|
|
4809
|
+
}
|
|
4810
|
+
)
|
|
4811
|
+
] })
|
|
4812
|
+
] }),
|
|
4813
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-white p-4 min-h-[260px]", children: [
|
|
4814
|
+
!draft.is_pregnant && /* @__PURE__ */ jsx("div", { className: "h-full flex items-center justify-center text-center text-sm text-muted-foreground px-6 py-10", children: 'Only for "Pregnant Women" and enter LMP to calculate gestational age and EDD' }),
|
|
4815
|
+
draft.is_pregnant && !rightPanelEnabled && /* @__PURE__ */ jsx("div", { className: "h-full flex items-center justify-center text-center text-sm text-muted-foreground px-6 py-10", children: "Enter LMP and/or EDD (USG) to enable gestational age and EDD calculations." }),
|
|
4816
|
+
draft.is_pregnant && rightPanelEnabled && /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
4817
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border p-4", children: [
|
|
4818
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
4819
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm font-semibold text-blue-700", children: "Expected Delivery Date (EDD)" }),
|
|
4820
|
+
storedComputed.gestationalAge?.basedOn && /* @__PURE__ */ jsxs("span", { className: "rounded-full bg-blue-100 px-2 py-1 text-[11px] text-blue-700", children: [
|
|
4821
|
+
"Based on ",
|
|
4822
|
+
storedComputed.gestationalAge.basedOn.toUpperCase()
|
|
4823
|
+
] })
|
|
4824
|
+
] }),
|
|
4825
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-3", children: [
|
|
4826
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: "Gestational Age:" }),
|
|
4827
|
+
/* @__PURE__ */ jsx("div", { className: "text-lg font-semibold", children: storedComputed.gestationalAge ? `${storedComputed.gestationalAge.weeks} weeks ${storedComputed.gestationalAge.days} days` : "\u2014" }),
|
|
4828
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground mt-1", children: storedComputed.trimester ? `Trimester ${storedComputed.trimester}` : "Trimester \u2014" })
|
|
4829
|
+
] })
|
|
4830
|
+
] }),
|
|
4831
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
4832
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: "EDD (from LMP):" }),
|
|
4833
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-md border bg-muted/20 px-3 py-2 text-sm font-semibold", children: storedComputed.edd?.lmp ? formatDdMmYyyy(storedComputed.edd.lmp) : "\u2014" })
|
|
4834
|
+
] }),
|
|
4835
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
4836
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: `${fieldId}-edd-usg`, className: "text-sm", children: "EDD (from USG):" }),
|
|
4837
|
+
/* @__PURE__ */ jsx(
|
|
4838
|
+
Input,
|
|
4839
|
+
{
|
|
4840
|
+
id: `${fieldId}-edd-usg`,
|
|
4841
|
+
type: "date",
|
|
4842
|
+
value: draft.eddUSG,
|
|
4843
|
+
onChange: (e) => handleEddUsgChange(e.target.value)
|
|
4844
|
+
}
|
|
4845
|
+
)
|
|
4846
|
+
] }),
|
|
4847
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
4848
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium", children: "Primary EDD:" }),
|
|
4849
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
4850
|
+
/* @__PURE__ */ jsx(
|
|
4851
|
+
"button",
|
|
4852
|
+
{
|
|
4853
|
+
type: "button",
|
|
4854
|
+
onClick: () => handlePrimaryEdd("lmp"),
|
|
4855
|
+
className: cn(
|
|
4856
|
+
"flex-1 rounded-md border px-3 py-2 text-sm",
|
|
4857
|
+
draft.primaryEDD === "lmp" ? "bg-blue-600 text-white border-blue-600" : "bg-white"
|
|
4858
|
+
),
|
|
4859
|
+
children: "LMP"
|
|
4860
|
+
}
|
|
4861
|
+
),
|
|
4862
|
+
/* @__PURE__ */ jsx(
|
|
4863
|
+
"button",
|
|
4864
|
+
{
|
|
4865
|
+
type: "button",
|
|
4866
|
+
onClick: () => handlePrimaryEdd("usg"),
|
|
4867
|
+
className: cn(
|
|
4868
|
+
"flex-1 rounded-md border px-3 py-2 text-sm",
|
|
4869
|
+
draft.primaryEDD === "usg" ? "bg-blue-600 text-white border-blue-600" : "bg-white"
|
|
4870
|
+
),
|
|
4871
|
+
children: "USG"
|
|
4872
|
+
}
|
|
4873
|
+
)
|
|
4874
|
+
] }),
|
|
4875
|
+
primaryEddError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-600", children: primaryEddError })
|
|
4876
|
+
] })
|
|
4877
|
+
] })
|
|
4878
|
+
] })
|
|
4879
|
+
] }),
|
|
4880
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-yellow-50/60 p-4", children: [
|
|
4881
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
4882
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm font-semibold", children: "Pregnancy Outcome (Optional - To Close Episode)" }),
|
|
4883
|
+
draft.outcome && /* @__PURE__ */ jsx("button", { type: "button", className: "text-sm text-red-600 hover:underline", onClick: clearOutcome, children: "Clear" })
|
|
4884
|
+
] }),
|
|
4885
|
+
!draft.outcome && /* @__PURE__ */ jsx(
|
|
4886
|
+
"button",
|
|
4887
|
+
{
|
|
4888
|
+
type: "button",
|
|
4889
|
+
onClick: ensureOutcome,
|
|
4890
|
+
className: "mt-3 w-full rounded-md border border-yellow-300 bg-yellow-100 px-3 py-2 text-sm font-medium",
|
|
4891
|
+
children: "+ Add Pregnancy Outcome"
|
|
4892
|
+
}
|
|
4893
|
+
),
|
|
4894
|
+
draft.outcome && /* @__PURE__ */ jsxs("div", { className: "mt-4 space-y-3", children: [
|
|
4895
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
4896
|
+
/* @__PURE__ */ jsxs(Label, { className: "text-sm", children: [
|
|
4897
|
+
"Outcome Type ",
|
|
4898
|
+
/* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
|
|
4899
|
+
] }),
|
|
4900
|
+
/* @__PURE__ */ jsxs(
|
|
4901
|
+
"select",
|
|
4902
|
+
{
|
|
4903
|
+
className: "w-full rounded-md border px-3 py-2 text-sm bg-white",
|
|
4904
|
+
value: draft.outcome.type,
|
|
4905
|
+
onChange: (e) => updateOutcomeImmediate((o) => ({ ...o, type: e.target.value })),
|
|
4906
|
+
children: [
|
|
4907
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Select outcome..." }),
|
|
4908
|
+
/* @__PURE__ */ jsx("option", { value: "delivery", children: "Normal Delivery" }),
|
|
4909
|
+
/* @__PURE__ */ jsx("option", { value: "cesarean", children: "Cesarean Section" }),
|
|
4910
|
+
/* @__PURE__ */ jsx("option", { value: "abortion", children: "Abortion" }),
|
|
4911
|
+
/* @__PURE__ */ jsx("option", { value: "miscarriage", children: "Miscarriage" }),
|
|
4912
|
+
/* @__PURE__ */ jsx("option", { value: "stillbirth", children: "Stillbirth" })
|
|
4913
|
+
]
|
|
4914
|
+
}
|
|
4915
|
+
)
|
|
4916
|
+
] }),
|
|
4917
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
4918
|
+
/* @__PURE__ */ jsxs(Label, { htmlFor: `${fieldId}-outcome-date`, className: "text-sm", children: [
|
|
4919
|
+
"Date ",
|
|
4920
|
+
/* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
|
|
4921
|
+
] }),
|
|
4922
|
+
/* @__PURE__ */ jsx(
|
|
4923
|
+
Input,
|
|
4924
|
+
{
|
|
4925
|
+
id: `${fieldId}-outcome-date`,
|
|
4926
|
+
type: "date",
|
|
4927
|
+
max: today,
|
|
4928
|
+
value: draft.outcome.date,
|
|
4929
|
+
onChange: (e) => updateOutcomeImmediate((o) => ({ ...o, date: e.target.value }))
|
|
4930
|
+
}
|
|
4931
|
+
),
|
|
4932
|
+
draft.outcome.date && /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
4933
|
+
"Selected: ",
|
|
4934
|
+
formatDdMmYyyy(draft.outcome.date)
|
|
4935
|
+
] })
|
|
4936
|
+
] }),
|
|
4937
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
4938
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: `${fieldId}-outcome-notes`, className: "text-sm", children: "Notes" }),
|
|
4939
|
+
/* @__PURE__ */ jsx(
|
|
4940
|
+
Textarea,
|
|
4941
|
+
{
|
|
4942
|
+
id: `${fieldId}-outcome-notes`,
|
|
4943
|
+
placeholder: "e.g. Normal vaginal delivery, healthy baby boy, 3.2kg",
|
|
4944
|
+
value: draft.outcome.notes,
|
|
4945
|
+
onChange: (e) => updateOutcomeNotesDebounced(e.target.value),
|
|
4946
|
+
className: "min-h-[90px]"
|
|
4947
|
+
}
|
|
4948
|
+
)
|
|
4949
|
+
] }),
|
|
4950
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-md border bg-white p-3", children: [
|
|
4951
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm", children: [
|
|
4952
|
+
/* @__PURE__ */ jsx(
|
|
4953
|
+
"input",
|
|
4954
|
+
{
|
|
4955
|
+
type: "checkbox",
|
|
4956
|
+
checked: !!draft.outcome.is_final,
|
|
4957
|
+
onChange: (e) => updateOutcomeImmediate((o) => ({ ...o, is_final: e.target.checked }))
|
|
4958
|
+
}
|
|
4959
|
+
),
|
|
4960
|
+
"Close this pregnancy episode"
|
|
4961
|
+
] }),
|
|
4962
|
+
draft.outcome.is_final && /* @__PURE__ */ jsx("div", { className: "mt-3 rounded-md border border-red-300 bg-red-50 px-3 py-2 text-xs text-red-800", children: "Checking this will mark the pregnancy as completed and is intended to close the maternity episode." })
|
|
4963
|
+
] })
|
|
4964
|
+
] })
|
|
4965
|
+
] })
|
|
4966
|
+
] })
|
|
4967
|
+
] });
|
|
4968
|
+
};
|
|
4217
4969
|
var FieldRenderer = ({ fieldId }) => {
|
|
4218
4970
|
const { fieldDef, visible } = useField(fieldId);
|
|
4219
4971
|
if (!visible || !fieldDef) {
|
|
@@ -4262,6 +5014,8 @@ var FieldRenderer = ({ fieldId }) => {
|
|
|
4262
5014
|
return /* @__PURE__ */ jsx(FollowupWidget, { fieldId });
|
|
4263
5015
|
case "smart_textarea":
|
|
4264
5016
|
return /* @__PURE__ */ jsx(SmartTextareaWidget, { fieldId });
|
|
5017
|
+
case "obstetric_history":
|
|
5018
|
+
return /* @__PURE__ */ jsx(ObstetricHistoryWidget, { fieldId });
|
|
4265
5019
|
case "static_text": {
|
|
4266
5020
|
const def = fieldDef;
|
|
4267
5021
|
const size = def.size ?? "regular";
|
|
@@ -5010,6 +5764,6 @@ function createUploadHandler(options) {
|
|
|
5010
5764
|
};
|
|
5011
5765
|
}
|
|
5012
5766
|
|
|
5013
|
-
export { AddInvestigationField, AddMedicationField, DifferentialDiagnosis, DynamicForm, EMAIL_REGEX, FieldRenderer, FormControls, FormProvider, FormStore, ImageUploadWidget, ReadOnlyForm, ReadOnlyImageUpload, ReadOnlySignature, ReadOnlyTable, SignatureUploadWidget, SmartForm, SmartTextareaWidget, createUploadHandler, evaluateRules, useField, useFieldHandlers, useForm, useFormStore, useSmartKeywords, validateField, validateForm };
|
|
5767
|
+
export { AddInvestigationField, AddMedicationField, DifferentialDiagnosis, DynamicForm, EMAIL_REGEX, FieldRenderer, FormControls, FormProvider, FormStore, ImageUploadWidget, ReadOnlyForm, ReadOnlyImageUpload, ReadOnlySignature, ReadOnlyTable, SignatureUploadWidget, SmartForm, SmartTextareaWidget, createUploadHandler, evaluateRules, useField, useFieldHandlers, useForm, useFormStore, useFrequentItems, useSmartKeywords, validateField, validateForm };
|
|
5014
5768
|
//# sourceMappingURL=index.mjs.map
|
|
5015
5769
|
//# sourceMappingURL=index.mjs.map
|