formanitor 0.0.28 → 0.0.30

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
@@ -1,6 +1,7 @@
1
- import * as React13 from 'react';
2
- import React13__default, { createContext, useContext, useRef, useEffect, useState, useMemo, useCallback, useReducer } from 'react';
1
+ import * as React15 from 'react';
2
+ import React15__default, { createContext, useContext, useRef, useEffect, useState, useMemo, useCallback, useReducer } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
+ import { ChevronDown, ChevronUp, Check, Circle, X, Image, Upload, Trash2, Plus, Loader2, PenTool, Mic, Undo, Redo, ChevronRight, Calendar as Calendar$1, ChevronLeft, RefreshCw, Clock, Bold, Italic, Underline as Underline$1, Strikethrough, List, ListOrdered } from 'lucide-react';
4
5
  import { clsx } from 'clsx';
5
6
  import { twMerge } from 'tailwind-merge';
6
7
  import * as LabelPrimitive from '@radix-ui/react-label';
@@ -9,7 +10,6 @@ import { useEditor, EditorContent } from '@tiptap/react';
9
10
  import StarterKit from '@tiptap/starter-kit';
10
11
  import Placeholder from '@tiptap/extension-placeholder';
11
12
  import Underline from '@tiptap/extension-underline';
12
- import { ChevronDown, ChevronUp, Check, Circle, X, Image, Upload, Trash2, Plus, Loader2, PenTool, Undo, Redo, ChevronRight, Calendar as Calendar$1, ChevronLeft, RefreshCw, Clock, Bold, Italic, Underline as Underline$1, Strikethrough, List, ListOrdered } from 'lucide-react';
13
13
  import { Slot } from '@radix-ui/react-slot';
14
14
  import * as SeparatorPrimitive from '@radix-ui/react-separator';
15
15
  import * as SelectPrimitive from '@radix-ui/react-select';
