formanitor 0.0.48 → 0.0.50

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.mjs CHANGED
@@ -32,8 +32,25 @@ function fieldMetaRequestsMarMedicationOrdersButton(meta) {
32
32
 
33
33
  // src/core/validate.ts
34
34
  var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
35
- function validateField(value, field) {
35
+ function validateField(value, field, allValues) {
36
36
  if (field.hidden || field.disabled) return null;
37
+ if (field.type === "otp_input") {
38
+ if (field.required) {
39
+ if (!value || typeof value !== "object" || value.verified !== true) {
40
+ return "Please verify your mobile number with OTP";
41
+ }
42
+ const otpField = field;
43
+ const phoneFieldId = otpField.meta?.phoneFieldId ?? "phone";
44
+ if (allValues) {
45
+ const phoneRaw = allValues[phoneFieldId] ?? "";
46
+ const e164 = phoneRaw.startsWith("+") ? phoneRaw : `+91${phoneRaw}`;
47
+ if (value.phone && value.phone !== e164) {
48
+ return "Mobile number changed \u2014 please re-verify";
49
+ }
50
+ }
51
+ }
52
+ return null;
53
+ }
37
54
  if (field.required) {
38
55
  if (value === null || value === void 0 || value === "") {
39
56
  return "This field is required";
@@ -94,7 +111,7 @@ function validateForm(values, fields) {
94
111
  const errors = {};
95
112
  for (const [key, field] of Object.entries(fields)) {
96
113
  if (field.type === "static_text") continue;
97
- const error = validateField(values[key], field);
114
+ const error = validateField(values[key], field, values);
98
115
  if (error) {
99
116
  errors[key] = error;
100
117
  }
@@ -1171,6 +1188,9 @@ var FormStore = class {
1171
1188
  persistence;
1172
1189
  prefillData = {};
1173
1190
  config;
1191
+ // Widget-owned errors that schema validation cannot express (e.g. "OTP not sent yet").
1192
+ // Merged on top of validateForm output in evaluate().
1193
+ externalErrors = {};
1174
1194
  // Cache for debounce
1175
1195
  saveTimeout = null;
1176
1196
  draftCallbackTimeout = null;
@@ -1290,6 +1310,9 @@ var FormStore = class {
1290
1310
  getSchema() {
1291
1311
  return this.schema;
1292
1312
  }
1313
+ getConfig() {
1314
+ return this.config;
1315
+ }
1293
1316
  getFieldDef(fieldId) {
1294
1317
  return this.fieldMap[fieldId];
1295
1318
  }
@@ -1337,6 +1360,17 @@ var FormStore = class {
1337
1360
  this.notify();
1338
1361
  this.scheduleSave();
1339
1362
  }
1363
+ /**
1364
+ * Let a widget report an error that schema validation cannot express
1365
+ * (e.g. "Send OTP to continue" until the API call succeeds).
1366
+ * Pass `null` to clear a previously set external error.
1367
+ */
1368
+ setExternalError(fieldId, message) {
1369
+ if ((this.externalErrors[fieldId] ?? null) === message) return;
1370
+ this.externalErrors = { ...this.externalErrors, [fieldId]: message };
1371
+ this.evaluate();
1372
+ this.notify();
1373
+ }
1340
1374
  setTouched(fieldId) {
1341
1375
  if (this.state.touched[fieldId]) return;
1342
1376
  this.state.touched = { ...this.state.touched, [fieldId]: true };
@@ -1465,16 +1499,42 @@ var FormStore = class {
1465
1499
  result[field.id] = parts.length > 0 ? parts.join("\n\n") : null;
1466
1500
  return;
1467
1501
  }
1468
- if (field.type === "image_upload" || field.type === "media_upload" || field.type === "signature") {
1502
+ if (field.type === "otp_input") {
1469
1503
  const raw = values[field.id];
1470
- if (raw !== void 0 && raw !== null && raw !== "") {
1471
- const key = typeof raw === "string" ? raw : raw.s3_key || raw.value || null;
1472
- if (key && typeof key === "string") {
1473
- result[field.id] = {
1474
- _type: "s3_key",
1475
- value: key
1476
- };
1504
+ if (typeof raw === "string") {
1505
+ result[field.id] = raw;
1506
+ return;
1507
+ }
1508
+ if (raw && typeof raw === "object" && !Array.isArray(raw) && raw.verified === true) {
1509
+ const code = raw.code;
1510
+ result[field.id] = typeof code === "string" ? code : null;
1511
+ return;
1512
+ }
1513
+ result[field.id] = null;
1514
+ return;
1515
+ }
1516
+ if (field.type === "image_upload" || field.type === "media_upload" || field.type === "signature" || field.type === "file_upload") {
1517
+ const raw = values[field.id];
1518
+ if (raw === void 0 || raw === null || raw === "") {
1519
+ return;
1520
+ }
1521
+ const wrapKey = (key2) => {
1522
+ if (typeof key2 !== "string" || !key2) return null;
1523
+ return { _type: "s3_key", value: key2 };
1524
+ };
1525
+ if (Array.isArray(raw)) {
1526
+ const wrapped2 = raw.map(
1527
+ (item) => typeof item === "string" ? wrapKey(item) : wrapKey(item.s3_key ?? item.value)
1528
+ ).filter(Boolean);
1529
+ if (wrapped2.length > 0) {
1530
+ result[field.id] = wrapped2;
1477
1531
  }
1532
+ return;
1533
+ }
1534
+ const key = typeof raw === "string" ? raw : raw.s3_key ?? raw.value ?? null;
1535
+ const wrapped = wrapKey(key);
1536
+ if (wrapped) {
1537
+ result[field.id] = wrapped;
1478
1538
  }
1479
1539
  }
1480
1540
  });
@@ -1581,8 +1641,12 @@ var FormStore = class {
1581
1641
  };
1582
1642
  });
1583
1643
  const errors = validateForm(this.state.values, effectiveFields);
1584
- this.state.errors = errors;
1585
- this.state.isValid = Object.keys(errors).length === 0;
1644
+ const merged = { ...errors };
1645
+ for (const [id, msg] of Object.entries(this.externalErrors)) {
1646
+ if (msg) merged[id] = msg;
1647
+ }
1648
+ this.state.errors = merged;
1649
+ this.state.isValid = Object.keys(merged).length === 0;
1586
1650
  }
1587
1651
  // --- Workflow ---
1588
1652
  getAvailableTransitions() {
@@ -3708,6 +3772,190 @@ var SignatureUploadWidget = ({ fieldId }) => {
3708
3772
  showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
3709
3773
  ] });
3710
3774
  };
3775
+ function Upload3({
3776
+ value,
3777
+ accept,
3778
+ multiple,
3779
+ disabled,
3780
+ onChange,
3781
+ className,
3782
+ formatsLabel,
3783
+ placeholder = "Upload File",
3784
+ beforeUploadContent,
3785
+ id: idProp
3786
+ }) {
3787
+ const inputRef = React15__default.useRef(null);
3788
+ const generatedId = React15__default.useId();
3789
+ const inputId = idProp ?? generatedId;
3790
+ const handleFileChange = (e) => {
3791
+ onChange(e.target.files ?? null);
3792
+ };
3793
+ React15__default.useEffect(() => {
3794
+ if (!value && inputRef.current) {
3795
+ inputRef.current.value = "";
3796
+ }
3797
+ }, [value]);
3798
+ const count = value?.length ?? 0;
3799
+ const formatsText = formatsLabel ?? accept;
3800
+ return /* @__PURE__ */ jsxs(
3801
+ "div",
3802
+ {
3803
+ className: cn(
3804
+ "border border-dashed bg-[#F7F7F7] border-gray-200 rounded-lg py-5 px-4 flex items-center justify-center text-[#989898]",
3805
+ disabled && "opacity-50 pointer-events-none",
3806
+ className
3807
+ ),
3808
+ children: [
3809
+ /* @__PURE__ */ jsx(
3810
+ "input",
3811
+ {
3812
+ type: "file",
3813
+ ref: inputRef,
3814
+ accept,
3815
+ id: inputId,
3816
+ className: "hidden",
3817
+ multiple,
3818
+ disabled,
3819
+ onChange: handleFileChange
3820
+ }
3821
+ ),
3822
+ /* @__PURE__ */ jsx(
3823
+ "label",
3824
+ {
3825
+ htmlFor: inputId,
3826
+ className: cn("cursor-pointer w-full", disabled && "cursor-not-allowed"),
3827
+ children: /* @__PURE__ */ jsx("div", { children: count > 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center text-sm font-semibold text-gray-700", children: [
3828
+ count,
3829
+ " file",
3830
+ count === 1 ? "" : "s",
3831
+ " selected"
3832
+ ] }) : beforeUploadContent ? beforeUploadContent : /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center", children: [
3833
+ /* @__PURE__ */ jsx(Upload, { size: 16, className: "rotate-180" }),
3834
+ /* @__PURE__ */ jsx("div", { className: "text-xs font-semibold mt-0.5 text-gray-700", children: placeholder }),
3835
+ formatsText ? /* @__PURE__ */ jsxs("div", { className: "mt-3 text-[10px]", children: [
3836
+ "Supported formats - ",
3837
+ formatsText
3838
+ ] }) : null
3839
+ ] }) })
3840
+ }
3841
+ )
3842
+ ]
3843
+ }
3844
+ );
3845
+ }
3846
+ function fileListFromArray(files) {
3847
+ const dt = new DataTransfer();
3848
+ files.forEach((f) => dt.items.add(f));
3849
+ return dt.files;
3850
+ }
3851
+ function matchesAccept(file, accept) {
3852
+ if (!accept || accept === "*/*") return true;
3853
+ const tokens = accept.split(",").map((t) => t.trim().toLowerCase());
3854
+ const name = file.name.toLowerCase();
3855
+ const type = file.type.toLowerCase();
3856
+ return tokens.some((token) => {
3857
+ if (token.startsWith(".")) return name.endsWith(token);
3858
+ if (token.endsWith("/*")) {
3859
+ const prefix = token.slice(0, -1);
3860
+ return type.startsWith(prefix);
3861
+ }
3862
+ return type === token;
3863
+ });
3864
+ }
3865
+ var FormFileUploadWidget = ({
3866
+ fieldId
3867
+ }) => {
3868
+ const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
3869
+ const store = useFormStore();
3870
+ const { state } = useForm();
3871
+ const [localFiles, setLocalFiles] = useState(null);
3872
+ const [isUploading, setIsUploading] = useState(false);
3873
+ const showError = !!error && (touched || state.submitAttempted);
3874
+ if (!fieldDef || fieldDef.type !== "file_upload") return null;
3875
+ const def = fieldDef;
3876
+ const accept = def.accept ?? "*/*";
3877
+ const maxSize = def.maxSize ?? 10 * 1024 * 1024;
3878
+ const allowMultiple = def.multiple === true;
3879
+ const uploadHandler = store.getUploadHandler();
3880
+ if (!uploadHandler) {
3881
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
3882
+ /* @__PURE__ */ jsxs(Label, { htmlFor: fieldId, children: [
3883
+ fieldDef.label,
3884
+ fieldDef.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
3885
+ ] }),
3886
+ /* @__PURE__ */ jsx("div", { className: "border-2 border-red-300 rounded-lg p-4 bg-red-50", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-red-600", children: "Upload handler not configured. Please provide an onUpload function in FormProvider config." }) })
3887
+ ] });
3888
+ }
3889
+ const hasStoredValue = value !== null && value !== void 0 && value !== "" && !(Array.isArray(value) && value.length === 0);
3890
+ const handleChange = async (files) => {
3891
+ setTouched();
3892
+ if (!files || files.length === 0) {
3893
+ setLocalFiles(null);
3894
+ setValue(null);
3895
+ return;
3896
+ }
3897
+ const selected = Array.from(files);
3898
+ for (const file of selected) {
3899
+ if (!matchesAccept(file, accept)) {
3900
+ alert(`File type not allowed: ${file.name}`);
3901
+ return;
3902
+ }
3903
+ if (file.size > maxSize) {
3904
+ alert(
3905
+ `File must be less than ${Math.round(maxSize / (1024 * 1024))}MB: ${file.name}`
3906
+ );
3907
+ return;
3908
+ }
3909
+ }
3910
+ const toUpload = allowMultiple ? selected : [selected[0]];
3911
+ setLocalFiles(fileListFromArray(toUpload));
3912
+ setIsUploading(true);
3913
+ store.incrementPendingUploads();
3914
+ try {
3915
+ if (allowMultiple) {
3916
+ const keys = [];
3917
+ for (const file of toUpload) {
3918
+ keys.push(await uploadHandler(file, file.name));
3919
+ }
3920
+ setValue(keys);
3921
+ } else {
3922
+ const key = await uploadHandler(toUpload[0], toUpload[0].name);
3923
+ setValue(key);
3924
+ }
3925
+ } catch (err) {
3926
+ console.error("[FormFileUpload] Upload failed:", err);
3927
+ const message = err instanceof Error ? err.message : "Upload failed. Please try again.";
3928
+ alert(message);
3929
+ setLocalFiles(null);
3930
+ setValue(null);
3931
+ } finally {
3932
+ setIsUploading(false);
3933
+ store.decrementPendingUploads();
3934
+ }
3935
+ };
3936
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
3937
+ /* @__PURE__ */ jsxs(Label, { htmlFor: fieldId, children: [
3938
+ fieldDef.label,
3939
+ fieldDef.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
3940
+ ] }),
3941
+ /* @__PURE__ */ jsx(
3942
+ Upload3,
3943
+ {
3944
+ accept,
3945
+ multiple: allowMultiple,
3946
+ value: localFiles,
3947
+ onChange: handleChange,
3948
+ disabled: disabled || isUploading,
3949
+ placeholder: isUploading ? "Uploading..." : def.uploadPlaceholder ?? "Upload File",
3950
+ formatsLabel: def.uploadFormats,
3951
+ className: isUploading ? "opacity-70" : void 0
3952
+ }
3953
+ ),
3954
+ hasStoredValue && /* @__PURE__ */ jsx("p", { className: "text-xs text-green-600", children: allowMultiple && Array.isArray(value) ? `${value.length} file(s) uploaded` : "File uploaded" }),
3955
+ fieldDef.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500", children: fieldDef.description }),
3956
+ showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
3957
+ ] });
3958
+ };
3711
3959
  var EditableTableWidget = ({
3712
3960
  fieldId
3713
3961
  }) => {
@@ -13775,6 +14023,347 @@ var OBGPathwayWidget = ({ fieldId }) => {
13775
14023
  ] })
