@bikdotai/bik-component-library 0.0.849-beta.1 → 0.0.849-beta.3

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.
Files changed (45) hide show
  1. package/dist/cjs/components/agent-builder/components/ConfigToolPanel.js +11 -11
  2. package/dist/cjs/components/agent-builder/components/ConfigToolPanel.js.map +1 -1
  3. package/dist/cjs/components/agent-builder/components/CreateSubAgentPanel.js +5 -5
  4. package/dist/cjs/components/agent-builder/components/CreateSubAgentPanel.js.map +1 -1
  5. package/dist/cjs/components/agent-builder/components/MentionEditor.js.map +1 -1
  6. package/dist/cjs/components/agent-builder/components/RestApiToolPanel.js +7 -7
  7. package/dist/cjs/components/agent-builder/components/RestApiToolPanel.js.map +1 -1
  8. package/dist/cjs/components/agent-builder/components/ToolInstructionsField.js +2 -2
  9. package/dist/cjs/components/agent-builder/components/ToolInstructionsField.js.map +1 -1
  10. package/dist/cjs/components/agent-builder/components/VariableTriggerArea.js +9 -0
  11. package/dist/cjs/components/agent-builder/components/VariableTriggerArea.js.map +1 -0
  12. package/dist/cjs/components/agent-builder/steps/Step3HowItResponds.js +1 -1
  13. package/dist/cjs/components/agent-builder/steps/Step3HowItResponds.js.map +1 -1
  14. package/dist/cjs/components/agent-builder/utils/mentionSerialization.js +4 -4
  15. package/dist/cjs/components/agent-builder/utils/mentionSerialization.js.map +1 -1
  16. package/dist/cjs/editor/extensions/mention/MentionDropdown.js +1 -1
  17. package/dist/cjs/editor/extensions/mention/MentionDropdown.js.map +1 -1
  18. package/dist/cjs/editor/extensions/mention/MentionExtension.js +1 -1
  19. package/dist/cjs/editor/extensions/mention/MentionExtension.js.map +1 -1
  20. package/dist/esm/components/agent-builder/components/ConfigToolPanel.d.ts +8 -0
  21. package/dist/esm/components/agent-builder/components/ConfigToolPanel.js +151 -124
  22. package/dist/esm/components/agent-builder/components/ConfigToolPanel.js.map +1 -1
  23. package/dist/esm/components/agent-builder/components/CreateSubAgentPanel.js +90 -88
  24. package/dist/esm/components/agent-builder/components/CreateSubAgentPanel.js.map +1 -1
  25. package/dist/esm/components/agent-builder/components/MentionEditor.d.ts +2 -2
  26. package/dist/esm/components/agent-builder/components/MentionEditor.js.map +1 -1
  27. package/dist/esm/components/agent-builder/components/RestApiToolPanel.d.ts +7 -0
  28. package/dist/esm/components/agent-builder/components/RestApiToolPanel.js +174 -133
  29. package/dist/esm/components/agent-builder/components/RestApiToolPanel.js.map +1 -1
  30. package/dist/esm/components/agent-builder/components/ToolInstructionsField.d.ts +9 -0
  31. package/dist/esm/components/agent-builder/components/ToolInstructionsField.js +65 -47
  32. package/dist/esm/components/agent-builder/components/ToolInstructionsField.js.map +1 -1
  33. package/dist/esm/components/agent-builder/components/VariableTriggerArea.d.ts +27 -0
  34. package/dist/esm/components/agent-builder/components/VariableTriggerArea.js +70 -0
  35. package/dist/esm/components/agent-builder/components/VariableTriggerArea.js.map +1 -0
  36. package/dist/esm/components/agent-builder/steps/Step3HowItResponds.js +93 -91
  37. package/dist/esm/components/agent-builder/steps/Step3HowItResponds.js.map +1 -1
  38. package/dist/esm/components/agent-builder/utils/mentionSerialization.d.ts +1 -1
  39. package/dist/esm/components/agent-builder/utils/mentionSerialization.js +10 -10
  40. package/dist/esm/components/agent-builder/utils/mentionSerialization.js.map +1 -1
  41. package/dist/esm/editor/extensions/mention/MentionDropdown.js +19 -19
  42. package/dist/esm/editor/extensions/mention/MentionDropdown.js.map +1 -1
  43. package/dist/esm/editor/extensions/mention/MentionExtension.js +15 -15
  44. package/dist/esm/editor/extensions/mention/MentionExtension.js.map +1 -1
  45. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"MentionDropdown.js","sources":["../../../../../src/editor/extensions/mention/MentionDropdown.tsx"],"sourcesContent":["import React, {\n\tforwardRef,\n\tuseCallback,\n\tuseEffect,\n\tuseImperativeHandle,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport type {\n\tMentionDropdownRenderProps,\n\tMentionItem,\n} from '../../BikEditor.types';\nimport {\n\tDropdownContainer,\n\tDropdownItem,\n\tMentionAvatar,\n\tMentionAvatarFallback,\n\tMentionLabel,\n\tMentionPresenceDot,\n} from '../editorDropdown.styles';\n\ninterface Props {\n\titems: MentionItem[];\n\tquery: string;\n\tcommand: (item: MentionItem) => void;\n\t/** Custom per-row renderer. Receives the item and whether it is the active row. */\n\trenderItem?: (item: MentionItem, isActive: boolean) => React.ReactNode;\n\t/**\n\t * Full custom dropdown renderer. Takes priority over renderItem.\n\t * The editor passes activeIndex and onSelect — you handle all the visual rendering.\n\t */\n\trenderDropdown?: (props: MentionDropdownRenderProps) => React.ReactNode;\n\t/** Close the menu without selecting (strips the typed trigger). Injected by the extension. */\n\tdismiss?: () => void;\n}\n\nexport const MentionDropdown = forwardRef<any, Props>(\n\t({ items, query, command, renderItem, renderDropdown, dismiss }, ref) => {\n\t\tconst [selectedIndex, setSelectedIndex] = useState(0);\n\t\tconst containerRef = useRef<HTMLDivElement>(null);\n\t\t// A custom dropdown (renderDropdown) can claim keyboard nav for itself.\n\t\tconst customKeyHandlerRef = useRef<\n\t\t\t((event: KeyboardEvent) => boolean) | null\n\t\t>(null);\n\n\t\tconst registerKeyHandler = useCallback(\n\t\t\t(handler: ((event: KeyboardEvent) => boolean) | null) => {\n\t\t\t\tcustomKeyHandlerRef.current = handler;\n\t\t\t},\n\t\t\t[],\n\t\t);\n\n\t\tconst scrollToIndex = useCallback((index: number) => {\n\t\t\tconst container = containerRef.current;\n\t\t\tif (!container) return;\n\t\t\tconst item = container.children[index] as HTMLElement | undefined;\n\t\t\titem?.scrollIntoView({ block: 'nearest' });\n\t\t}, []);\n\n\t\tconst select = (i: number) => {\n\t\t\tif (items[i]) command(items[i]);\n\t\t};\n\n\t\tuseImperativeHandle(ref, () => ({\n\t\t\tonKeyDown: ({ event }: { event: KeyboardEvent }) => {\n\t\t\t\t// A custom dropdown that registered a handler owns navigation.\n\t\t\t\tif (renderDropdown && customKeyHandlerRef.current) {\n\t\t\t\t\treturn customKeyHandlerRef.current(event);\n\t\t\t\t}\n\t\t\t\tif (!items.length) return false;\n\t\t\t\tif (event.key === 'ArrowUp') {\n\t\t\t\t\tsetSelectedIndex((prev) => {\n\t\t\t\t\t\tconst next = (prev + items.length - 1) % items.length;\n\t\t\t\t\t\tscrollToIndex(next);\n\t\t\t\t\t\treturn next;\n\t\t\t\t\t});\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (event.key === 'ArrowDown') {\n\t\t\t\t\tsetSelectedIndex((prev) => {\n\t\t\t\t\t\tconst next = (prev + 1) % items.length;\n\t\t\t\t\t\tscrollToIndex(next);\n\t\t\t\t\t\treturn next;\n\t\t\t\t\t});\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (event.key === 'Enter') {\n\t\t\t\t\tselect(selectedIndex);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t}));\n\n\t\tuseEffect(() => setSelectedIndex(0), [items]);\n\n\t\tif (!items.length) return null;\n\n\t\t// Full custom dropdown — editor still manages keyboard nav via selectedIndex\n\t\tif (renderDropdown) {\n\t\t\treturn (\n\t\t\t\t<>\n\t\t\t\t\t{renderDropdown({\n\t\t\t\t\t\titems,\n\t\t\t\t\t\tquery,\n\t\t\t\t\t\tactiveIndex: selectedIndex,\n\t\t\t\t\t\tonSelect: (item) => command(item),\n\t\t\t\t\t\tregisterKeyHandler,\n\t\t\t\t\t\tonClose: dismiss,\n\t\t\t\t\t})}\n\t\t\t\t</>\n\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\t<DropdownContainer ref={containerRef}>\n\t\t\t\t{items.map((item, i) => (\n\t\t\t\t\t<DropdownItem\n\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\t$isActive={i === selectedIndex}\n\t\t\t\t\t\tonMouseEnter={() => setSelectedIndex(i)}\n\t\t\t\t\t\tonClick={() => select(i)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{renderItem ? (\n\t\t\t\t\t\t\trenderItem(item, i === selectedIndex)\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t{item.avatarUrl ? (\n\t\t\t\t\t\t\t\t\t<MentionAvatar src={item.avatarUrl} alt=\"\" />\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<MentionAvatarFallback>\n\t\t\t\t\t\t\t\t\t\t{item.label.charAt(0).toUpperCase()}\n\t\t\t\t\t\t\t\t\t</MentionAvatarFallback>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t<MentionLabel>{item.label}</MentionLabel>\n\t\t\t\t\t\t\t\t{item.isOnline !== undefined && (\n\t\t\t\t\t\t\t\t\t<MentionPresenceDot $online={item.isOnline} />\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</DropdownItem>\n\t\t\t\t))}\n\t\t\t</DropdownContainer>\n\t\t);\n\t},\n);\nMentionDropdown.displayName = 'MentionDropdown';\n"],"names":["MentionDropdown","forwardRef","items","query","command","renderItem","renderDropdown","dismiss","ref","selectedIndex","setSelectedIndex","useState","containerRef","useRef","customKeyHandlerRef","registerKeyHandler","useCallback","handler","scrollToIndex","index","container","select","i","useImperativeHandle","event","prev","next","useEffect","item","jsx","DropdownContainer","DropdownItem","jsxs","Fragment","MentionAvatar","MentionAvatarFallback","MentionLabel","MentionPresenceDot"],"mappings":"iLAoCaA,EAAkBC,EAAAA,WAC9B,CAAC,CAAE,MAAAC,EAAO,MAAAC,EAAO,QAAAC,EAAS,WAAAC,EAAY,eAAAC,EAAgB,QAAAC,CAAA,EAAWC,IAAQ,CACxE,KAAM,CAACC,EAAeC,CAAgB,EAAIC,EAAAA,SAAS,CAAC,EAC9CC,EAAeC,EAAAA,OAAuB,IAAI,EAE1CC,EAAsBD,EAAAA,OAE1B,IAAI,EAEAE,EAAqBC,EAAAA,YACzBC,GAAwD,CACxDH,EAAoB,QAAUG,CAC/B,EACA,CAAA,CAAC,EAGIC,EAAgBF,cAAaG,GAAkB,CACpD,MAAMC,EAAYR,EAAa,QAC/B,GAAI,CAACQ,EAAW,OACHA,EAAU,SAASD,CAAK,GAC/B,eAAe,CAAE,MAAO,SAAA,CAAW,CAC1C,EAAG,CAAA,CAAE,EAECE,EAAUC,GAAc,CACzBpB,EAAMoB,CAAC,GAAGlB,EAAQF,EAAMoB,CAAC,CAAC,CAC/B,EAmCA,OAjCAC,EAAAA,oBAAoBf,EAAK,KAAO,CAC/B,UAAW,CAAC,CAAE,MAAAgB,KAETlB,GAAkBQ,EAAoB,QAClCA,EAAoB,QAAQU,CAAK,EAEpCtB,EAAM,OACPsB,EAAM,MAAQ,WACjBd,EAAkBe,GAAS,CAC1B,MAAMC,GAAQD,EAAOvB,EAAM,OAAS,GAAKA,EAAM,OAC/C,OAAAgB,EAAcQ,CAAI,EACXA,CACR,CAAC,EACM,IAEJF,EAAM,MAAQ,aACjBd,EAAkBe,GAAS,CAC1B,MAAMC,GAAQD,EAAO,GAAKvB,EAAM,OAChC,OAAAgB,EAAcQ,CAAI,EACXA,CACR,CAAC,EACM,IAEJF,EAAM,MAAQ,SACjBH,EAAOZ,CAAa,EACb,IAED,GArBmB,EAsB3B,EACC,EAEFkB,EAAAA,UAAU,IAAMjB,EAAiB,CAAC,EAAG,CAACR,CAAK,CAAC,EAEvCA,EAAM,OAGPI,oBAGA,SAAAA,EAAe,CACf,MAAAJ,EACA,MAAAC,EACA,YAAaM,EACb,SAAWmB,GAASxB,EAAQwB,CAAI,EAChC,mBAAAb,EACA,QAASR,CAAA,CACT,EACF,EAKDsB,MAACC,EAAAA,mBAAkB,IAAKlB,EACtB,WAAM,IAAI,CAACgB,EAAMN,IACjBO,EAAAA,IAACE,EAAAA,aAAA,CAEA,UAAWT,IAAMb,EACjB,aAAc,IAAMC,EAAiBY,CAAC,EACtC,QAAS,IAAMD,EAAOC,CAAC,EAEtB,WACAjB,EAAWuB,EAAMN,IAAMb,CAAa,EAEpCuB,EAAAA,KAAAC,WAAA,CACE,SAAA,CAAAL,EAAK,UACLC,EAAAA,IAACK,gBAAA,CAAc,IAAKN,EAAK,UAAW,IAAI,EAAA,CAAG,EAE3CC,EAAAA,IAACM,EAAAA,uBACC,SAAAP,EAAK,MAAM,OAAO,CAAC,EAAE,cACvB,EAEDC,EAAAA,IAACO,EAAAA,aAAA,CAAc,SAAAR,EAAK,KAAA,CAAM,EACzBA,EAAK,WAAa,cACjBS,EAAAA,mBAAA,CAAmB,QAAST,EAAK,QAAA,CAAU,CAAA,CAAA,CAE9C,CAAA,EApBIA,EAAK,EAAA,CAuBX,EACF,EA9CyB,IAgD3B,CACD,EACA5B,EAAgB,YAAc"}