@@ -251,6 +251,9 @@ var FormStore = class {
251
251
  getFieldDef(fieldId) {
252
252
  return this.fieldMap[fieldId];
253
253
  }
254
+ getVoice() {
255
+ return this.config.voice;
256
+ }
254
257
  hasPersistence() {
255
258
  return this.persistence !== NO_OP_PROVIDER;
256
259
  }
@@ -603,6 +606,7 @@ var FormStore = class {
603
606
  if (next.onUpload !== void 0) this.config.onUpload = next.onUpload;
604
607
  if (next.onEvent !== void 0) this.config.onEvent = next.onEvent;
605
608
  if (next.onDraftChange !== void 0) this.config.onDraftChange = next.onDraftChange;
609
+ if (next.voice !== void 0) this.config.voice = next.voice;
606
610
  if (next.role !== void 0 && next.role !== this.config.role) {
607
611
  this.config.role = next.role;
608
612
  needsReeval = true;
@@ -664,6 +668,21 @@ var FormStore = class {
664
668
  this.listeners.forEach((l) => l(this.state));
665
669
  }
666
670
  };
671
+ var VoiceContext = createContext({
672
+ activeFieldId: null,
673
+ setActiveFieldId: () => {
674
+ }
675
+ });
676
+ function useVoiceContext() {
677
+ return useContext(VoiceContext);
678
+ }
679
+ function VoiceContextProvider({ children }) {
680
+ const [activeFieldId, setActiveFieldIdState] = useState(null);
681
+ const setActiveFieldId = useCallback((id) => {
682
+ setActiveFieldIdState(id);
683
+ }, []);
684
+ return /* @__PURE__ */ jsx(VoiceContext.Provider, { value: { activeFieldId, setActiveFieldId }, children });
685
+ }
667
686
  var FormContext = createContext(null);
668
687
  var emptyFrequentItems = {
669
688
  medications: [],
@@ -699,7 +718,7 @@ var FormProvider = ({
699
718
  storeRef.current?.load();
700
719
  }, []);
701
720
  const frequentItemsValue = frequentItems ?? emptyFrequentItems;
702
- return /* @__PURE__ */ jsx(FormContext.Provider, { value: storeRef.current, children: /* @__PURE__ */ jsx(FieldHandlersContext.Provider, { value: fieldHandlers ?? {}, children: /* @__PURE__ */ jsx(FrequentItemsContext.Provider, { value: frequentItemsValue, children }) }) });
721
+ return /* @__PURE__ */ jsx(FormContext.Provider, { value: storeRef.current, children: /* @__PURE__ */ jsx(FieldHandlersContext.Provider, { value: fieldHandlers ?? {}, children: /* @__PURE__ */ jsx(FrequentItemsContext.Provider, { value: frequentItemsValue, children: /* @__PURE__ */ jsx(VoiceContextProvider, { children }) }) }) });
703
722
  };
704
723
  function useFormStore() {
705
724
  const context = useContext(FormContext);
@@ -756,10 +775,76 @@ function useField(fieldId) {
756
775
  setTouched
757
776
  };
758
777
  }
778
+ function RecordingWave() {
779
+ const bars = [
780
+ { dur: "0.6s", values: "3;10;3", yValues: "4.5;0;4.5", delay: "0s" },
781
+ { dur: "0.6s", values: "8;3;8", yValues: "2;4.5;2", delay: "0.1s" },
782
+ { dur: "0.6s", values: "5;11;5", yValues: "3.5;0.5;3.5", delay: "0.05s" },
783
+ { dur: "0.6s", values: "10;4;10", yValues: "1;4;1", delay: "0.15s" }
784
+ ];
785
+ return /* @__PURE__ */ jsx("svg", { width: "16", height: "12", viewBox: "0 0 18 12", "aria-hidden": true, children: bars.map((b, i) => /* @__PURE__ */ jsxs("rect", { x: i * 4 + 1, width: "2.5", rx: "1.25", fill: "currentColor", y: "0", height: "12", children: [
786
+ /* @__PURE__ */ jsx("animate", { attributeName: "height", values: b.values, dur: b.dur, begin: b.delay, repeatCount: "indefinite" }),
787
+ /* @__PURE__ */ jsx("animate", { attributeName: "y", values: b.yValues, dur: b.dur, begin: b.delay, repeatCount: "indefinite" })
788
+ ] }, i)) });
789
+ }
790
+ function VoiceMicButton({ fieldId, onTranscriptReady }) {
791
+ const store = useFormStore();
792
+ const { activeFieldId, setActiveFieldId } = useVoiceContext();
793
+ const [status, setStatus] = useState("idle");
794
+ const voice = store.getVoice();
795
+ const isActive = activeFieldId === fieldId;
796
+ const isRecording = status === "recording" && isActive;
797
+ const isTranscribing = status === "transcribing" && isActive;
798
+ const isBlocked = activeFieldId !== null && !isActive;
799
+ const handleClick = useCallback(async () => {
800
+ if (!voice || isBlocked || isTranscribing) return;
801
+ if (isRecording) {
802
+ setStatus("transcribing");
803
+ try {
804
+ const transcript = await voice.stopRecording();
805
+ if (transcript) onTranscriptReady(transcript);
806
+ } catch {
807
+ } finally {
808
+ setStatus("idle");
809
+ setActiveFieldId(null);
810
+ }
811
+ } else {
812
+ setActiveFieldId(fieldId);
813
+ setStatus("recording");
814
+ try {
815
+ await voice.startRecording();
816
+ } catch {
817
+ setStatus("idle");
818
+ setActiveFieldId(null);
819
+ }
820
+ }
821
+ }, [voice, isBlocked, isTranscribing, isRecording, fieldId, onTranscriptReady, setActiveFieldId]);
822
+ const title = isTranscribing ? "Processing\u2026" : isRecording ? "Stop recording" : "Dictate this field";
823
+ return /* @__PURE__ */ jsx(
824
+ "button",
825
+ {
826
+ type: "button",
827
+ onClick: handleClick,
828
+ disabled: isBlocked || isTranscribing,
829
+ title,
830
+ className: [
831
+ "flex items-center gap-1 rounded px-1 py-0.5",
832
+ "text-[11px] font-medium transition-opacity",
833
+ isBlocked ? "pointer-events-none opacity-30" : "",
834
+ isTranscribing ? "cursor-wait opacity-50" : "",
835
+ !isBlocked && !isTranscribing ? "hover:opacity-70" : ""
836
+ ].filter(Boolean).join(" "),
837
+ children: isTranscribing ? /* @__PURE__ */ jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin text-slate-400" }) : isRecording ? /* @__PURE__ */ jsxs(Fragment, { children: [
838
+ /* @__PURE__ */ jsx("span", { className: "text-rose-400", children: /* @__PURE__ */ jsx(RecordingWave, {}) }),
839
+ /* @__PURE__ */ jsx("span", { className: "text-rose-400", children: "Stop" })
840
+ ] }) : /* @__PURE__ */ jsx(Mic, { className: "h-4 w-4 text-slate-400" })
841
+ }
842
+ );
843
+ }
759
844
  function cn(...inputs) {
760
845
  return twMerge(clsx(inputs));
761
846
  }