13776
14024
  ] });
13777
14025
  };
14026
+ var RESEND_COOLDOWN_SECONDS = 30;
14027
+ var PhoneInputWidget = ({ fieldId }) => {
14028
+ const { fieldDef, error, touched, disabled, value: fieldValue } = useField(fieldId);
14029
+ const { state } = useForm();
14030
+ const store = useFormStore();
14031
+ const rawPhone = fieldValue ?? "";
14032
+ const wasAlreadySent = rawPhone.length === 10 && !error;
14033
+ const [status, setStatus] = useState(wasAlreadySent ? "sent" : "idle");
14034
+ const [resendCooldown, setResendCooldown] = useState(0);
14035
+ const [resendError, setResendError] = useState("");
14036
+ const hasSentRef = useRef(wasAlreadySent);
14037
+ const sentPhoneRef = useRef(wasAlreadySent ? rawPhone : "");
14038
+ const isSendingRef = useRef(false);
14039
+ const isResendingRef = useRef(false);
14040
+ const showError = !!error && (touched || state.submitAttempted) && status !== "sending" && status !== "sent";
14041
+ useEffect(() => {
14042
+ if (resendCooldown <= 0) return;
14043
+ const t = setTimeout(() => setResendCooldown((c) => Math.max(0, c - 1)), 1e3);
14044
+ return () => clearTimeout(t);
14045
+ }, [resendCooldown]);
14046
+ if (!fieldDef) return null;
14047
+ const placeholder = typeof fieldDef.placeholder === "string" && fieldDef.placeholder.trim() ? fieldDef.placeholder : "Enter 10-digit mobile number";
14048
+ const handleChange = (e) => {
14049
+ const digits = e.target.value.replace(/\D/g, "").slice(0, 10);
14050
+ if (hasSentRef.current && digits !== sentPhoneRef.current) {
14051
+ hasSentRef.current = false;
14052
+ sentPhoneRef.current = "";
14053
+ setStatus("idle");
14054
+ setResendCooldown(0);
14055
+ setResendError("");
14056
+ store.setExternalError(fieldId, "Send OTP to continue");
14057
+ const otpFieldId = fieldDef.meta?.otpFieldId;
14058
+ if (otpFieldId) {
14059
+ store.setValue(otpFieldId, "");
14060
+ store.setExternalError(otpFieldId, "Verify OTP to continue");
14061
+ }
14062
+ }
14063
+ store.setValue(fieldId, digits);
14064
+ if (digits.length === 10 && !hasSentRef.current && !isSendingRef.current) {
14065
+ sendOtp(digits);
14066
+ }
14067
+ };
14068
+ const sendOtp = async (phone) => {
14069
+ if (isSendingRef.current) return;
14070
+ isSendingRef.current = true;
14071
+ setStatus("sending");
14072
+ store.setExternalError(fieldId, "Sending OTP...");
14073
+ try {
14074
+ const authCfg = store.getConfig().auth;
14075
+ const base = authCfg?.baseUrl ?? ((typeof process !== "undefined" && process.env?.NEXT_PUBLIC_API_URL) ?? "");
14076
+ const sendPath = authCfg?.sendPath ?? "/api/auth/otp/send/";
14077
+ const countryCode = authCfg?.defaultCountryCode ?? "+91";
14078
+ const res = await fetch(`${base}${sendPath}`, {
14079
+ method: "POST",
14080
+ headers: { "Content-Type": "application/json" },
14081
+ body: JSON.stringify({ mobile_number: `${countryCode}${phone}` })
14082
+ });
14083
+ const data = await res.json().catch(() => ({}));
14084
+ if (res.ok) {
14085
+ hasSentRef.current = true;
14086
+ sentPhoneRef.current = phone;
14087
+ setStatus("sent");
14088
+ setResendCooldown(RESEND_COOLDOWN_SECONDS);
14089
+ store.setExternalError(fieldId, null);
14090
+ } else {
14091
+ setStatus("error");
14092
+ store.setExternalError(fieldId, data.error ?? "Failed to send OTP. Please try again.");
14093
+ }
14094
+ } catch {
14095
+ setStatus("error");
14096
+ store.setExternalError(fieldId, "Network error. Please try again.");
14097
+ } finally {
14098
+ isSendingRef.current = false;
14099
+ }
14100
+ };
14101
+ const handleResend = async () => {
14102
+ if (isResendingRef.current || resendCooldown > 0) return;
14103
+ isResendingRef.current = true;
14104
+ setResendError("");
14105
+ try {
14106
+ const authCfg = store.getConfig().auth;
14107
+ const base = authCfg?.baseUrl ?? ((typeof process !== "undefined" && process.env?.NEXT_PUBLIC_API_URL) ?? "");
14108
+ const resendPath = authCfg?.resendPath ?? "/api/auth/otp/resend/";
14109
+ const countryCode = authCfg?.defaultCountryCode ?? "+91";
14110
+ const res = await fetch(`${base}${resendPath}`, {
14111
+ method: "POST",
14112
+ headers: { "Content-Type": "application/json" },
14113
+ body: JSON.stringify({ mobile_number: `${countryCode}${rawPhone}`, retrytype: "text" })
14114
+ });
14115
+ const data = await res.json().catch(() => ({}));
14116
+ if (res.ok) {
14117
+ setResendCooldown(RESEND_COOLDOWN_SECONDS);
14118
+ setResendError("");
14119
+ } else {
14120
+ setResendError(data.error ?? "Failed to resend OTP. Please try again.");
14121
+ }
14122
+ } catch {
14123
+ setResendError("Network error. Please try again.");
14124
+ } finally {
14125
+ isResendingRef.current = false;
14126
+ }
14127
+ };
14128
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
14129
+ /* @__PURE__ */ jsxs(Label, { htmlFor: fieldId, children: [
14130
+ fieldDef.label,
14131
+ " ",
14132
+ fieldDef.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
14133
+ ] }),
14134
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
14135
+ /* @__PURE__ */ jsx(
14136
+ Input,
14137
+ {
14138
+ id: fieldId,
14139
+ type: "tel",
14140
+ inputMode: "numeric",
14141
+ value: rawPhone,
14142
+ onChange: handleChange,
14143
+ onBlur: () => store.setTouched(fieldId),
14144
+ disabled: disabled || status === "sending",
14145
+ placeholder,
14146
+ maxLength: 10,
14147
+ className: cn(
14148
+ showError && "border-red-500",
14149
+ status === "sent" && "border-green-500 pr-9",
14150
+ status === "sending" && "pr-9"
14151
+ )
14152
+ }
14153
+ ),
14154
+ status === "sending" && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-3 flex items-center pointer-events-none", children: /* @__PURE__ */ jsxs(
14155
+ "svg",
14156
+ {
14157
+ className: "animate-spin h-4 w-4 text-muted-foreground",
14158
+ viewBox: "0 0 24 24",
14159
+ fill: "none",
14160
+ children: [
14161
+ /* @__PURE__ */ jsx(
14162
+ "circle",
14163
+ {
14164
+ className: "opacity-25",
14165
+ cx: "12",
14166
+ cy: "12",
14167
+ r: "10",
14168
+ stroke: "currentColor",
14169
+ strokeWidth: "4"
14170
+ }
14171
+ ),
14172
+ /* @__PURE__ */ jsx(
14173
+ "path",
14174
+ {
14175
+ className: "opacity-75",
14176
+ fill: "currentColor",
14177
+ d: "M4 12a8 8 0 018-8v8H4z"
14178
+ }
14179
+ )
14180
+ ]
14181
+ }
14182
+ ) }),
14183
+ status === "sent" && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-3 flex items-center pointer-events-none", children: /* @__PURE__ */ jsx(
14184
+ "svg",
14185
+ {
14186
+ className: "h-4 w-4 text-green-500",
14187
+ viewBox: "0 0 20 20",
14188
+ fill: "currentColor",
14189
+ children: /* @__PURE__ */ jsx(
14190
+ "path",
14191
+ {
14192
+ fillRule: "evenodd",
14193
+ d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z",
14194
+ clipRule: "evenodd"
14195
+ }
14196
+ )
14197
+ }
14198
+ ) })
14199
+ ] }),
14200
+ status === "sent" && /* @__PURE__ */ jsxs("p", { className: "text-xs text-green-600", children: [
14201
+ "OTP sent to +91",
14202
+ rawPhone
14203
+ ] }),
14204
+ showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error }),
14205
+ status === "sent" && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
14206
+ /* @__PURE__ */ jsx("span", { children: "Didn't receive it?" }),
14207
+ /* @__PURE__ */ jsx(
14208
+ "button",
14209
+ {
14210
+ type: "button",
14211
+ onClick: handleResend,
14212
+ disabled: resendCooldown > 0,
14213
+ className: cn(
14214
+ "underline transition-colors",
14215
+ resendCooldown > 0 ? "opacity-40 cursor-not-allowed" : "text-primary hover:text-primary/80 cursor-pointer"
14216
+ ),
14217
+ children: resendCooldown > 0 ? `Resend in ${resendCooldown}s` : "Resend OTP"
14218
+ }
14219
+ )
14220
+ ] }),
14221
+ resendError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: resendError })
14222
+ ] });
14223
+ };
14224
+ var OtpInputWidget = ({ fieldId }) => {
14225
+ const { fieldDef, error, touched, disabled } = useField(fieldId);
14226
+ const { state } = useForm();
14227
+ const store = useFormStore();
14228
+ const phoneFieldId = fieldDef?.meta?.phoneFieldId ?? "phone";
14229
+ const { value: phoneValue } = useField(phoneFieldId);
14230
+ const phone = phoneValue ?? "";
14231
+ const e164Phone = phone.startsWith("+") ? phone : `+91${phone}`;
14232
+ const [otp, setOtp] = useState("");
14233
+ const [status, setStatus] = useState("idle");
14234
+ const isVerifyingRef = useRef(false);
14235
+ const showError = !!error && (touched || state.submitAttempted) && status !== "verifying" && status !== "verified";
14236
+ if (!fieldDef) return null;
14237
+ const placeholder = typeof fieldDef.placeholder === "string" && fieldDef.placeholder.trim() ? fieldDef.placeholder : "Enter 4-digit OTP";
14238
+ const handleChange = (e) => {
14239
+ const digits = e.target.value.replace(/\D/g, "").slice(0, 4);
14240
+ if (status === "failed") {
14241
+ setStatus("idle");
14242
+ store.setExternalError(fieldId, null);
14243
+ }
14244
+ setOtp(digits);
14245
+ store.setValue(fieldId, digits);
14246
+ if (digits.length === 4 && !isVerifyingRef.current) {
14247
+ verifyOtp(digits);
14248
+ }
14249
+ };
14250
+ const verifyOtp = async (code) => {
14251
+ if (isVerifyingRef.current) return;
14252
+ isVerifyingRef.current = true;
14253
+ setStatus("verifying");
14254
+ store.setExternalError(fieldId, "Verifying...");
14255
+ try {
14256
+ const authCfg = store.getConfig().auth;
14257
+ const base = authCfg?.baseUrl ?? ((typeof process !== "undefined" && process.env?.NEXT_PUBLIC_API_URL) ?? "");
14258
+ const verifyPath = authCfg?.verifyPath ?? "/api/auth/otp/verify/";
14259
+ const res = await fetch(`${base}${verifyPath}`, {
14260
+ method: "POST",
14261
+ headers: { "Content-Type": "application/json" },
14262
+ body: JSON.stringify({ mobile_number: e164Phone, otp_code: code })
14263
+ });
14264
+ const data = await res.json().catch(() => ({}));
14265
+ if (res.ok) {
14266
+ setStatus("verified");
14267
+ store.setExternalError(fieldId, null);
14268
+ store.setValue(fieldId, {
14269
+ verified: true,
14270
+ phone: e164Phone,
14271
+ code,
14272
+ ...data?.verification_token ? { token: data.verification_token } : {}
14273
+ });
14274
+ } else {
14275
+ setStatus("failed");
14276
+ const msg = data.error ?? "Invalid OTP. Please try again.";
14277
+ store.setExternalError(fieldId, msg);
14278
+ setOtp("");
14279
+ store.setValue(fieldId, "");
14280
+ }
14281
+ } catch {
14282
+ setStatus("failed");
14283
+ store.setExternalError(fieldId, "Network error. Please try again.");
14284
+ setOtp("");
14285
+ store.setValue(fieldId, "");
14286
+ } finally {
14287
+ isVerifyingRef.current = false;
14288
+ }
14289
+ };
14290
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
14291
+ /* @__PURE__ */ jsxs(Label, { htmlFor: fieldId, children: [
14292
+ fieldDef.label,
14293
+ " ",
14294
+ fieldDef.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
14295
+ ] }),
14296
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
14297
+ /* @__PURE__ */ jsx(
14298
+ Input,
14299
+ {
14300
+ id: fieldId,
14301
+ type: "tel",
14302
+ inputMode: "numeric",
14303
+ value: otp,
14304
+ onChange: handleChange,
14305
+ onBlur: () => store.setTouched(fieldId),
14306
+ disabled: disabled || status === "verifying" || status === "verified",
14307
+ placeholder,
14308
+ maxLength: 4,
14309
+ className: cn(
14310
+ "tracking-widest text-center text-lg",
14311
+ showError && "border-red-500",
14312
+ status === "verified" && "border-green-500 pr-9",
14313
+ status === "verifying" && "pr-9"
14314
+ )
14315
+ }
14316
+ ),
14317
+ status === "verifying" && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-3 flex items-center pointer-events-none", children: /* @__PURE__ */ jsxs(
14318
+ "svg",
14319
+ {
14320
+ className: "animate-spin h-4 w-4 text-muted-foreground",
14321
+ viewBox: "0 0 24 24",
14322
+ fill: "none",
14323
+ children: [
14324
+ /* @__PURE__ */ jsx(
14325
+ "circle",
14326
+ {
14327
+ className: "opacity-25",
14328
+ cx: "12",
14329
+ cy: "12",
14330
+ r: "10",
14331
+ stroke: "currentColor",
14332
+ strokeWidth: "4"
14333
+ }
14334
+ ),
14335
+ /* @__PURE__ */ jsx(
14336
+ "path",
14337
+ {
14338
+ className: "opacity-75",
14339
+ fill: "currentColor",
14340
+ d: "M4 12a8 8 0 018-8v8H4z"
14341
+ }
14342
+ )
14343
+ ]
14344
+ }
14345
+ ) }),
14346
+ status === "verified" && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-3 flex items-center pointer-events-none", children: /* @__PURE__ */ jsx(
14347
+ "svg",
14348
+ {
14349
+ className: "h-4 w-4 text-green-500",
14350
+ viewBox: "0 0 20 20",
14351
+ fill: "currentColor",
14352
+ children: /* @__PURE__ */ jsx(
14353
+ "path",
14354
+ {
14355
+ fillRule: "evenodd",
14356
+ d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z",
14357
+ clipRule: "evenodd"
14358
+ }
14359
+ )
14360
+ }
14361
+ ) })
14362
+ ] }),
14363
+ status === "verified" && /* @__PURE__ */ jsx("p", { className: "text-xs text-green-600", children: "Mobile number verified successfully" }),
14364
+ showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
14365
+ ] });
14366
+ };
13778
14367
  var FieldRenderer = ({ fieldId }) => {
13779
14368
  const { fieldDef, visible } = useField(fieldId);
13780
14369
  if (!visible || !fieldDef) {
@@ -13814,6 +14403,8 @@ function renderWidget(fieldId, fieldDef) {
13814
14403
  return /* @__PURE__ */ jsx(ImageUploadWidget, { fieldId });
13815
14404
  case "media_upload":
13816
14405
  return /* @__PURE__ */ jsx(MediaUploadWidget, { fieldId });
14406
+ case "file_upload":
14407
+ return /* @__PURE__ */ jsx(FormFileUploadWidget, { fieldId });
13817
14408
  case "signature":
13818
14409
  return /* @__PURE__ */ jsx(SignatureUploadWidget, { fieldId });
13819
14410
  case "editable_table":
@@ -13866,6 +14457,10 @@ function renderWidget(fieldId, fieldDef) {
13866
14457
  return /* @__PURE__ */ jsx(OBGExaminationWidget, { fieldId });
13867
14458
  case "obg_pathway":
13868
14459
  return /* @__PURE__ */ jsx(OBGPathwayWidget, { fieldId });
14460
+ case "phone_input":
14461
+ return /* @__PURE__ */ jsx(PhoneInputWidget, { fieldId });
14462
+ case "otp_input":
14463
+ return /* @__PURE__ */ jsx(OtpInputWidget, { fieldId });
13869
14464
  case "toggle": {
13870
14465
  const { value, setValue, setTouched, disabled } = useField(fieldId);
13871
14466
  const store = useFormStore();
@@ -13986,16 +14581,6 @@ var DynamicForm = () => {
13986
14581
  })
13987
14582
  ] });
13988
14583
  };