1
+ {"version":3,"file":"MentionDropdown.js","sources":["../../../../../src/editor/extensions/mention/MentionDropdown.tsx"],"sourcesContent":["import React, {\n\tforwardRef,\n\tuseCallback,\n\tuseEffect,\n\tuseImperativeHandle,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport type {\n\tMentionDropdownRenderProps,\n\tMentionItem,\n} from '../../BikEditor.types';\nimport {\n\tDropdownContainer,\n\tDropdownItem,\n\tMentionAvatar,\n\tMentionAvatarFallback,\n\tMentionLabel,\n\tMentionPresenceDot,\n} from '../editorDropdown.styles';\n\ninterface Props {\n\titems: MentionItem[];\n\tquery: string;\n\tcommand: (item: MentionItem) => void;\n\t/** Custom per-row renderer. Receives the item and whether it is the active row. */\n\trenderItem?: (item: MentionItem, isActive: boolean) => React.ReactNode;\n\t/**\n\t * Full custom dropdown renderer. Takes priority over renderItem.\n\t * The editor passes activeIndex and onSelect — you handle all the visual rendering.\n\t */\n\trenderDropdown?: (props: MentionDropdownRenderProps) => React.ReactNode;\n\t/** Close the menu without selecting (strips the typed trigger). Injected by the extension. */\n\tdismiss?: () => void;\n}\n\nexport const MentionDropdown = forwardRef<any, Props>(\n\t({ items, query, command, renderItem, renderDropdown, dismiss }, ref) => {\n\t\tconst [selectedIndex, setSelectedIndex] = useState(0);\n\t\tconst containerRef = useRef<HTMLDivElement>(null);\n\t\t// A custom dropdown (renderDropdown) can claim keyboard nav for itself.\n\t\tconst customKeyHandlerRef = useRef<\n\t\t\t((event: KeyboardEvent) => boolean) | null\n\t\t>(null);\n\n\t\tconst registerKeyHandler = useCallback(\n\t\t\t(handler: ((event: KeyboardEvent) => boolean) | null) => {\n\t\t\t\tcustomKeyHandlerRef.current = handler;\n\t\t\t},\n\t\t\t[],\n\t\t);\n\n\t\tconst scrollToIndex = useCallback((index: number) => {\n\t\t\tconst container = containerRef.current;\n\t\t\tif (!container) return;\n\t\t\tconst item = container.children[index] as HTMLElement | undefined;\n\t\t\titem?.scrollIntoView({ block: 'nearest' });\n\t\t}, []);\n\n\t\tconst select = (i: number) => {\n\t\t\tif (items[i]) command(items[i]);\n\t\t};\n\n\t\tuseImperativeHandle(ref, () => ({\n\t\t\tonKeyDown: ({ event }: { event: KeyboardEvent }) => {\n\t\t\t\t// A custom dropdown that registered a handler owns navigation.\n\t\t\t\tif (renderDropdown && customKeyHandlerRef.current) {\n\t\t\t\t\treturn customKeyHandlerRef.current(event);\n\t\t\t\t}\n\t\t\t\tif (!items.length) return false;\n\t\t\t\tif (event.key === 'ArrowUp') {\n\t\t\t\t\tsetSelectedIndex((prev) => {\n\t\t\t\t\t\tconst next = (prev + items.length - 1) % items.length;\n\t\t\t\t\t\tscrollToIndex(next);\n\t\t\t\t\t\treturn next;\n\t\t\t\t\t});\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (event.key === 'ArrowDown') {\n\t\t\t\t\tsetSelectedIndex((prev) => {\n\t\t\t\t\t\tconst next = (prev + 1) % items.length;\n\t\t\t\t\t\tscrollToIndex(next);\n\t\t\t\t\t\treturn next;\n\t\t\t\t\t});\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (event.key === 'Enter') {\n\t\t\t\t\tselect(selectedIndex);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t}));\n\n\t\tuseEffect(() => setSelectedIndex(0), [items]);\n\n\t\t// A custom dropdown owns its own empty state — it can have content even\n\t\t// with zero mention items (e.g. the agent-builder's variables-only mode).\n\t\t// Only the default row list bails on empty.\n\t\tif (!items.length && !renderDropdown) return null;\n\n\t\t// Full custom dropdown — editor still manages keyboard nav via selectedIndex\n\t\tif (renderDropdown) {\n\t\t\treturn (\n\t\t\t\t<>\n\t\t\t\t\t{renderDropdown({\n\t\t\t\t\t\titems,\n\t\t\t\t\t\tquery,\n\t\t\t\t\t\tactiveIndex: selectedIndex,\n\t\t\t\t\t\tonSelect: (item) => command(item),\n\t\t\t\t\t\tregisterKeyHandler,\n\t\t\t\t\t\tonClose: dismiss,\n\t\t\t\t\t})}\n\t\t\t\t</>\n\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\t<DropdownContainer ref={containerRef}>\n\t\t\t\t{items.map((item, i) => (\n\t\t\t\t\t<DropdownItem\n\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\t$isActive={i === selectedIndex}\n\t\t\t\t\t\tonMouseEnter={() => setSelectedIndex(i)}\n\t\t\t\t\t\tonClick={() => select(i)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{renderItem ? (\n\t\t\t\t\t\t\trenderItem(item, i === selectedIndex)\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t{item.avatarUrl ? (\n\t\t\t\t\t\t\t\t\t<MentionAvatar src={item.avatarUrl} alt=\"\" />\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<MentionAvatarFallback>\n\t\t\t\t\t\t\t\t\t\t{item.label.charAt(0).toUpperCase()}\n\t\t\t\t\t\t\t\t\t</MentionAvatarFallback>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t<MentionLabel>{item.label}</MentionLabel>\n\t\t\t\t\t\t\t\t{item.isOnline !== undefined && (\n\t\t\t\t\t\t\t\t\t<MentionPresenceDot $online={item.isOnline} />\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</DropdownItem>\n\t\t\t\t))}\n\t\t\t</DropdownContainer>\n\t\t);\n\t},\n);\nMentionDropdown.displayName = 'MentionDropdown';\n"],"names":["MentionDropdown","forwardRef","items","query","command","renderItem","renderDropdown","dismiss","ref","selectedIndex","setSelectedIndex","useState","containerRef","useRef","customKeyHandlerRef","registerKeyHandler","useCallback","handler","scrollToIndex","index","container","select","i","useImperativeHandle","event","prev","next","useEffect","item","jsx","DropdownContainer","DropdownItem","jsxs","Fragment","MentionAvatar","MentionAvatarFallback","MentionLabel","MentionPresenceDot"],"mappings":"iLAoCaA,EAAkBC,EAAAA,WAC9B,CAAC,CAAE,MAAAC,EAAO,MAAAC,EAAO,QAAAC,EAAS,WAAAC,EAAY,eAAAC,EAAgB,QAAAC,CAAA,EAAWC,IAAQ,CACxE,KAAM,CAACC,EAAeC,CAAgB,EAAIC,EAAAA,SAAS,CAAC,EAC9CC,EAAeC,EAAAA,OAAuB,IAAI,EAE1CC,EAAsBD,EAAAA,OAE1B,IAAI,EAEAE,EAAqBC,EAAAA,YACzBC,GAAwD,CACxDH,EAAoB,QAAUG,CAC/B,EACA,CAAA,CAAC,EAGIC,EAAgBF,cAAaG,GAAkB,CACpD,MAAMC,EAAYR,EAAa,QAC/B,GAAI,CAACQ,EAAW,OACHA,EAAU,SAASD,CAAK,GAC/B,eAAe,CAAE,MAAO,SAAA,CAAW,CAC1C,EAAG,CAAA,CAAE,EAECE,EAAUC,GAAc,CACzBpB,EAAMoB,CAAC,GAAGlB,EAAQF,EAAMoB,CAAC,CAAC,CAC/B,EAsCA,OApCAC,EAAAA,oBAAoBf,EAAK,KAAO,CAC/B,UAAW,CAAC,CAAE,MAAAgB,KAETlB,GAAkBQ,EAAoB,QAClCA,EAAoB,QAAQU,CAAK,EAEpCtB,EAAM,OACPsB,EAAM,MAAQ,WACjBd,EAAkBe,GAAS,CAC1B,MAAMC,GAAQD,EAAOvB,EAAM,OAAS,GAAKA,EAAM,OAC/C,OAAAgB,EAAcQ,CAAI,EACXA,CACR,CAAC,EACM,IAEJF,EAAM,MAAQ,aACjBd,EAAkBe,GAAS,CAC1B,MAAMC,GAAQD,EAAO,GAAKvB,EAAM,OAChC,OAAAgB,EAAcQ,CAAI,EACXA,CACR,CAAC,EACM,IAEJF,EAAM,MAAQ,SACjBH,EAAOZ,CAAa,EACb,IAED,GArBmB,EAsB3B,EACC,EAEFkB,EAAAA,UAAU,IAAMjB,EAAiB,CAAC,EAAG,CAACR,CAAK,CAAC,EAKxC,CAACA,EAAM,QAAU,CAACI,EAAuB,KAGzCA,oBAGA,SAAAA,EAAe,CACf,MAAAJ,EACA,MAAAC,EACA,YAAaM,EACb,SAAWmB,GAASxB,EAAQwB,CAAI,EAChC,mBAAAb,EACA,QAASR,CAAA,CACT,EACF,EAKDsB,MAACC,EAAAA,mBAAkB,IAAKlB,EACtB,WAAM,IAAI,CAACgB,EAAMN,IACjBO,EAAAA,IAACE,EAAAA,aAAA,CAEA,UAAWT,IAAMb,EACjB,aAAc,IAAMC,EAAiBY,CAAC,EACtC,QAAS,IAAMD,EAAOC,CAAC,EAEtB,WACAjB,EAAWuB,EAAMN,IAAMb,CAAa,EAEpCuB,EAAAA,KAAAC,WAAA,CACE,SAAA,CAAAL,EAAK,UACLC,EAAAA,IAACK,gBAAA,CAAc,IAAKN,EAAK,UAAW,IAAI,EAAA,CAAG,EAE3CC,EAAAA,IAACM,EAAAA,uBACC,SAAAP,EAAK,MAAM,OAAO,CAAC,EAAE,cACvB,EAEDC,EAAAA,IAACO,EAAAA,aAAA,CAAc,SAAAR,EAAK,KAAA,CAAM,EACzBA,EAAK,WAAa,cACjBS,EAAAA,mBAAA,CAAmB,QAAST,EAAK,QAAA,CAAU,CAAA,CAAA,CAE9C,CAAA,EApBIA,EAAK,EAAA,CAuBX,EACF,CAEF,CACD,EACA5B,EAAgB,YAAc"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("../../../node_modules/@tiptap/core/dist/index.js"),b=require("@tiptap/extension-mention"),k=require("@tiptap/react"),M=require("../suggestionPopup.js"),w=require("./MentionDropdown.js"),p=i=>i&&typeof i=="object"&&"default"in i?i:{default:i},D=p(b);function T(i,o){const{renderItem:d,renderDropdown:u,removeTriggerOnDismiss:s}=i;return()=>{let a,r,e,t=null;const l=()=>{if(o.picked=!0,e?.editor&&e?.range){const{editor:n,range:c}=e;n.chain().focus().deleteRange(c).run()}};return{onStart:n=>{e=n,o.picked=!1,a=new k.ReactRenderer(w.MentionDropdown,{props:{...n,renderItem:d,renderDropdown:u,dismiss:l},editor:n.editor}),r=M.createSuggestionPopup(a.element,n.clientRect),t=c=>{const g=c.target;!g||r.element.contains(g)||e?.editor?.view?.dom?.contains(g)||(o.picked=!0,e?.editor&&e?.range&&e.editor.chain().deleteRange(e.range).run(),r.hide())},document.addEventListener("mousedown",t)},onUpdate:n=>{if(e=n,a.updateProps({...n,renderItem:d,renderDropdown:u,dismiss:l}),!n.items?.length){r.hide();return}r.show(),r.updatePosition(n.clientRect)},onKeyDown:n=>n.event.key==="Escape"?(r.hide(),!0):a.ref?.onKeyDown(n)??!1,onExit:()=>{if(t&&(document.removeEventListener("mousedown",t),t=null),r.destroy(),a.destroy(),s&&!o.picked&&e?.editor&&e?.range){const{editor:n,range:c}=e;setTimeout(()=>{n.isDestroyed||n.chain().deleteRange(c).run()},0)}}}}}function m(i,o,d,u,s,a){const r={picked:!1};return D.default.extend({name:i,addAttributes(){return{...this.parent?.(),kind:{default:null,parseHTML:e=>e.getAttribute("data-kind"),renderHTML:e=>e.kind?{"data-kind":String(e.kind)}:{}}}}}).configure({HTMLAttributes:{class:o},renderText:({options:e,node:t})=>`${t.attrs.kind?"":e.suggestion.char}${t.attrs.label}`,renderHTML:({options:e,node:t})=>["span",f.mergeAttributes(e.HTMLAttributes,t.attrs.kind?{"data-kind":String(t.attrs.kind)}:{}),`${t.attrs.kind?"":e.suggestion.char}${t.attrs.label}`],suggestion:{char:d,allowSpaces:!0,items:({query:e})=>u.current.filter(t=>t.label.toLowerCase().includes(e.toLowerCase())),command:({editor:e,range:t,props:l})=>{r.picked=!0,e.chain().focus().deleteRange(t).insertContent({type:i,attrs:{id:l.id,label:l.label,kind:l.meta?.kind??null}}).run(),s?.(l,d)},render:T(a,r)}})}function h(i,o,d,u,s){return m("mentionAgent","bik-mention bik-mention--agent","@",i,o,{renderItem:d,renderDropdown:u,removeTriggerOnDismiss:s})}function y(i,o,d,u,s){return m("mentionTeam","bik-mention bik-mention--team","#",i,o,{renderItem:d,renderDropdown:u,removeTriggerOnDismiss:s})}exports.buildAgentMentionExtension=h;exports.buildTeamMentionExtension=y;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("../../../node_modules/@tiptap/core/dist/index.js"),b=require("@tiptap/extension-mention"),k=require("@tiptap/react"),M=require("../suggestionPopup.js"),w=require("./MentionDropdown.js"),p=i=>i&&typeof i=="object"&&"default"in i?i:{default:i},D=p(b);function T(i,o){const{renderItem:d,renderDropdown:u,removeTriggerOnDismiss:s}=i;return()=>{let a,r,e,t=null;const l=()=>{if(o.picked=!0,e?.editor&&e?.range){const{editor:n,range:c}=e;n.chain().focus().deleteRange(c).run()}};return{onStart:n=>{e=n,o.picked=!1,a=new k.ReactRenderer(w.MentionDropdown,{props:{...n,renderItem:d,renderDropdown:u,dismiss:l},editor:n.editor}),r=M.createSuggestionPopup(a.element,n.clientRect),t=c=>{const g=c.target;!g||r.element.contains(g)||e?.editor?.view?.dom?.contains(g)||(o.picked=!0,e?.editor&&e?.range&&e.editor.chain().deleteRange(e.range).run(),r.hide())},document.addEventListener("mousedown",t)},onUpdate:n=>{if(e=n,a.updateProps({...n,renderItem:d,renderDropdown:u,dismiss:l}),!n.items?.length&&!u){r.hide();return}r.show(),r.updatePosition(n.clientRect)},onKeyDown:n=>n.event.key==="Escape"?(r.hide(),!0):a.ref?.onKeyDown(n)??!1,onExit:()=>{if(t&&(document.removeEventListener("mousedown",t),t=null),r.destroy(),a.destroy(),s&&!o.picked&&e?.editor&&e?.range){const{editor:n,range:c}=e;setTimeout(()=>{n.isDestroyed||n.chain().deleteRange(c).run()},0)}}}}}function m(i,o,d,u,s,a){const r={picked:!1};return D.default.extend({name:i,addAttributes(){return{...this.parent?.(),kind:{default:null,parseHTML:e=>e.getAttribute("data-kind"),renderHTML:e=>e.kind?{"data-kind":String(e.kind)}:{}}}}}).configure({HTMLAttributes:{class:o},renderText:({options:e,node:t})=>`${t.attrs.kind?"":e.suggestion.char}${t.attrs.label}`,renderHTML:({options:e,node:t})=>["span",f.mergeAttributes(e.HTMLAttributes,t.attrs.kind?{"data-kind":String(t.attrs.kind)}:{}),`${t.attrs.kind?"":e.suggestion.char}${t.attrs.label}`],suggestion:{char:d,allowSpaces:!0,items:({query:e})=>u.current.filter(t=>t.label.toLowerCase().includes(e.toLowerCase())),command:({editor:e,range:t,props:l})=>{r.picked=!0,e.chain().focus().deleteRange(t).insertContent({type:i,attrs:{id:l.id,label:l.label,kind:l.meta?.kind??null}}).run(),s?.(l,d)},render:T(a,r)}})}function h(i,o,d,u,s){return m("mentionAgent","bik-mention bik-mention--agent","@",i,o,{renderItem:d,renderDropdown:u,removeTriggerOnDismiss:s})}function y(i,o,d,u,s){return m("mentionTeam","bik-mention bik-mention--team","#",i,o,{renderItem:d,renderDropdown:u,removeTriggerOnDismiss:s})}exports.buildAgentMentionExtension=h;exports.buildTeamMentionExtension=y;
2
2
  //# sourceMappingURL=MentionExtension.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MentionExtension.js","sources":["../../../../../src/editor/extensions/mention/MentionExtension.ts"],"sourcesContent":["import { mergeAttributes } from '@tiptap/core';\nimport Mention from '@tiptap/extension-mention';\nimport { ReactRenderer } from '@tiptap/react';\nimport type { ReactNode } from 'react';\nimport type {\n\tMentionDropdownRenderProps,\n\tMentionItem,\n} from '../../BikEditor.types';\nimport {\n\tcreateSuggestionPopup,\n\ttype SuggestionPopup,\n} from '../suggestionPopup';\nimport { MentionDropdown } from './MentionDropdown';\n\ninterface MentionBuildOptions {\n\trenderItem?: (item: MentionItem, isActive: boolean) => ReactNode;\n\trenderDropdown?: (props: MentionDropdownRenderProps) => ReactNode;\n\t/** Remove the typed trigger char + query if the menu closes without a selection. */\n\tremoveTriggerOnDismiss?: boolean;\n}\n\nfunction buildRender(\n\toptions: MentionBuildOptions,\n\tpickedRef: { picked: boolean },\n) {\n\tconst { renderItem, renderDropdown, removeTriggerOnDismiss } = options;\n\treturn () => {\n\t\tlet component: ReactRenderer;\n\t\tlet popup: SuggestionPopup;\n\t\tlet latestProps: any;\n\t\t// Closes the menu when the user clicks anywhere outside it. The `@` popup\n\t\t// lives on document.body (not inside the editor), so nothing dismisses it on\n\t\t// an outside click otherwise — only Escape / moving the cursor did.\n\t\tlet onDocMouseDown: ((event: MouseEvent) => void) | null = null;\n\n\t\t// Close the menu without a selection: drop the typed \"@query\" so no orphan\n\t\t// trigger is left, and mark as picked so onExit doesn't delete it twice.\n\t\tconst dismiss = () => {\n\t\t\tpickedRef.picked = true;\n\t\t\tif (latestProps?.editor && latestProps?.range) {\n\t\t\t\tconst { editor, range } = latestProps;\n\t\t\t\teditor.chain().focus().deleteRange(range).run();\n\t\t\t}\n\t\t};\n\n\t\treturn {\n\t\t\tonStart: (props: any) => {\n\t\t\t\tlatestProps = props;\n\t\t\t\tpickedRef.picked = false;\n\t\t\t\tcomponent = new ReactRenderer(MentionDropdown, {\n\t\t\t\t\tprops: { ...props, renderItem, renderDropdown, dismiss },\n\t\t\t\t\teditor: props.editor,\n\t\t\t\t});\n\t\t\t\tpopup = createSuggestionPopup(component.element, props.clientRect);\n\t\t\t\tonDocMouseDown = (event: MouseEvent) => {\n\t\t\t\t\tconst target = event.target as Node | null;\n\t\t\t\t\tif (!target) return;\n\t\t\t\t\t// Inside the picker → keep open (row clicks fire on `click`).\n\t\t\t\t\tif (popup.element.contains(target)) return;\n\t\t\t\t\t// Inside the editor → the suggestion plugin already closes it.\n\t\t\t\t\tconst editorDom = latestProps?.editor?.view?.dom as\n\t\t\t\t\t\t| HTMLElement\n\t\t\t\t\t\t| undefined;\n\t\t\t\t\tif (editorDom?.contains(target)) return;\n\t\t\t\t\t// Anywhere else → drop the typed \"@query\" (no refocus — clicking\n\t\t\t\t\t// away shouldn't yank focus back) and close.\n\t\t\t\t\tpickedRef.picked = true;\n\t\t\t\t\tif (latestProps?.editor && latestProps?.range) {\n\t\t\t\t\t\tlatestProps.editor.chain().deleteRange(latestProps.range).run();\n\t\t\t\t\t}\n\t\t\t\t\tpopup.hide();\n\t\t\t\t};\n\t\t\t\tdocument.addEventListener('mousedown', onDocMouseDown);\n\t\t\t},\n\t\t\tonUpdate: (props: any) => {\n\t\t\t\tlatestProps = props;\n\t\t\t\tcomponent.updateProps({\n\t\t\t\t\t...props,\n\t\t\t\t\trenderItem,\n\t\t\t\t\trenderDropdown,\n\t\t\t\t\tdismiss,\n\t\t\t\t});\n\t\t\t\tif (!props.items?.length) {\n\t\t\t\t\tpopup.hide();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tpopup.show();\n\t\t\t\tpopup.updatePosition(props.clientRect);\n\t\t\t},\n\t\t\tonKeyDown: (props: any) => {\n\t\t\t\tif (props.event.key === 'Escape') {\n\t\t\t\t\tpopup.hide();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn (component.ref as any)?.onKeyDown(props) ?? false;\n\t\t\t},\n\t\t\tonExit: () => {\n\t\t\t\tif (onDocMouseDown) {\n\t\t\t\t\tdocument.removeEventListener('mousedown', onDocMouseDown);\n\t\t\t\t\tonDocMouseDown = null;\n\t\t\t\t}\n\t\t\t\tpopup.destroy();\n\t\t\t\tcomponent.destroy();\n\t\t\t\t// Nothing was picked → strip the orphan \"@query\" the user typed.\n\t\t\t\tif (\n\t\t\t\t\tremoveTriggerOnDismiss &&\n\t\t\t\t\t!pickedRef.picked &&\n\t\t\t\t\tlatestProps?.editor &&\n\t\t\t\t\tlatestProps?.range\n\t\t\t\t) {\n\t\t\t\t\tconst { editor, range } = latestProps;\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tif (!editor.isDestroyed) {\n\t\t\t\t\t\t\teditor.chain().deleteRange(range).run();\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 0);\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t};\n}\n\n/**\n * Builds a TipTap Mention extension.\n *\n * Each inserted node carries an optional `kind` attribute. When set, the chip is\n * rendered WITHOUT the trigger char (the `label` already encodes the full text)\n * and a `data-kind` attribute is emitted so CSS can colour it per kind. When\n * `kind` is null the legacy `${char}${label}` chip is rendered (back-compatible).\n */\nfunction buildMentionExtension(\n\tname: 'mentionAgent' | 'mentionTeam',\n\tcssClass: string,\n\tchar: '@' | '#',\n\titemsRef: { current: MentionItem[] },\n\tonSelect: ((item: MentionItem, char: '@' | '#') => void) | undefined,\n\toptions: MentionBuildOptions,\n) {\n\tconst pickedRef = { picked: false };\n\n\treturn Mention.extend({\n\t\tname,\n\t\taddAttributes() {\n\t\t\treturn {\n\t\t\t\t...this.parent?.(),\n\t\t\t\tkind: {\n\t\t\t\t\tdefault: null,\n\t\t\t\t\tparseHTML: (el: HTMLElement) => el.getAttribute('data-kind'),\n\t\t\t\t\trenderHTML: (attrs: Record<string, unknown>) =>\n\t\t\t\t\t\tattrs['kind'] ? { 'data-kind': String(attrs['kind']) } : {},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t}).configure({\n\t\tHTMLAttributes: { class: cssClass },\n\t\trenderText: ({ options: opt, node }: any) =>\n\t\t\t`${node.attrs['kind'] ? '' : opt.suggestion.char}${node.attrs['label']}`,\n\t\trenderHTML: ({ options: opt, node }: any) => [\n\t\t\t'span',\n\t\t\tmergeAttributes(\n\t\t\t\topt.HTMLAttributes,\n\t\t\t\tnode.attrs['kind'] ? { 'data-kind': String(node.attrs['kind']) } : {},\n\t\t\t),\n\t\t\t`${node.attrs['kind'] ? '' : opt.suggestion.char}${node.attrs['label']}`,\n\t\t],\n\t\tsuggestion: {\n\t\t\tchar,\n\t\t\tallowSpaces: true,\n\t\t\titems: ({ query }: { query: string }) =>\n\t\t\t\titemsRef.current.filter((a) =>\n\t\t\t\t\ta.label.toLowerCase().includes(query.toLowerCase()),\n\t\t\t\t),\n\t\t\tcommand: ({ editor, range, props }: any) => {\n\t\t\t\tpickedRef.picked = true;\n\t\t\t\teditor\n\t\t\t\t\t.chain()\n\t\t\t\t\t.focus()\n\t\t\t\t\t.deleteRange(range)\n\t\t\t\t\t.insertContent({\n\t\t\t\t\t\ttype: name,\n\t\t\t\t\t\tattrs: {\n\t\t\t\t\t\t\tid: props.id,\n\t\t\t\t\t\t\tlabel: props.label,\n\t\t\t\t\t\t\tkind: props.meta?.kind ?? null,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\t.run();\n\t\t\t\tonSelect?.(props, char);\n\t\t\t},\n\t\t\trender: buildRender(options, pickedRef),\n\t\t},\n\t});\n}\n\nexport function buildAgentMentionExtension(\n\tagentsRef: { current: MentionItem[] },\n\tonSelect?: (item: MentionItem, char: '@' | '#') => void,\n\trenderItem?: (item: MentionItem, isActive: boolean) => ReactNode,\n\trenderDropdown?: (props: MentionDropdownRenderProps) => ReactNode,\n\tremoveTriggerOnDismiss?: boolean,\n) {\n\treturn buildMentionExtension(\n\t\t'mentionAgent',\n\t\t'bik-mention bik-mention--agent',\n\t\t'@',\n\t\tagentsRef,\n\t\tonSelect,\n\t\t{ renderItem, renderDropdown, removeTriggerOnDismiss },\n\t);\n}\n\nexport function buildTeamMentionExtension(\n\tteamsRef: { current: MentionItem[] },\n\tonSelect?: (item: MentionItem, char: '@' | '#') => void,\n\trenderItem?: (item: MentionItem, isActive: boolean) => ReactNode,\n\trenderDropdown?: (props: MentionDropdownRenderProps) => ReactNode,\n\tremoveTriggerOnDismiss?: boolean,\n) {\n\treturn buildMentionExtension(\n\t\t'mentionTeam',\n\t\t'bik-mention bik-mention--team',\n\t\t'#',\n\t\tteamsRef,\n\t\tonSelect,\n\t\t{ renderItem, renderDropdown, removeTriggerOnDismiss },\n\t);\n}\n"],"names":["buildRender","options","pickedRef","renderItem","renderDropdown","removeTriggerOnDismiss","component","popup","latestProps","onDocMouseDown","dismiss","editor","range","props","ReactRenderer","MentionDropdown","createSuggestionPopup","event","target","buildMentionExtension","name","cssClass","char","itemsRef","onSelect","Mention","el","attrs","opt","node","mergeAttributes","query","a","buildAgentMentionExtension","agentsRef","buildTeamMentionExtension","teamsRef"],"mappings":"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"}
1
+ {"version":3,"file":"MentionExtension.js","sources":["../../../../../src/editor/extensions/mention/MentionExtension.ts"],"sourcesContent":["import { mergeAttributes } from '@tiptap/core';\nimport Mention from '@tiptap/extension-mention';\nimport { ReactRenderer } from '@tiptap/react';\nimport type { ReactNode } from 'react';\nimport type {\n\tMentionDropdownRenderProps,\n\tMentionItem,\n} from '../../BikEditor.types';\nimport {\n\tcreateSuggestionPopup,\n\ttype SuggestionPopup,\n} from '../suggestionPopup';\nimport { MentionDropdown } from './MentionDropdown';\n\ninterface MentionBuildOptions {\n\trenderItem?: (item: MentionItem, isActive: boolean) => ReactNode;\n\trenderDropdown?: (props: MentionDropdownRenderProps) => ReactNode;\n\t/** Remove the typed trigger char + query if the menu closes without a selection. */\n\tremoveTriggerOnDismiss?: boolean;\n}\n\nfunction buildRender(\n\toptions: MentionBuildOptions,\n\tpickedRef: { picked: boolean },\n) {\n\tconst { renderItem, renderDropdown, removeTriggerOnDismiss } = options;\n\treturn () => {\n\t\tlet component: ReactRenderer;\n\t\tlet popup: SuggestionPopup;\n\t\tlet latestProps: any;\n\t\t// Closes the menu when the user clicks anywhere outside it. The `@` popup\n\t\t// lives on document.body (not inside the editor), so nothing dismisses it on\n\t\t// an outside click otherwise — only Escape / moving the cursor did.\n\t\tlet onDocMouseDown: ((event: MouseEvent) => void) | null = null;\n\n\t\t// Close the menu without a selection: drop the typed \"@query\" so no orphan\n\t\t// trigger is left, and mark as picked so onExit doesn't delete it twice.\n\t\tconst dismiss = () => {\n\t\t\tpickedRef.picked = true;\n\t\t\tif (latestProps?.editor && latestProps?.range) {\n\t\t\t\tconst { editor, range } = latestProps;\n\t\t\t\teditor.chain().focus().deleteRange(range).run();\n\t\t\t}\n\t\t};\n\n\t\treturn {\n\t\t\tonStart: (props: any) => {\n\t\t\t\tlatestProps = props;\n\t\t\t\tpickedRef.picked = false;\n\t\t\t\tcomponent = new ReactRenderer(MentionDropdown, {\n\t\t\t\t\tprops: { ...props, renderItem, renderDropdown, dismiss },\n\t\t\t\t\teditor: props.editor,\n\t\t\t\t});\n\t\t\t\tpopup = createSuggestionPopup(component.element, props.clientRect);\n\t\t\t\tonDocMouseDown = (event: MouseEvent) => {\n\t\t\t\t\tconst target = event.target as Node | null;\n\t\t\t\t\tif (!target) return;\n\t\t\t\t\t// Inside the picker → keep open (row clicks fire on `click`).\n\t\t\t\t\tif (popup.element.contains(target)) return;\n\t\t\t\t\t// Inside the editor → the suggestion plugin already closes it.\n\t\t\t\t\tconst editorDom = latestProps?.editor?.view?.dom as\n\t\t\t\t\t\t| HTMLElement\n\t\t\t\t\t\t| undefined;\n\t\t\t\t\tif (editorDom?.contains(target)) return;\n\t\t\t\t\t// Anywhere else → drop the typed \"@query\" (no refocus — clicking\n\t\t\t\t\t// away shouldn't yank focus back) and close.\n\t\t\t\t\tpickedRef.picked = true;\n\t\t\t\t\tif (latestProps?.editor && latestProps?.range) {\n\t\t\t\t\t\tlatestProps.editor.chain().deleteRange(latestProps.range).run();\n\t\t\t\t\t}\n\t\t\t\t\tpopup.hide();\n\t\t\t\t};\n\t\t\t\tdocument.addEventListener('mousedown', onDocMouseDown);\n\t\t\t},\n\t\t\tonUpdate: (props: any) => {\n\t\t\t\tlatestProps = props;\n\t\t\t\tcomponent.updateProps({\n\t\t\t\t\t...props,\n\t\t\t\t\trenderItem,\n\t\t\t\t\trenderDropdown,\n\t\t\t\t\tdismiss,\n\t\t\t\t});\n\t\t\t\t// Empty result list closes the DEFAULT dropdown; a custom dropdown\n\t\t\t\t// (renderDropdown) may have content of its own with zero items —\n\t\t\t\t// e.g. the agent-builder's variables-only mode — so it stays open.\n\t\t\t\tif (!props.items?.length && !renderDropdown) {\n\t\t\t\t\tpopup.hide();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tpopup.show();\n\t\t\t\tpopup.updatePosition(props.clientRect);\n\t\t\t},\n\t\t\tonKeyDown: (props: any) => {\n\t\t\t\tif (props.event.key === 'Escape') {\n\t\t\t\t\tpopup.hide();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn (component.ref as any)?.onKeyDown(props) ?? false;\n\t\t\t},\n\t\t\tonExit: () => {\n\t\t\t\tif (onDocMouseDown) {\n\t\t\t\t\tdocument.removeEventListener('mousedown', onDocMouseDown);\n\t\t\t\t\tonDocMouseDown = null;\n\t\t\t\t}\n\t\t\t\tpopup.destroy();\n\t\t\t\tcomponent.destroy();\n\t\t\t\t// Nothing was picked → strip the orphan \"@query\" the user typed.\n\t\t\t\tif (\n\t\t\t\t\tremoveTriggerOnDismiss &&\n\t\t\t\t\t!pickedRef.picked &&\n\t\t\t\t\tlatestProps?.editor &&\n\t\t\t\t\tlatestProps?.range\n\t\t\t\t) {\n\t\t\t\t\tconst { editor, range } = latestProps;\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tif (!editor.isDestroyed) {\n\t\t\t\t\t\t\teditor.chain().deleteRange(range).run();\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 0);\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t};\n}\n\n/**\n * Builds a TipTap Mention extension.\n *\n * Each inserted node carries an optional `kind` attribute. When set, the chip is\n * rendered WITHOUT the trigger char (the `label` already encodes the full text)\n * and a `data-kind` attribute is emitted so CSS can colour it per kind. When\n * `kind` is null the legacy `${char}${label}` chip is rendered (back-compatible).\n */\nfunction buildMentionExtension(\n\tname: 'mentionAgent' | 'mentionTeam',\n\tcssClass: string,\n\tchar: '@' | '#',\n\titemsRef: { current: MentionItem[] },\n\tonSelect: ((item: MentionItem, char: '@' | '#') => void) | undefined,\n\toptions: MentionBuildOptions,\n) {\n\tconst pickedRef = { picked: false };\n\n\treturn Mention.extend({\n\t\tname,\n\t\taddAttributes() {\n\t\t\treturn {\n\t\t\t\t...this.parent?.(),\n\t\t\t\tkind: {\n\t\t\t\t\tdefault: null,\n\t\t\t\t\tparseHTML: (el: HTMLElement) => el.getAttribute('data-kind'),\n\t\t\t\t\trenderHTML: (attrs: Record<string, unknown>) =>\n\t\t\t\t\t\tattrs['kind'] ? { 'data-kind': String(attrs['kind']) } : {},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t}).configure({\n\t\tHTMLAttributes: { class: cssClass },\n\t\trenderText: ({ options: opt, node }: any) =>\n\t\t\t`${node.attrs['kind'] ? '' : opt.suggestion.char}${node.attrs['label']}`,\n\t\trenderHTML: ({ options: opt, node }: any) => [\n\t\t\t'span',\n\t\t\tmergeAttributes(\n\t\t\t\topt.HTMLAttributes,\n\t\t\t\tnode.attrs['kind'] ? { 'data-kind': String(node.attrs['kind']) } : {},\n\t\t\t),\n\t\t\t`${node.attrs['kind'] ? '' : opt.suggestion.char}${node.attrs['label']}`,\n\t\t],\n\t\tsuggestion: {\n\t\t\tchar,\n\t\t\tallowSpaces: true,\n\t\t\titems: ({ query }: { query: string }) =>\n\t\t\t\titemsRef.current.filter((a) =>\n\t\t\t\t\ta.label.toLowerCase().includes(query.toLowerCase()),\n\t\t\t\t),\n\t\t\tcommand: ({ editor, range, props }: any) => {\n\t\t\t\tpickedRef.picked = true;\n\t\t\t\teditor\n\t\t\t\t\t.chain()\n\t\t\t\t\t.focus()\n\t\t\t\t\t.deleteRange(range)\n\t\t\t\t\t.insertContent({\n\t\t\t\t\t\ttype: name,\n\t\t\t\t\t\tattrs: {\n\t\t\t\t\t\t\tid: props.id,\n\t\t\t\t\t\t\tlabel: props.label,\n\t\t\t\t\t\t\tkind: props.meta?.kind ?? null,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\t.run();\n\t\t\t\tonSelect?.(props, char);\n\t\t\t},\n\t\t\trender: buildRender(options, pickedRef),\n\t\t},\n\t});\n}\n\nexport function buildAgentMentionExtension(\n\tagentsRef: { current: MentionItem[] },\n\tonSelect?: (item: MentionItem, char: '@' | '#') => void,\n\trenderItem?: (item: MentionItem, isActive: boolean) => ReactNode,\n\trenderDropdown?: (props: MentionDropdownRenderProps) => ReactNode,\n\tremoveTriggerOnDismiss?: boolean,\n) {\n\treturn buildMentionExtension(\n\t\t'mentionAgent',\n\t\t'bik-mention bik-mention--agent',\n\t\t'@',\n\t\tagentsRef,\n\t\tonSelect,\n\t\t{ renderItem, renderDropdown, removeTriggerOnDismiss },\n\t);\n}\n\nexport function buildTeamMentionExtension(\n\tteamsRef: { current: MentionItem[] },\n\tonSelect?: (item: MentionItem, char: '@' | '#') => void,\n\trenderItem?: (item: MentionItem, isActive: boolean) => ReactNode,\n\trenderDropdown?: (props: MentionDropdownRenderProps) => ReactNode,\n\tremoveTriggerOnDismiss?: boolean,\n) {\n\treturn buildMentionExtension(\n\t\t'mentionTeam',\n\t\t'bik-mention bik-mention--team',\n\t\t'#',\n\t\tteamsRef,\n\t\tonSelect,\n\t\t{ renderItem, renderDropdown, removeTriggerOnDismiss },\n\t);\n}\n"],"names":["buildRender","options","pickedRef","renderItem","renderDropdown","removeTriggerOnDismiss","component","popup","latestProps","onDocMouseDown","dismiss","editor","range","props","ReactRenderer","MentionDropdown","createSuggestionPopup","event","target","buildMentionExtension","name","cssClass","char","itemsRef","onSelect","Mention","el","attrs","opt","node","mergeAttributes","query","a","buildAgentMentionExtension","agentsRef","buildTeamMentionExtension","teamsRef"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { default as React } from 'react';
2
+ import { VariableListInterfaceV3 } from '../../variable-picker-v3/model';
2
3
  import { ConfigToolConfig, ConfigToolKey, ParamsBlob } from '../AgentBuilder.model';
3
4
  import { AgentCharLimits } from '../constants/charLimits';
4
5
  interface ConfigToolPanelProps {
@@ -18,6 +19,13 @@ interface ConfigToolPanelProps {
18
19
  /** Optional "Improve with AI" for multiline fields. Omit to hide it. */
19
20
  onImprove?: (text: string) => Promise<string>;
20
21
  charLimits?: AgentCharLimits;
22
+ /**
23
+ * Variable catalog for the `@` trigger. When non-empty, `@` in the email
24
+ * tool's Subject / Send To / Reply To / CC opens the variable picker
25
+ * directly, and Message Instructions upgrades to the variables-only mention
26
+ * editor. Absent → the drawer behaves exactly as before.
27
+ */
28
+ variablesData?: VariableListInterfaceV3[];
21
29
  /** SideModal stacking order — raise it when opened over another drawer. */
22
30
  zIndex?: number;
23
31
  }
@@ -1,18 +1,19 @@
1
- import { jsx as r, jsxs as k } from "react/jsx-runtime";
2
- import $ from "../../../assets/icons/cross.svg.js";
3
- import { useState as w } from "react";
4
- import u from "styled-components";
5
- import { TitleSmall as C, BodyCaption as E } from "../../TypographyStyle.js";
6
- import { COLORS as i } from "../../../constants/Theme.js";
7
- import { FieldBlock as D } from "../AgentBuilder.styled.js";
8
- import { AGENT_CHAR_LIMITS as O } from "../constants/charLimits.js";
9
- import { DRAWER_BODY_STYLE as R, DRAWER_HEADER_STYLE as L, DrawerHeaderText as A } from "./DrawerHeaderText.js";
10
- import { ToolInstructionsField as j } from "./ToolInstructionsField.js";
11
- import { SideModal as P } from "../../side-modal/SideModal.js";
12
- import { Switch as Y } from "../../switch/Switch.js";
13
- import { Input as F } from "../../input/Input.js";
14
- import { Tag as z } from "../../tag/Tag.js";
15
- const V = {
1
+ import { jsx as o, jsxs as S } from "react/jsx-runtime";
2
+ import D from "../../../assets/icons/cross.svg.js";
3
+ import F, { useState as w } from "react";
4
+ import y from "styled-components";
5
+ import { TitleSmall as $, BodyCaption as R } from "../../TypographyStyle.js";
6
+ import { COLORS as s } from "../../../constants/Theme.js";
7
+ import { FieldBlock as P } from "../AgentBuilder.styled.js";
8
+ import { AGENT_CHAR_LIMITS as Y } from "../constants/charLimits.js";
9
+ import { DRAWER_BODY_STYLE as V, DRAWER_HEADER_STYLE as z, DrawerHeaderText as H } from "./DrawerHeaderText.js";
10
+ import { ToolInstructionsField as M } from "./ToolInstructionsField.js";
11
+ import { VariableTriggerArea as O } from "./VariableTriggerArea.js";
12
+ import { SideModal as W } from "../../side-modal/SideModal.js";
13
+ import { Switch as G } from "../../switch/Switch.js";
14
+ import { Input as N } from "../../input/Input.js";
15
+ import { Tag as q } from "../../tag/Tag.js";
16
+ const J = {
16
17
  send_email: {
17
18
  title: "Send Email",
18
19
  subtitle: "Notify someone by email when this agent can't continue. You pick the recipient, the AI drafts the message."
@@ -21,222 +22,248 @@ const V = {
21
22
  title: "Send Slack message",
22
23
  subtitle: "Post a message to a Slack channel. You pick the channel, the AI composes the message from the conversation."
23
24
  }
24
- }, H = ({
25
- chips: n,
26
- onChange: a,
27
- placeholder: c,
28
- nativeID: p,
29
- hint: d
25
+ }, K = ({
26
+ chips: e,
27
+ onChange: i,
28
+ placeholder: p,
29
+ nativeID: m,
30
+ hint: g
30
31
  }) => {
31
- const [m, h] = w(""), y = () => {
32
- const e = m.split(",").map((s) => s.trim()).filter(Boolean);
33
- e.length && a([...n, ...e.filter((s) => !n.includes(s))]), h("");
32
+ const [h, k] = w(""), u = () => {
33
+ const a = h.split(",").map((r) => r.trim()).filter(Boolean);
34
+ a.length && i([...e, ...a.filter((r) => !e.includes(r))]), k("");
34
35
  };
35
- return /* @__PURE__ */ k(G, { children: [
36
- /* @__PURE__ */ r(
37
- N,
36
+ return /* @__PURE__ */ S(U, { children: [
37
+ /* @__PURE__ */ o(
38
+ X,
38
39
  {
39
- id: p,
40
+ id: m,
40
41
  type: "text",
41
- placeholder: c,
42
- value: m,
43
- onChange: (e) => h(e.target.value),
44
- onBlur: y,
45
- onKeyDown: (e) => {
46
- e.key === "Enter" || e.key === "," ? (e.preventDefault(), y()) : e.key === "Backspace" && m === "" && n.length > 0 && a(n.slice(0, -1));
42
+ placeholder: p,
43
+ value: h,
44
+ onChange: (a) => k(a.target.value),
45
+ onBlur: u,
46
+ onKeyDown: (a) => {
47
+ a.key === "Enter" || a.key === "," ? (a.preventDefault(), u()) : a.key === "Backspace" && h === "" && e.length > 0 && i(e.slice(0, -1));
47
48
  }
48
49
  }
49
50
  ),
50
- d,
51
- n.length > 0 && /* @__PURE__ */ r(q, { children: n.map((e, s) => /* @__PURE__ */ r(
52
- z,
51
+ g,
52
+ e.length > 0 && /* @__PURE__ */ o(Z, { children: e.map((a, r) => /* @__PURE__ */ o(
53
+ q,
53
54
  {
54
- tagText: e,
55
+ tagText: a,
55
56
  theme: "light",
56
57
  type: "neutral",
57
58
  variant: "regular",
58
- TrailingIcon: $,
59
- onTrailingIconClicked: () => a(n.filter((x, g) => g !== s))
59
+ TrailingIcon: D,
60
+ onTrailingIconClicked: () => i(e.filter((C, f) => f !== r))
60
61
  },
61
- `${e}-${s}`
62
+ `${a}-${r}`
62
63
  )) })
63
64
  ] });
64
- }, M = (n, a) => {
65
- const c = {};
66
- return Object.keys(n).forEach((p) => {
67
- c[p] = a?.params[p]?.value ?? n[p].value;
68
- }), c;
69
- }, W = (n) => String(n ?? "").split(",").map((a) => a.trim()).filter(Boolean), pt = ({
70
- toolKey: n,
71
- template: a,
72
- onClose: c,
73
- onSave: p,
74
- initial: d,
75
- onImprove: m,
76
- charLimits: h = O,
77
- zIndex: y
65
+ }, Q = (e, i) => {
66
+ const p = {};
67
+ return Object.keys(e).forEach((m) => {
68
+ p[m] = i?.params[m]?.value ?? e[m].value;
69
+ }), p;
70
+ }, A = (e) => String(e ?? "").split(",").map((i) => i.trim()).filter(Boolean), kt = ({
71
+ toolKey: e,
72
+ template: i,
73
+ onClose: p,
74
+ onSave: m,
75
+ initial: g,
76
+ onImprove: h,
77
+ charLimits: k = Y,
78
+ variablesData: u,
79
+ zIndex: a
78
80
  }) => {
79
- const [e, s] = w(
80
- () => M(a, d)
81
- ), [x, g] = w(!1), v = Object.values(a), B = n === "send_email", f = (t, l) => s((o) => ({ ...o, [t]: l })), T = v.every(
82
- (t) => !t.required || String(e[t.key] ?? "").trim() !== ""
83
- ), I = async () => {
84
- if (!T || x)
81
+ const [r, C] = w(
82
+ () => Q(i, g)
83
+ ), [f, I] = w(!1), v = Object.values(i), E = e === "send_email", d = (t, l) => C((c) => ({ ...c, [t]: l })), _ = v.every(
84
+ (t) => !t.required || String(r[t.key] ?? "").trim() !== ""
85
+ ), L = async () => {
86
+ if (!_ || f)
85
87
  return;
86
88
  const t = {};
87
- v.forEach((S) => {
88
- t[S.key] = { ...S, value: e[S.key] };
89
+ v.forEach((n) => {
90
+ t[n.key] = { ...n, value: r[n.key] };
89
91
  });
90
92
  const l = {
91
- id: d?.id ?? `${n}_${Date.now().toString(36)}`,
92
- tool_key: n,
93
+ id: g?.id ?? `${e}_${Date.now().toString(36)}`,
94
+ tool_key: e,
93
95
  params: t
94
- }, o = p(l);
95
- if (o && typeof o.then == "function") {
96
- g(!0);
96
+ }, c = m(l);
97
+ if (c && typeof c.then == "function") {
98
+ I(!0);
97
99
  try {
98
- await o;
100
+ await c;
99
101
  } finally {
100
- g(!1);
102
+ I(!1);
101
103
  }
102
104
  }
103
- }, _ = (t) => {
105
+ }, j = (t) => {
104
106
  const l = `config-tool-${t.key.toLowerCase()}`;
105
107
  switch (t.component) {
106
108
  // Multi-value email chips — only for the email tool. Slack's KeywordInput
107
109
  // (channelId) falls through to the plain input below.
108
110
  case "KeywordInput":
109
- if (!B)
111
+ if (!E)
110
112
  break;
111
- return /* @__PURE__ */ k(D, { children: [
112
- /* @__PURE__ */ r(C, { color: i.content.primary, children: t.title }),
113
- /* @__PURE__ */ r(
114
- H,
113
+ return /* @__PURE__ */ S(P, { children: [
114
+ /* @__PURE__ */ o($, { color: s.content.primary, children: t.title }),
115
+ /* @__PURE__ */ o(
116
+ O,
115
117
  {
116
- nativeID: l,
117
- placeholder: t.hint ?? "",
118
- chips: W(e[t.key]),
119
- onChange: (o) => f(t.key, o.join(",")),
120
- hint: /* @__PURE__ */ r(E, { color: i.content.secondary, children: "Press Enter or comma to add multiple emails" })
118
+ variablesData: u,
119
+ onInsert: (n) => {
120
+ const x = A(r[t.key]);
121
+ x.includes(n) || d(t.key, [...x, n].join(","));
122
+ },
123
+ children: /* @__PURE__ */ o(
124
+ K,
125
+ {
126
+ nativeID: l,
127
+ placeholder: t.hint ?? "",
128
+ chips: A(r[t.key]),
129
+ onChange: (n) => d(t.key, n.join(",")),
130
+ hint: /* @__PURE__ */ o(R, { color: s.content.secondary, children: "Press Enter or comma to add multiple emails" })
131
+ }
132
+ )
121
133
  }
122
134
  )
123
135
  ] }, t.key);
124
136
  case "MultilineInput":
125
- return /* @__PURE__ */ r(
126
- j,
137
+ return /* @__PURE__ */ o(
138
+ M,
127
139
  {
128
140
  "data-test": l,
129
141
  label: t.title,
130
- value: String(e[t.key] ?? ""),
131
- onChange: (o) => f(t.key, o),
132
- maxLength: h.instructions,
142
+ value: String(r[t.key] ?? ""),
143
+ onChange: (n) => d(t.key, n),
144
+ maxLength: k.instructions,
133
145
  placeholder: t.hint ?? "",
134
- onImprove: m
146
+ onImprove: h,
147
+ variablesData: u
135
148
  },
136
149
  t.key
137
150
  );
138
151
  case "Switch":
139
- return /* @__PURE__ */ k(J, { children: [
140
- /* @__PURE__ */ k(K, { children: [
141
- /* @__PURE__ */ r(C, { color: i.content.primary, children: t.title }),
142
- t.hint && /* @__PURE__ */ r(E, { color: i.content.secondary, children: t.hint })
152
+ return /* @__PURE__ */ S(tt, { children: [
153
+ /* @__PURE__ */ S(et, { children: [
154
+ /* @__PURE__ */ o($, { color: s.content.primary, children: t.title }),
155
+ t.hint && /* @__PURE__ */ o(R, { color: s.content.secondary, children: t.hint })
143
156
  ] }),
144
- /* @__PURE__ */ r(
145
- Y,
157
+ /* @__PURE__ */ o(
158
+ G,
146
159
  {
147
160
  "data-test": l,
148
- value: !!e[t.key],
149
- onValueChange: async (o) => f(t.key, o)
161
+ value: !!r[t.key],
162
+ onValueChange: async (n) => d(t.key, n)
150
163
  }
151
164
  )
152
165
  ] }, t.key);
153
166
  }
154
- return /* @__PURE__ */ r(
155
- F,
167
+ const c = /* @__PURE__ */ o(
168
+ N,
156
169
  {
157
170
  "data-test": l,
158
171
  variant: "small",
159
172
  labelText: t.title,
160
173
  labelTextBold: !0,
161
174
  placeholder: t.hint ?? "",
162
- value: String(e[t.key] ?? ""),
163
- onChangeText: (o) => f(t.key, o)
175
+ value: String(r[t.key] ?? ""),
176
+ onChangeText: (n) => d(t.key, n)
177
+ }
178
+ );
179
+ return E ? /* @__PURE__ */ o(
180
+ O,
181
+ {
182
+ variablesData: u,
183
+ onInsert: (n, x) => {
184
+ const T = String(r[t.key] ?? ""), B = x ?? T.length;
185
+ d(
186
+ t.key,
187
+ `${T.slice(0, B)}${n}${T.slice(B)}`
188
+ );
189
+ },
190
+ children: c
164
191
  },
165
192
  t.key
166
- );
167
- }, b = V[n];
168
- return /* @__PURE__ */ r(
169
- P,
193
+ ) : /* @__PURE__ */ o(F.Fragment, { children: c }, t.key);
194
+ }, b = J[e];
195
+ return /* @__PURE__ */ o(
196
+ W,
170
197
  {
171
198
  header: b.title,
172
199
  closeOnEscapeKey: !1,
173
- zIndex: y,
174
- headerCustomComponent: /* @__PURE__ */ r(A, { title: b.title, subtitle: b.subtitle }),
200
+ zIndex: a,
201
+ headerCustomComponent: /* @__PURE__ */ o(H, { title: b.title, subtitle: b.subtitle }),
175
202
  hideCrossButton: !1,
176
203
  width: "431px",
177
- headerStyle: L,
178
- bodyStyle: R,
179
- onClose: c,
204
+ headerStyle: z,
205
+ bodyStyle: V,
206
+ onClose: p,
180
207
  saveButtonProps: {
181
208
  "data-test": "config-tool-save",
182
209
  buttonText: "Save",
183
210
  buttonType: "primary",
184
211
  size: "small",
185
- disabled: !T,
186
- isLoading: x,
187
- onClick: I
212
+ disabled: !_,
213
+ isLoading: f,
214
+ onClick: L
188
215
  },
189
216
  cancelButtonProps: {
190
217
  "data-test": "config-tool-cancel",
191
218
  buttonText: "Cancel",
192
219
  buttonType: "tertiaryGray",
193
220
  size: "small",
194
- onClick: c
221
+ onClick: p
195
222
  },
196
- children: v.map(_)
223
+ children: v.map(j)
197
224
  }
198
225
  );
199
- }, G = u.div`
226
+ }, U = y.div`
200
227
  display: flex;
201
228
  flex-direction: column;
202
229
  gap: 8px;
203
- `, N = u.input`
230
+ `, X = y.input`
204
231
  width: 100%;
205
232
  min-width: 0;
206
233
  box-sizing: border-box;
207
234
  height: 32px;
208
235
  padding: 0 8px;
209
- border: 1px solid ${i.stroke.primary};
236
+ border: 1px solid ${s.stroke.primary};
210
237
  border-radius: 4px;
211
238
  font-family: 'Inter', sans-serif;
212
239
  font-size: 14px;
213
- color: ${i.content.primary};
214
- background: ${i.surface.standard};
240
+ color: ${s.content.primary};
241
+ background: ${s.surface.standard};
215
242
  outline: none;
216
243
 
217
244
  &::placeholder {
218
- color: ${i.content.secondary};
245
+ color: ${s.content.secondary};
219
246
  }
220
247
 
221
248
  &:focus {
222
- border-color: ${i.stroke.brand};
249
+ border-color: ${s.stroke.brand};
223
250
  }
224
- `, q = u.div`
251
+ `, Z = y.div`
225
252
  display: flex;
226
253
  flex-wrap: wrap;
227
254
  gap: 6px;
228
- `, J = u.div`
255
+ `, tt = y.div`
229
256
  display: flex;
230
257
  align-items: center;
231
258
  justify-content: space-between;
232
259
  gap: 12px;
233
- `, K = u.div`
260
+ `, et = y.div`
234
261
  display: flex;
235
262
  flex-direction: column;
236
263
  gap: 4px;
237
264
  min-width: 0;
238
265
  `;
239
266
  export {
240
- pt as ConfigToolPanel
267
+ kt as ConfigToolPanel
241
268
  };
242
269
  //# sourceMappingURL=ConfigToolPanel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ConfigToolPanel.js","sources":["../../../../../src/components/agent-builder/components/ConfigToolPanel.tsx"],"sourcesContent":["import CrossIcon from '@src/assets/icons/cross.svg';\nimport React, { useState } from 'react';\nimport styled from 'styled-components';\nimport { Input } from '@src/components/input';\nimport { SideModal } from '@src/components/side-modal';\nimport { Switch } from '@src/components/switch';\nimport { Tag } from '@src/components/tag';\nimport { BodyCaption, TitleSmall } from '@src/components/TypographyStyle';\nimport { COLORS } from '@src/constants/Theme';\nimport {\n\tConfigToolConfig,\n\tConfigToolKey,\n\tParamField,\n\tParamsBlob,\n} from '../AgentBuilder.model';\nimport { FieldBlock } from '../AgentBuilder.styled';\nimport type { AgentCharLimits } from '../constants/charLimits';\nimport { AGENT_CHAR_LIMITS } from '../constants/charLimits';\nimport {\n\tDRAWER_BODY_STYLE,\n\tDRAWER_HEADER_STYLE,\n\tDrawerHeaderText,\n} from './DrawerHeaderText';\nimport { ToolInstructionsField } from './ToolInstructionsField';\n\n/** Header copy per shared-drawer tool. */\nconst TOOL_COPY: Record<ConfigToolKey, { title: string; subtitle: string }> = {\n\tsend_email: {\n\t\ttitle: 'Send Email',\n\t\tsubtitle:\n\t\t\t\"Notify someone by email when this agent can't continue. You pick the recipient, the AI drafts the message.\",\n\t},\n\tsend_slack_message: {\n\t\ttitle: 'Send Slack message',\n\t\tsubtitle:\n\t\t\t'Post a message to a Slack channel. You pick the channel, the AI composes the message from the conversation.',\n\t},\n};\n\ninterface ConfigToolPanelProps {\n\t/** Which tool this drawer configures (drives copy + persistence). */\n\ttoolKey: ConfigToolKey;\n\t/**\n\t * The backend template (`list-catalog` → params) for `toolKey`. The form is\n\t * DYNAMIC: exactly these fields render, in this order, each by its\n\t * `component` kind (KeywordInput | MultilineInput | Switch | fallback input).\n\t */\n\ttemplate: ParamsBlob;\n\tonClose: () => void;\n\t/** Persist the filled template. A pending promise shows the Save loader. */\n\tonSave: (config: ConfigToolConfig) => void | Promise<void>;\n\t/** Seed values when editing an existing tool. */\n\tinitial?: ConfigToolConfig;\n\t/** Optional \"Improve with AI\" for multiline fields. Omit to hide it. */\n\tonImprove?: (text: string) => Promise<string>;\n\tcharLimits?: AgentCharLimits;\n\t/** SideModal stacking order — raise it when opened over another drawer. */\n\tzIndex?: number;\n}\n\ninterface EmailChipsFieldProps {\n\tchips: string[];\n\tonChange: (next: string[]) => void;\n\tplaceholder: string;\n\tnativeID?: string;\n\t/** Optional helper caption shown between the input and the chips. */\n\thint?: React.ReactNode;\n}\n\n/**\n * Email entry field: type an address and press Enter / comma (or blur) to add\n * it. Added emails render as removable chips BELOW the input — not inside it.\n * Backspace on an empty input removes the last chip.\n */\nconst EmailChipsField: React.FC<EmailChipsFieldProps> = ({\n\tchips,\n\tonChange,\n\tplaceholder,\n\tnativeID,\n\thint,\n}) => {\n\tconst [buffer, setBuffer] = useState('');\n\n\tconst commit = () => {\n\t\tconst parts = buffer\n\t\t\t.split(',')\n\t\t\t.map((s) => s.trim())\n\t\t\t.filter(Boolean);\n\t\tif (parts.length) {\n\t\t\tonChange([...chips, ...parts.filter((p) => !chips.includes(p))]);\n\t\t}\n\t\tsetBuffer('');\n\t};\n\n\treturn (\n\t\t<ChipsFieldWrap>\n\t\t\t<EmailInputBox\n\t\t\t\tid={nativeID}\n\t\t\t\ttype=\"text\"\n\t\t\t\tplaceholder={placeholder}\n\t\t\t\tvalue={buffer}\n\t\t\t\tonChange={(e) => setBuffer(e.target.value)}\n\t\t\t\tonBlur={commit}\n\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\tif (e.key === 'Enter' || e.key === ',') {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tcommit();\n\t\t\t\t\t} else if (\n\t\t\t\t\t\te.key === 'Backspace' &&\n\t\t\t\t\t\tbuffer === '' &&\n\t\t\t\t\t\tchips.length > 0\n\t\t\t\t\t) {\n\t\t\t\t\t\tonChange(chips.slice(0, -1));\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t/>\n\t\t\t{hint}\n\t\t\t{chips.length > 0 && (\n\t\t\t\t<ChipRow>\n\t\t\t\t\t{chips.map((email, i) => (\n\t\t\t\t\t\t<Tag\n\t\t\t\t\t\t\tkey={`${email}-${i}`}\n\t\t\t\t\t\t\ttagText={email}\n\t\t\t\t\t\t\ttheme=\"light\"\n\t\t\t\t\t\t\ttype=\"neutral\"\n\t\t\t\t\t\t\tvariant=\"regular\"\n\t\t\t\t\t\t\tTrailingIcon={CrossIcon}\n\t\t\t\t\t\t\tonTrailingIconClicked={() =>\n\t\t\t\t\t\t\t\tonChange(chips.filter((_, idx) => idx !== i))\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</ChipRow>\n\t\t\t)}\n\t\t</ChipsFieldWrap>\n\t);\n};\n\n/** Field values keyed by param key (the editable part of a {@link ParamsBlob}). */\ntype ParamValues = Record<string, string | boolean | number | object>;\n\nconst seedValues = (\n\ttemplate: ParamsBlob,\n\tinitial?: ConfigToolConfig,\n): ParamValues => {\n\tconst values: ParamValues = {};\n\tObject.keys(template).forEach((key) => {\n\t\tvalues[key] = initial?.params[key]?.value ?? template[key].value;\n\t});\n\treturn values;\n};\n\n/** Chips ↔ the string value KeywordInput fields carry (comma-separated). */\nconst toChips = (value: unknown): string[] =>\n\tString(value ?? '')\n\t\t.split(',')\n\t\t.map((s) => s.trim())\n\t\t.filter(Boolean);\n\n/**\n * Shared right-side drawer for the params-driven configurable tools (email /\n * Slack). Fully backend-driven: it renders the template fields by their\n * `component` kind and returns the same blob with values filled in. KeywordInput\n * renders as multi-value email chips only for `send_email`; every other tool\n * gets a plain single-line input. Mount it fresh per open (key it) so `initial`\n * seeds the state. Built on the shared `SideModal` shell.\n */\nexport const ConfigToolPanel: React.FC<ConfigToolPanelProps> = ({\n\ttoolKey,\n\ttemplate,\n\tonClose,\n\tonSave,\n\tinitial,\n\tonImprove,\n\tcharLimits = AGENT_CHAR_LIMITS,\n\tzIndex,\n}) => {\n\tconst [values, setValues] = useState<ParamValues>(() =>\n\t\tseedValues(template, initial),\n\t);\n\tconst [saving, setSaving] = useState(false);\n\n\tconst fields = Object.values(template);\n\tconst isEmail = toolKey === 'send_email';\n\tconst setValue = (key: string, value: string | boolean | number | object) =>\n\t\tsetValues((prev) => ({ ...prev, [key]: value }));\n\n\tconst canSave = fields.every(\n\t\t(f) => !f.required || String(values[f.key] ?? '').trim() !== '',\n\t);\n\n\tconst handleSave = async () => {\n\t\tif (!canSave || saving) {\n\t\t\treturn;\n\t\t}\n\t\tconst params: ParamsBlob = {};\n\t\tfields.forEach((f) => {\n\t\t\t// Save the FULL descriptor with only `value` changed — the backend\n\t\t\t// infers each field's type from `component` and reads `required`.\n\t\t\tparams[f.key] = { ...f, value: values[f.key] };\n\t\t});\n\t\tconst config: ConfigToolConfig = {\n\t\t\tid: initial?.id ?? `${toolKey}_${Date.now().toString(36)}`,\n\t\t\ttool_key: toolKey,\n\t\t\tparams,\n\t\t};\n\t\tconst result = onSave(config);\n\t\tif (result && typeof (result as Promise<void>).then === 'function') {\n\t\t\tsetSaving(true);\n\t\t\ttry {\n\t\t\t\tawait result;\n\t\t\t} finally {\n\t\t\t\tsetSaving(false);\n\t\t\t}\n\t\t}\n\t};\n\n\tconst renderField = (field: ParamField) => {\n\t\tconst testId = `config-tool-${field.key.toLowerCase()}`;\n\t\tswitch (field.component) {\n\t\t\t// Multi-value email chips — only for the email tool. Slack's KeywordInput\n\t\t\t// (channelId) falls through to the plain input below.\n\t\t\tcase 'KeywordInput':\n\t\t\t\tif (!isEmail) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn (\n\t\t\t\t\t<FieldBlock key={field.key}>\n\t\t\t\t\t\t<TitleSmall color={COLORS.content.primary}>\n\t\t\t\t\t\t\t{field.title}\n\t\t\t\t\t\t</TitleSmall>\n\t\t\t\t\t\t<EmailChipsField\n\t\t\t\t\t\t\tnativeID={testId}\n\t\t\t\t\t\t\tplaceholder={field.hint ?? ''}\n\t\t\t\t\t\t\tchips={toChips(values[field.key])}\n\t\t\t\t\t\t\tonChange={(chips) => setValue(field.key, chips.join(','))}\n\t\t\t\t\t\t\thint={\n\t\t\t\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t\t\t\t\tPress Enter or comma to add multiple emails\n\t\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</FieldBlock>\n\t\t\t\t);\n\t\t\tcase 'MultilineInput':\n\t\t\t\treturn (\n\t\t\t\t\t<ToolInstructionsField\n\t\t\t\t\t\tkey={field.key}\n\t\t\t\t\t\tdata-test={testId}\n\t\t\t\t\t\tlabel={field.title}\n\t\t\t\t\t\tvalue={String(values[field.key] ?? '')}\n\t\t\t\t\t\tonChange={(text) => setValue(field.key, text)}\n\t\t\t\t\t\tmaxLength={charLimits.instructions}\n\t\t\t\t\t\tplaceholder={field.hint ?? ''}\n\t\t\t\t\t\tonImprove={onImprove}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\tcase 'Switch':\n\t\t\t\treturn (\n\t\t\t\t\t<SwitchRow key={field.key}>\n\t\t\t\t\t\t<SwitchText>\n\t\t\t\t\t\t\t<TitleSmall color={COLORS.content.primary}>\n\t\t\t\t\t\t\t\t{field.title}\n\t\t\t\t\t\t\t</TitleSmall>\n\t\t\t\t\t\t\t{field.hint && (\n\t\t\t\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t\t\t\t\t{field.hint}\n\t\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</SwitchText>\n\t\t\t\t\t\t<Switch\n\t\t\t\t\t\t\tdata-test={testId}\n\t\t\t\t\t\t\tvalue={Boolean(values[field.key])}\n\t\t\t\t\t\t\tonValueChange={async (next) => setValue(field.key, next)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</SwitchRow>\n\t\t\t\t);\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\treturn (\n\t\t\t<Input\n\t\t\t\tkey={field.key}\n\t\t\t\tdata-test={testId}\n\t\t\t\tvariant=\"small\"\n\t\t\t\tlabelText={field.title}\n\t\t\t\tlabelTextBold\n\t\t\t\tplaceholder={field.hint ?? ''}\n\t\t\t\tvalue={String(values[field.key] ?? '')}\n\t\t\t\tonChangeText={(text) => setValue(field.key, text)}\n\t\t\t/>\n\t\t);\n\t};\n\n\tconst copy = TOOL_COPY[toolKey];\n\n\treturn (\n\t\t<SideModal\n\t\t\theader={copy.title}\n\t\t\tcloseOnEscapeKey={false}\n\t\t\tzIndex={zIndex}\n\t\t\theaderCustomComponent={\n\t\t\t\t<DrawerHeaderText title={copy.title} subtitle={copy.subtitle} />\n\t\t\t}\n\t\t\thideCrossButton={false}\n\t\t\twidth=\"431px\"\n\t\t\theaderStyle={DRAWER_HEADER_STYLE}\n\t\t\tbodyStyle={DRAWER_BODY_STYLE}\n\t\t\tonClose={onClose}\n\t\t\tsaveButtonProps={{\n\t\t\t\t'data-test': 'config-tool-save',\n\t\t\t\tbuttonText: 'Save',\n\t\t\t\tbuttonType: 'primary',\n\t\t\t\tsize: 'small',\n\t\t\t\tdisabled: !canSave,\n\t\t\t\tisLoading: saving,\n\t\t\t\tonClick: handleSave,\n\t\t\t}}\n\t\t\tcancelButtonProps={{\n\t\t\t\t'data-test': 'config-tool-cancel',\n\t\t\t\tbuttonText: 'Cancel',\n\t\t\t\tbuttonType: 'tertiaryGray',\n\t\t\t\tsize: 'small',\n\t\t\t\tonClick: onClose,\n\t\t\t}}\n\t\t>\n\t\t\t{fields.map(renderField)}\n\t\t</SideModal>\n\t);\n};\n\nconst ChipsFieldWrap = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n`;\n\nconst EmailInputBox = styled.input`\n\twidth: 100%;\n\tmin-width: 0;\n\tbox-sizing: border-box;\n\theight: 32px;\n\tpadding: 0 8px;\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 4px;\n\tfont-family: 'Inter', sans-serif;\n\tfont-size: 14px;\n\tcolor: ${COLORS.content.primary};\n\tbackground: ${COLORS.surface.standard};\n\toutline: none;\n\n\t&::placeholder {\n\t\tcolor: ${COLORS.content.secondary};\n\t}\n\n\t&:focus {\n\t\tborder-color: ${COLORS.stroke.brand};\n\t}\n`;\n\nconst ChipRow = styled.div`\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 6px;\n`;\n\nconst SwitchRow = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: space-between;\n\tgap: 12px;\n`;\n\nconst SwitchText = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n\tmin-width: 0;\n`;\n"],"names":["TOOL_COPY","EmailChipsField","chips","onChange","placeholder","nativeID","hint","buffer","setBuffer","useState","commit","parts","p","ChipsFieldWrap","jsx","EmailInputBox","ChipRow","email","i","Tag","CrossIcon","_","idx","seedValues","template","initial","values","key","toChips","value","s","ConfigToolPanel","toolKey","onClose","onSave","onImprove","charLimits","AGENT_CHAR_LIMITS","zIndex","setValues","saving","setSaving","fields","isEmail","setValue","prev","canSave","f","handleSave","params","config","result","renderField","field","testId","FieldBlock","TitleSmall","COLORS","BodyCaption","ToolInstructionsField","text","SwitchRow","jsxs","SwitchText","Switch","next","Input","copy","SideModal","DrawerHeaderText","DRAWER_HEADER_STYLE","DRAWER_BODY_STYLE","styled"],"mappings":"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"}
1
+ {"version":3,"file":"ConfigToolPanel.js","sources":["../../../../../src/components/agent-builder/components/ConfigToolPanel.tsx"],"sourcesContent":["import CrossIcon from '@src/assets/icons/cross.svg';\nimport React, { useState } from 'react';\nimport styled from 'styled-components';\nimport { Input } from '@src/components/input';\nimport { SideModal } from '@src/components/side-modal';\nimport { Switch } from '@src/components/switch';\nimport { Tag } from '@src/components/tag';\nimport { BodyCaption, TitleSmall } from '@src/components/TypographyStyle';\nimport { COLORS } from '@src/constants/Theme';\nimport type { VariableListInterfaceV3 } from '../../variable-picker-v3/model';\nimport {\n\tConfigToolConfig,\n\tConfigToolKey,\n\tParamField,\n\tParamsBlob,\n} from '../AgentBuilder.model';\nimport { FieldBlock } from '../AgentBuilder.styled';\nimport type { AgentCharLimits } from '../constants/charLimits';\nimport { AGENT_CHAR_LIMITS } from '../constants/charLimits';\nimport {\n\tDRAWER_BODY_STYLE,\n\tDRAWER_HEADER_STYLE,\n\tDrawerHeaderText,\n} from './DrawerHeaderText';\nimport { ToolInstructionsField } from './ToolInstructionsField';\nimport { VariableTriggerArea } from './VariableTriggerArea';\n\n/** Header copy per shared-drawer tool. */\nconst TOOL_COPY: Record<ConfigToolKey, { title: string; subtitle: string }> = {\n\tsend_email: {\n\t\ttitle: 'Send Email',\n\t\tsubtitle:\n\t\t\t\"Notify someone by email when this agent can't continue. You pick the recipient, the AI drafts the message.\",\n\t},\n\tsend_slack_message: {\n\t\ttitle: 'Send Slack message',\n\t\tsubtitle:\n\t\t\t'Post a message to a Slack channel. You pick the channel, the AI composes the message from the conversation.',\n\t},\n};\n\ninterface ConfigToolPanelProps {\n\t/** Which tool this drawer configures (drives copy + persistence). */\n\ttoolKey: ConfigToolKey;\n\t/**\n\t * The backend template (`list-catalog` → params) for `toolKey`. The form is\n\t * DYNAMIC: exactly these fields render, in this order, each by its\n\t * `component` kind (KeywordInput | MultilineInput | Switch | fallback input).\n\t */\n\ttemplate: ParamsBlob;\n\tonClose: () => void;\n\t/** Persist the filled template. A pending promise shows the Save loader. */\n\tonSave: (config: ConfigToolConfig) => void | Promise<void>;\n\t/** Seed values when editing an existing tool. */\n\tinitial?: ConfigToolConfig;\n\t/** Optional \"Improve with AI\" for multiline fields. Omit to hide it. */\n\tonImprove?: (text: string) => Promise<string>;\n\tcharLimits?: AgentCharLimits;\n\t/**\n\t * Variable catalog for the `@` trigger. When non-empty, `@` in the email\n\t * tool's Subject / Send To / Reply To / CC opens the variable picker\n\t * directly, and Message Instructions upgrades to the variables-only mention\n\t * editor. Absent → the drawer behaves exactly as before.\n\t */\n\tvariablesData?: VariableListInterfaceV3[];\n\t/** SideModal stacking order — raise it when opened over another drawer. */\n\tzIndex?: number;\n}\n\ninterface EmailChipsFieldProps {\n\tchips: string[];\n\tonChange: (next: string[]) => void;\n\tplaceholder: string;\n\tnativeID?: string;\n\t/** Optional helper caption shown between the input and the chips. */\n\thint?: React.ReactNode;\n}\n\n/**\n * Email entry field: type an address and press Enter / comma (or blur) to add\n * it. Added emails render as removable chips BELOW the input — not inside it.\n * Backspace on an empty input removes the last chip.\n */\nconst EmailChipsField: React.FC<EmailChipsFieldProps> = ({\n\tchips,\n\tonChange,\n\tplaceholder,\n\tnativeID,\n\thint,\n}) => {\n\tconst [buffer, setBuffer] = useState('');\n\n\tconst commit = () => {\n\t\tconst parts = buffer\n\t\t\t.split(',')\n\t\t\t.map((s) => s.trim())\n\t\t\t.filter(Boolean);\n\t\tif (parts.length) {\n\t\t\tonChange([...chips, ...parts.filter((p) => !chips.includes(p))]);\n\t\t}\n\t\tsetBuffer('');\n\t};\n\n\treturn (\n\t\t<ChipsFieldWrap>\n\t\t\t<EmailInputBox\n\t\t\t\tid={nativeID}\n\t\t\t\ttype=\"text\"\n\t\t\t\tplaceholder={placeholder}\n\t\t\t\tvalue={buffer}\n\t\t\t\tonChange={(e) => setBuffer(e.target.value)}\n\t\t\t\tonBlur={commit}\n\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\tif (e.key === 'Enter' || e.key === ',') {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tcommit();\n\t\t\t\t\t} else if (\n\t\t\t\t\t\te.key === 'Backspace' &&\n\t\t\t\t\t\tbuffer === '' &&\n\t\t\t\t\t\tchips.length > 0\n\t\t\t\t\t) {\n\t\t\t\t\t\tonChange(chips.slice(0, -1));\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t/>\n\t\t\t{hint}\n\t\t\t{chips.length > 0 && (\n\t\t\t\t<ChipRow>\n\t\t\t\t\t{chips.map((email, i) => (\n\t\t\t\t\t\t<Tag\n\t\t\t\t\t\t\tkey={`${email}-${i}`}\n\t\t\t\t\t\t\ttagText={email}\n\t\t\t\t\t\t\ttheme=\"light\"\n\t\t\t\t\t\t\ttype=\"neutral\"\n\t\t\t\t\t\t\tvariant=\"regular\"\n\t\t\t\t\t\t\tTrailingIcon={CrossIcon}\n\t\t\t\t\t\t\tonTrailingIconClicked={() =>\n\t\t\t\t\t\t\t\tonChange(chips.filter((_, idx) => idx !== i))\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</ChipRow>\n\t\t\t)}\n\t\t</ChipsFieldWrap>\n\t);\n};\n\n/** Field values keyed by param key (the editable part of a {@link ParamsBlob}). */\ntype ParamValues = Record<string, string | boolean | number | object>;\n\nconst seedValues = (\n\ttemplate: ParamsBlob,\n\tinitial?: ConfigToolConfig,\n): ParamValues => {\n\tconst values: ParamValues = {};\n\tObject.keys(template).forEach((key) => {\n\t\tvalues[key] = initial?.params[key]?.value ?? template[key].value;\n\t});\n\treturn values;\n};\n\n/** Chips ↔ the string value KeywordInput fields carry (comma-separated). */\nconst toChips = (value: unknown): string[] =>\n\tString(value ?? '')\n\t\t.split(',')\n\t\t.map((s) => s.trim())\n\t\t.filter(Boolean);\n\n/**\n * Shared right-side drawer for the params-driven configurable tools (email /\n * Slack). Fully backend-driven: it renders the template fields by their\n * `component` kind and returns the same blob with values filled in. KeywordInput\n * renders as multi-value email chips only for `send_email`; every other tool\n * gets a plain single-line input. Mount it fresh per open (key it) so `initial`\n * seeds the state. Built on the shared `SideModal` shell.\n */\nexport const ConfigToolPanel: React.FC<ConfigToolPanelProps> = ({\n\ttoolKey,\n\ttemplate,\n\tonClose,\n\tonSave,\n\tinitial,\n\tonImprove,\n\tcharLimits = AGENT_CHAR_LIMITS,\n\tvariablesData,\n\tzIndex,\n}) => {\n\tconst [values, setValues] = useState<ParamValues>(() =>\n\t\tseedValues(template, initial),\n\t);\n\tconst [saving, setSaving] = useState(false);\n\n\tconst fields = Object.values(template);\n\tconst isEmail = toolKey === 'send_email';\n\tconst setValue = (key: string, value: string | boolean | number | object) =>\n\t\tsetValues((prev) => ({ ...prev, [key]: value }));\n\n\tconst canSave = fields.every(\n\t\t(f) => !f.required || String(values[f.key] ?? '').trim() !== '',\n\t);\n\n\tconst handleSave = async () => {\n\t\tif (!canSave || saving) {\n\t\t\treturn;\n\t\t}\n\t\tconst params: ParamsBlob = {};\n\t\tfields.forEach((f) => {\n\t\t\t// Save the FULL descriptor with only `value` changed — the backend\n\t\t\t// infers each field's type from `component` and reads `required`.\n\t\t\tparams[f.key] = { ...f, value: values[f.key] };\n\t\t});\n\t\tconst config: ConfigToolConfig = {\n\t\t\tid: initial?.id ?? `${toolKey}_${Date.now().toString(36)}`,\n\t\t\ttool_key: toolKey,\n\t\t\tparams,\n\t\t};\n\t\tconst result = onSave(config);\n\t\tif (result && typeof (result as Promise<void>).then === 'function') {\n\t\t\tsetSaving(true);\n\t\t\ttry {\n\t\t\t\tawait result;\n\t\t\t} finally {\n\t\t\t\tsetSaving(false);\n\t\t\t}\n\t\t}\n\t};\n\n\tconst renderField = (field: ParamField) => {\n\t\tconst testId = `config-tool-${field.key.toLowerCase()}`;\n\t\tswitch (field.component) {\n\t\t\t// Multi-value email chips — only for the email tool. Slack's KeywordInput\n\t\t\t// (channelId) falls through to the plain input below.\n\t\t\tcase 'KeywordInput':\n\t\t\t\tif (!isEmail) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn (\n\t\t\t\t\t<FieldBlock key={field.key}>\n\t\t\t\t\t\t<TitleSmall color={COLORS.content.primary}>\n\t\t\t\t\t\t\t{field.title}\n\t\t\t\t\t\t</TitleSmall>\n\t\t\t\t\t\t{/* `@` at the start of an entry picks a variable (added as a\n\t\t\t\t\t\t chip); `@` inside an address types normally. */}\n\t\t\t\t\t\t<VariableTriggerArea\n\t\t\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\t\t\tonInsert={(token) => {\n\t\t\t\t\t\t\t\tconst chips = toChips(values[field.key]);\n\t\t\t\t\t\t\t\tif (!chips.includes(token)) {\n\t\t\t\t\t\t\t\t\tsetValue(field.key, [...chips, token].join(','));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<EmailChipsField\n\t\t\t\t\t\t\t\tnativeID={testId}\n\t\t\t\t\t\t\t\tplaceholder={field.hint ?? ''}\n\t\t\t\t\t\t\t\tchips={toChips(values[field.key])}\n\t\t\t\t\t\t\t\tonChange={(chips) => setValue(field.key, chips.join(','))}\n\t\t\t\t\t\t\t\thint={\n\t\t\t\t\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t\t\t\t\t\tPress Enter or comma to add multiple emails\n\t\t\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</VariableTriggerArea>\n\t\t\t\t\t</FieldBlock>\n\t\t\t\t);\n\t\t\tcase 'MultilineInput':\n\t\t\t\treturn (\n\t\t\t\t\t<ToolInstructionsField\n\t\t\t\t\t\tkey={field.key}\n\t\t\t\t\t\tdata-test={testId}\n\t\t\t\t\t\tlabel={field.title}\n\t\t\t\t\t\tvalue={String(values[field.key] ?? '')}\n\t\t\t\t\t\tonChange={(text) => setValue(field.key, text)}\n\t\t\t\t\t\tmaxLength={charLimits.instructions}\n\t\t\t\t\t\tplaceholder={field.hint ?? ''}\n\t\t\t\t\t\tonImprove={onImprove}\n\t\t\t\t\t\tvariablesData={variablesData}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\tcase 'Switch':\n\t\t\t\treturn (\n\t\t\t\t\t<SwitchRow key={field.key}>\n\t\t\t\t\t\t<SwitchText>\n\t\t\t\t\t\t\t<TitleSmall color={COLORS.content.primary}>\n\t\t\t\t\t\t\t\t{field.title}\n\t\t\t\t\t\t\t</TitleSmall>\n\t\t\t\t\t\t\t{field.hint && (\n\t\t\t\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t\t\t\t\t{field.hint}\n\t\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</SwitchText>\n\t\t\t\t\t\t<Switch\n\t\t\t\t\t\t\tdata-test={testId}\n\t\t\t\t\t\t\tvalue={Boolean(values[field.key])}\n\t\t\t\t\t\t\tonValueChange={async (next) => setValue(field.key, next)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</SwitchRow>\n\t\t\t\t);\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\tconst plainInput = (\n\t\t\t<Input\n\t\t\t\tdata-test={testId}\n\t\t\t\tvariant=\"small\"\n\t\t\t\tlabelText={field.title}\n\t\t\t\tlabelTextBold\n\t\t\t\tplaceholder={field.hint ?? ''}\n\t\t\t\tvalue={String(values[field.key] ?? '')}\n\t\t\t\tonChangeText={(text) => setValue(field.key, text)}\n\t\t\t/>\n\t\t);\n\t\t// `@` variables only in the email tool's free-text fields (Subject) —\n\t\t// a Slack channel id can't hold a variable.\n\t\tif (!isEmail) {\n\t\t\treturn <React.Fragment key={field.key}>{plainInput}</React.Fragment>;\n\t\t}\n\t\treturn (\n\t\t\t<VariableTriggerArea\n\t\t\t\tkey={field.key}\n\t\t\t\tvariablesData={variablesData}\n\t\t\t\tonInsert={(token, caret) => {\n\t\t\t\t\tconst current = String(values[field.key] ?? '');\n\t\t\t\t\tconst at = caret ?? current.length;\n\t\t\t\t\tsetValue(\n\t\t\t\t\t\tfield.key,\n\t\t\t\t\t\t`${current.slice(0, at)}${token}${current.slice(at)}`,\n\t\t\t\t\t);\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{plainInput}\n\t\t\t</VariableTriggerArea>\n\t\t);\n\t};\n\n\tconst copy = TOOL_COPY[toolKey];\n\n\treturn (\n\t\t<SideModal\n\t\t\theader={copy.title}\n\t\t\tcloseOnEscapeKey={false}\n\t\t\tzIndex={zIndex}\n\t\t\theaderCustomComponent={\n\t\t\t\t<DrawerHeaderText title={copy.title} subtitle={copy.subtitle} />\n\t\t\t}\n\t\t\thideCrossButton={false}\n\t\t\twidth=\"431px\"\n\t\t\theaderStyle={DRAWER_HEADER_STYLE}\n\t\t\tbodyStyle={DRAWER_BODY_STYLE}\n\t\t\tonClose={onClose}\n\t\t\tsaveButtonProps={{\n\t\t\t\t'data-test': 'config-tool-save',\n\t\t\t\tbuttonText: 'Save',\n\t\t\t\tbuttonType: 'primary',\n\t\t\t\tsize: 'small',\n\t\t\t\tdisabled: !canSave,\n\t\t\t\tisLoading: saving,\n\t\t\t\tonClick: handleSave,\n\t\t\t}}\n\t\t\tcancelButtonProps={{\n\t\t\t\t'data-test': 'config-tool-cancel',\n\t\t\t\tbuttonText: 'Cancel',\n\t\t\t\tbuttonType: 'tertiaryGray',\n\t\t\t\tsize: 'small',\n\t\t\t\tonClick: onClose,\n\t\t\t}}\n\t\t>\n\t\t\t{fields.map(renderField)}\n\t\t</SideModal>\n\t);\n};\n\nconst ChipsFieldWrap = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n`;\n\nconst EmailInputBox = styled.input`\n\twidth: 100%;\n\tmin-width: 0;\n\tbox-sizing: border-box;\n\theight: 32px;\n\tpadding: 0 8px;\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 4px;\n\tfont-family: 'Inter', sans-serif;\n\tfont-size: 14px;\n\tcolor: ${COLORS.content.primary};\n\tbackground: ${COLORS.surface.standard};\n\toutline: none;\n\n\t&::placeholder {\n\t\tcolor: ${COLORS.content.secondary};\n\t}\n\n\t&:focus {\n\t\tborder-color: ${COLORS.stroke.brand};\n\t}\n`;\n\nconst ChipRow = styled.div`\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 6px;\n`;\n\nconst SwitchRow = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: space-between;\n\tgap: 12px;\n`;\n\nconst SwitchText = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n\tmin-width: 0;\n`;\n"],"names":["TOOL_COPY","EmailChipsField","chips","onChange","placeholder","nativeID","hint","buffer","setBuffer","useState","commit","parts","s","p","ChipsFieldWrap","jsx","EmailInputBox","e","ChipRow","email","i","Tag","CrossIcon","_","idx","seedValues","template","initial","values","key","toChips","value","ConfigToolPanel","toolKey","onClose","onSave","onImprove","charLimits","AGENT_CHAR_LIMITS","variablesData","zIndex","setValues","saving","setSaving","fields","isEmail","setValue","prev","canSave","f","handleSave","params","config","result","renderField","field","testId","FieldBlock","TitleSmall","COLORS","VariableTriggerArea","token","BodyCaption","ToolInstructionsField","text","SwitchRow","jsxs","SwitchText","Switch","next","plainInput","Input","caret","current","at","React","copy","SideModal","DrawerHeaderText","DRAWER_HEADER_STYLE","DRAWER_BODY_STYLE","styled"],"mappings":"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"}