762
- var Input = React13.forwardRef(
847
+ var Input = React15.forwardRef(
763
848
  ({ className, type, ...props }, ref) => {
764
849
  return /* @__PURE__ */ jsx(
765
850
  "input",
@@ -779,7 +864,7 @@ Input.displayName = "Input";
779
864
  var labelVariants = cva(
780
865
  "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
781
866
  );
782
- var Label = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
867
+ var Label = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
783
868
  LabelPrimitive.Root,
784
869
  {
785
870
  ref,
@@ -788,7 +873,7 @@ var Label = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
788
873
  }
789
874
  ));
790
875
  Label.displayName = LabelPrimitive.Root.displayName;
791
- var Textarea = React13.forwardRef(
876
+ var Textarea = React15.forwardRef(
792
877
  ({ className, height, style, ...props }, ref) => {
793
878
  return /* @__PURE__ */ jsx(
794
879
  "textarea",
@@ -832,6 +917,8 @@ function getThemeConfig(fieldType, themeName) {
832
917
  var TextWidget = ({ fieldId }) => {
833
918
  const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
834
919
  const { state } = useForm();
920
+ const store = useFormStore();
921
+ const hasVoice = !!(fieldDef?.voice && store.getVoice());
835
922
  const showError = !!error && (touched || state.submitAttempted);
836
923
  if (!fieldDef) return null;
837
924
  const Component = fieldDef.type === "textarea" ? Textarea : Input;
@@ -849,8 +936,12 @@ var TextWidget = ({ fieldId }) => {
849
936
  " ",
850
937
  fieldDef.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
851
938
  ] });
939
+ const labelEl = theme ? /* @__PURE__ */ jsx(Label, { htmlFor: fieldId, className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { htmlFor: fieldId, children: labelContent });
852
940
  return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
853
- theme ? /* @__PURE__ */ jsx(Label, { htmlFor: fieldId, className: labelClass, children: labelContent }) : /* @__PURE__ */ jsx(Label, { htmlFor: fieldId, children: labelContent }),
941
+ hasVoice ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
942
+ labelEl,
943
+ /* @__PURE__ */ jsx(VoiceMicButton, { fieldId, onTranscriptReady: setValue })
944
+ ] }) : labelEl,
854
945
  /* @__PURE__ */ jsx(
855
946
  Component,
856
947
  {
@@ -892,7 +983,7 @@ var buttonVariants = cva(
892
983
  }
893
984
  }
894
985
  );
895
- var Button = React13.forwardRef(
986
+ var Button = React15.forwardRef(
896
987
  ({ className, variant, size, asChild = false, ...props }, ref) => {
897
988
  const Comp = asChild ? Slot : "button";
898
989
  return /* @__PURE__ */ jsx(
@@ -906,7 +997,7 @@ var Button = React13.forwardRef(
906
997
  }
907
998
  );
908
999
  Button.displayName = "Button";
909
- var Separator = React13.forwardRef(
1000
+ var Separator = React15.forwardRef(
910
1001
  ({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ jsx(
911
1002
  SeparatorPrimitive.Root,
912
1003
  {
@@ -1038,6 +1129,8 @@ function RichTextToolbar({
1038
1129
  var RichTextWidget = ({ fieldId }) => {
1039
1130
  const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);
1040
1131
  const { state } = useForm();
1132
+ const store = useFormStore();
1133
+ const hasVoice = !!(fieldDef?.voice && store.getVoice());
1041
1134
  const showError = !!error && (touched || state.submitAttempted);
1042
1135
  const def = fieldDef;
1043
1136
  const placeholder = def?.placeholder ?? "Start typing\u2026";
@@ -1119,8 +1212,12 @@ var RichTextWidget = ({ fieldId }) => {
1119
1212
  " ",
1120
1213
  fieldDef.required && /* @__PURE__ */ jsx("span", { className: "text-red-500", children: "*" })
1121
1214
  ] });
1215
+ const labelEl = /* @__PURE__ */ jsx(Label, { htmlFor: fieldId, children: labelContent });
1122
1216
  return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1123
- /* @__PURE__ */ jsx(Label, { htmlFor: fieldId, children: labelContent }),
1217
+ hasVoice ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1218
+ labelEl,
1219
+ /* @__PURE__ */ jsx(VoiceMicButton, { fieldId, onTranscriptReady: setValue })
1220
+ ] }) : labelEl,
1124
1221
  /* @__PURE__ */ jsxs(
1125
1222
  "div",
1126
1223
  {
@@ -1158,7 +1255,7 @@ var RichTextWidget = ({ fieldId }) => {
1158
1255
  };
1159
1256
  var Select = SelectPrimitive.Root;
1160
1257
  var SelectValue = SelectPrimitive.Value;
1161
- var SelectTrigger = React13.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
1258
+ var SelectTrigger = React15.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
1162
1259
  SelectPrimitive.Trigger,
1163
1260
  {
1164
1261
  ref,
@@ -1174,7 +1271,7 @@ var SelectTrigger = React13.forwardRef(({ className, children, ...props }, ref)
1174
1271
  }
1175
1272
  ));
1176
1273
  SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
1177
- var SelectScrollUpButton = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1274
+ var SelectScrollUpButton = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1178
1275
  SelectPrimitive.ScrollUpButton,
1179
1276
  {
1180
1277
  ref,
@@ -1187,7 +1284,7 @@ var SelectScrollUpButton = React13.forwardRef(({ className, ...props }, ref) =>
1187
1284
  }
1188
1285
  ));
1189
1286
  SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
1190
- var SelectScrollDownButton = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1287
+ var SelectScrollDownButton = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1191
1288
  SelectPrimitive.ScrollDownButton,
1192
1289
  {
1193
1290
  ref,
@@ -1200,7 +1297,7 @@ var SelectScrollDownButton = React13.forwardRef(({ className, ...props }, ref) =
1200
1297
  }
1201
1298
  ));
1202
1299
  SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
1203
- var SelectContent = React13.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
1300
+ var SelectContent = React15.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
1204
1301
  SelectPrimitive.Content,
1205
1302
  {
1206
1303
  ref,
@@ -1228,7 +1325,7 @@ var SelectContent = React13.forwardRef(({ className, children, position = "poppe
1228
1325
  }
1229
1326
  ) }));
1230
1327
  SelectContent.displayName = SelectPrimitive.Content.displayName;
1231
- var SelectLabel = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1328
+ var SelectLabel = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1232
1329
  SelectPrimitive.Label,
1233
1330
  {
1234
1331
  ref,
@@ -1237,7 +1334,7 @@ var SelectLabel = React13.forwardRef(({ className, ...props }, ref) => /* @__PUR
1237
1334
  }
1238
1335
  ));
1239
1336
  SelectLabel.displayName = SelectPrimitive.Label.displayName;
1240
- var SelectItem = React13.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
1337
+ var SelectItem = React15.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
1241
1338
  SelectPrimitive.Item,
1242
1339
  {
1243
1340
  ref,
@@ -1253,7 +1350,7 @@ var SelectItem = React13.forwardRef(({ className, children, ...props }, ref) =>
1253
1350
  }
1254
1351
  ));
1255
1352
  SelectItem.displayName = SelectPrimitive.Item.displayName;
1256
- var SelectSeparator = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1353
+ var SelectSeparator = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1257
1354
  SelectPrimitive.Separator,
1258
1355
  {
1259
1356
  ref,
@@ -1342,7 +1439,7 @@ var SelectWidget = ({ fieldId }) => {
1342
1439
  showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
1343
1440
  ] });
1344
1441
  };
1345
- var Checkbox = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1442
+ var Checkbox = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1346
1443
  CheckboxPrimitive.Root,
1347
1444
  {
1348
1445
  ref,
@@ -1416,7 +1513,7 @@ var MultiSelectWidget = ({ fieldId }) => {
1416
1513
  showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
1417
1514
  ] });
1418
1515
  };
1419
- var Table = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsx(
1516
+ var Table = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsx(
1420
1517
  "table",
1421
1518
  {
1422
1519
  ref,
@@ -1425,9 +1522,9 @@ var Table = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
1425
1522
  }
1426
1523
  ) }));
1427
1524
  Table.displayName = "Table";
1428
- var TableHeader = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("thead", { ref, className: cn("[&_tr]:border-b", className), ...props }));
1525
+ var TableHeader = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("thead", { ref, className: cn("[&_tr]:border-b", className), ...props }));
1429
1526
  TableHeader.displayName = "TableHeader";
1430
- var TableBody = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1527
+ var TableBody = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1431
1528
  "tbody",
1432
1529
  {
1433
1530
  ref,
@@ -1436,7 +1533,7 @@ var TableBody = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE_
1436
1533
  }
1437
1534
  ));
1438
1535
  TableBody.displayName = "TableBody";
1439
- var TableFooter = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1536
+ var TableFooter = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1440
1537
  "tfoot",
1441
1538
  {
1442
1539
  ref,
@@ -1448,7 +1545,7 @@ var TableFooter = React13.forwardRef(({ className, ...props }, ref) => /* @__PUR
1448
1545
  }
1449
1546
  ));
1450
1547
  TableFooter.displayName = "TableFooter";
1451
- var TableRow = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1548
+ var TableRow = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1452
1549
  "tr",
1453
1550
  {
1454
1551
  ref,
@@ -1460,7 +1557,7 @@ var TableRow = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__
1460
1557
  }
1461
1558
  ));
1462
1559
  TableRow.displayName = "TableRow";
1463
- var TableHead = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1560
+ var TableHead = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1464
1561
  "th",
1465
1562
  {
1466
1563
  ref,
@@ -1472,7 +1569,7 @@ var TableHead = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE_
1472
1569
  }
1473
1570
  ));
1474
1571
  TableHead.displayName = "TableHead";
1475
- var TableCell = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1572
+ var TableCell = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1476
1573
  "td",
1477
1574
  {
1478
1575
  ref,
@@ -1481,7 +1578,7 @@ var TableCell = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE_
1481
1578
  }
1482
1579
  ));
1483
1580
  TableCell.displayName = "TableCell";
1484
- var TableCaption = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1581
+ var TableCaption = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1485
1582
  "caption",
1486
1583
  {
1487
1584
  ref,
@@ -1497,7 +1594,7 @@ var RepeatableWidget = ({
1497
1594
  if (!fieldDef || fieldDef.type !== "repeatable") return null;
1498
1595
  const def = fieldDef;
1499
1596
  const rows = Array.isArray(value) ? value : [];
1500
- const [hasInteracted, setHasInteracted] = React13__default.useState(false);
1597
+ const [hasInteracted, setHasInteracted] = React15__default.useState(false);
1501
1598
  const showError = !!error && (touched || hasInteracted);
1502
1599
  const addRow = () => {
1503
1600
  setValue([...rows, {}]);
@@ -1583,29 +1680,66 @@ var RepeatableWidget = ({
1583
1680
  showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
1584
1681
  ] });
1585
1682
  };
1683
+ function CalendarDropdown(props) {
1684
+ const { options, value, onChange } = props;
1685
+ const handleValueChange = (newValue) => {
1686
+ if (!onChange) return;
1687
+ const syntheticEvent = {
1688
+ target: { value: newValue }
1689
+ };
1690
+ onChange(syntheticEvent);
1691
+ };
1692
+ return /* @__PURE__ */ jsxs(Select, { value: value?.toString(), onValueChange: handleValueChange, children: [
1693
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "h-7 px-2 text-sm", "aria-label": props["aria-label"], children: /* @__PURE__ */ jsx(SelectValue, {}) }),
1694
+ /* @__PURE__ */ jsx(SelectContent, { children: options?.map((option) => /* @__PURE__ */ jsx(
1695
+ SelectItem,
1696
+ {
1697
+ value: option.value.toString(),
1698
+ disabled: option.disabled,
1699
+ children: option.label
1700
+ },
1701
+ option.value.toString()
1702
+ )) })
1703
+ ] });
1704
+ }
1586
1705
  function Calendar({
1587
1706
  className,
1588
1707
  classNames,
1589
1708
  showOutsideDays = true,
1590
1709
  ...props
1591
1710
  }) {
1711
+ const captionLayout = props.captionLayout ?? "dropdown";
1712
+ const isDropdownCaption = captionLayout === "dropdown" || captionLayout === "dropdown-months" || captionLayout === "dropdown-years";
1713
+ const startMonth = props.startMonth ?? (isDropdownCaption ? new Date(1900, 0) : void 0);
1714
+ const endMonth = props.endMonth ?? (isDropdownCaption ? new Date(2100, 11) : void 0);
1592
1715
  return /* @__PURE__ */ jsx(
1593
1716
  DayPicker,
1594
1717
  {
1595
1718
  showOutsideDays,
1719
+ captionLayout,
1720
+ hideNavigation: props.hideNavigation ?? isDropdownCaption,
1721
+ navLayout: props.navLayout ?? (isDropdownCaption ? "around" : void 0),
1722
+ startMonth,
1723
+ endMonth,
1596
1724
  className: cn("p-3 relative", className),
1597
1725
  classNames: {
1598
1726
  months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0",
1599
1727
  month: "space-y-4",
1600
1728
  caption: "flex justify-center pt-1 relative items-center",
1601
- caption_label: "text-sm font-medium",
1729
+ caption_label: cn(
1730
+ "text-sm font-medium",
1731
+ isDropdownCaption && "sr-only"
1732
+ ),
1733
+ dropdowns: "flex items-center gap-2",
1734
+ months_dropdown: "h-7 rounded-md border border-input bg-background px-2 text-sm",
1735
+ years_dropdown: "h-7 rounded-md border border-input bg-background px-2 text-sm",
1602
1736
  nav: "space-x-1 flex items-center",
1603
1737
  nav_button: cn(
1604
1738
  buttonVariants({ variant: "outline" }),
1605
1739
  "h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100"
1606
1740
  ),
1607
- nav_button_previous: "absolute left-1",
1608
- nav_button_next: "absolute right-1",
1741
+ nav_button_previous: isDropdownCaption ? "" : "absolute left-1",
1742
+ nav_button_next: isDropdownCaption ? "" : "absolute right-1",
1609
1743
  table: "w-full border-collapse space-y-1",
1610
1744
  head_row: "flex",
1611
1745
  head_cell: "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]",
@@ -1626,12 +1760,12 @@ function Calendar({
1626
1760
  button_previous: cn(
1627
1761
  buttonVariants({ variant: "outline" }),
1628
1762
  "h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
1629
- "absolute left-1 top-3"
1763
+ isDropdownCaption ? "" : "absolute left-1 top-3"
1630
1764
  ),
1631
1765
  button_next: cn(
1632
1766
  buttonVariants({ variant: "outline" }),
1633
1767
  "h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
1634
- "absolute right-1 top-3"
1768
+ isDropdownCaption ? "" : "absolute right-1 top-3"
1635
1769
  ),
1636
1770
  month_grid: "w-full border-collapse space-y-1",
1637
1771
  weekdays: "flex",
@@ -1651,9 +1785,11 @@ function Calendar({
1651
1785
  ...classNames
1652
1786
  },
1653
1787
  components: {
1654
- IconLeft: ({ ...props2 }) => /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" }),
1655
- IconRight: ({ ...props2 }) => /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" }),
1656
- // @ts-ignore
1788
+ IconLeft: () => /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" }),
1789
+ IconRight: () => /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" }),
1790
+ // @ts-expect-error react-day-picker v9 component typing differences
1791
+ Dropdown: CalendarDropdown,
1792
+ // @ts-expect-error react-day-picker v9 component typing differences
1657
1793
  Chevron: ({ orientation }) => {
1658
1794
  const Icon2 = orientation === "left" ? ChevronLeft : ChevronRight;
1659
1795
  return /* @__PURE__ */ jsx(Icon2, { className: "h-4 w-4" });
@@ -1666,7 +1802,7 @@ function Calendar({
1666
1802
  Calendar.displayName = "Calendar";
1667
1803
  var Popover = PopoverPrimitive.Root;
1668
1804
  var PopoverTrigger = PopoverPrimitive.Trigger;
1669
- var PopoverContent = React13.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
1805
+ var PopoverContent = React15.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
1670
1806
  PopoverPrimitive.Content,
1671
1807
  {
1672
1808
  ref,
@@ -1745,14 +1881,14 @@ function DateTimePicker({
1745
1881
  className,
1746
1882
  placeholder = "Pick date & time"
1747
1883
  }) {
1748
- const [internalDate, setInternalDate] = React13.useState(dateTime);
1749
- const [timeString, setTimeString] = React13.useState(() => {
1884
+ const [internalDate, setInternalDate] = React15.useState(dateTime);
1885
+ const [timeString, setTimeString] = React15.useState(() => {
1750
1886
  if (!dateTime) return "";
1751
1887
  const hours = dateTime.getHours().toString().padStart(2, "0");
1752
1888
  const minutes = dateTime.getMinutes().toString().padStart(2, "0");
1753
1889
  return `${hours}:${minutes}`;
1754
1890
  });
1755
- React13.useEffect(() => {
1891
+ React15.useEffect(() => {
1756
1892
  setInternalDate(dateTime);
1757
1893
  if (!dateTime) {
1758
1894
  setTimeString("");
@@ -1896,7 +2032,7 @@ var ImageUploadWidget = ({ fieldId }) => {
1896
2032
  /* @__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." }) })
1897
2033
  ] });
1898
2034
  }
1899
- React13__default.useEffect(() => {
2035
+ React15__default.useEffect(() => {
1900
2036
  if (value && typeof value === "string") {
1901
2037
  setPreview(value);
1902
2038
  } else {
@@ -2535,7 +2671,7 @@ var EditableTableWidget = ({
2535
2671
  ] })
2536
2672
  ] });
2537
2673
  };
2538
- var RadioGroup = React13.forwardRef(({ className, ...props }, ref) => {
2674
+ var RadioGroup = React15.forwardRef(({ className, ...props }, ref) => {
2539
2675
  return /* @__PURE__ */ jsx(
2540
2676
  RadioGroupPrimitive.Root,
2541
2677
  {
@@ -2546,7 +2682,7 @@ var RadioGroup = React13.forwardRef(({ className, ...props }, ref) => {
2546
2682
  );
2547
2683
  });
2548
2684
  RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
2549
- var RadioGroupItem = React13.forwardRef(({ className, ...props }, ref) => {
2685
+ var RadioGroupItem = React15.forwardRef(({ className, ...props }, ref) => {
2550
2686
  return /* @__PURE__ */ jsx(
2551
2687
  RadioGroupPrimitive.Item,
2552
2688
  {
@@ -2693,7 +2829,7 @@ function useAISuggestions() {
2693
2829
  var AISuggestionsProvider = AISuggestionsContext.Provider;
2694
2830
  var Dialog = DialogPrimitive.Root;
2695
2831
  var DialogPortal = DialogPrimitive.Portal;
2696
- var DialogOverlay = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2832
+ var DialogOverlay = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2697
2833
  DialogPrimitive.Overlay,
2698
2834
  {
2699
2835
  ref,
@@ -2705,7 +2841,7 @@ var DialogOverlay = React13.forwardRef(({ className, ...props }, ref) => /* @__P
2705
2841
  }
2706
2842
  ));
2707
2843
  DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
2708
- var DialogContent = React13.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
2844
+ var DialogContent = React15.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
2709
2845
  /* @__PURE__ */ jsx(DialogOverlay, {}),
2710
2846
  /* @__PURE__ */ jsxs(
2711
2847
  DialogPrimitive.Content,
@@ -2741,7 +2877,7 @@ var DialogHeader = ({
2741
2877
  }
2742
2878
  );
2743
2879
  DialogHeader.displayName = "DialogHeader";
2744
- var DialogTitle = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2880
+ var DialogTitle = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2745
2881
  DialogPrimitive.Title,
2746
2882
  {
2747
2883
  ref,
@@ -2753,7 +2889,7 @@ var DialogTitle = React13.forwardRef(({ className, ...props }, ref) => /* @__PUR
2753
2889
  }
2754
2890
  ));
2755
2891
  DialogTitle.displayName = DialogPrimitive.Title.displayName;
2756
- var DialogDescription = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2892
+ var DialogDescription = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2757
2893
  DialogPrimitive.Description,
2758
2894
  {
2759
2895
  ref,
@@ -3901,7 +4037,7 @@ var DifferentialDiagnosisWidget = ({ fieldId }) => {
3901
4037
  const items = Array.isArray(value) ? value : [];
3902
4038
  return /* @__PURE__ */ jsx(DifferentialDiagnosis, { differentialDiagnosis: items });
3903
4039
  };
3904
- var Spinner2 = React13.forwardRef(
4040
+ var Spinner2 = React15.forwardRef(
3905
4041
  ({ className, size = "md", ...props }, ref) => {
3906
4042
  const sizeClasses = {
3907
4043
  sm: "h-4 w-4 border-2",
@@ -4257,7 +4393,7 @@ var ReferralWidget = ({ fieldId }) => {
4257
4393
  showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
4258
4394
  ] });
4259
4395
  };
4260
- var Card = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4396
+ var Card = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4261
4397
  "div",
4262
4398
  {
4263
4399
  ref,
@@ -4269,7 +4405,7 @@ var Card = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
4269
4405
  }
4270
4406
  ));
4271
4407
  Card.displayName = "Card";
4272
- var CardHeader = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4408
+ var CardHeader = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4273
4409
  "div",
4274
4410
  {
4275
4411
  ref,
@@ -4278,7 +4414,7 @@ var CardHeader = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE
4278
4414
  }
4279
4415
  ));
4280
4416
  CardHeader.displayName = "CardHeader";
4281
- var CardTitle = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4417
+ var CardTitle = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4282
4418
  "h3",
4283
4419
  {
4284
4420
  ref,
@@ -4290,7 +4426,7 @@ var CardTitle = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE_
4290
4426
  }
4291
4427
  ));
4292
4428
  CardTitle.displayName = "CardTitle";
4293
- var CardDescription = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4429
+ var CardDescription = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4294
4430
  "p",
4295
4431
  {
4296
4432
  ref,
@@ -4299,9 +4435,9 @@ var CardDescription = React13.forwardRef(({ className, ...props }, ref) => /* @_
4299
4435
  }
4300
4436
  ));
4301
4437
  CardDescription.displayName = "CardDescription";
4302
- var CardContent = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
4438
+ var CardContent = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
4303
4439
  CardContent.displayName = "CardContent";
4304
- var CardFooter = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4440
+ var CardFooter = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4305
4441
  "div",
4306
4442
  {
4307
4443
  ref,
@@ -4723,7 +4859,7 @@ var SmartTextareaWidget = ({ fieldId }) => {
4723
4859
  },
4724
4860
  [setValue]
4725
4861
  );
4726
- React13__default.useEffect(() => {
4862
+ React15__default.useEffect(() => {
4727
4863
  if (nextKeywords !== currentKeywords) {
4728
4864
  writeValue(textValue, nextKeywords);
4729
4865
  }
@@ -4799,9 +4935,9 @@ var DiagnosisTextareaWidget = ({ fieldId }) => {
4799
4935
  const { state } = useForm();
4800
4936
  const handler = useFieldHandlers(fieldId);
4801
4937
  const def = fieldDef;
4802
- const [gradeGroups, setGradeGroups] = React13__default.useState([]);
4803
- const [isLoadingGrades, setIsLoadingGrades] = React13__default.useState(false);
4804
- const normalized = React13__default.useMemo(() => {
4938
+ const [gradeGroups, setGradeGroups] = React15__default.useState([]);
4939
+ const [isLoadingGrades, setIsLoadingGrades] = React15__default.useState(false);
4940
+ const normalized = React15__default.useMemo(() => {
4805
4941
  const raw = value;
4806
4942
  if (typeof raw === "string") {
4807
4943
  return { text: raw, selectedGradesByCondition: {} };
@@ -4833,7 +4969,7 @@ var DiagnosisTextareaWidget = ({ fieldId }) => {
4833
4969
  }, [value]);
4834
4970
  const textValue = normalized.text;
4835
4971
  const showError = !!error && (touched || state.submitAttempted);
4836
- React13__default.useEffect(() => {
4972
+ React15__default.useEffect(() => {
4837
4973
  const query = textValue.trim();
4838
4974
  const fetchGrades = handler.onFetchDiagnosisGrades;
4839
4975
  const debounceMs = def?.debounceDelay ?? 1e3;
@@ -6851,7 +6987,7 @@ var OphthalDiagnosisWidget = ({ fieldId }) => {
6851
6987
  ] })
6852
6988
  ] });
6853
6989
  };
6854
- var Slider = React13.forwardRef(({ className, trackClassName, thumbClassName, ...props }, ref) => /* @__PURE__ */ jsxs(
6990
+ var Slider = React15.forwardRef(({ className, trackClassName, thumbClassName, ...props }, ref) => /* @__PURE__ */ jsxs(
6855
6991
  SliderPrimitive.Root,
6856
6992
  {
6857
6993
  ref,
@@ -7239,6 +7375,9 @@ var FieldRenderer = ({ fieldId }) => {
7239
7375
  if (!visible || !fieldDef) {
7240
7376
  return null;
7241
7377
  }
7378
+ return renderWidget(fieldId, fieldDef);
7379
+ };
7380
+ function renderWidget(fieldId, fieldDef) {
7242
7381
  switch (fieldDef.type) {
7243
7382
  case "text":
7244
7383
  case "number":
@@ -7311,7 +7450,7 @@ var FieldRenderer = ({ fieldId }) => {
7311
7450
  fieldDef.type
7312
7451
  ] });
7313
7452
  }
7314
- };
7453
+ }
7315
7454
  var Section = ({ title, children }) => {
7316
7455
  const [expanded, setExpanded] = useState(true);
7317
7456
  const handleToggle = () => setExpanded((prev) => !prev);
@@ -7366,7 +7505,7 @@ var DynamicForm = () => {
7366
7505
  children: child.children.map((fieldId) => /* @__PURE__ */ jsx(FieldRenderer, { fieldId }, fieldId))
7367
7506
  },
7368
7507
  child.id
7369
- ) : /* @__PURE__ */ jsx(React13__default.Fragment, {}, child.id ?? index)
7508
+ ) : /* @__PURE__ */ jsx(React15__default.Fragment, {}, child.id ?? index)
7370
7509
  ) }, node.id);
7371
7510
  }
7372
7511
  if (node.type === "column_layout") {
@@ -7950,7 +8089,7 @@ var ReadOnlyForm = ({ schema, submission }) => {
7950
8089
  child.id
7951
8090
  );
7952
8091
  }
7953
- return /* @__PURE__ */ jsx(React13__default.Fragment, {}, child.id ?? index);
8092
+ return /* @__PURE__ */ jsx(React15__default.Fragment, {}, child.id ?? index);
7954
8093
  };
7955
8094
  const hasContent = node.children.some(
7956
8095
  (child) => typeof child === "string" ? fieldMap.has(child) : child.type === "column_layout" && child.children?.some((id) => fieldMap.has(id))