13989
- function PlainSection({
13990
- title,
13991
- showHeading,
13992
- children
13993
- }) {
13994
- return /* @__PURE__ */ jsxs("div", { className: "mb-6 space-y-4", children: [
13995
- showHeading ? /* @__PURE__ */ jsx("h2", { className: "text-base font-medium text-foreground", children: title }) : null,
13996
- children
13997
- ] });
13998
- }
13999
14584
  function renderSectionChildren(children) {
14000
14585
  return children.map((child, index) => {
14001
14586
  if (typeof child === "string") {
@@ -14015,6 +14600,16 @@ function renderSectionChildren(children) {
14015
14600
  return /* @__PURE__ */ jsx(React15__default.Fragment, {}, index);
14016
14601
  });
14017
14602
  }
14603
+ function PlainSection({
14604
+ title,
14605
+ showHeading,
14606
+ children
14607
+ }) {
14608
+ return /* @__PURE__ */ jsxs("div", { className: "mb-6 space-y-4", children: [
14609
+ showHeading ? /* @__PURE__ */ jsx("h2", { className: "text-base font-medium text-foreground", children: title }) : null,
14610
+ children
14611
+ ] });
14612
+ }
14018
14613
  var DynamicFormV2 = ({
14019
14614
  showTitle = true,
14020
14615
  sectionMode = "plain",
@@ -14055,6 +14650,247 @@ var DynamicFormV2 = ({
14055
14650
  })
14056
14651
  ] });
14057
14652
  };
