formanitor 0.2.3 → 0.2.4
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/BpeChartWidget-HATASHAC.mjs +7 -0
- package/dist/BpeChartWidget-HATASHAC.mjs.map +1 -0
- package/dist/BpeChartWidget-VZRH7M7L.cjs +28 -0
- package/dist/BpeChartWidget-VZRH7M7L.cjs.map +1 -0
- package/dist/{DateTimeWidget-3AUBZYYK.mjs → DateTimeWidget-KRX4O6OD.mjs} +5 -4
- package/dist/DateTimeWidget-KRX4O6OD.mjs.map +1 -0
- package/dist/{DateTimeWidget-OS7ER5F6.cjs → DateTimeWidget-RJ7SATVA.cjs} +6 -5
- package/dist/DateTimeWidget-RJ7SATVA.cjs.map +1 -0
- package/dist/{DateWidget-KCTE6N5G.mjs → DateWidget-JEKDKPNS.mjs} +4 -3
- package/dist/DateWidget-JEKDKPNS.mjs.map +1 -0
- package/dist/{DateWidget-UNLX544Z.cjs → DateWidget-T7IQUWEA.cjs} +8 -7
- package/dist/DateWidget-T7IQUWEA.cjs.map +1 -0
- package/dist/DentalChartWidget-LYLOFWZU.cjs +21 -0
- package/dist/DentalChartWidget-LYLOFWZU.cjs.map +1 -0
- package/dist/DentalChartWidget-P2YPKAMO.mjs +8 -0
- package/dist/DentalChartWidget-P2YPKAMO.mjs.map +1 -0
- package/dist/{EditableTable-VQ72UEFF.cjs → EditableTable-OW5LC6OC.cjs} +6 -5
- package/dist/EditableTable-OW5LC6OC.cjs.map +1 -0
- package/dist/{EditableTable-XFCPKSUY.mjs → EditableTable-VZ66IXYI.mjs} +5 -4
- package/dist/EditableTable-VZ66IXYI.mjs.map +1 -0
- package/dist/ExtraOralExamWidget-JVKJ4ZWC.mjs +438 -0
- package/dist/ExtraOralExamWidget-JVKJ4ZWC.mjs.map +1 -0
- package/dist/ExtraOralExamWidget-ZIOSKMIO.cjs +440 -0
- package/dist/ExtraOralExamWidget-ZIOSKMIO.cjs.map +1 -0
- package/dist/{FollowupWidget-MAYTHM2E.cjs → FollowupWidget-2STSJSDY.cjs} +8 -7
- package/dist/FollowupWidget-2STSJSDY.cjs.map +1 -0
- package/dist/{FollowupWidget-BFZ6P2JE.mjs → FollowupWidget-GCGPWZVY.mjs} +4 -3
- package/dist/FollowupWidget-GCGPWZVY.mjs.map +1 -0
- package/dist/{OBGPathwayWidget-X67XKRIH.mjs → OBGPathwayWidget-QJNWUIEM.mjs} +4 -3
- package/dist/OBGPathwayWidget-QJNWUIEM.mjs.map +1 -0
- package/dist/{OBGPathwayWidget-XGN3HEWS.cjs → OBGPathwayWidget-YRU36UL7.cjs} +13 -12
- package/dist/OBGPathwayWidget-YRU36UL7.cjs.map +1 -0
- package/dist/{ObstetricHistoryWidget-Z4VAXH3E.mjs → ObstetricHistoryWidget-EW6JLNQ7.mjs} +4 -3
- package/dist/ObstetricHistoryWidget-EW6JLNQ7.mjs.map +1 -0
- package/dist/{ObstetricHistoryWidget-RP7NY4PV.cjs → ObstetricHistoryWidget-OOWCVFRB.cjs} +10 -9
- package/dist/ObstetricHistoryWidget-OOWCVFRB.cjs.map +1 -0
- package/dist/PregnancyStatusWidget-QTTVFBOE.cjs +96 -0
- package/dist/PregnancyStatusWidget-QTTVFBOE.cjs.map +1 -0
- package/dist/PregnancyStatusWidget-U2BEJGBJ.mjs +94 -0
- package/dist/PregnancyStatusWidget-U2BEJGBJ.mjs.map +1 -0
- package/dist/{SuggestionTextareaWidget-DY6M5JPO.cjs → SuggestionTextareaWidget-FWRZ46MV.cjs} +5 -5
- package/dist/{SuggestionTextareaWidget-DY6M5JPO.cjs.map → SuggestionTextareaWidget-FWRZ46MV.cjs.map} +1 -1
- package/dist/{SuggestionTextareaWidget-GQTWCFBG.mjs → SuggestionTextareaWidget-UNL3FZRI.mjs} +3 -3
- package/dist/{SuggestionTextareaWidget-GQTWCFBG.mjs.map → SuggestionTextareaWidget-UNL3FZRI.mjs.map} +1 -1
- package/dist/TreatmentPlanWidget-665HLKYV.mjs +317 -0
- package/dist/TreatmentPlanWidget-665HLKYV.mjs.map +1 -0
- package/dist/TreatmentPlanWidget-TATWSPLY.cjs +319 -0
- package/dist/TreatmentPlanWidget-TATWSPLY.cjs.map +1 -0
- package/dist/{chunk-4PMNVBJD.mjs → chunk-2OMQV2ZB.mjs} +4 -3
- package/dist/chunk-2OMQV2ZB.mjs.map +1 -0
- package/dist/chunk-5RT3S67O.cjs +30 -0
- package/dist/chunk-5RT3S67O.cjs.map +1 -0
- package/dist/chunk-6YUVILN5.mjs +42 -0
- package/dist/chunk-6YUVILN5.mjs.map +1 -0
- package/dist/{chunk-YEFM2ERQ.cjs → chunk-7OQFO6TM.cjs} +8 -7
- package/dist/chunk-7OQFO6TM.cjs.map +1 -0
- package/dist/chunk-BBD3Y37O.cjs +220 -0
- package/dist/chunk-BBD3Y37O.cjs.map +1 -0
- package/dist/chunk-EJ7MKHER.mjs +45 -0
- package/dist/chunk-EJ7MKHER.mjs.map +1 -0
- package/dist/{chunk-XN2QLBLT.mjs → chunk-G6Y4UJPN.mjs} +5 -4
- package/dist/chunk-G6Y4UJPN.mjs.map +1 -0
- package/dist/{chunk-AZSAPO2V.cjs → chunk-HXY3IX3G.cjs} +3 -44
- package/dist/chunk-HXY3IX3G.cjs.map +1 -0
- package/dist/{chunk-BMNY7F6H.mjs → chunk-JM7WNDNT.mjs} +4 -21
- package/dist/chunk-JM7WNDNT.mjs.map +1 -0
- package/dist/chunk-MQHZ7HD2.mjs +215 -0
- package/dist/chunk-MQHZ7HD2.mjs.map +1 -0
- package/dist/{chunk-ML47UEDU.cjs → chunk-O4FSJPU3.cjs} +2 -27
- package/dist/chunk-O4FSJPU3.cjs.map +1 -0
- package/dist/chunk-Q66LXMRR.mjs +28 -0
- package/dist/chunk-Q66LXMRR.mjs.map +1 -0
- package/dist/chunk-RILRMRXB.cjs +50 -0
- package/dist/chunk-RILRMRXB.cjs.map +1 -0
- package/dist/chunk-SQ2KNAUD.cjs +64 -0
- package/dist/chunk-SQ2KNAUD.cjs.map +1 -0
- package/dist/{chunk-TVFUWRTE.cjs → chunk-TCQQUJCL.cjs} +5 -4
- package/dist/chunk-TCQQUJCL.cjs.map +1 -0
- package/dist/chunk-UKSP3B3W.mjs +600 -0
- package/dist/chunk-UKSP3B3W.mjs.map +1 -0
- package/dist/chunk-X4AJCTON.cjs +607 -0
- package/dist/chunk-X4AJCTON.cjs.map +1 -0
- package/dist/chunk-ZZX3IG2T.mjs +25 -0
- package/dist/chunk-ZZX3IG2T.mjs.map +1 -0
- package/dist/index.cjs +104 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +67 -3
- package/dist/index.d.ts +67 -3
- package/dist/index.mjs +70 -42
- package/dist/index.mjs.map +1 -1
- package/dist/read-only-table.d.cts +1 -1
- package/dist/read-only-table.d.ts +1 -1
- package/dist/smart.d.cts +1 -1
- package/dist/smart.d.ts +1 -1
- package/dist/{types-CYtJk8H9.d.ts → types-BbOnd5IN.d.cts} +53 -3
- package/dist/{types-CYtJk8H9.d.cts → types-BbOnd5IN.d.ts} +53 -3
- package/package.json +1 -1
- package/dist/DateTimeWidget-3AUBZYYK.mjs.map +0 -1
- package/dist/DateTimeWidget-OS7ER5F6.cjs.map +0 -1
- package/dist/DateWidget-KCTE6N5G.mjs.map +0 -1
- package/dist/DateWidget-UNLX544Z.cjs.map +0 -1
- package/dist/EditableTable-VQ72UEFF.cjs.map +0 -1
- package/dist/EditableTable-XFCPKSUY.mjs.map +0 -1
- package/dist/FollowupWidget-BFZ6P2JE.mjs.map +0 -1
- package/dist/FollowupWidget-MAYTHM2E.cjs.map +0 -1
- package/dist/OBGPathwayWidget-X67XKRIH.mjs.map +0 -1
- package/dist/OBGPathwayWidget-XGN3HEWS.cjs.map +0 -1
- package/dist/ObstetricHistoryWidget-RP7NY4PV.cjs.map +0 -1
- package/dist/ObstetricHistoryWidget-Z4VAXH3E.mjs.map +0 -1
- package/dist/chunk-4HDMR2LX.mjs +0 -69
- package/dist/chunk-4HDMR2LX.mjs.map +0 -1
- package/dist/chunk-4PMNVBJD.mjs.map +0 -1
- package/dist/chunk-AZSAPO2V.cjs.map +0 -1
- package/dist/chunk-BMNY7F6H.mjs.map +0 -1
- package/dist/chunk-ML47UEDU.cjs.map +0 -1
- package/dist/chunk-TVFUWRTE.cjs.map +0 -1
- package/dist/chunk-XN2QLBLT.mjs.map +0 -1
- package/dist/chunk-YEFM2ERQ.cjs.map +0 -1
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkSQ2KNAUD_cjs = require('./chunk-SQ2KNAUD.cjs');
|
|
4
|
+
var chunk5E3APMY6_cjs = require('./chunk-5E3APMY6.cjs');
|
|
5
|
+
var chunkTJHG5WHX_cjs = require('./chunk-TJHG5WHX.cjs');
|
|
6
|
+
var chunkTB33A4PD_cjs = require('./chunk-TB33A4PD.cjs');
|
|
7
|
+
var chunkJMGUUFOJ_cjs = require('./chunk-JMGUUFOJ.cjs');
|
|
8
|
+
require('./chunk-FHHISVCH.cjs');
|
|
9
|
+
require('react');
|
|
10
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
11
|
+
|
|
12
|
+
function normalizePregnancyStatus(raw) {
|
|
13
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
14
|
+
const v = raw;
|
|
15
|
+
return {
|
|
16
|
+
is_pregnant: v.is_pregnant === true,
|
|
17
|
+
is_breastfeeding: v.is_breastfeeding === true,
|
|
18
|
+
pregnant_notes: typeof v.pregnant_notes === "string" ? v.pregnant_notes : "",
|
|
19
|
+
breastfeeding_notes: typeof v.breastfeeding_notes === "string" ? v.breastfeeding_notes : ""
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
return { is_pregnant: false, is_breastfeeding: false, pregnant_notes: "", breastfeeding_notes: "" };
|
|
23
|
+
}
|
|
24
|
+
var PregnancyStatusWidget = ({ fieldId }) => {
|
|
25
|
+
const { fieldDef, value, setValue, setTouched, disabled } = chunkTB33A4PD_cjs.useField(fieldId);
|
|
26
|
+
const safe = normalizePregnancyStatus(value);
|
|
27
|
+
const update = (patch) => {
|
|
28
|
+
setValue({ ...safe, ...patch });
|
|
29
|
+
setTouched();
|
|
30
|
+
};
|
|
31
|
+
if (!fieldDef) return null;
|
|
32
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunk5E3APMY6_cjs.fieldWrapperClass(fieldDef, "space-y-2.5"), children: [
|
|
33
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
34
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
35
|
+
chunkSQ2KNAUD_cjs.Switch,
|
|
36
|
+
{
|
|
37
|
+
id: `${fieldId}-pregnant`,
|
|
38
|
+
checked: safe.is_pregnant,
|
|
39
|
+
disabled,
|
|
40
|
+
onCheckedChange: (checked) => update({ is_pregnant: checked, pregnant_notes: checked ? safe.pregnant_notes : "" })
|
|
41
|
+
}
|
|
42
|
+
),
|
|
43
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
44
|
+
chunkJMGUUFOJ_cjs.Label,
|
|
45
|
+
{
|
|
46
|
+
htmlFor: `${fieldId}-pregnant`,
|
|
47
|
+
className: "w-28 cursor-pointer text-sm font-medium leading-none",
|
|
48
|
+
children: "Pregnant"
|
|
49
|
+
}
|
|
50
|
+
),
|
|
51
|
+
safe.is_pregnant && /* @__PURE__ */ jsxRuntime.jsx(
|
|
52
|
+
chunkTJHG5WHX_cjs.Input,
|
|
53
|
+
{
|
|
54
|
+
className: "h-7 flex-1 text-xs",
|
|
55
|
+
placeholder: "e.g. 14 weeks, G2P1\u2026",
|
|
56
|
+
value: safe.pregnant_notes ?? "",
|
|
57
|
+
disabled,
|
|
58
|
+
onChange: (e) => update({ pregnant_notes: e.target.value })
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
] }),
|
|
62
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
63
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
64
|
+
chunkSQ2KNAUD_cjs.Switch,
|
|
65
|
+
{
|
|
66
|
+
id: `${fieldId}-breastfeeding`,
|
|
67
|
+
checked: safe.is_breastfeeding,
|
|
68
|
+
disabled,
|
|
69
|
+
onCheckedChange: (checked) => update({ is_breastfeeding: checked, breastfeeding_notes: checked ? safe.breastfeeding_notes : "" })
|
|
70
|
+
}
|
|
71
|
+
),
|
|
72
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
73
|
+
chunkJMGUUFOJ_cjs.Label,
|
|
74
|
+
{
|
|
75
|
+
htmlFor: `${fieldId}-breastfeeding`,
|
|
76
|
+
className: "w-28 cursor-pointer text-sm font-medium leading-none",
|
|
77
|
+
children: "Breastfeeding"
|
|
78
|
+
}
|
|
79
|
+
),
|
|
80
|
+
safe.is_breastfeeding && /* @__PURE__ */ jsxRuntime.jsx(
|
|
81
|
+
chunkTJHG5WHX_cjs.Input,
|
|
82
|
+
{
|
|
83
|
+
className: "h-7 flex-1 text-xs",
|
|
84
|
+
placeholder: "e.g. exclusively, 3 months\u2026",
|
|
85
|
+
value: safe.breastfeeding_notes ?? "",
|
|
86
|
+
disabled,
|
|
87
|
+
onChange: (e) => update({ breastfeeding_notes: e.target.value })
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
] })
|
|
91
|
+
] });
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
exports.PregnancyStatusWidget = PregnancyStatusWidget;
|
|
95
|
+
//# sourceMappingURL=PregnancyStatusWidget-QTTVFBOE.cjs.map
|
|
96
|
+
//# sourceMappingURL=PregnancyStatusWidget-QTTVFBOE.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ui/widgets/PregnancyStatusWidget.tsx"],"names":["useField","fieldWrapperClass","jsxs","jsx","Switch","Label","Input"],"mappings":"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","file":"PregnancyStatusWidget-QTTVFBOE.cjs","sourcesContent":["import React from 'react';\nimport { useField } from '../../react/useField';\nimport { Switch } from '../shadcn/switch';\nimport { Label } from '../shadcn/label';\nimport { Input } from '../shadcn/input';\nimport type { PregnancyStatusValue } from '../../core/types';\nimport { fieldWrapperClass } from '../../react/fieldStyle';\n\nfunction normalizePregnancyStatus(raw: unknown): PregnancyStatusValue {\n if (raw && typeof raw === 'object' && !Array.isArray(raw)) {\n const v = raw as Record<string, unknown>;\n return {\n is_pregnant: v.is_pregnant === true,\n is_breastfeeding: v.is_breastfeeding === true,\n pregnant_notes: typeof v.pregnant_notes === 'string' ? v.pregnant_notes : '',\n breastfeeding_notes: typeof v.breastfeeding_notes === 'string' ? v.breastfeeding_notes : '',\n };\n }\n return { is_pregnant: false, is_breastfeeding: false, pregnant_notes: '', breastfeeding_notes: '' };\n}\n\nexport const PregnancyStatusWidget: React.FC<{ fieldId: string }> = ({ fieldId }) => {\n const { fieldDef, value, setValue, setTouched, disabled } = useField(fieldId);\n const safe = normalizePregnancyStatus(value);\n\n const update = (patch: Partial<PregnancyStatusValue>) => {\n setValue({ ...safe, ...patch });\n setTouched();\n };\n\n if (!fieldDef) return null;\n\n return (\n <div className={fieldWrapperClass(fieldDef, 'space-y-2.5')}>\n {/* Pregnant row */}\n <div className=\"flex items-center gap-3\">\n <Switch\n id={`${fieldId}-pregnant`}\n checked={safe.is_pregnant}\n disabled={disabled}\n onCheckedChange={(checked) =>\n update({ is_pregnant: checked, pregnant_notes: checked ? safe.pregnant_notes : '' })\n }\n />\n <Label\n htmlFor={`${fieldId}-pregnant`}\n className=\"w-28 cursor-pointer text-sm font-medium leading-none\"\n >\n Pregnant\n </Label>\n {safe.is_pregnant && (\n <Input\n className=\"h-7 flex-1 text-xs\"\n placeholder=\"e.g. 14 weeks, G2P1…\"\n value={safe.pregnant_notes ?? ''}\n disabled={disabled}\n onChange={(e) => update({ pregnant_notes: e.target.value })}\n />\n )}\n </div>\n\n {/* Breastfeeding row */}\n <div className=\"flex items-center gap-3\">\n <Switch\n id={`${fieldId}-breastfeeding`}\n checked={safe.is_breastfeeding}\n disabled={disabled}\n onCheckedChange={(checked) =>\n update({ is_breastfeeding: checked, breastfeeding_notes: checked ? safe.breastfeeding_notes : '' })\n }\n />\n <Label\n htmlFor={`${fieldId}-breastfeeding`}\n className=\"w-28 cursor-pointer text-sm font-medium leading-none\"\n >\n Breastfeeding\n </Label>\n {safe.is_breastfeeding && (\n <Input\n className=\"h-7 flex-1 text-xs\"\n placeholder=\"e.g. exclusively, 3 months…\"\n value={safe.breastfeeding_notes ?? ''}\n disabled={disabled}\n onChange={(e) => update({ breastfeeding_notes: e.target.value })}\n />\n )}\n </div>\n </div>\n );\n};\n"]}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Switch } from './chunk-6YUVILN5.mjs';
|
|
2
|
+
import { fieldWrapperClass } from './chunk-WYVXXEZI.mjs';
|
|
3
|
+
import { Input } from './chunk-VNFBUAZD.mjs';
|
|
4
|
+
import { useField } from './chunk-2BGJZ44Q.mjs';
|
|
5
|
+
import { Label } from './chunk-HEFZA2AH.mjs';
|
|
6
|
+
import './chunk-VPU66PI6.mjs';
|
|
7
|
+
import 'react';
|
|
8
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
9
|
+
|
|
10
|
+
function normalizePregnancyStatus(raw) {
|
|
11
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
12
|
+
const v = raw;
|
|
13
|
+
return {
|
|
14
|
+
is_pregnant: v.is_pregnant === true,
|
|
15
|
+
is_breastfeeding: v.is_breastfeeding === true,
|
|
16
|
+
pregnant_notes: typeof v.pregnant_notes === "string" ? v.pregnant_notes : "",
|
|
17
|
+
breastfeeding_notes: typeof v.breastfeeding_notes === "string" ? v.breastfeeding_notes : ""
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
return { is_pregnant: false, is_breastfeeding: false, pregnant_notes: "", breastfeeding_notes: "" };
|
|
21
|
+
}
|
|
22
|
+
var PregnancyStatusWidget = ({ fieldId }) => {
|
|
23
|
+
const { fieldDef, value, setValue, setTouched, disabled } = useField(fieldId);
|
|
24
|
+
const safe = normalizePregnancyStatus(value);
|
|
25
|
+
const update = (patch) => {
|
|
26
|
+
setValue({ ...safe, ...patch });
|
|
27
|
+
setTouched();
|
|
28
|
+
};
|
|
29
|
+
if (!fieldDef) return null;
|
|
30
|
+
return /* @__PURE__ */ jsxs("div", { className: fieldWrapperClass(fieldDef, "space-y-2.5"), children: [
|
|
31
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
32
|
+
/* @__PURE__ */ jsx(
|
|
33
|
+
Switch,
|
|
34
|
+
{
|
|
35
|
+
id: `${fieldId}-pregnant`,
|
|
36
|
+
checked: safe.is_pregnant,
|
|
37
|
+
disabled,
|
|
38
|
+
onCheckedChange: (checked) => update({ is_pregnant: checked, pregnant_notes: checked ? safe.pregnant_notes : "" })
|
|
39
|
+
}
|
|
40
|
+
),
|
|
41
|
+
/* @__PURE__ */ jsx(
|
|
42
|
+
Label,
|
|
43
|
+
{
|
|
44
|
+
htmlFor: `${fieldId}-pregnant`,
|
|
45
|
+
className: "w-28 cursor-pointer text-sm font-medium leading-none",
|
|
46
|
+
children: "Pregnant"
|
|
47
|
+
}
|
|
48
|
+
),
|
|
49
|
+
safe.is_pregnant && /* @__PURE__ */ jsx(
|
|
50
|
+
Input,
|
|
51
|
+
{
|
|
52
|
+
className: "h-7 flex-1 text-xs",
|
|
53
|
+
placeholder: "e.g. 14 weeks, G2P1\u2026",
|
|
54
|
+
value: safe.pregnant_notes ?? "",
|
|
55
|
+
disabled,
|
|
56
|
+
onChange: (e) => update({ pregnant_notes: e.target.value })
|
|
57
|
+
}
|
|
58
|
+
)
|
|
59
|
+
] }),
|
|
60
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
61
|
+
/* @__PURE__ */ jsx(
|
|
62
|
+
Switch,
|
|
63
|
+
{
|
|
64
|
+
id: `${fieldId}-breastfeeding`,
|
|
65
|
+
checked: safe.is_breastfeeding,
|
|
66
|
+
disabled,
|
|
67
|
+
onCheckedChange: (checked) => update({ is_breastfeeding: checked, breastfeeding_notes: checked ? safe.breastfeeding_notes : "" })
|
|
68
|
+
}
|
|
69
|
+
),
|
|
70
|
+
/* @__PURE__ */ jsx(
|
|
71
|
+
Label,
|
|
72
|
+
{
|
|
73
|
+
htmlFor: `${fieldId}-breastfeeding`,
|
|
74
|
+
className: "w-28 cursor-pointer text-sm font-medium leading-none",
|
|
75
|
+
children: "Breastfeeding"
|
|
76
|
+
}
|
|
77
|
+
),
|
|
78
|
+
safe.is_breastfeeding && /* @__PURE__ */ jsx(
|
|
79
|
+
Input,
|
|
80
|
+
{
|
|
81
|
+
className: "h-7 flex-1 text-xs",
|
|
82
|
+
placeholder: "e.g. exclusively, 3 months\u2026",
|
|
83
|
+
value: safe.breastfeeding_notes ?? "",
|
|
84
|
+
disabled,
|
|
85
|
+
onChange: (e) => update({ breastfeeding_notes: e.target.value })
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
] })
|
|
89
|
+
] });
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export { PregnancyStatusWidget };
|
|
93
|
+
//# sourceMappingURL=PregnancyStatusWidget-U2BEJGBJ.mjs.map
|
|
94
|
+
//# sourceMappingURL=PregnancyStatusWidget-U2BEJGBJ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ui/widgets/PregnancyStatusWidget.tsx"],"names":[],"mappings":"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","file":"PregnancyStatusWidget-U2BEJGBJ.mjs","sourcesContent":["import React from 'react';\nimport { useField } from '../../react/useField';\nimport { Switch } from '../shadcn/switch';\nimport { Label } from '../shadcn/label';\nimport { Input } from '../shadcn/input';\nimport type { PregnancyStatusValue } from '../../core/types';\nimport { fieldWrapperClass } from '../../react/fieldStyle';\n\nfunction normalizePregnancyStatus(raw: unknown): PregnancyStatusValue {\n if (raw && typeof raw === 'object' && !Array.isArray(raw)) {\n const v = raw as Record<string, unknown>;\n return {\n is_pregnant: v.is_pregnant === true,\n is_breastfeeding: v.is_breastfeeding === true,\n pregnant_notes: typeof v.pregnant_notes === 'string' ? v.pregnant_notes : '',\n breastfeeding_notes: typeof v.breastfeeding_notes === 'string' ? v.breastfeeding_notes : '',\n };\n }\n return { is_pregnant: false, is_breastfeeding: false, pregnant_notes: '', breastfeeding_notes: '' };\n}\n\nexport const PregnancyStatusWidget: React.FC<{ fieldId: string }> = ({ fieldId }) => {\n const { fieldDef, value, setValue, setTouched, disabled } = useField(fieldId);\n const safe = normalizePregnancyStatus(value);\n\n const update = (patch: Partial<PregnancyStatusValue>) => {\n setValue({ ...safe, ...patch });\n setTouched();\n };\n\n if (!fieldDef) return null;\n\n return (\n <div className={fieldWrapperClass(fieldDef, 'space-y-2.5')}>\n {/* Pregnant row */}\n <div className=\"flex items-center gap-3\">\n <Switch\n id={`${fieldId}-pregnant`}\n checked={safe.is_pregnant}\n disabled={disabled}\n onCheckedChange={(checked) =>\n update({ is_pregnant: checked, pregnant_notes: checked ? safe.pregnant_notes : '' })\n }\n />\n <Label\n htmlFor={`${fieldId}-pregnant`}\n className=\"w-28 cursor-pointer text-sm font-medium leading-none\"\n >\n Pregnant\n </Label>\n {safe.is_pregnant && (\n <Input\n className=\"h-7 flex-1 text-xs\"\n placeholder=\"e.g. 14 weeks, G2P1…\"\n value={safe.pregnant_notes ?? ''}\n disabled={disabled}\n onChange={(e) => update({ pregnant_notes: e.target.value })}\n />\n )}\n </div>\n\n {/* Breastfeeding row */}\n <div className=\"flex items-center gap-3\">\n <Switch\n id={`${fieldId}-breastfeeding`}\n checked={safe.is_breastfeeding}\n disabled={disabled}\n onCheckedChange={(checked) =>\n update({ is_breastfeeding: checked, breastfeeding_notes: checked ? safe.breastfeeding_notes : '' })\n }\n />\n <Label\n htmlFor={`${fieldId}-breastfeeding`}\n className=\"w-28 cursor-pointer text-sm font-medium leading-none\"\n >\n Breastfeeding\n </Label>\n {safe.is_breastfeeding && (\n <Input\n className=\"h-7 flex-1 text-xs\"\n placeholder=\"e.g. exclusively, 3 months…\"\n value={safe.breastfeeding_notes ?? ''}\n disabled={disabled}\n onChange={(e) => update({ breastfeeding_notes: e.target.value })}\n />\n )}\n </div>\n </div>\n );\n};\n"]}
|
package/dist/{SuggestionTextareaWidget-DY6M5JPO.cjs → SuggestionTextareaWidget-FWRZ46MV.cjs}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkTCQQUJCL_cjs = require('./chunk-TCQQUJCL.cjs');
|
|
4
4
|
var chunkUGGUIXUS_cjs = require('./chunk-UGGUIXUS.cjs');
|
|
5
5
|
var chunkPHADAQSH_cjs = require('./chunk-PHADAQSH.cjs');
|
|
6
6
|
var chunkP62377LB_cjs = require('./chunk-P62377LB.cjs');
|
|
@@ -57,9 +57,9 @@ function EmbeddedSchemaField({ fieldId }) {
|
|
|
57
57
|
case "text":
|
|
58
58
|
case "number":
|
|
59
59
|
case "textarea":
|
|
60
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
60
|
+
return /* @__PURE__ */ jsxRuntime.jsx(chunkTCQQUJCL_cjs.TextWidget, { fieldId });
|
|
61
61
|
case "select":
|
|
62
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
62
|
+
return /* @__PURE__ */ jsxRuntime.jsx(chunkTCQQUJCL_cjs.SelectWidget, { fieldId });
|
|
63
63
|
default:
|
|
64
64
|
return null;
|
|
65
65
|
}
|
|
@@ -222,5 +222,5 @@ Object.defineProperty(exports, "toggleSuggestionTokenInText", {
|
|
|
222
222
|
exports.ComplaintChipsWidget = ComplaintChipsWidget;
|
|
223
223
|
exports.SuggestionTextareaWidget = SuggestionTextareaWidget;
|
|
224
224
|
exports.deriveKnownSuggestionChipValues = deriveKnownSuggestionChipValues;
|
|
225
|
-
//# sourceMappingURL=SuggestionTextareaWidget-
|
|
226
|
-
//# sourceMappingURL=SuggestionTextareaWidget-
|
|
225
|
+
//# sourceMappingURL=SuggestionTextareaWidget-FWRZ46MV.cjs.map
|
|
226
|
+
//# sourceMappingURL=SuggestionTextareaWidget-FWRZ46MV.cjs.map
|
package/dist/{SuggestionTextareaWidget-DY6M5JPO.cjs.map → SuggestionTextareaWidget-FWRZ46MV.cjs.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ui/widgets/SuggestionTextareaWidget.tsx"],"names":["getSuggestionTokensFromText","useFormStore","jsx","TextWidget","SelectWidget","useField","useForm","useState","useMemo","useEffect","fetchOptions","getThemeConfig","cn","fieldControlClass","jsxs","Fragment","FieldRequiredIndicator","isLabelVisible","Label","fieldLabelClass","toggleSuggestionTokenInText","fieldWrapperClass","VoiceMicButton","fieldDescriptionClass","Textarea","fieldErrorClass"],"mappings":"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","file":"SuggestionTextareaWidget-DY6M5JPO.cjs","sourcesContent":["import React, { useEffect, useMemo, useState } from 'react';\nimport { useField } from '../../react/useField';\nimport { useForm } from '../../react/useForm';\nimport { useFormStore } from '../../react/FormProvider';\nimport { VoiceMicButton } from '../../react/VoiceMicButton';\nimport { Label } from '../shadcn/label';\nimport { Textarea } from '../shadcn/textarea';\nimport { getThemeConfig } from '../themes';\nimport { fetchOptions } from '../../core/asyncOptions';\nimport { cn } from '../../core/utils';\nimport type { SelectOption, SuggestionTextareaFieldDef } from '../../core/types';\nimport {\n FieldRequiredIndicator,\n fieldControlClass,\n fieldDescriptionClass,\n fieldErrorClass,\n fieldLabelClass,\n fieldWrapperClass,\n isLabelVisible,\n} from '../../react/fieldStyle';\nimport { TextWidget } from './Text';\nimport { SelectWidget } from './Select';\n\nimport { getSuggestionTokensFromText, toggleSuggestionTokenInText } from '../../core/suggestionTokens';\n\nexport { getSuggestionTokensFromText, toggleSuggestionTokenInText };\n\nconst DEFAULT_TOKEN_SEPARATOR = ', ';\n\nfunction getAppendSeparator(def: SuggestionTextareaFieldDef): string {\n const raw = def.meta && typeof (def.meta as { appendSeparator?: unknown }).appendSeparator === 'string'\n ? (def.meta as { appendSeparator: string }).appendSeparator\n : DEFAULT_TOKEN_SEPARATOR;\n return raw;\n}\n\nfunction isTokenSelected(text: string, optionValue: unknown): boolean {\n const t = String(optionValue).trim();\n if (!t) return false;\n return getSuggestionTokensFromText(text).some((p) => p === t);\n}\n\n/**\n * Chip option values present in `text` as comma-separated tokens (same typing as schema `options[].value`).\n * Order follows left-to-right token order; duplicates in text only appear once.\n */\nexport function deriveKnownSuggestionChipValues(text: string, options: SelectOption[]): unknown[] {\n if (!options.length) return [];\n const allowed = new Map<string, unknown>(options.map((o) => [String(o.value), o.value] as const));\n const tokens = getSuggestionTokensFromText(text);\n const out: unknown[] = [];\n const seen = new Set<string>();\n for (const t of tokens) {\n if (!allowed.has(t) || seen.has(t)) continue;\n seen.add(t);\n out.push(allowed.get(t)!);\n }\n return out;\n}\n\nfunction parallelChipArraysEqual(a: unknown, b: unknown): boolean {\n if (!Array.isArray(a) || !Array.isArray(b)) return false;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n\nfunction isSuggestionField(type: string | undefined): type is SuggestionTextareaFieldDef['type'] {\n return type === 'suggestion_textarea' || type === 'complaint_chips';\n}\n\n/**\n * Renders a sibling schema field inside the suggestion textarea shell. Uses concrete widgets\n * (not FieldRenderer) so `hidden` layout fields still render here without circular imports.\n * Supported: text, number, textarea, select.\n */\nfunction EmbeddedSchemaField({ fieldId }: { fieldId: string }) {\n const store = useFormStore();\n const fieldDef = store.getFieldDef(fieldId);\n if (!fieldDef) return null;\n switch (fieldDef.type) {\n case 'text':\n case 'number':\n case 'textarea':\n return <TextWidget fieldId={fieldId} />;\n case 'select':\n return <SelectWidget fieldId={fieldId} />;\n default:\n return null;\n }\n}\n\n/**\n * Reusable textarea with schema-driven **suggestion chips** inside the input area (same white\n * shell as the textarea). The field value is a **single string**: clicking a chip **appends**\n * that option’s `value` or **removes** it if already selected. When chip options are loaded,\n * slugs are kept on the **last line** (comma + space by default), with prose above separated by\n * a newline. Optional `meta.parallelChipFieldId` mirrors chip selections into a sibling\n * **`multiselect`** array. Free typing is still allowed.\n */\nexport const SuggestionTextareaWidget: React.FC<{ fieldId: string }> = ({ fieldId }) => {\n const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);\n const { state } = useForm();\n const store = useFormStore();\n const hasVoice = !!(fieldDef?.voice && store.getVoice());\n\n const [options, setOptions] = useState<SelectOption[]>([]);\n const [loading, setLoading] = useState(false);\n const showError = !!error && (touched || state.submitAttempted);\n\n const def =\n fieldDef && isSuggestionField(fieldDef.type) ? (fieldDef as SuggestionTextareaFieldDef) : undefined;\n\n const textValue = value == null || typeof value === 'string' ? value || '' : String(value);\n\n const parallelChipFieldId =\n def?.meta &&\n typeof (def.meta as { parallelChipFieldId?: unknown }).parallelChipFieldId === 'string'\n ? (def.meta as { parallelChipFieldId: string }).parallelChipFieldId.trim()\n : undefined;\n\n const embeddedFieldIds = useMemo(() => {\n const raw = def?.meta && Array.isArray((def.meta as { embeddedFieldIds?: unknown }).embeddedFieldIds)\n ? (def.meta as { embeddedFieldIds: unknown[] }).embeddedFieldIds\n : [];\n return raw\n .filter((id): id is string => typeof id === 'string' && id.trim().length > 0)\n .map((id) => id.trim())\n .filter((id) => store.getFieldDef(id));\n }, [def?.meta, store]);\n\n useEffect(() => {\n if (!def) {\n setOptions([]);\n return;\n }\n if (def.options?.length) {\n setOptions(def.options);\n } else if (def.dataSource) {\n setLoading(true);\n fetchOptions(def.dataSource.source, def.dataSource.params)\n .then((opts) => setOptions(opts as SelectOption[]))\n .finally(() => setLoading(false));\n } else {\n setOptions([]);\n }\n }, [def]);\n\n const chipAllowedSet = useMemo(\n () => new Set(options.map((o) => String(o.value).trim()).filter(Boolean)),\n [options],\n );\n\n useEffect(() => {\n if (!parallelChipFieldId) return;\n const parallelDef = store.getFieldDef(parallelChipFieldId);\n if (!parallelDef || parallelDef.type !== 'multiselect') return;\n const next = deriveKnownSuggestionChipValues(textValue, options);\n const prev = store.getFieldState(parallelChipFieldId).value;\n if (parallelChipArraysEqual(prev, next)) return;\n store.setValues({ [parallelChipFieldId]: next }, { touch: false });\n }, [def, parallelChipFieldId, textValue, options, store]);\n\n if (!def) {\n return null;\n }\n\n const appendSeparator = getAppendSeparator(def);\n const suggestionsAria =\n def.meta && typeof (def.meta as { suggestionsAriaLabel?: string }).suggestionsAriaLabel === 'string'\n ? (def.meta as { suggestionsAriaLabel: string }).suggestionsAriaLabel\n : 'Quick suggestions';\n\n const theme = getThemeConfig('textarea', def.theme);\n const wrapperClass = theme?.wrapperClassName ?? 'space-y-2';\n const labelClass = theme?.labelClassName;\n const inputClass = cn(theme?.inputClassName, showError && 'border-red-500');\n const inputWithStyle = fieldControlClass(def, inputClass);\n const height =\n def.height != null\n ? typeof def.height === 'string'\n ? Number(def.height) || undefined\n : def.height\n : undefined;\n\n const labelContent = (\n <>\n {def.label}{' '}\n <FieldRequiredIndicator fieldDef={def} />\n </>\n );\n\n const showLabel = isLabelVisible(def);\n\n const labelEl = showLabel ? (\n theme ? (\n <Label className={fieldLabelClass(def, labelClass)}>{labelContent}</Label>\n ) : (\n <Label className={fieldLabelClass(def)}>{labelContent}</Label>\n )\n ) : null;\n\n const onChipClick = (optValue: unknown) => {\n if (disabled) return;\n setValue(toggleSuggestionTokenInText(textValue, String(optValue), appendSeparator, chipAllowedSet));\n };\n\n const hasSuggestions = options.length > 0;\n const hasEmbedded = embeddedFieldIds.length > 0;\n const hasShell = hasSuggestions || hasEmbedded;\n const isHighlightLabel = def.theme === 'highlight-label';\n\n const suggestionShellClass = cn(\n 'flex min-w-0 flex-col overflow-hidden',\n hasShell &&\n (isHighlightLabel\n ? '-mt-1 rounded-b-md border-[#D0D0D0] bg-white'\n : 'rounded-md border border-input bg-background'),\n );\n\n const chipsRowClass = cn(\n 'flex flex-wrap gap-2 px-3 pb-2 pt-3',\n hasSuggestions &&\n (isHighlightLabel ? '' : 'border-b border-input/70'),\n disabled && 'pointer-events-none opacity-50',\n );\n\n const embeddedRowClass = cn(\n 'grid gap-3 px-3 sm:grid-cols-3',\n hasEmbedded &&\n (hasSuggestions\n ? cn('py-2', isHighlightLabel && 'border-t border-input/70')\n : 'border-b border-input/70 py-3'),\n disabled && 'pointer-events-none opacity-50',\n );\n\n const textareaShellClass = cn(\n inputWithStyle,\n hasShell &&\n cn(\n 'mt-0 rounded-t-none rounded-b-md border-0 shadow-none focus-visible:ring-offset-0',\n isHighlightLabel ? 'border-t-0' : 'min-h-[80px]',\n ),\n );\n\n const suggestionButtons =\n loading ? (\n <span className=\"text-xs text-muted-foreground\">Loading suggestions…</span>\n ) : (\n options.map((opt) => {\n const on = isTokenSelected(textValue, opt.value);\n return (\n <button\n key={String(opt.value)}\n type=\"button\"\n onClick={() => onChipClick(opt.value)}\n className={cn(\n 'inline-flex min-h-8 items-center rounded-full border px-3 py-1 text-xs font-medium leading-none transition-colors',\n on\n ? 'border-primary bg-primary/10 text-primary'\n : 'border-muted-foreground/30 bg-background hover:bg-muted/60',\n )}\n >\n {opt.label}\n </button>\n );\n })\n );\n\n return (\n <div className={fieldWrapperClass(def, wrapperClass)}>\n {hasVoice ? (\n <div className=\"flex items-center justify-between\">\n {labelEl}\n <VoiceMicButton fieldId={fieldId} onTranscriptReady={setValue} />\n </div>\n ) : (\n labelEl\n )}\n\n {def.description && (\n <p className={fieldDescriptionClass(def, 'text-xs text-muted-foreground')}>\n {def.description}\n </p>\n )}\n\n {hasShell ? (\n <div className={suggestionShellClass}>\n {hasSuggestions && (\n <div className={chipsRowClass} role=\"group\" aria-label={suggestionsAria}>\n {suggestionButtons}\n </div>\n )}\n {hasEmbedded && (\n <div className={embeddedRowClass}>\n {embeddedFieldIds.map((id) => (\n <EmbeddedSchemaField key={id} fieldId={id} />\n ))}\n </div>\n )}\n <Textarea\n id={fieldId}\n value={textValue}\n onChange={(e) => setValue(e.target.value)}\n onBlur={setTouched}\n disabled={disabled}\n className={textareaShellClass}\n placeholder={def.placeholder}\n style={height != null && Number.isFinite(height) ? { minHeight: height } : undefined}\n aria-label={!showLabel ? def.label : undefined}\n />\n </div>\n ) : (\n <Textarea\n id={fieldId}\n value={textValue}\n onChange={(e) => setValue(e.target.value)}\n onBlur={setTouched}\n disabled={disabled}\n className={inputWithStyle}\n placeholder={def.placeholder}\n style={height != null && Number.isFinite(height) ? { minHeight: height } : undefined}\n aria-label={!showLabel ? def.label : undefined}\n />\n )}\n\n {showError && (\n <p className={fieldErrorClass(def, 'text-xs text-red-500')}>{error}</p>\n )}\n </div>\n );\n};\n\n/** @deprecated Use `SuggestionTextareaWidget`. Kept for schema compatibility. */\nexport const ComplaintChipsWidget = SuggestionTextareaWidget;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/ui/widgets/SuggestionTextareaWidget.tsx"],"names":["getSuggestionTokensFromText","useFormStore","jsx","TextWidget","SelectWidget","useField","useForm","useState","useMemo","useEffect","fetchOptions","getThemeConfig","cn","fieldControlClass","jsxs","Fragment","FieldRequiredIndicator","isLabelVisible","Label","fieldLabelClass","toggleSuggestionTokenInText","fieldWrapperClass","VoiceMicButton","fieldDescriptionClass","Textarea","fieldErrorClass"],"mappings":"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","file":"SuggestionTextareaWidget-FWRZ46MV.cjs","sourcesContent":["import React, { useEffect, useMemo, useState } from 'react';\nimport { useField } from '../../react/useField';\nimport { useForm } from '../../react/useForm';\nimport { useFormStore } from '../../react/FormProvider';\nimport { VoiceMicButton } from '../../react/VoiceMicButton';\nimport { Label } from '../shadcn/label';\nimport { Textarea } from '../shadcn/textarea';\nimport { getThemeConfig } from '../themes';\nimport { fetchOptions } from '../../core/asyncOptions';\nimport { cn } from '../../core/utils';\nimport type { SelectOption, SuggestionTextareaFieldDef } from '../../core/types';\nimport {\n FieldRequiredIndicator,\n fieldControlClass,\n fieldDescriptionClass,\n fieldErrorClass,\n fieldLabelClass,\n fieldWrapperClass,\n isLabelVisible,\n} from '../../react/fieldStyle';\nimport { TextWidget } from './Text';\nimport { SelectWidget } from './Select';\n\nimport { getSuggestionTokensFromText, toggleSuggestionTokenInText } from '../../core/suggestionTokens';\n\nexport { getSuggestionTokensFromText, toggleSuggestionTokenInText };\n\nconst DEFAULT_TOKEN_SEPARATOR = ', ';\n\nfunction getAppendSeparator(def: SuggestionTextareaFieldDef): string {\n const raw = def.meta && typeof (def.meta as { appendSeparator?: unknown }).appendSeparator === 'string'\n ? (def.meta as { appendSeparator: string }).appendSeparator\n : DEFAULT_TOKEN_SEPARATOR;\n return raw;\n}\n\nfunction isTokenSelected(text: string, optionValue: unknown): boolean {\n const t = String(optionValue).trim();\n if (!t) return false;\n return getSuggestionTokensFromText(text).some((p) => p === t);\n}\n\n/**\n * Chip option values present in `text` as comma-separated tokens (same typing as schema `options[].value`).\n * Order follows left-to-right token order; duplicates in text only appear once.\n */\nexport function deriveKnownSuggestionChipValues(text: string, options: SelectOption[]): unknown[] {\n if (!options.length) return [];\n const allowed = new Map<string, unknown>(options.map((o) => [String(o.value), o.value] as const));\n const tokens = getSuggestionTokensFromText(text);\n const out: unknown[] = [];\n const seen = new Set<string>();\n for (const t of tokens) {\n if (!allowed.has(t) || seen.has(t)) continue;\n seen.add(t);\n out.push(allowed.get(t)!);\n }\n return out;\n}\n\nfunction parallelChipArraysEqual(a: unknown, b: unknown): boolean {\n if (!Array.isArray(a) || !Array.isArray(b)) return false;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n\nfunction isSuggestionField(type: string | undefined): type is SuggestionTextareaFieldDef['type'] {\n return type === 'suggestion_textarea' || type === 'complaint_chips';\n}\n\n/**\n * Renders a sibling schema field inside the suggestion textarea shell. Uses concrete widgets\n * (not FieldRenderer) so `hidden` layout fields still render here without circular imports.\n * Supported: text, number, textarea, select.\n */\nfunction EmbeddedSchemaField({ fieldId }: { fieldId: string }) {\n const store = useFormStore();\n const fieldDef = store.getFieldDef(fieldId);\n if (!fieldDef) return null;\n switch (fieldDef.type) {\n case 'text':\n case 'number':\n case 'textarea':\n return <TextWidget fieldId={fieldId} />;\n case 'select':\n return <SelectWidget fieldId={fieldId} />;\n default:\n return null;\n }\n}\n\n/**\n * Reusable textarea with schema-driven **suggestion chips** inside the input area (same white\n * shell as the textarea). The field value is a **single string**: clicking a chip **appends**\n * that option’s `value` or **removes** it if already selected. When chip options are loaded,\n * slugs are kept on the **last line** (comma + space by default), with prose above separated by\n * a newline. Optional `meta.parallelChipFieldId` mirrors chip selections into a sibling\n * **`multiselect`** array. Free typing is still allowed.\n */\nexport const SuggestionTextareaWidget: React.FC<{ fieldId: string }> = ({ fieldId }) => {\n const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);\n const { state } = useForm();\n const store = useFormStore();\n const hasVoice = !!(fieldDef?.voice && store.getVoice());\n\n const [options, setOptions] = useState<SelectOption[]>([]);\n const [loading, setLoading] = useState(false);\n const showError = !!error && (touched || state.submitAttempted);\n\n const def =\n fieldDef && isSuggestionField(fieldDef.type) ? (fieldDef as SuggestionTextareaFieldDef) : undefined;\n\n const textValue = value == null || typeof value === 'string' ? value || '' : String(value);\n\n const parallelChipFieldId =\n def?.meta &&\n typeof (def.meta as { parallelChipFieldId?: unknown }).parallelChipFieldId === 'string'\n ? (def.meta as { parallelChipFieldId: string }).parallelChipFieldId.trim()\n : undefined;\n\n const embeddedFieldIds = useMemo(() => {\n const raw = def?.meta && Array.isArray((def.meta as { embeddedFieldIds?: unknown }).embeddedFieldIds)\n ? (def.meta as { embeddedFieldIds: unknown[] }).embeddedFieldIds\n : [];\n return raw\n .filter((id): id is string => typeof id === 'string' && id.trim().length > 0)\n .map((id) => id.trim())\n .filter((id) => store.getFieldDef(id));\n }, [def?.meta, store]);\n\n useEffect(() => {\n if (!def) {\n setOptions([]);\n return;\n }\n if (def.options?.length) {\n setOptions(def.options);\n } else if (def.dataSource) {\n setLoading(true);\n fetchOptions(def.dataSource.source, def.dataSource.params)\n .then((opts) => setOptions(opts as SelectOption[]))\n .finally(() => setLoading(false));\n } else {\n setOptions([]);\n }\n }, [def]);\n\n const chipAllowedSet = useMemo(\n () => new Set(options.map((o) => String(o.value).trim()).filter(Boolean)),\n [options],\n );\n\n useEffect(() => {\n if (!parallelChipFieldId) return;\n const parallelDef = store.getFieldDef(parallelChipFieldId);\n if (!parallelDef || parallelDef.type !== 'multiselect') return;\n const next = deriveKnownSuggestionChipValues(textValue, options);\n const prev = store.getFieldState(parallelChipFieldId).value;\n if (parallelChipArraysEqual(prev, next)) return;\n store.setValues({ [parallelChipFieldId]: next }, { touch: false });\n }, [def, parallelChipFieldId, textValue, options, store]);\n\n if (!def) {\n return null;\n }\n\n const appendSeparator = getAppendSeparator(def);\n const suggestionsAria =\n def.meta && typeof (def.meta as { suggestionsAriaLabel?: string }).suggestionsAriaLabel === 'string'\n ? (def.meta as { suggestionsAriaLabel: string }).suggestionsAriaLabel\n : 'Quick suggestions';\n\n const theme = getThemeConfig('textarea', def.theme);\n const wrapperClass = theme?.wrapperClassName ?? 'space-y-2';\n const labelClass = theme?.labelClassName;\n const inputClass = cn(theme?.inputClassName, showError && 'border-red-500');\n const inputWithStyle = fieldControlClass(def, inputClass);\n const height =\n def.height != null\n ? typeof def.height === 'string'\n ? Number(def.height) || undefined\n : def.height\n : undefined;\n\n const labelContent = (\n <>\n {def.label}{' '}\n <FieldRequiredIndicator fieldDef={def} />\n </>\n );\n\n const showLabel = isLabelVisible(def);\n\n const labelEl = showLabel ? (\n theme ? (\n <Label className={fieldLabelClass(def, labelClass)}>{labelContent}</Label>\n ) : (\n <Label className={fieldLabelClass(def)}>{labelContent}</Label>\n )\n ) : null;\n\n const onChipClick = (optValue: unknown) => {\n if (disabled) return;\n setValue(toggleSuggestionTokenInText(textValue, String(optValue), appendSeparator, chipAllowedSet));\n };\n\n const hasSuggestions = options.length > 0;\n const hasEmbedded = embeddedFieldIds.length > 0;\n const hasShell = hasSuggestions || hasEmbedded;\n const isHighlightLabel = def.theme === 'highlight-label';\n\n const suggestionShellClass = cn(\n 'flex min-w-0 flex-col overflow-hidden',\n hasShell &&\n (isHighlightLabel\n ? '-mt-1 rounded-b-md border-[#D0D0D0] bg-white'\n : 'rounded-md border border-input bg-background'),\n );\n\n const chipsRowClass = cn(\n 'flex flex-wrap gap-2 px-3 pb-2 pt-3',\n hasSuggestions &&\n (isHighlightLabel ? '' : 'border-b border-input/70'),\n disabled && 'pointer-events-none opacity-50',\n );\n\n const embeddedRowClass = cn(\n 'grid gap-3 px-3 sm:grid-cols-3',\n hasEmbedded &&\n (hasSuggestions\n ? cn('py-2', isHighlightLabel && 'border-t border-input/70')\n : 'border-b border-input/70 py-3'),\n disabled && 'pointer-events-none opacity-50',\n );\n\n const textareaShellClass = cn(\n inputWithStyle,\n hasShell &&\n cn(\n 'mt-0 rounded-t-none rounded-b-md border-0 shadow-none focus-visible:ring-offset-0',\n isHighlightLabel ? 'border-t-0' : 'min-h-[80px]',\n ),\n );\n\n const suggestionButtons =\n loading ? (\n <span className=\"text-xs text-muted-foreground\">Loading suggestions…</span>\n ) : (\n options.map((opt) => {\n const on = isTokenSelected(textValue, opt.value);\n return (\n <button\n key={String(opt.value)}\n type=\"button\"\n onClick={() => onChipClick(opt.value)}\n className={cn(\n 'inline-flex min-h-8 items-center rounded-full border px-3 py-1 text-xs font-medium leading-none transition-colors',\n on\n ? 'border-primary bg-primary/10 text-primary'\n : 'border-muted-foreground/30 bg-background hover:bg-muted/60',\n )}\n >\n {opt.label}\n </button>\n );\n })\n );\n\n return (\n <div className={fieldWrapperClass(def, wrapperClass)}>\n {hasVoice ? (\n <div className=\"flex items-center justify-between\">\n {labelEl}\n <VoiceMicButton fieldId={fieldId} onTranscriptReady={setValue} />\n </div>\n ) : (\n labelEl\n )}\n\n {def.description && (\n <p className={fieldDescriptionClass(def, 'text-xs text-muted-foreground')}>\n {def.description}\n </p>\n )}\n\n {hasShell ? (\n <div className={suggestionShellClass}>\n {hasSuggestions && (\n <div className={chipsRowClass} role=\"group\" aria-label={suggestionsAria}>\n {suggestionButtons}\n </div>\n )}\n {hasEmbedded && (\n <div className={embeddedRowClass}>\n {embeddedFieldIds.map((id) => (\n <EmbeddedSchemaField key={id} fieldId={id} />\n ))}\n </div>\n )}\n <Textarea\n id={fieldId}\n value={textValue}\n onChange={(e) => setValue(e.target.value)}\n onBlur={setTouched}\n disabled={disabled}\n className={textareaShellClass}\n placeholder={def.placeholder}\n style={height != null && Number.isFinite(height) ? { minHeight: height } : undefined}\n aria-label={!showLabel ? def.label : undefined}\n />\n </div>\n ) : (\n <Textarea\n id={fieldId}\n value={textValue}\n onChange={(e) => setValue(e.target.value)}\n onBlur={setTouched}\n disabled={disabled}\n className={inputWithStyle}\n placeholder={def.placeholder}\n style={height != null && Number.isFinite(height) ? { minHeight: height } : undefined}\n aria-label={!showLabel ? def.label : undefined}\n />\n )}\n\n {showError && (\n <p className={fieldErrorClass(def, 'text-xs text-red-500')}>{error}</p>\n )}\n </div>\n );\n};\n\n/** @deprecated Use `SuggestionTextareaWidget`. Kept for schema compatibility. */\nexport const ComplaintChipsWidget = SuggestionTextareaWidget;\n"]}
|
package/dist/{SuggestionTextareaWidget-GQTWCFBG.mjs → SuggestionTextareaWidget-UNL3FZRI.mjs}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SelectWidget, TextWidget } from './chunk-
|
|
1
|
+
import { SelectWidget, TextWidget } from './chunk-G6Y4UJPN.mjs';
|
|
2
2
|
import { fetchOptions } from './chunk-IFMQKLNW.mjs';
|
|
3
3
|
import { Textarea } from './chunk-4BAKQIPJ.mjs';
|
|
4
4
|
import { getThemeConfig } from './chunk-Y7TIWH4I.mjs';
|
|
@@ -211,5 +211,5 @@ var SuggestionTextareaWidget = ({ fieldId }) => {
|
|
|
211
211
|
var ComplaintChipsWidget = SuggestionTextareaWidget;
|
|
212
212
|
|
|
213
213
|
export { ComplaintChipsWidget, SuggestionTextareaWidget, deriveKnownSuggestionChipValues };
|
|
214
|
-
//# sourceMappingURL=SuggestionTextareaWidget-
|
|
215
|
-
//# sourceMappingURL=SuggestionTextareaWidget-
|
|
214
|
+
//# sourceMappingURL=SuggestionTextareaWidget-UNL3FZRI.mjs.map
|
|
215
|
+
//# sourceMappingURL=SuggestionTextareaWidget-UNL3FZRI.mjs.map
|
package/dist/{SuggestionTextareaWidget-GQTWCFBG.mjs.map → SuggestionTextareaWidget-UNL3FZRI.mjs.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ui/widgets/SuggestionTextareaWidget.tsx"],"names":[],"mappings":"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","file":"SuggestionTextareaWidget-GQTWCFBG.mjs","sourcesContent":["import React, { useEffect, useMemo, useState } from 'react';\nimport { useField } from '../../react/useField';\nimport { useForm } from '../../react/useForm';\nimport { useFormStore } from '../../react/FormProvider';\nimport { VoiceMicButton } from '../../react/VoiceMicButton';\nimport { Label } from '../shadcn/label';\nimport { Textarea } from '../shadcn/textarea';\nimport { getThemeConfig } from '../themes';\nimport { fetchOptions } from '../../core/asyncOptions';\nimport { cn } from '../../core/utils';\nimport type { SelectOption, SuggestionTextareaFieldDef } from '../../core/types';\nimport {\n FieldRequiredIndicator,\n fieldControlClass,\n fieldDescriptionClass,\n fieldErrorClass,\n fieldLabelClass,\n fieldWrapperClass,\n isLabelVisible,\n} from '../../react/fieldStyle';\nimport { TextWidget } from './Text';\nimport { SelectWidget } from './Select';\n\nimport { getSuggestionTokensFromText, toggleSuggestionTokenInText } from '../../core/suggestionTokens';\n\nexport { getSuggestionTokensFromText, toggleSuggestionTokenInText };\n\nconst DEFAULT_TOKEN_SEPARATOR = ', ';\n\nfunction getAppendSeparator(def: SuggestionTextareaFieldDef): string {\n const raw = def.meta && typeof (def.meta as { appendSeparator?: unknown }).appendSeparator === 'string'\n ? (def.meta as { appendSeparator: string }).appendSeparator\n : DEFAULT_TOKEN_SEPARATOR;\n return raw;\n}\n\nfunction isTokenSelected(text: string, optionValue: unknown): boolean {\n const t = String(optionValue).trim();\n if (!t) return false;\n return getSuggestionTokensFromText(text).some((p) => p === t);\n}\n\n/**\n * Chip option values present in `text` as comma-separated tokens (same typing as schema `options[].value`).\n * Order follows left-to-right token order; duplicates in text only appear once.\n */\nexport function deriveKnownSuggestionChipValues(text: string, options: SelectOption[]): unknown[] {\n if (!options.length) return [];\n const allowed = new Map<string, unknown>(options.map((o) => [String(o.value), o.value] as const));\n const tokens = getSuggestionTokensFromText(text);\n const out: unknown[] = [];\n const seen = new Set<string>();\n for (const t of tokens) {\n if (!allowed.has(t) || seen.has(t)) continue;\n seen.add(t);\n out.push(allowed.get(t)!);\n }\n return out;\n}\n\nfunction parallelChipArraysEqual(a: unknown, b: unknown): boolean {\n if (!Array.isArray(a) || !Array.isArray(b)) return false;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n\nfunction isSuggestionField(type: string | undefined): type is SuggestionTextareaFieldDef['type'] {\n return type === 'suggestion_textarea' || type === 'complaint_chips';\n}\n\n/**\n * Renders a sibling schema field inside the suggestion textarea shell. Uses concrete widgets\n * (not FieldRenderer) so `hidden` layout fields still render here without circular imports.\n * Supported: text, number, textarea, select.\n */\nfunction EmbeddedSchemaField({ fieldId }: { fieldId: string }) {\n const store = useFormStore();\n const fieldDef = store.getFieldDef(fieldId);\n if (!fieldDef) return null;\n switch (fieldDef.type) {\n case 'text':\n case 'number':\n case 'textarea':\n return <TextWidget fieldId={fieldId} />;\n case 'select':\n return <SelectWidget fieldId={fieldId} />;\n default:\n return null;\n }\n}\n\n/**\n * Reusable textarea with schema-driven **suggestion chips** inside the input area (same white\n * shell as the textarea). The field value is a **single string**: clicking a chip **appends**\n * that option’s `value` or **removes** it if already selected. When chip options are loaded,\n * slugs are kept on the **last line** (comma + space by default), with prose above separated by\n * a newline. Optional `meta.parallelChipFieldId` mirrors chip selections into a sibling\n * **`multiselect`** array. Free typing is still allowed.\n */\nexport const SuggestionTextareaWidget: React.FC<{ fieldId: string }> = ({ fieldId }) => {\n const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);\n const { state } = useForm();\n const store = useFormStore();\n const hasVoice = !!(fieldDef?.voice && store.getVoice());\n\n const [options, setOptions] = useState<SelectOption[]>([]);\n const [loading, setLoading] = useState(false);\n const showError = !!error && (touched || state.submitAttempted);\n\n const def =\n fieldDef && isSuggestionField(fieldDef.type) ? (fieldDef as SuggestionTextareaFieldDef) : undefined;\n\n const textValue = value == null || typeof value === 'string' ? value || '' : String(value);\n\n const parallelChipFieldId =\n def?.meta &&\n typeof (def.meta as { parallelChipFieldId?: unknown }).parallelChipFieldId === 'string'\n ? (def.meta as { parallelChipFieldId: string }).parallelChipFieldId.trim()\n : undefined;\n\n const embeddedFieldIds = useMemo(() => {\n const raw = def?.meta && Array.isArray((def.meta as { embeddedFieldIds?: unknown }).embeddedFieldIds)\n ? (def.meta as { embeddedFieldIds: unknown[] }).embeddedFieldIds\n : [];\n return raw\n .filter((id): id is string => typeof id === 'string' && id.trim().length > 0)\n .map((id) => id.trim())\n .filter((id) => store.getFieldDef(id));\n }, [def?.meta, store]);\n\n useEffect(() => {\n if (!def) {\n setOptions([]);\n return;\n }\n if (def.options?.length) {\n setOptions(def.options);\n } else if (def.dataSource) {\n setLoading(true);\n fetchOptions(def.dataSource.source, def.dataSource.params)\n .then((opts) => setOptions(opts as SelectOption[]))\n .finally(() => setLoading(false));\n } else {\n setOptions([]);\n }\n }, [def]);\n\n const chipAllowedSet = useMemo(\n () => new Set(options.map((o) => String(o.value).trim()).filter(Boolean)),\n [options],\n );\n\n useEffect(() => {\n if (!parallelChipFieldId) return;\n const parallelDef = store.getFieldDef(parallelChipFieldId);\n if (!parallelDef || parallelDef.type !== 'multiselect') return;\n const next = deriveKnownSuggestionChipValues(textValue, options);\n const prev = store.getFieldState(parallelChipFieldId).value;\n if (parallelChipArraysEqual(prev, next)) return;\n store.setValues({ [parallelChipFieldId]: next }, { touch: false });\n }, [def, parallelChipFieldId, textValue, options, store]);\n\n if (!def) {\n return null;\n }\n\n const appendSeparator = getAppendSeparator(def);\n const suggestionsAria =\n def.meta && typeof (def.meta as { suggestionsAriaLabel?: string }).suggestionsAriaLabel === 'string'\n ? (def.meta as { suggestionsAriaLabel: string }).suggestionsAriaLabel\n : 'Quick suggestions';\n\n const theme = getThemeConfig('textarea', def.theme);\n const wrapperClass = theme?.wrapperClassName ?? 'space-y-2';\n const labelClass = theme?.labelClassName;\n const inputClass = cn(theme?.inputClassName, showError && 'border-red-500');\n const inputWithStyle = fieldControlClass(def, inputClass);\n const height =\n def.height != null\n ? typeof def.height === 'string'\n ? Number(def.height) || undefined\n : def.height\n : undefined;\n\n const labelContent = (\n <>\n {def.label}{' '}\n <FieldRequiredIndicator fieldDef={def} />\n </>\n );\n\n const showLabel = isLabelVisible(def);\n\n const labelEl = showLabel ? (\n theme ? (\n <Label className={fieldLabelClass(def, labelClass)}>{labelContent}</Label>\n ) : (\n <Label className={fieldLabelClass(def)}>{labelContent}</Label>\n )\n ) : null;\n\n const onChipClick = (optValue: unknown) => {\n if (disabled) return;\n setValue(toggleSuggestionTokenInText(textValue, String(optValue), appendSeparator, chipAllowedSet));\n };\n\n const hasSuggestions = options.length > 0;\n const hasEmbedded = embeddedFieldIds.length > 0;\n const hasShell = hasSuggestions || hasEmbedded;\n const isHighlightLabel = def.theme === 'highlight-label';\n\n const suggestionShellClass = cn(\n 'flex min-w-0 flex-col overflow-hidden',\n hasShell &&\n (isHighlightLabel\n ? '-mt-1 rounded-b-md border-[#D0D0D0] bg-white'\n : 'rounded-md border border-input bg-background'),\n );\n\n const chipsRowClass = cn(\n 'flex flex-wrap gap-2 px-3 pb-2 pt-3',\n hasSuggestions &&\n (isHighlightLabel ? '' : 'border-b border-input/70'),\n disabled && 'pointer-events-none opacity-50',\n );\n\n const embeddedRowClass = cn(\n 'grid gap-3 px-3 sm:grid-cols-3',\n hasEmbedded &&\n (hasSuggestions\n ? cn('py-2', isHighlightLabel && 'border-t border-input/70')\n : 'border-b border-input/70 py-3'),\n disabled && 'pointer-events-none opacity-50',\n );\n\n const textareaShellClass = cn(\n inputWithStyle,\n hasShell &&\n cn(\n 'mt-0 rounded-t-none rounded-b-md border-0 shadow-none focus-visible:ring-offset-0',\n isHighlightLabel ? 'border-t-0' : 'min-h-[80px]',\n ),\n );\n\n const suggestionButtons =\n loading ? (\n <span className=\"text-xs text-muted-foreground\">Loading suggestions…</span>\n ) : (\n options.map((opt) => {\n const on = isTokenSelected(textValue, opt.value);\n return (\n <button\n key={String(opt.value)}\n type=\"button\"\n onClick={() => onChipClick(opt.value)}\n className={cn(\n 'inline-flex min-h-8 items-center rounded-full border px-3 py-1 text-xs font-medium leading-none transition-colors',\n on\n ? 'border-primary bg-primary/10 text-primary'\n : 'border-muted-foreground/30 bg-background hover:bg-muted/60',\n )}\n >\n {opt.label}\n </button>\n );\n })\n );\n\n return (\n <div className={fieldWrapperClass(def, wrapperClass)}>\n {hasVoice ? (\n <div className=\"flex items-center justify-between\">\n {labelEl}\n <VoiceMicButton fieldId={fieldId} onTranscriptReady={setValue} />\n </div>\n ) : (\n labelEl\n )}\n\n {def.description && (\n <p className={fieldDescriptionClass(def, 'text-xs text-muted-foreground')}>\n {def.description}\n </p>\n )}\n\n {hasShell ? (\n <div className={suggestionShellClass}>\n {hasSuggestions && (\n <div className={chipsRowClass} role=\"group\" aria-label={suggestionsAria}>\n {suggestionButtons}\n </div>\n )}\n {hasEmbedded && (\n <div className={embeddedRowClass}>\n {embeddedFieldIds.map((id) => (\n <EmbeddedSchemaField key={id} fieldId={id} />\n ))}\n </div>\n )}\n <Textarea\n id={fieldId}\n value={textValue}\n onChange={(e) => setValue(e.target.value)}\n onBlur={setTouched}\n disabled={disabled}\n className={textareaShellClass}\n placeholder={def.placeholder}\n style={height != null && Number.isFinite(height) ? { minHeight: height } : undefined}\n aria-label={!showLabel ? def.label : undefined}\n />\n </div>\n ) : (\n <Textarea\n id={fieldId}\n value={textValue}\n onChange={(e) => setValue(e.target.value)}\n onBlur={setTouched}\n disabled={disabled}\n className={inputWithStyle}\n placeholder={def.placeholder}\n style={height != null && Number.isFinite(height) ? { minHeight: height } : undefined}\n aria-label={!showLabel ? def.label : undefined}\n />\n )}\n\n {showError && (\n <p className={fieldErrorClass(def, 'text-xs text-red-500')}>{error}</p>\n )}\n </div>\n );\n};\n\n/** @deprecated Use `SuggestionTextareaWidget`. Kept for schema compatibility. */\nexport const ComplaintChipsWidget = SuggestionTextareaWidget;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/ui/widgets/SuggestionTextareaWidget.tsx"],"names":[],"mappings":"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","file":"SuggestionTextareaWidget-UNL3FZRI.mjs","sourcesContent":["import React, { useEffect, useMemo, useState } from 'react';\nimport { useField } from '../../react/useField';\nimport { useForm } from '../../react/useForm';\nimport { useFormStore } from '../../react/FormProvider';\nimport { VoiceMicButton } from '../../react/VoiceMicButton';\nimport { Label } from '../shadcn/label';\nimport { Textarea } from '../shadcn/textarea';\nimport { getThemeConfig } from '../themes';\nimport { fetchOptions } from '../../core/asyncOptions';\nimport { cn } from '../../core/utils';\nimport type { SelectOption, SuggestionTextareaFieldDef } from '../../core/types';\nimport {\n FieldRequiredIndicator,\n fieldControlClass,\n fieldDescriptionClass,\n fieldErrorClass,\n fieldLabelClass,\n fieldWrapperClass,\n isLabelVisible,\n} from '../../react/fieldStyle';\nimport { TextWidget } from './Text';\nimport { SelectWidget } from './Select';\n\nimport { getSuggestionTokensFromText, toggleSuggestionTokenInText } from '../../core/suggestionTokens';\n\nexport { getSuggestionTokensFromText, toggleSuggestionTokenInText };\n\nconst DEFAULT_TOKEN_SEPARATOR = ', ';\n\nfunction getAppendSeparator(def: SuggestionTextareaFieldDef): string {\n const raw = def.meta && typeof (def.meta as { appendSeparator?: unknown }).appendSeparator === 'string'\n ? (def.meta as { appendSeparator: string }).appendSeparator\n : DEFAULT_TOKEN_SEPARATOR;\n return raw;\n}\n\nfunction isTokenSelected(text: string, optionValue: unknown): boolean {\n const t = String(optionValue).trim();\n if (!t) return false;\n return getSuggestionTokensFromText(text).some((p) => p === t);\n}\n\n/**\n * Chip option values present in `text` as comma-separated tokens (same typing as schema `options[].value`).\n * Order follows left-to-right token order; duplicates in text only appear once.\n */\nexport function deriveKnownSuggestionChipValues(text: string, options: SelectOption[]): unknown[] {\n if (!options.length) return [];\n const allowed = new Map<string, unknown>(options.map((o) => [String(o.value), o.value] as const));\n const tokens = getSuggestionTokensFromText(text);\n const out: unknown[] = [];\n const seen = new Set<string>();\n for (const t of tokens) {\n if (!allowed.has(t) || seen.has(t)) continue;\n seen.add(t);\n out.push(allowed.get(t)!);\n }\n return out;\n}\n\nfunction parallelChipArraysEqual(a: unknown, b: unknown): boolean {\n if (!Array.isArray(a) || !Array.isArray(b)) return false;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n\nfunction isSuggestionField(type: string | undefined): type is SuggestionTextareaFieldDef['type'] {\n return type === 'suggestion_textarea' || type === 'complaint_chips';\n}\n\n/**\n * Renders a sibling schema field inside the suggestion textarea shell. Uses concrete widgets\n * (not FieldRenderer) so `hidden` layout fields still render here without circular imports.\n * Supported: text, number, textarea, select.\n */\nfunction EmbeddedSchemaField({ fieldId }: { fieldId: string }) {\n const store = useFormStore();\n const fieldDef = store.getFieldDef(fieldId);\n if (!fieldDef) return null;\n switch (fieldDef.type) {\n case 'text':\n case 'number':\n case 'textarea':\n return <TextWidget fieldId={fieldId} />;\n case 'select':\n return <SelectWidget fieldId={fieldId} />;\n default:\n return null;\n }\n}\n\n/**\n * Reusable textarea with schema-driven **suggestion chips** inside the input area (same white\n * shell as the textarea). The field value is a **single string**: clicking a chip **appends**\n * that option’s `value` or **removes** it if already selected. When chip options are loaded,\n * slugs are kept on the **last line** (comma + space by default), with prose above separated by\n * a newline. Optional `meta.parallelChipFieldId` mirrors chip selections into a sibling\n * **`multiselect`** array. Free typing is still allowed.\n */\nexport const SuggestionTextareaWidget: React.FC<{ fieldId: string }> = ({ fieldId }) => {\n const { fieldDef, value, setValue, setTouched, error, disabled, touched } = useField(fieldId);\n const { state } = useForm();\n const store = useFormStore();\n const hasVoice = !!(fieldDef?.voice && store.getVoice());\n\n const [options, setOptions] = useState<SelectOption[]>([]);\n const [loading, setLoading] = useState(false);\n const showError = !!error && (touched || state.submitAttempted);\n\n const def =\n fieldDef && isSuggestionField(fieldDef.type) ? (fieldDef as SuggestionTextareaFieldDef) : undefined;\n\n const textValue = value == null || typeof value === 'string' ? value || '' : String(value);\n\n const parallelChipFieldId =\n def?.meta &&\n typeof (def.meta as { parallelChipFieldId?: unknown }).parallelChipFieldId === 'string'\n ? (def.meta as { parallelChipFieldId: string }).parallelChipFieldId.trim()\n : undefined;\n\n const embeddedFieldIds = useMemo(() => {\n const raw = def?.meta && Array.isArray((def.meta as { embeddedFieldIds?: unknown }).embeddedFieldIds)\n ? (def.meta as { embeddedFieldIds: unknown[] }).embeddedFieldIds\n : [];\n return raw\n .filter((id): id is string => typeof id === 'string' && id.trim().length > 0)\n .map((id) => id.trim())\n .filter((id) => store.getFieldDef(id));\n }, [def?.meta, store]);\n\n useEffect(() => {\n if (!def) {\n setOptions([]);\n return;\n }\n if (def.options?.length) {\n setOptions(def.options);\n } else if (def.dataSource) {\n setLoading(true);\n fetchOptions(def.dataSource.source, def.dataSource.params)\n .then((opts) => setOptions(opts as SelectOption[]))\n .finally(() => setLoading(false));\n } else {\n setOptions([]);\n }\n }, [def]);\n\n const chipAllowedSet = useMemo(\n () => new Set(options.map((o) => String(o.value).trim()).filter(Boolean)),\n [options],\n );\n\n useEffect(() => {\n if (!parallelChipFieldId) return;\n const parallelDef = store.getFieldDef(parallelChipFieldId);\n if (!parallelDef || parallelDef.type !== 'multiselect') return;\n const next = deriveKnownSuggestionChipValues(textValue, options);\n const prev = store.getFieldState(parallelChipFieldId).value;\n if (parallelChipArraysEqual(prev, next)) return;\n store.setValues({ [parallelChipFieldId]: next }, { touch: false });\n }, [def, parallelChipFieldId, textValue, options, store]);\n\n if (!def) {\n return null;\n }\n\n const appendSeparator = getAppendSeparator(def);\n const suggestionsAria =\n def.meta && typeof (def.meta as { suggestionsAriaLabel?: string }).suggestionsAriaLabel === 'string'\n ? (def.meta as { suggestionsAriaLabel: string }).suggestionsAriaLabel\n : 'Quick suggestions';\n\n const theme = getThemeConfig('textarea', def.theme);\n const wrapperClass = theme?.wrapperClassName ?? 'space-y-2';\n const labelClass = theme?.labelClassName;\n const inputClass = cn(theme?.inputClassName, showError && 'border-red-500');\n const inputWithStyle = fieldControlClass(def, inputClass);\n const height =\n def.height != null\n ? typeof def.height === 'string'\n ? Number(def.height) || undefined\n : def.height\n : undefined;\n\n const labelContent = (\n <>\n {def.label}{' '}\n <FieldRequiredIndicator fieldDef={def} />\n </>\n );\n\n const showLabel = isLabelVisible(def);\n\n const labelEl = showLabel ? (\n theme ? (\n <Label className={fieldLabelClass(def, labelClass)}>{labelContent}</Label>\n ) : (\n <Label className={fieldLabelClass(def)}>{labelContent}</Label>\n )\n ) : null;\n\n const onChipClick = (optValue: unknown) => {\n if (disabled) return;\n setValue(toggleSuggestionTokenInText(textValue, String(optValue), appendSeparator, chipAllowedSet));\n };\n\n const hasSuggestions = options.length > 0;\n const hasEmbedded = embeddedFieldIds.length > 0;\n const hasShell = hasSuggestions || hasEmbedded;\n const isHighlightLabel = def.theme === 'highlight-label';\n\n const suggestionShellClass = cn(\n 'flex min-w-0 flex-col overflow-hidden',\n hasShell &&\n (isHighlightLabel\n ? '-mt-1 rounded-b-md border-[#D0D0D0] bg-white'\n : 'rounded-md border border-input bg-background'),\n );\n\n const chipsRowClass = cn(\n 'flex flex-wrap gap-2 px-3 pb-2 pt-3',\n hasSuggestions &&\n (isHighlightLabel ? '' : 'border-b border-input/70'),\n disabled && 'pointer-events-none opacity-50',\n );\n\n const embeddedRowClass = cn(\n 'grid gap-3 px-3 sm:grid-cols-3',\n hasEmbedded &&\n (hasSuggestions\n ? cn('py-2', isHighlightLabel && 'border-t border-input/70')\n : 'border-b border-input/70 py-3'),\n disabled && 'pointer-events-none opacity-50',\n );\n\n const textareaShellClass = cn(\n inputWithStyle,\n hasShell &&\n cn(\n 'mt-0 rounded-t-none rounded-b-md border-0 shadow-none focus-visible:ring-offset-0',\n isHighlightLabel ? 'border-t-0' : 'min-h-[80px]',\n ),\n );\n\n const suggestionButtons =\n loading ? (\n <span className=\"text-xs text-muted-foreground\">Loading suggestions…</span>\n ) : (\n options.map((opt) => {\n const on = isTokenSelected(textValue, opt.value);\n return (\n <button\n key={String(opt.value)}\n type=\"button\"\n onClick={() => onChipClick(opt.value)}\n className={cn(\n 'inline-flex min-h-8 items-center rounded-full border px-3 py-1 text-xs font-medium leading-none transition-colors',\n on\n ? 'border-primary bg-primary/10 text-primary'\n : 'border-muted-foreground/30 bg-background hover:bg-muted/60',\n )}\n >\n {opt.label}\n </button>\n );\n })\n );\n\n return (\n <div className={fieldWrapperClass(def, wrapperClass)}>\n {hasVoice ? (\n <div className=\"flex items-center justify-between\">\n {labelEl}\n <VoiceMicButton fieldId={fieldId} onTranscriptReady={setValue} />\n </div>\n ) : (\n labelEl\n )}\n\n {def.description && (\n <p className={fieldDescriptionClass(def, 'text-xs text-muted-foreground')}>\n {def.description}\n </p>\n )}\n\n {hasShell ? (\n <div className={suggestionShellClass}>\n {hasSuggestions && (\n <div className={chipsRowClass} role=\"group\" aria-label={suggestionsAria}>\n {suggestionButtons}\n </div>\n )}\n {hasEmbedded && (\n <div className={embeddedRowClass}>\n {embeddedFieldIds.map((id) => (\n <EmbeddedSchemaField key={id} fieldId={id} />\n ))}\n </div>\n )}\n <Textarea\n id={fieldId}\n value={textValue}\n onChange={(e) => setValue(e.target.value)}\n onBlur={setTouched}\n disabled={disabled}\n className={textareaShellClass}\n placeholder={def.placeholder}\n style={height != null && Number.isFinite(height) ? { minHeight: height } : undefined}\n aria-label={!showLabel ? def.label : undefined}\n />\n </div>\n ) : (\n <Textarea\n id={fieldId}\n value={textValue}\n onChange={(e) => setValue(e.target.value)}\n onBlur={setTouched}\n disabled={disabled}\n className={inputWithStyle}\n placeholder={def.placeholder}\n style={height != null && Number.isFinite(height) ? { minHeight: height } : undefined}\n aria-label={!showLabel ? def.label : undefined}\n />\n )}\n\n {showError && (\n <p className={fieldErrorClass(def, 'text-xs text-red-500')}>{error}</p>\n )}\n </div>\n );\n};\n\n/** @deprecated Use `SuggestionTextareaWidget`. Kept for schema compatibility. */\nexport const ComplaintChipsWidget = SuggestionTextareaWidget;\n"]}
|