14653
+ function flattenStepFieldIds(step) {
14654
+ const ids = [];
14655
+ for (const child of step.children) {
14656
+ if (typeof child === "string") {
14657
+ ids.push(child);
14658
+ } else if (child.type === "column_layout") {
14659
+ ids.push(...child.children);
14660
+ }
14661
+ }
14662
+ return ids;
14663
+ }
14664
+ function isFieldComplete(id, state, fieldMap) {
14665
+ if (state.visibility[id] === false) return true;
14666
+ if (state.errors[id]) return false;
14667
+ const def = fieldMap[id];
14668
+ if (def?.required) {
14669
+ const v = state.values[id];
14670
+ if (v === null || v === void 0 || v === "") return false;
14671
+ if (Array.isArray(v) && v.length === 0) return false;
14672
+ }
14673
+ return true;
14674
+ }
14675
+ function isStepComplete(step, state, fieldMap) {
14676
+ return flattenStepFieldIds(step).every(
14677
+ (id) => isFieldComplete(id, state, fieldMap)
14678
+ );
14679
+ }
14680
+ var Stepper2 = ({ steps, statuses, variant }) => {
14681
+ if (variant === "dots") {
14682
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 mb-6", children: steps.map((step, i) => {
14683
+ const status = statuses[i];
14684
+ return /* @__PURE__ */ jsxs(React15__default.Fragment, { children: [
14685
+ /* @__PURE__ */ jsx(
14686
+ "div",
14687
+ {
14688
+ className: cn(
14689
+ "h-2.5 w-2.5 rounded-full transition-colors",
14690
+ status === "complete" && "bg-primary",
14691
+ status === "active" && "bg-primary ring-2 ring-primary/30",
14692
+ status === "locked" && "bg-muted"
14693
+ ),
14694
+ title: step.title
14695
+ }
14696
+ ),
14697
+ i < steps.length - 1 && /* @__PURE__ */ jsx(
14698
+ "div",
14699
+ {
14700
+ className: cn(
14701
+ "flex-1 h-px transition-colors",
14702
+ status === "complete" ? "bg-primary" : "bg-border"
14703
+ )
14704
+ }
14705
+ )
14706
+ ] }, step.id);
14707
+ }) });
14708
+ }
14709
+ if (variant === "labels") {
14710
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-0 mb-6", children: steps.map((step, i) => {
14711
+ const status = statuses[i];
14712
+ return /* @__PURE__ */ jsxs(React15__default.Fragment, { children: [
14713
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1", children: [
14714
+ /* @__PURE__ */ jsx(
14715
+ "div",
14716
+ {
14717
+ className: cn(
14718
+ "h-2 w-2 rounded-full",
14719
+ status === "complete" && "bg-primary",
14720
+ status === "active" && "bg-primary",
14721
+ status === "locked" && "bg-muted"
14722
+ )
14723
+ }
14724
+ ),
14725
+ /* @__PURE__ */ jsx(
14726
+ "span",
14727
+ {
14728
+ className: cn(
14729
+ "text-xs whitespace-nowrap",
14730
+ status === "locked" ? "text-muted-foreground" : "text-foreground"
14731
+ ),
14732
+ children: step.title
14733
+ }
14734
+ )
14735
+ ] }),
14736
+ i < steps.length - 1 && /* @__PURE__ */ jsx(
14737
+ "div",
14738
+ {
14739
+ className: cn(
14740
+ "flex-1 h-px mb-4 transition-colors",
14741
+ status === "complete" ? "bg-primary" : "bg-border"
14742
+ )
14743
+ }
14744
+ )
14745
+ ] }, step.id);
14746
+ }) });
14747
+ }
14748
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-0 mb-6", children: steps.map((step, i) => {
14749
+ const status = statuses[i];
14750
+ return /* @__PURE__ */ jsxs(React15__default.Fragment, { children: [
14751
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
14752
+ /* @__PURE__ */ jsx(
14753
+ "div",
14754
+ {
14755
+ className: cn(
14756
+ "flex h-7 w-7 items-center justify-center rounded-full text-xs font-semibold border-2 transition-colors",
14757
+ status === "complete" && "border-primary bg-primary text-primary-foreground",
14758
+ status === "active" && "border-primary bg-background text-primary",
14759
+ status === "locked" && "border-border bg-background text-muted-foreground"
14760
+ ),
14761
+ children: status === "complete" ? /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5" }) : i + 1
14762
+ }
14763
+ ),
14764
+ /* @__PURE__ */ jsx(
14765
+ "span",
14766
+ {
14767
+ className: cn(
14768
+ "text-sm font-medium hidden sm:block",
14769
+ status === "locked" ? "text-muted-foreground" : "text-foreground"
14770
+ ),
14771
+ children: step.title
14772
+ }
14773
+ )
14774
+ ] }),
14775
+ i < steps.length - 1 && /* @__PURE__ */ jsx(
14776
+ "div",
14777
+ {
14778
+ className: cn(
14779
+ "flex-1 h-px mx-3 transition-colors",
14780
+ status === "complete" ? "bg-primary" : "bg-border"
14781
+ )
14782
+ }
14783
+ )
14784
+ ] }, step.id);
14785
+ }) });
14786
+ };
14787
+ var ActiveStep = ({
14788
+ title,
14789
+ children
14790
+ }) => /* @__PURE__ */ jsxs("div", { className: "mb-4 space-y-4", children: [
14791
+ /* @__PURE__ */ jsx("h2", { className: "text-base font-medium text-foreground", children: title }),
14792
+ children
14793
+ ] });
14794
+ var Wizard = ({ node }) => {
14795
+ const store = useFormStore();
14796
+ const [formState, setFormState] = useState(() => ({
14797
+ ...store.getState()
14798
+ }));
14799
+ useEffect(() => {
14800
+ return store.subscribe((state) => {
14801
+ console.log("[MultiStepForm] store update \u2192", {
14802
+ values: state.values,
14803
+ errors: state.errors,
14804
+ visibility: state.visibility
14805
+ });
14806
+ setFormState({ ...state });
14807
+ });
14808
+ }, [store]);
14809
+ const schema = store.getSchema();
14810
+ const fieldMap = {};
14811
+ schema.fields.forEach((f) => {
14812
+ fieldMap[f.id] = f;
14813
+ });
14814
+ const { steps, meta } = node;
14815
+ const showStepper = meta?.showStepper !== false;
14816
+ const variant = meta?.stepperVariant ?? "numbered";
14817
+ const collapseCompleted = meta?.collapseCompleted !== false;
14818
+ const stepComplete = steps.map((s) => {
14819
+ const fieldIds = flattenStepFieldIds(s);
14820
+ const complete = isStepComplete(s, formState, fieldMap);
14821
+ console.log(`[MultiStepForm] step "${s.id}" fieldIds=${JSON.stringify(fieldIds)} complete=${complete}`, {
14822
+ errors: fieldIds.map((id) => ({ id, error: formState.errors[id] })),
14823
+ values: fieldIds.map((id) => ({ id, value: formState.values[id] }))
14824
+ });
14825
+ return complete;
14826
+ });
14827
+ const activeIndex = stepComplete.findIndex((c) => !c) === -1 ? steps.length : stepComplete.findIndex((c) => !c);
14828
+ console.log(`[MultiStepForm] activeIndex=${activeIndex} stepComplete=${JSON.stringify(stepComplete)}`);
14829
+ const statuses = steps.map((_, i) => {
14830
+ if (i < activeIndex) return "complete";
14831
+ if (i === activeIndex) return "active";
14832
+ return "locked";
14833
+ });
14834
+ return /* @__PURE__ */ jsxs("div", { children: [
14835
+ node.title && /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold mb-4", children: node.title }),
14836
+ showStepper && /* @__PURE__ */ jsx(Stepper2, { steps, statuses, variant }),
14837
+ /* @__PURE__ */ jsx("div", { className: "space-y-2", children: steps.map((step, i) => {
14838
+ const status = statuses[i];
14839
+ if (status === "locked") return null;
14840
+ const children = renderSectionChildren(step.children);
14841
+ if (status === "complete") {
14842
+ if (collapseCompleted) {
14843
+ return /* @__PURE__ */ jsx(Section, { title: step.title, children }, step.id);
14844
+ }
14845
+ return /* @__PURE__ */ jsxs(
14846
+ "div",
14847
+ {
14848
+ className: "mb-4 opacity-60 pointer-events-none select-none space-y-4",
14849
+ children: [
14850
+ /* @__PURE__ */ jsx("h2", { className: "text-base font-medium text-foreground", children: step.title }),
14851
+ children
14852
+ ]
14853
+ },
14854
+ step.id
14855
+ );
14856
+ }
14857
+ return /* @__PURE__ */ jsx(ActiveStep, { title: step.title, children }, step.id);
14858
+ }) })
14859
+ ] });
14860
+ };
14861
+ var MultiStepForm = ({
14862
+ showTitle = true,
14863
+ className
14864
+ }) => {
14865
+ const store = useFormStore();
14866
+ const schema = store.getSchema();
14867
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-6", className), children: [
14868
+ showTitle && /* @__PURE__ */ jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold", children: schema.title }) }),
14869
+ schema.layout.map((node) => {
14870
+ if (node.type === "multi_step") {
14871
+ return /* @__PURE__ */ jsx(Wizard, { node }, node.id);
14872
+ }
14873
+ if (node.type === "section") {
14874
+ return /* @__PURE__ */ jsxs("div", { className: "mb-6 space-y-4", children: [
14875
+ /* @__PURE__ */ jsx("h2", { className: "text-base font-medium text-foreground", children: node.title }),
14876
+ renderSectionChildren(node.children)
14877
+ ] }, node.id);
14878
+ }
14879
+ if (node.type === "column_layout") {
14880
+ return /* @__PURE__ */ jsx(
14881
+ ColumnLayout,
14882
+ {
14883
+ columns: node.columns,
14884
+ label: node.label,
14885
+ children: node.children.map((fieldId) => /* @__PURE__ */ jsx(FieldRenderer, { fieldId }, fieldId))
14886
+ },
14887
+ node.id
14888
+ );
14889
+ }
14890
+ return null;
14891
+ })
14892
+ ] });
14893
+ };
14058
14894
  var SUGGESTION_KEYS = /* @__PURE__ */ new Set(["medications", "investigations", "procedures"]);
14059
14895
  function shallowEqualKeys(a, b) {
14060
14896
  const keysA = Object.keys(a);
@@ -14667,6 +15503,8 @@ var ReadOnlyFieldRenderer = ({
14667
15503
  return /* @__PURE__ */ jsx(ReadOnlyImageUpload, { fieldDef, value });
14668
15504
  case "media_upload":
14669
15505
  return /* @__PURE__ */ jsx(ReadOnlyMediaUpload, { fieldDef, value });
15506
+ case "file_upload":
15507
+ return /* @__PURE__ */ jsx(ReadOnlyMediaUpload, { fieldDef, value });
14670
15508
  case "signature":
14671
15509
  return /* @__PURE__ */ jsx(ReadOnlySignature, { fieldDef, value });
14672
15510
  case "editable_table":
@@ -15017,7 +15855,8 @@ var FormControls = ({
15017
15855
  actionsFullWidth = false,
15018
15856
  buttonClassName,
15019
15857
  onSaveDraft,
15020
- onSubmit
15858
+ onSubmit,
15859
+ submitLabel
15021
15860
  }) => {
15022
15861
  const {
15023
15862
  state,
@@ -15106,7 +15945,7 @@ var FormControls = ({
15106
15945
  disabled: !state.isValid || hasUploadsInFlight,
15107
15946
  size: "sm",
15108
15947
  className: buttonCn,
15109
- children: hasUploadsInFlight ? "Upload in progress\u2026" : availableTransitions.length > 1 ? `Submit to ${t.to}` : "Submit"
15948
+ children: hasUploadsInFlight ? "Upload in progress\u2026" : availableTransitions.length > 1 ? `Submit to ${t.to}` : submitLabel ?? "Submit"
15110
15949
  },
15111
15950
  t.to
15112
15951
  )) : onSubmit ? /* @__PURE__ */ jsx(
@@ -15119,7 +15958,7 @@ var FormControls = ({
15119
15958
  disabled: !state.isValid || hasUploadsInFlight,
15120
15959
  size: "sm",
15121
15960
  className: buttonCn,
15122
- children: hasUploadsInFlight ? "Upload in progress\u2026" : "Submit"
15961
+ children: hasUploadsInFlight ? "Upload in progress\u2026" : submitLabel ?? "Submit"
15123
15962
  }
15124
15963
  ) : null })
15125
15964
  ]
@@ -15160,6 +15999,6 @@ function createUploadHandler(options) {
15160
15999
  };
15161
16000
  }
15162
16001
 
15163
- export { AddInvestigationField, AddMedicationField, DifferentialDiagnosis, DynamicForm, DynamicFormV2, EMAIL_REGEX, FieldRenderer, FormControls, FormProvider, FormStore, ImageUploadWidget, MAR_MEDICATION_ORDERS_META_KEY, MediaUploadWidget, ReadOnlyForm, ReadOnlyImageUpload, ReadOnlyMediaUpload, ReadOnlySignature, ReadOnlyTable, RichTextWidget, SignatureUploadWidget, SmartForm, SmartTextareaWidget, createUploadHandler, evaluateRules, fieldMetaRequestsMarMedicationOrdersButton, useField, useFieldHandlers, useForm, useFormStore, useFrequentItems, usePackages, useSmartKeywords, validateField, validateForm };
16002
+ export { AddInvestigationField, AddMedicationField, DifferentialDiagnosis, DynamicForm, DynamicFormV2, EMAIL_REGEX, FieldRenderer, FormControls, FormFileUploadWidget, FormProvider, FormStore, ImageUploadWidget, MAR_MEDICATION_ORDERS_META_KEY, MediaUploadWidget, MultiStepForm, ReadOnlyForm, ReadOnlyImageUpload, ReadOnlyMediaUpload, ReadOnlySignature, ReadOnlyTable, RichTextWidget, SignatureUploadWidget, SmartForm, SmartTextareaWidget, Upload3 as Upload, createUploadHandler, evaluateRules, fieldMetaRequestsMarMedicationOrdersButton, useField, useFieldHandlers, useForm, useFormStore, useFrequentItems, usePackages, useSmartKeywords, validateField, validateForm };
15164
16003
  //# sourceMappingURL=index.mjs.map
15165
16004
  //# sourceMappingURL=index.mjs.map