@ai-group/chat-sdk 3.7.1-alpha9 → 3.7.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 (84) hide show
  1. package/dist/cjs/components/XAdkChatbot/styles.js +8 -1
  2. package/dist/cjs/components/XAdkChatbot/styles.js.map +2 -2
  3. package/dist/cjs/components/XAdkProvider/compound/DefaultLayout.js +17 -50
  4. package/dist/cjs/components/XAdkProvider/compound/DefaultLayout.js.map +2 -2
  5. package/dist/cjs/components/XAdkProvider/compound/Sender.d.ts +3 -2
  6. package/dist/cjs/components/XAdkProvider/compound/Sender.js +81 -4
  7. package/dist/cjs/components/XAdkProvider/compound/Sender.js.map +3 -3
  8. package/dist/cjs/components/XAdkProvider/context/DefaultLayoutContext.d.ts +9 -0
  9. package/dist/cjs/components/XAdkProvider/context/DefaultLayoutContext.js +34 -0
  10. package/dist/cjs/components/XAdkProvider/context/DefaultLayoutContext.js.map +7 -0
  11. package/dist/cjs/components/XAdkProvider/context/index.d.ts +5 -4
  12. package/dist/cjs/components/XAdkProvider/context/index.js +3 -1
  13. package/dist/cjs/components/XAdkProvider/context/index.js.map +2 -2
  14. package/dist/cjs/components/XAdkSender/InlineTagInput.d.ts +4 -0
  15. package/dist/cjs/components/XAdkSender/InlineTagInput.js +28 -1
  16. package/dist/cjs/components/XAdkSender/InlineTagInput.js.map +2 -2
  17. package/dist/cjs/components/XAdkSender/{QuickList.d.ts → InputSuggestionList.d.ts} +4 -3
  18. package/dist/cjs/components/XAdkSender/{QuickList.js → InputSuggestionList.js} +55 -30
  19. package/dist/cjs/components/XAdkSender/InputSuggestionList.js.map +7 -0
  20. package/dist/cjs/components/XAdkSender/index.js +35 -13
  21. package/dist/cjs/components/XAdkSender/index.js.map +3 -3
  22. package/dist/cjs/components/XAdkSender/styles.js +13 -1
  23. package/dist/cjs/components/XAdkSender/styles.js.map +2 -2
  24. package/dist/cjs/components/XAiConversations/index.js +1 -1
  25. package/dist/cjs/components/XAiConversations/index.js.map +2 -2
  26. package/dist/cjs/components/XAiConversations/styles.js +11 -1
  27. package/dist/cjs/components/XAiConversations/styles.js.map +2 -2
  28. package/dist/cjs/index.d.ts +3 -3
  29. package/dist/cjs/index.js +5 -1
  30. package/dist/cjs/index.js.map +2 -2
  31. package/dist/cjs/presets/xgroup/index.d.ts +1 -0
  32. package/dist/cjs/presets/xgroup/index.js +2 -0
  33. package/dist/cjs/presets/xgroup/index.js.map +2 -2
  34. package/dist/cjs/presets/xgroup/knowledgeReference.js +3 -1
  35. package/dist/cjs/presets/xgroup/knowledgeReference.js.map +2 -2
  36. package/dist/cjs/presets/xgroup/webReference.d.ts +10 -0
  37. package/dist/cjs/presets/xgroup/webReference.js +85 -0
  38. package/dist/cjs/presets/xgroup/webReference.js.map +7 -0
  39. package/dist/cjs/types/XAdkSender.d.ts +4 -0
  40. package/dist/cjs/types/XAdkSender.js.map +1 -1
  41. package/dist/esm/components/XAdkChatbot/styles.js +3 -3
  42. package/dist/esm/components/XAdkChatbot/styles.js.map +1 -1
  43. package/dist/esm/components/XAdkProvider/compound/DefaultLayout.js +16 -41
  44. package/dist/esm/components/XAdkProvider/compound/DefaultLayout.js.map +1 -1
  45. package/dist/esm/components/XAdkProvider/compound/Sender.d.ts +3 -2
  46. package/dist/esm/components/XAdkProvider/compound/Sender.js +70 -7
  47. package/dist/esm/components/XAdkProvider/compound/Sender.js.map +1 -1
  48. package/dist/esm/components/XAdkProvider/context/DefaultLayoutContext.d.ts +9 -0
  49. package/dist/esm/components/XAdkProvider/context/DefaultLayoutContext.js +9 -0
  50. package/dist/esm/components/XAdkProvider/context/DefaultLayoutContext.js.map +1 -0
  51. package/dist/esm/components/XAdkProvider/context/index.d.ts +5 -4
  52. package/dist/esm/components/XAdkProvider/context/index.js +1 -0
  53. package/dist/esm/components/XAdkProvider/context/index.js.map +1 -1
  54. package/dist/esm/components/XAdkSender/InlineTagInput.d.ts +4 -0
  55. package/dist/esm/components/XAdkSender/InlineTagInput.js +26 -7
  56. package/dist/esm/components/XAdkSender/InlineTagInput.js.map +1 -1
  57. package/dist/esm/components/XAdkSender/{QuickList.d.ts → InputSuggestionList.d.ts} +4 -3
  58. package/dist/esm/components/XAdkSender/{QuickList.js → InputSuggestionList.js} +53 -28
  59. package/dist/esm/components/XAdkSender/InputSuggestionList.js.map +1 -0
  60. package/dist/esm/components/XAdkSender/index.js +39 -18
  61. package/dist/esm/components/XAdkSender/index.js.map +1 -1
  62. package/dist/esm/components/XAdkSender/styles.js +2 -2
  63. package/dist/esm/components/XAdkSender/styles.js.map +1 -1
  64. package/dist/esm/components/XAiConversations/index.js +2 -1
  65. package/dist/esm/components/XAiConversations/index.js.map +1 -1
  66. package/dist/esm/components/XAiConversations/styles.js +3 -3
  67. package/dist/esm/components/XAiConversations/styles.js.map +1 -1
  68. package/dist/esm/index.d.ts +3 -3
  69. package/dist/esm/index.js +2 -2
  70. package/dist/esm/index.js.map +1 -1
  71. package/dist/esm/presets/xgroup/index.d.ts +1 -0
  72. package/dist/esm/presets/xgroup/index.js +1 -0
  73. package/dist/esm/presets/xgroup/index.js.map +1 -1
  74. package/dist/esm/presets/xgroup/knowledgeReference.js +2 -1
  75. package/dist/esm/presets/xgroup/knowledgeReference.js.map +1 -1
  76. package/dist/esm/presets/xgroup/webReference.d.ts +10 -0
  77. package/dist/esm/presets/xgroup/webReference.js +46 -0
  78. package/dist/esm/presets/xgroup/webReference.js.map +1 -0
  79. package/dist/esm/types/XAdkSender.d.ts +4 -0
  80. package/dist/esm/types/XAdkSender.js.map +1 -1
  81. package/dist/umd/chat-sdk.min.js +1 -1
  82. package/package.json +1 -1
  83. package/dist/cjs/components/XAdkSender/QuickList.js.map +0 -7
  84. package/dist/esm/components/XAdkSender/QuickList.js.map +0 -1
@@ -81,6 +81,8 @@ var useStyles = (0, import_common.withBasicStyles)(() => ({
81
81
  userMsg: import_css.css`
82
82
  display: flex;
83
83
  justify-content: flex-end;
84
+ width: 100%;
85
+ min-width: 0;
84
86
  margin-bottom: 24px;
85
87
  `,
86
88
  userContainer: import_css.css`
@@ -88,15 +90,20 @@ var useStyles = (0, import_common.withBasicStyles)(() => ({
88
90
  flex-direction: column;
89
91
  justify-content: flex-end;
90
92
  align-items: flex-end;
93
+ min-width: 0;
94
+ max-width: 100%;
91
95
  `,
92
96
  card: import_css.css`
93
97
  display: inline-block;
98
+ box-sizing: border-box;
99
+ min-width: 0;
94
100
  padding: 12px 16px;
95
101
  background: #d5e3ff;
96
102
  border-radius: 12px;
97
103
  max-width: 100%;
98
104
  white-space: pre-line;
99
- word-break: break-all;
105
+ overflow-wrap: anywhere;
106
+ word-break: break-word;
100
107
  `,
101
108
  botMsg: import_css.css`
102
109
  margin-bottom: 12px;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/components/XAdkChatbot/styles.tsx"],
4
- "sourcesContent": ["import { css } from \"@emotion/css\";\nimport { withBasicStyles } from \"@/styles/common\";\n\nexport const useStyles = withBasicStyles(() => ({\n wrapper: css`\n padding: 0 16px;\n min-height: 300px;\n height: 100%;\n border-radius: 8px;\n display: flex;\n flex-direction: column;\n\n .x-markdown {\n --margin-ul-ol: 0 0 1em 1em;\n\n code {\n background: rgba(150, 150, 150, 0.2);\n border-radius: 3px;\n }\n\n .ant-highlightCode-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n color: var(--ant-highlight-code-color-text-title);\n background: var(--ant-highlight-code-color-bg-title);\n padding: var(--ant-padding-sm);\n border-top-left-radius: var(--ant-border-radius);\n border-top-right-radius: var(--ant-border-radius);\n }\n }\n `,\n\n list: css`\n flex: 1;\n margin-top: 16px;\n overflow-y: auto;\n /* Chrome, Safari, Edge, Opera */\n &::-webkit-scrollbar {\n display: none;\n }\n /* Firefox */\n scrollbar-width: none;\n /* IE 10+ */\n -ms-overflow-style: none;\n `,\n\n prologue: css`\n margin-bottom: 12px;\n `,\n\n suggestion: css`\n margin-bottom: 12px;\n `,\n\n suggestContent: css`\n display: inline-flex;\n border: 2px solid #e7e7e7;\n border-radius: 8px;\n `,\n\n userMsg: css`\n display: flex;\n justify-content: flex-end;\n margin-bottom: 24px;\n `,\n\n userContainer: css`\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n align-items: flex-end;\n `,\n\n card: css`\n display: inline-block;\n padding: 12px 16px;\n background: #d5e3ff;\n border-radius: 12px;\n max-width: 100%;\n white-space: pre-line;\n word-break: break-all;\n `,\n\n botMsg: css`\n margin-bottom: 12px;\n `,\n\n emptyWrapper: css`\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n min-height: 200px;\n `,\n\n // 新增样式\n welcomeWrapper: css`\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 40px 20px;\n text-align: center;\n `,\n\n welcomeIcon: css`\n width: 64px;\n height: 64px;\n border-radius: 12px;\n margin-bottom: 16px;\n `,\n\n welcomeTitle: css`\n font-size: 24px;\n font-weight: 600;\n color: rgba(0, 0, 0, 0.88);\n margin-bottom: 8px;\n `,\n\n welcomeDesc: css`\n font-size: 14px;\n color: rgba(0, 0, 0, 0.65);\n margin-bottom: 24px;\n `,\n\n suggestionWrapper: css`\n margin-top: 16px;\n `,\n\n successBadge: css`\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 12px;\n background: #f6ffed;\n border: 1px solid #b7eb8f;\n border-radius: 4px;\n color: #52c41a;\n font-size: 13px;\n margin-bottom: 12px;\n `,\n\n fileSection: css`\n margin: 12px 0;\n `,\n\n fileHeader: css`\n font-size: 13px;\n color: rgba(0, 0, 0, 0.65);\n margin-bottom: 8px;\n `,\n\n metaFooter: css`\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n margin-top: 12px;\n padding-top: 12px;\n border-top: 1px solid #f0f0f0;\n `,\n\n actionIcons: css`\n color: rgba(0, 0, 0, 0.45);\n\n & > span {\n cursor: pointer;\n transition: color 0.2s;\n\n &:hover {\n color: #1890ff;\n }\n }\n `,\n\n fnCall: css`\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 11px;\n border-radius: 24px;\n line-height: 16px;\n border: 1px solid #e7e7e7;\n cursor: pointer;\n `,\n\n confirm: css`\n padding: 12px;\n border-radius: 12px;\n border: 1px solid #e7e7e7;\n `,\n\n footer: css`\n /* senderWrap and tip moved to top-level keys so they are\n accessible as styles.senderWrap and styles.tip in the component */\n `,\n\n sender: css`\n width: 100%;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 8px 8px 12px;\n border: 1px solid #e7e7e7;\n border-radius: 24px;\n\n /* .input moved to top-level key so component can use styles.input */\n `,\n\n senderWrap: css`\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n `,\n\n tip: css`\n padding: 4px;\n font-size: 12px;\n text-align: center;\n color: rgba(0, 0, 0, 0.4);\n `,\n\n input: css`\n padding: 0;\n margin: 5px 0;\n line-height: 22px;\n font-size: 15px;\n border-radius: 0;\n border: none;\n\n &:focus {\n box-shadow: none;\n }\n `,\n}));\n\nexport default useStyles;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAoB;AACpB,oBAAgC;AAEzB,IAAM,gBAAY,+BAAgB,OAAO;AAAA,EAC9C,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA6BT,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcN,UAAU;AAAA;AAAA;AAAA,EAIV,YAAY;AAAA;AAAA;AAAA,EAIZ,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOf,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUN,QAAQ;AAAA;AAAA;AAAA,EAIR,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASd,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQhB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOb,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOd,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAMb,mBAAmB;AAAA;AAAA;AAAA,EAInB,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAad,aAAa;AAAA;AAAA;AAAA,EAIb,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,EAMZ,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUZ,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAab,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWR,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT,QAAQ;AAAA;AAAA;AAAA;AAAA,EAKR,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYR,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOZ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOL,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYT,EAAE;AAEF,IAAO,iBAAQ;",
4
+ "sourcesContent": ["import { css } from \"@emotion/css\";\nimport { withBasicStyles } from \"@/styles/common\";\n\nexport const useStyles = withBasicStyles(() => ({\n wrapper: css`\n padding: 0 16px;\n min-height: 300px;\n height: 100%;\n border-radius: 8px;\n display: flex;\n flex-direction: column;\n\n .x-markdown {\n --margin-ul-ol: 0 0 1em 1em;\n\n code {\n background: rgba(150, 150, 150, 0.2);\n border-radius: 3px;\n }\n\n .ant-highlightCode-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n color: var(--ant-highlight-code-color-text-title);\n background: var(--ant-highlight-code-color-bg-title);\n padding: var(--ant-padding-sm);\n border-top-left-radius: var(--ant-border-radius);\n border-top-right-radius: var(--ant-border-radius);\n }\n }\n `,\n\n list: css`\n flex: 1;\n margin-top: 16px;\n overflow-y: auto;\n /* Chrome, Safari, Edge, Opera */\n &::-webkit-scrollbar {\n display: none;\n }\n /* Firefox */\n scrollbar-width: none;\n /* IE 10+ */\n -ms-overflow-style: none;\n `,\n\n prologue: css`\n margin-bottom: 12px;\n `,\n\n suggestion: css`\n margin-bottom: 12px;\n `,\n\n suggestContent: css`\n display: inline-flex;\n border: 2px solid #e7e7e7;\n border-radius: 8px;\n `,\n\n userMsg: css`\n display: flex;\n justify-content: flex-end;\n width: 100%;\n min-width: 0;\n margin-bottom: 24px;\n `,\n\n userContainer: css`\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n align-items: flex-end;\n min-width: 0;\n max-width: 100%;\n `,\n\n card: css`\n display: inline-block;\n box-sizing: border-box;\n min-width: 0;\n padding: 12px 16px;\n background: #d5e3ff;\n border-radius: 12px;\n max-width: 100%;\n white-space: pre-line;\n overflow-wrap: anywhere;\n word-break: break-word;\n `,\n\n botMsg: css`\n margin-bottom: 12px;\n `,\n\n emptyWrapper: css`\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n min-height: 200px;\n `,\n\n // 新增样式\n welcomeWrapper: css`\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 40px 20px;\n text-align: center;\n `,\n\n welcomeIcon: css`\n width: 64px;\n height: 64px;\n border-radius: 12px;\n margin-bottom: 16px;\n `,\n\n welcomeTitle: css`\n font-size: 24px;\n font-weight: 600;\n color: rgba(0, 0, 0, 0.88);\n margin-bottom: 8px;\n `,\n\n welcomeDesc: css`\n font-size: 14px;\n color: rgba(0, 0, 0, 0.65);\n margin-bottom: 24px;\n `,\n\n suggestionWrapper: css`\n margin-top: 16px;\n `,\n\n successBadge: css`\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 12px;\n background: #f6ffed;\n border: 1px solid #b7eb8f;\n border-radius: 4px;\n color: #52c41a;\n font-size: 13px;\n margin-bottom: 12px;\n `,\n\n fileSection: css`\n margin: 12px 0;\n `,\n\n fileHeader: css`\n font-size: 13px;\n color: rgba(0, 0, 0, 0.65);\n margin-bottom: 8px;\n `,\n\n metaFooter: css`\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n margin-top: 12px;\n padding-top: 12px;\n border-top: 1px solid #f0f0f0;\n `,\n\n actionIcons: css`\n color: rgba(0, 0, 0, 0.45);\n\n & > span {\n cursor: pointer;\n transition: color 0.2s;\n\n &:hover {\n color: #1890ff;\n }\n }\n `,\n\n fnCall: css`\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 11px;\n border-radius: 24px;\n line-height: 16px;\n border: 1px solid #e7e7e7;\n cursor: pointer;\n `,\n\n confirm: css`\n padding: 12px;\n border-radius: 12px;\n border: 1px solid #e7e7e7;\n `,\n\n footer: css`\n /* senderWrap and tip moved to top-level keys so they are\n accessible as styles.senderWrap and styles.tip in the component */\n `,\n\n sender: css`\n width: 100%;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 8px 8px 12px;\n border: 1px solid #e7e7e7;\n border-radius: 24px;\n\n /* .input moved to top-level key so component can use styles.input */\n `,\n\n senderWrap: css`\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n `,\n\n tip: css`\n padding: 4px;\n font-size: 12px;\n text-align: center;\n color: rgba(0, 0, 0, 0.4);\n `,\n\n input: css`\n padding: 0;\n margin: 5px 0;\n line-height: 22px;\n font-size: 15px;\n border-radius: 0;\n border: none;\n\n &:focus {\n box-shadow: none;\n }\n `,\n}));\n\nexport default useStyles;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAoB;AACpB,oBAAgC;AAEzB,IAAM,gBAAY,+BAAgB,OAAO;AAAA,EAC9C,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA6BT,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcN,UAAU;AAAA;AAAA;AAAA,EAIV,YAAY;AAAA;AAAA;AAAA,EAIZ,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQT,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASf,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaN,QAAQ;AAAA;AAAA;AAAA,EAIR,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASd,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQhB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOb,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOd,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAMb,mBAAmB;AAAA;AAAA;AAAA,EAInB,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAad,aAAa;AAAA;AAAA;AAAA,EAIb,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,EAMZ,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUZ,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAab,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWR,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT,QAAQ;AAAA;AAAA;AAAA;AAAA,EAKR,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYR,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOZ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOL,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYT,EAAE;AAEF,IAAO,iBAAQ;",
6
6
  "names": []
7
7
  }
@@ -34,10 +34,9 @@ __export(DefaultLayout_exports, {
34
34
  module.exports = __toCommonJS(DefaultLayout_exports);
35
35
  var import_react = require("react");
36
36
  var import_x = require("@ant-design/x");
37
- var import_antd = require("antd");
38
- var import_icons = require("@ant-design/icons");
39
37
  var import_ChatStateContext = require("../context/ChatStateContext");
40
38
  var import_ChatSenderStateContext = require("../context/ChatSenderStateContext");
39
+ var import_DefaultLayoutContext = require("../context/DefaultLayoutContext");
41
40
  var import_Sidebar = __toESM(require("./Sidebar"));
42
41
  var import_Messages = __toESM(require("./Messages"));
43
42
  var import_Welcome = __toESM(require("./Welcome"));
@@ -62,8 +61,14 @@ var DefaultLayout = ({
62
61
  const styles = (0, import_styles.useStyles)();
63
62
  const chatAreaRef = (0, import_react.useRef)(null);
64
63
  const senderRef = (0, import_react.useRef)(null);
65
- const fileInputRef = (0, import_react.useRef)(null);
66
64
  const [dropFileList, setDropFileList] = (0, import_react.useState)([]);
65
+ const registerSender = (0, import_react.useCallback)((sender) => {
66
+ senderRef.current = sender;
67
+ }, []);
68
+ const layoutContextValue = (0, import_react.useMemo)(
69
+ () => ({ allowUpload: mergedAllowUpload, registerSender }),
70
+ [mergedAllowUpload, registerSender]
71
+ );
67
72
  const enableDragUpload = mergedAllowUpload && mergedDraggable;
68
73
  const handleFiles = (0, import_react.useCallback)((files) => {
69
74
  var _a;
@@ -79,31 +84,6 @@ var DefaultLayout = ({
79
84
  },
80
85
  [handleFiles]
81
86
  );
82
- const handleFileInputChange = (0, import_react.useCallback)(
83
- (e) => {
84
- if (e.target.files) {
85
- handleFiles(Array.from(e.target.files));
86
- e.target.value = "";
87
- }
88
- },
89
- [handleFiles]
90
- );
91
- const renderUploadButton = (0, import_react.useCallback)(
92
- () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Tooltip, { title: "上传文件", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
93
- "button",
94
- {
95
- type: "button",
96
- className: styles.uploadButton,
97
- onClick: () => {
98
- var _a;
99
- return (_a = fileInputRef.current) == null ? void 0 : _a.click();
100
- },
101
- "aria-label": "上传文件",
102
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.PaperClipOutlined, {})
103
- }
104
- ) }),
105
- [styles]
106
- );
107
87
  const isEmpty = messages.length === 0 && !prologue && (!suggestions || suggestions.length === 0);
108
88
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
109
89
  "div",
@@ -234,28 +214,15 @@ var DefaultLayout = ({
234
214
  padding: isEmpty ? "0 24px" : "0",
235
215
  transition: "all 0.4s cubic-bezier(0.4, 0, 0.2, 1)"
236
216
  },
237
- children: footer || /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
238
- mergedAllowUpload && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
239
- "input",
240
- {
241
- ref: fileInputRef,
242
- type: "file",
243
- multiple: true,
244
- hidden: true,
245
- onChange: handleFileInputChange
246
- }
247
- ),
248
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
249
- import_Sender.default,
250
- {
251
- ref: senderRef,
252
- draggable: false,
253
- onFileSelect: handleFiles,
254
- clearBtnShow,
255
- footerLeft: mergedAllowUpload ? renderUploadButton : void 0
256
- }
257
- )
258
- ] })
217
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_DefaultLayoutContext.DefaultLayoutContext.Provider, { value: layoutContextValue, children: footer || /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
218
+ import_Sender.default,
219
+ {
220
+ ref: senderRef,
221
+ draggable: false,
222
+ onFileSelect: handleFiles,
223
+ clearBtnShow
224
+ }
225
+ ) })
259
226
  }
260
227
  ),
261
228
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/components/XAdkProvider/compound/DefaultLayout.tsx"],
4
- "sourcesContent": ["import React, { useRef, useCallback, useState } from \"react\";\nimport { Attachments } from \"@ant-design/x\";\nimport { Tooltip } from \"antd\";\nimport { PaperClipOutlined } from \"@ant-design/icons\";\nimport type { UploadFile } from \"antd\";\nimport { useChatState } from \"../context/ChatStateContext\";\nimport { useChatSenderState } from \"../context/ChatSenderStateContext\";\nimport Sidebar from \"./Sidebar\";\nimport Messages from \"./Messages\";\nimport Welcome from \"./Welcome\";\nimport Sender from \"./Sender\";\nimport { useStyles } from \"./styles\";\nimport type { ChatStrategies } from \"@/types\";\nimport type { XAdkSenderHandle } from \"@/types/XAdkSender\";\n\n/**\n * XAdkProvider 默认布局\n *\n * 提供类似 ChatGPT/DeepSeek 的默认布局:\n * - 左侧: 会话列表侧边栏 (可选,支持展开/收起)\n * - 右侧: 聊天区域 (标题 + 消息 + 输入框,居中显示,最大宽度800px)\n */\nexport interface DefaultLayoutProps {\n /** 是否显示会话列表 */\n showSessionList?: boolean;\n /** 自定义头部 */\n header?: React.ReactNode;\n /** 自定义底部 (替代默认 Sender) */\n footer?: React.ReactNode;\n /**\n * 是否启用内置上传入口(上传按钮 + 隐藏 file input + 拖拽)。\n * 未传时继承 XAdkProvider config.allowUpload。\n * 内核 XAdkSender 不再内置上传逻辑,上传能力统一由 DefaultLayout 管理。\n * 业务方自定义 footer 时可自行控制上传。\n */\n allowUpload?: boolean;\n /** 是否启用拖拽上传;未传时继承 config.draggable */\n draggable?: boolean;\n /** 是否显示清空按钮 */\n clearBtnShow?: boolean;\n /** 是否显示函数调用详情 */\n showFnCallDetail?: boolean;\n /** 自定义消息 Footer */\n messagesFooter?: (msg: any) => React.ReactNode;\n /** 自定义工具调用渲染函数,返回 null 则降级使用默认渲染 */\n renderFunctionCall?: (\n msg: import(\"@/types\").IMessage,\n ) => React.ReactNode | null;\n /** 局部策略覆盖,优先级高于 Provider preset/strategies */\n strategies?: ChatStrategies;\n}\n\nconst DefaultLayout: React.FC<DefaultLayoutProps> = ({\n showSessionList = false,\n header,\n footer,\n allowUpload,\n draggable,\n clearBtnShow = true,\n showFnCallDetail,\n renderFunctionCall,\n strategies,\n}) => {\n const { appInfo, messages, prologue, suggestions } = useChatState();\n const { allowUpload: providerAllowUpload, draggable: providerDraggable } =\n useChatSenderState();\n // Layout props 用于局部覆盖;未传时继承 Provider config,保证 NPM 与 UMD 接入一致。\n const mergedAllowUpload = allowUpload ?? providerAllowUpload;\n const mergedDraggable = draggable ?? providerDraggable;\n const styles = useStyles();\n const chatAreaRef = useRef<HTMLDivElement>(null);\n const senderRef = useRef<XAdkSenderHandle>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [dropFileList, setDropFileList] = useState<UploadFile[]>([]);\n\n // 拖拽上传只有在上传能力开启时生效,避免关闭上传后仍响应文件拖入。\n const enableDragUpload = mergedAllowUpload && mergedDraggable;\n\n // 文件注入到 Sender(按钮点击 + 拖拽统一走这里)\n const handleFiles = useCallback((files: File[]) => {\n if (files.length > 0) {\n senderRef.current?.addFiles(files);\n }\n }, []);\n\n // Attachments 拖拽文件后的回调\n const handleDropFiles = useCallback(\n (info: { fileList: UploadFile[] }) => {\n const rawFiles = info.fileList\n .map((f) => f.originFileObj)\n .filter(Boolean) as File[];\n handleFiles(rawFiles);\n // 清空 Attachments 文件列表,避免累积\n setDropFileList([]);\n },\n [handleFiles],\n );\n\n // 隐藏 file input 的 change 回调\n const handleFileInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n if (e.target.files) {\n handleFiles(Array.from(e.target.files));\n e.target.value = \"\";\n }\n },\n [handleFiles],\n );\n\n // 内置上传按钮:点击触发隐藏 file input\n const renderUploadButton = useCallback(\n () => (\n <Tooltip title=\"上传文件\">\n <button\n type=\"button\"\n className={styles.uploadButton}\n onClick={() => fileInputRef.current?.click()}\n aria-label=\"上传文件\"\n >\n <PaperClipOutlined />\n </button>\n </Tooltip>\n ),\n [styles],\n );\n\n // 判断是否为空状态(展示Welcome)\n const isEmpty =\n messages.length === 0 &&\n !prologue &&\n (!suggestions || suggestions.length === 0);\n\n return (\n <div\n style={{\n display: \"flex\",\n height: \"100%\",\n width: \"100%\",\n position: \"relative\",\n overflow: \"hidden\",\n }}\n >\n {/* 左侧会话列表 - XAiConversations 组件会处理展开/收起 */}\n {showSessionList && <Sidebar isNarrow={false} />}\n\n {/* 右侧聊天区域 - 使用 flex: 1 自动占据剩余空间 */}\n <div\n ref={chatAreaRef}\n style={{\n flex: 1,\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n position: \"relative\",\n }}\n >\n {/* 居中容器 - 最大宽度 800px */}\n <div\n style={{\n width: \"100%\",\n maxWidth: \"800px\",\n height: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {/* 头部 */}\n {header ||\n (appInfo && (\n <div\n style={{\n padding: \"16px 24px\",\n display: \"flex\",\n justifyContent: \"center\",\n background: \"white\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"12px\",\n }}\n >\n {appInfo.appName && (\n <div>\n <div\n style={{\n fontSize: \"16px\",\n fontWeight: 500,\n color: \"#000\",\n }}\n >\n {appInfo.appName}\n </div>\n </div>\n )}\n </div>\n </div>\n ))}\n\n {/* 消息区域或Welcome区域 */}\n <div\n style={{\n flex: 1,\n overflow: \"hidden\",\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {/* 上方弹性占位 - Welcome状态时占据空间 */}\n <div\n style={{\n flex: isEmpty ? 1 : 0,\n transition: \"flex 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n }}\n />\n\n {/* Welcome 组件 - 只在空状态显示 */}\n {isEmpty && (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n padding: \"0 24px\",\n marginBottom: \"24px\",\n }}\n >\n <Welcome />\n </div>\n )}\n\n {/* Messages 组件 - 只在非空状态显示 */}\n {!isEmpty && (\n <div\n style={{\n flex: 1,\n overflow: \"hidden\",\n position: \"relative\",\n }}\n >\n <Messages\n showFnCallDetail={showFnCallDetail}\n renderFunctionCall={renderFunctionCall}\n strategies={strategies}\n />\n </div>\n )}\n {/* 输入区域 - 始终存在,通过样式控制位置 */}\n <div\n className={styles.sendWrapper}\n style={{\n maxWidth: isEmpty ? \"600px\" : \"100%\",\n alignSelf: \"center\",\n padding: isEmpty ? \"0 24px\" : \"0\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n }}\n >\n {footer || (\n <>\n {/* 隐藏的原生 file input - 由 DefaultLayout 管理 */}\n {mergedAllowUpload && (\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n hidden\n onChange={handleFileInputChange}\n />\n )}\n <Sender\n ref={senderRef}\n draggable={false}\n onFileSelect={handleFiles}\n clearBtnShow={clearBtnShow}\n footerLeft={\n mergedAllowUpload ? renderUploadButton : undefined\n }\n />\n </>\n )}\n </div>\n\n {/* 下方弹性占位 - Welcome状态时占据更多空间,让内容偏上 */}\n <div\n style={{\n flex: isEmpty ? 1.5 : 0,\n transition: \"flex 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n }}\n />\n </div>\n </div>\n\n {/* Attachments 拖拽遮罩 - 仅用于拖拽上传功能 */}\n {enableDragUpload && (\n <Attachments\n style={{ display: \"none\" }}\n items={dropFileList}\n getDropContainer={() => chatAreaRef.current}\n multiple\n beforeUpload={() => false}\n onChange={handleDropFiles}\n />\n )}\n </div>\n </div>\n );\n};\n\nDefaultLayout.displayName = \"XAdkProvider.DefaultLayout\";\n\nexport default DefaultLayout;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import React, { useRef, useCallback, useState, useMemo } from \"react\";\nimport { Attachments } from \"@ant-design/x\";\nimport type { UploadFile } from \"antd\";\nimport { useChatState } from \"../context/ChatStateContext\";\nimport { useChatSenderState } from \"../context/ChatSenderStateContext\";\nimport { DefaultLayoutContext } from \"../context/DefaultLayoutContext\";\nimport Sidebar from \"./Sidebar\";\nimport Messages from \"./Messages\";\nimport Welcome from \"./Welcome\";\nimport Sender from \"./Sender\";\nimport { useStyles } from \"./styles\";\nimport type { ChatStrategies } from \"@/types\";\nimport type { XAdkSenderHandle } from \"@/types/XAdkSender\";\n\n/**\n * XAdkProvider 默认布局\n *\n * 提供类似 ChatGPT/DeepSeek 的默认布局:\n * - 左侧: 会话列表侧边栏 (可选,支持展开/收起)\n * - 右侧: 聊天区域 (标题 + 消息 + 输入框,居中显示,最大宽度800px)\n */\nexport interface DefaultLayoutProps {\n /** 是否显示会话列表 */\n showSessionList?: boolean;\n /** 自定义头部 */\n header?: React.ReactNode;\n /** 自定义底部 (替代默认 Sender) */\n footer?: React.ReactNode;\n /**\n * 是否启用内置上传入口(上传按钮 + 隐藏 file input + 拖拽)。\n * 未传时继承 XAdkProvider config.allowUpload。\n * 内核 XAdkSender 不再内置上传逻辑,上传能力统一由 DefaultLayout 管理。\n * 业务方自定义 footer 时可自行控制上传。\n */\n allowUpload?: boolean;\n /** 是否启用拖拽上传;未传时继承 config.draggable */\n draggable?: boolean;\n /** 是否显示清空按钮 */\n clearBtnShow?: boolean;\n /** 是否显示函数调用详情 */\n showFnCallDetail?: boolean;\n /** 自定义消息 Footer */\n messagesFooter?: (msg: any) => React.ReactNode;\n /** 自定义工具调用渲染函数,返回 null 则降级使用默认渲染 */\n renderFunctionCall?: (\n msg: import(\"@/types\").IMessage,\n ) => React.ReactNode | null;\n /** 局部策略覆盖,优先级高于 Provider preset/strategies */\n strategies?: ChatStrategies;\n}\n\nconst DefaultLayout: React.FC<DefaultLayoutProps> = ({\n showSessionList = false,\n header,\n footer,\n allowUpload,\n draggable,\n clearBtnShow = true,\n showFnCallDetail,\n renderFunctionCall,\n strategies,\n}) => {\n const { appInfo, messages, prologue, suggestions } = useChatState();\n const { allowUpload: providerAllowUpload, draggable: providerDraggable } =\n useChatSenderState();\n // Layout props 用于局部覆盖;未传时继承 Provider config,保证 NPM 与 UMD 接入一致。\n const mergedAllowUpload = allowUpload ?? providerAllowUpload;\n const mergedDraggable = draggable ?? providerDraggable;\n const styles = useStyles();\n const chatAreaRef = useRef<HTMLDivElement>(null);\n const senderRef = useRef<XAdkSenderHandle>(null);\n const [dropFileList, setDropFileList] = useState<UploadFile[]>([]);\n const registerSender = useCallback((sender: XAdkSenderHandle | null) => {\n senderRef.current = sender;\n }, []);\n const layoutContextValue = useMemo(\n () => ({ allowUpload: mergedAllowUpload, registerSender }),\n [mergedAllowUpload, registerSender],\n );\n\n // 拖拽上传只有在上传能力开启时生效,避免关闭上传后仍响应文件拖入。\n const enableDragUpload = mergedAllowUpload && mergedDraggable;\n\n // 文件注入到 Sender(按钮点击 + 拖拽统一走这里)\n const handleFiles = useCallback((files: File[]) => {\n if (files.length > 0) {\n senderRef.current?.addFiles(files);\n }\n }, []);\n\n // Attachments 拖拽文件后的回调\n const handleDropFiles = useCallback(\n (info: { fileList: UploadFile[] }) => {\n const rawFiles = info.fileList\n .map((f) => f.originFileObj)\n .filter(Boolean) as File[];\n handleFiles(rawFiles);\n // 清空 Attachments 文件列表,避免累积\n setDropFileList([]);\n },\n [handleFiles],\n );\n\n // 判断是否为空状态(展示Welcome)\n const isEmpty =\n messages.length === 0 &&\n !prologue &&\n (!suggestions || suggestions.length === 0);\n\n return (\n <div\n style={{\n display: \"flex\",\n height: \"100%\",\n width: \"100%\",\n position: \"relative\",\n overflow: \"hidden\",\n }}\n >\n {/* 左侧会话列表 - XAiConversations 组件会处理展开/收起 */}\n {showSessionList && <Sidebar isNarrow={false} />}\n\n {/* 右侧聊天区域 - 使用 flex: 1 自动占据剩余空间 */}\n <div\n ref={chatAreaRef}\n style={{\n flex: 1,\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n position: \"relative\",\n }}\n >\n {/* 居中容器 - 最大宽度 800px */}\n <div\n style={{\n width: \"100%\",\n maxWidth: \"800px\",\n height: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {/* 头部 */}\n {header ||\n (appInfo && (\n <div\n style={{\n padding: \"16px 24px\",\n display: \"flex\",\n justifyContent: \"center\",\n background: \"white\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"12px\",\n }}\n >\n {appInfo.appName && (\n <div>\n <div\n style={{\n fontSize: \"16px\",\n fontWeight: 500,\n color: \"#000\",\n }}\n >\n {appInfo.appName}\n </div>\n </div>\n )}\n </div>\n </div>\n ))}\n\n {/* 消息区域或Welcome区域 */}\n <div\n style={{\n flex: 1,\n overflow: \"hidden\",\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {/* 上方弹性占位 - Welcome状态时占据空间 */}\n <div\n style={{\n flex: isEmpty ? 1 : 0,\n transition: \"flex 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n }}\n />\n\n {/* Welcome 组件 - 只在空状态显示 */}\n {isEmpty && (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n padding: \"0 24px\",\n marginBottom: \"24px\",\n }}\n >\n <Welcome />\n </div>\n )}\n\n {/* Messages 组件 - 只在非空状态显示 */}\n {!isEmpty && (\n <div\n style={{\n flex: 1,\n overflow: \"hidden\",\n position: \"relative\",\n }}\n >\n <Messages\n showFnCallDetail={showFnCallDetail}\n renderFunctionCall={renderFunctionCall}\n strategies={strategies}\n />\n </div>\n )}\n {/* 输入区域 - 始终存在,通过样式控制位置 */}\n <div\n className={styles.sendWrapper}\n style={{\n maxWidth: isEmpty ? \"600px\" : \"100%\",\n alignSelf: \"center\",\n padding: isEmpty ? \"0 24px\" : \"0\",\n transition: \"all 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n }}\n >\n <DefaultLayoutContext.Provider value={layoutContextValue}>\n {footer || (\n <Sender\n ref={senderRef}\n draggable={false}\n onFileSelect={handleFiles}\n clearBtnShow={clearBtnShow}\n />\n )}\n </DefaultLayoutContext.Provider>\n </div>\n\n {/* 下方弹性占位 - Welcome状态时占据更多空间,让内容偏上 */}\n <div\n style={{\n flex: isEmpty ? 1.5 : 0,\n transition: \"flex 0.4s cubic-bezier(0.4, 0, 0.2, 1)\",\n }}\n />\n </div>\n </div>\n\n {/* Attachments 拖拽遮罩 - 仅用于拖拽上传功能 */}\n {enableDragUpload && (\n <Attachments\n style={{ display: \"none\" }}\n items={dropFileList}\n getDropContainer={() => chatAreaRef.current}\n multiple\n beforeUpload={() => false}\n onChange={handleDropFiles}\n />\n )}\n </div>\n </div>\n );\n};\n\nDefaultLayout.displayName = \"XAdkProvider.DefaultLayout\";\n\nexport default DefaultLayout;\n"],
5
+ "mappings": "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",
6
6
  "names": ["Sidebar", "Welcome", "Messages", "Sender"]
7
7
  }
@@ -11,14 +11,15 @@ import type { XAdkSenderProps, XAdkSenderHandle } from "../../../types";
11
11
  * <XAdkProvider url="..." token="...">
12
12
  * <XAdkProvider.Sender
13
13
  * clearBtnShow={true}
14
+ * allowUpload
14
15
  * uploadRequest={myUploadHandler}
15
16
  * />
16
17
  * </XAdkProvider>
17
18
  * ```
18
- *
19
- * 提示:如需内置上传按钮与拖拽上传,请使用 XAdkProvider.DefaultLayout 并设置 allowUpload。
20
19
  */
21
20
  export interface XAdkSenderCompoundProps extends Partial<Omit<XAdkSenderProps, "loading" | "onSubmit" | "onStop" | "onClear">> {
21
+ /** 是否显示内置上传按钮;未传时依次继承 DefaultLayout 与 Provider 配置。 */
22
+ allowUpload?: boolean;
22
23
  /** 额外的样式 */
23
24
  style?: React.CSSProperties;
24
25
  /** 额外的类名 */
@@ -33,18 +33,94 @@ __export(Sender_exports, {
33
33
  });
34
34
  module.exports = __toCommonJS(Sender_exports);
35
35
  var import_react = require("react");
36
+ var import_icons = require("@ant-design/icons");
37
+ var import_antd = require("antd");
36
38
  var import_XAdkSender = __toESM(require("../../XAdkSender"));
37
39
  var import_ChatSenderStateContext = require("../context/ChatSenderStateContext");
40
+ var import_DefaultLayoutContext = require("../context/DefaultLayoutContext");
38
41
  var import_ChatActionContext = require("../context/ChatActionContext");
42
+ var import_styles = require("./styles");
39
43
  var import_jsx_runtime = require("react/jsx-runtime");
40
44
  var Sender = (0, import_react.forwardRef)(
41
- (props, ref) => {
42
- const { loading, uploadRequest, senderValue, setSenderValue } = (0, import_ChatSenderStateContext.useChatSenderState)();
45
+ ({ allowUpload, uploadRequest: customUploadRequest, footerLeft, ...props }, ref) => {
46
+ const {
47
+ loading,
48
+ uploadRequest: providerUploadRequest,
49
+ allowUpload: providerAllowUpload,
50
+ senderValue,
51
+ setSenderValue
52
+ } = (0, import_ChatSenderStateContext.useChatSenderState)();
53
+ const layout = (0, import_DefaultLayoutContext.useDefaultLayoutContext)();
43
54
  const { chat, stopChat, clearChat } = (0, import_ChatActionContext.useChatActions)();
55
+ const styles = (0, import_styles.useStyles)();
56
+ const senderRef = (0, import_react.useRef)(null);
57
+ const fileInputRef = (0, import_react.useRef)(null);
58
+ const mergedAllowUpload = allowUpload ?? (layout == null ? void 0 : layout.allowUpload) ?? providerAllowUpload;
59
+ const uploadRequest = customUploadRequest ?? providerUploadRequest;
60
+ const setSenderRef = (0, import_react.useCallback)(
61
+ (sender) => {
62
+ var _a;
63
+ senderRef.current = sender;
64
+ (_a = layout == null ? void 0 : layout.registerSender) == null ? void 0 : _a.call(layout, sender);
65
+ if (typeof ref === "function")
66
+ ref(sender);
67
+ else if (ref)
68
+ ref.current = sender;
69
+ },
70
+ [layout, ref]
71
+ );
72
+ const handleFileChange = (0, import_react.useCallback)(
73
+ (event) => {
74
+ var _a;
75
+ const files = event.target.files;
76
+ if (files == null ? void 0 : files.length)
77
+ (_a = senderRef.current) == null ? void 0 : _a.addFiles(Array.from(files));
78
+ event.target.value = "";
79
+ },
80
+ []
81
+ );
82
+ const renderCustomFooterLeft = (0, import_react.useCallback)(
83
+ (oriNode, info) => {
84
+ if (footerLeft === false || footerLeft === void 0)
85
+ return null;
86
+ return typeof footerLeft === "function" ? footerLeft(oriNode, info) : footerLeft;
87
+ },
88
+ [footerLeft]
89
+ );
90
+ const mergedFooterLeft = mergedAllowUpload ? (oriNode, info) => {
91
+ var _a;
92
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
93
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
94
+ "input",
95
+ {
96
+ ref: fileInputRef,
97
+ type: "file",
98
+ multiple: true,
99
+ hidden: true,
100
+ accept: (_a = props.allowedFileTypes) == null ? void 0 : _a.join(","),
101
+ onChange: handleFileChange
102
+ }
103
+ ),
104
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_antd.Tooltip, { title: "上传文件", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
105
+ "button",
106
+ {
107
+ type: "button",
108
+ className: styles.uploadButton,
109
+ onClick: () => {
110
+ var _a2;
111
+ return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
112
+ },
113
+ "aria-label": "上传文件",
114
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.PaperClipOutlined, {})
115
+ }
116
+ ) }),
117
+ renderCustomFooterLeft(oriNode, info)
118
+ ] });
119
+ } : footerLeft;
44
120
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
45
121
  import_XAdkSender.default,
46
122
  {
47
- ref,
123
+ ref: setSenderRef,
48
124
  ...props,
49
125
  loading,
50
126
  value: senderValue,
@@ -52,7 +128,8 @@ var Sender = (0, import_react.forwardRef)(
52
128
  onSubmit: chat,
53
129
  onStop: stopChat,
54
130
  onClear: clearChat,
55
- uploadRequest
131
+ uploadRequest,
132
+ footerLeft: mergedFooterLeft
56
133
  }
57
134
  );
58
135
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/components/XAdkProvider/compound/Sender.tsx"],
4
- "sourcesContent": ["import React, { forwardRef } from \"react\";\nimport XAdkSender from \"@/components/XAdkSender\";\nimport { useChatSenderState } from \"../context/ChatSenderStateContext\";\nimport { useChatActions } from \"../context/ChatActionContext\";\nimport type { XAdkSenderProps, XAdkSenderHandle } from \"@/types\";\n\n/**\n * XAdkProvider.Sender - 输入框组件\n *\n * 从 Context 获取聊天动作并提供输入界面\n * 基于 XAdkSender 组件实现\n *\n * @example\n * ```tsx\n * <XAdkProvider url=\"...\" token=\"...\">\n * <XAdkProvider.Sender\n * clearBtnShow={true}\n * uploadRequest={myUploadHandler}\n * />\n * </XAdkProvider>\n * ```\n *\n * 提示:如需内置上传按钮与拖拽上传,请使用 XAdkProvider.DefaultLayout 并设置 allowUpload。\n */\nexport interface XAdkSenderCompoundProps extends Partial<\n Omit<XAdkSenderProps, \"loading\" | \"onSubmit\" | \"onStop\" | \"onClear\">\n> {\n /** 额外的样式 */\n style?: React.CSSProperties;\n /** 额外的类名 */\n className?: string;\n}\n\nconst Sender = forwardRef<XAdkSenderHandle, XAdkSenderCompoundProps>(\n (props, ref) => {\n const { loading, uploadRequest, senderValue, setSenderValue } = useChatSenderState();\n const { chat, stopChat, clearChat } = useChatActions();\n\n return (\n <XAdkSender\n ref={ref}\n {...props}\n loading={loading}\n value={senderValue}\n onChange={setSenderValue}\n onSubmit={chat}\n onStop={stopChat}\n onClear={clearChat}\n uploadRequest={uploadRequest}\n />\n );\n },\n);\n\nSender.displayName = \"XAdkProvider.Sender\";\n\nexport default Sender;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAkC;AAClC,wBAAuB;AACvB,oCAAmC;AACnC,+BAA+B;AAoCzB;AANN,IAAM,aAAS;AAAA,EACb,CAAC,OAAO,QAAQ;AACd,UAAM,EAAE,SAAS,eAAe,aAAa,eAAe,QAAI,kDAAmB;AACnF,UAAM,EAAE,MAAM,UAAU,UAAU,QAAI,yCAAe;AAErD,WACE;AAAA,MAAC,kBAAAA;AAAA,MAAA;AAAA,QACC;AAAA,QACC,GAAG;AAAA,QACJ;AAAA,QACA,OAAO;AAAA,QACP,UAAU;AAAA,QACV,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS;AAAA,QACT;AAAA;AAAA,IACF;AAAA,EAEJ;AACF;AAEA,OAAO,cAAc;AAErB,IAAO,iBAAQ;",
6
- "names": ["XAdkSender"]
4
+ "sourcesContent": ["import React, { forwardRef, useCallback, useRef } from \"react\";\nimport { PaperClipOutlined } from \"@ant-design/icons\";\nimport { Tooltip } from \"antd\";\nimport XAdkSender from \"@/components/XAdkSender\";\nimport { useChatSenderState } from \"../context/ChatSenderStateContext\";\nimport { useDefaultLayoutContext } from \"../context/DefaultLayoutContext\";\nimport { useChatActions } from \"../context/ChatActionContext\";\nimport type {\n ActionsComponents,\n SlotRenderFunction,\n XAdkSenderProps,\n XAdkSenderHandle,\n} from \"@/types\";\nimport { useStyles } from \"./styles\";\n\n/**\n * XAdkProvider.Sender - 输入框组件\n *\n * 从 Context 获取聊天动作并提供输入界面\n * 基于 XAdkSender 组件实现\n *\n * @example\n * ```tsx\n * <XAdkProvider url=\"...\" token=\"...\">\n * <XAdkProvider.Sender\n * clearBtnShow={true}\n * allowUpload\n * uploadRequest={myUploadHandler}\n * />\n * </XAdkProvider>\n * ```\n */\nexport interface XAdkSenderCompoundProps extends Partial<\n Omit<XAdkSenderProps, \"loading\" | \"onSubmit\" | \"onStop\" | \"onClear\">\n> {\n /** 是否显示内置上传按钮;未传时依次继承 DefaultLayout 与 Provider 配置。 */\n allowUpload?: boolean;\n /** 额外的样式 */\n style?: React.CSSProperties;\n /** 额外的类名 */\n className?: string;\n}\n\nconst Sender = forwardRef<XAdkSenderHandle, XAdkSenderCompoundProps>(\n (\n { allowUpload, uploadRequest: customUploadRequest, footerLeft, ...props },\n ref,\n ) => {\n const {\n loading,\n uploadRequest: providerUploadRequest,\n allowUpload: providerAllowUpload,\n senderValue,\n setSenderValue,\n } = useChatSenderState();\n const layout = useDefaultLayoutContext();\n const { chat, stopChat, clearChat } = useChatActions();\n const styles = useStyles();\n const senderRef = useRef<XAdkSenderHandle | null>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const mergedAllowUpload =\n allowUpload ?? layout?.allowUpload ?? providerAllowUpload;\n const uploadRequest = customUploadRequest ?? providerUploadRequest;\n\n // 同时维护业务 ref 与 DefaultLayout 的拖拽文件注入目标。\n const setSenderRef = useCallback(\n (sender: XAdkSenderHandle | null) => {\n senderRef.current = sender;\n layout?.registerSender?.(sender);\n if (typeof ref === \"function\") ref(sender);\n else if (ref) ref.current = sender;\n },\n [layout, ref],\n );\n\n const handleFileChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n const files = event.target.files;\n if (files?.length) senderRef.current?.addFiles(Array.from(files));\n event.target.value = \"\";\n },\n [],\n );\n\n const renderCustomFooterLeft = useCallback(\n (oriNode: React.ReactNode, info: { components: ActionsComponents }) => {\n if (footerLeft === false || footerLeft === undefined) return null;\n return typeof footerLeft === \"function\"\n ? footerLeft(oriNode, info)\n : footerLeft;\n },\n [footerLeft],\n );\n\n const mergedFooterLeft: SlotRenderFunction | React.ReactNode =\n mergedAllowUpload\n ? (oriNode, info) => (\n <>\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n hidden\n accept={props.allowedFileTypes?.join(\",\")}\n onChange={handleFileChange}\n />\n <Tooltip title=\"上传文件\">\n <button\n type=\"button\"\n className={styles.uploadButton}\n onClick={() => fileInputRef.current?.click()}\n aria-label=\"上传文件\"\n >\n <PaperClipOutlined />\n </button>\n </Tooltip>\n {renderCustomFooterLeft(oriNode, info)}\n </>\n )\n : footerLeft;\n\n return (\n <XAdkSender\n ref={setSenderRef}\n {...props}\n loading={loading}\n value={senderValue}\n onChange={setSenderValue}\n onSubmit={chat}\n onStop={stopChat}\n onClear={clearChat}\n uploadRequest={uploadRequest}\n footerLeft={mergedFooterLeft}\n />\n );\n },\n);\n\nSender.displayName = \"XAdkProvider.Sender\";\n\nexport default Sender;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAuD;AACvD,mBAAkC;AAClC,kBAAwB;AACxB,wBAAuB;AACvB,oCAAmC;AACnC,kCAAwC;AACxC,+BAA+B;AAO/B,oBAA0B;AAoFd;AAtDZ,IAAM,aAAS;AAAA,EACb,CACE,EAAE,aAAa,eAAe,qBAAqB,YAAY,GAAG,MAAM,GACxE,QACG;AACH,UAAM;AAAA,MACJ;AAAA,MACA,eAAe;AAAA,MACf,aAAa;AAAA,MACb;AAAA,MACA;AAAA,IACF,QAAI,kDAAmB;AACvB,UAAM,aAAS,qDAAwB;AACvC,UAAM,EAAE,MAAM,UAAU,UAAU,QAAI,yCAAe;AACrD,UAAM,aAAS,yBAAU;AACzB,UAAM,gBAAY,qBAAgC,IAAI;AACtD,UAAM,mBAAe,qBAAyB,IAAI;AAClD,UAAM,oBACJ,gBAAe,iCAAQ,gBAAe;AACxC,UAAM,gBAAgB,uBAAuB;AAG7C,UAAM,mBAAe;AAAA,MACnB,CAAC,WAAoC;AAlE3C;AAmEQ,kBAAU,UAAU;AACpB,+CAAQ,mBAAR,gCAAyB;AACzB,YAAI,OAAO,QAAQ;AAAY,cAAI,MAAM;AAAA,iBAChC;AAAK,cAAI,UAAU;AAAA,MAC9B;AAAA,MACA,CAAC,QAAQ,GAAG;AAAA,IACd;AAEA,UAAM,uBAAmB;AAAA,MACvB,CAAC,UAA+C;AA5EtD;AA6EQ,cAAM,QAAQ,MAAM,OAAO;AAC3B,YAAI,+BAAO;AAAQ,0BAAU,YAAV,mBAAmB,SAAS,MAAM,KAAK,KAAK;AAC/D,cAAM,OAAO,QAAQ;AAAA,MACvB;AAAA,MACA,CAAC;AAAA,IACH;AAEA,UAAM,6BAAyB;AAAA,MAC7B,CAAC,SAA0B,SAA4C;AACrE,YAAI,eAAe,SAAS,eAAe;AAAW,iBAAO;AAC7D,eAAO,OAAO,eAAe,aACzB,WAAW,SAAS,IAAI,IACxB;AAAA,MACN;AAAA,MACA,CAAC,UAAU;AAAA,IACb;AAEA,UAAM,mBACJ,oBACI,CAAC,SAAS,SAAM;AAhG1B;AAiGY,yFACE;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,MAAK;AAAA,YACL,UAAQ;AAAA,YACR,QAAM;AAAA,YACN,SAAQ,WAAM,qBAAN,mBAAwB,KAAK;AAAA,YACrC,UAAU;AAAA;AAAA,QACZ;AAAA,QACA,4CAAC,uBAAQ,OAAM,QACb;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAW,OAAO;AAAA,YAClB,SAAS,MAAG;AA9G9B,kBAAAA;AA8GiC,sBAAAA,MAAA,aAAa,YAAb,gBAAAA,IAAsB;AAAA;AAAA,YACrC,cAAW;AAAA,YAEX,sDAAC,kCAAkB;AAAA;AAAA,QACrB,GACF;AAAA,QACC,uBAAuB,SAAS,IAAI;AAAA,SACvC;AAAA,QAEF;AAEN,WACE;AAAA,MAAC,kBAAAC;AAAA,MAAA;AAAA,QACC,KAAK;AAAA,QACJ,GAAG;AAAA,QACJ;AAAA,QACA,OAAO;AAAA,QACP,UAAU;AAAA,QACV,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS;AAAA,QACT;AAAA,QACA,YAAY;AAAA;AAAA,IACd;AAAA,EAEJ;AACF;AAEA,OAAO,cAAc;AAErB,IAAO,iBAAQ;",
6
+ "names": ["_a", "XAdkSender"]
7
7
  }
@@ -0,0 +1,9 @@
1
+ /// <reference types="react" />
2
+ import type { XAdkSenderHandle } from "../../../types";
3
+ /** DefaultLayout 与自定义 footer Sender 之间的内部协作信息。 */
4
+ export interface DefaultLayoutContextType {
5
+ allowUpload?: boolean;
6
+ registerSender?: (sender: XAdkSenderHandle | null) => void;
7
+ }
8
+ export declare const DefaultLayoutContext: import("react").Context<DefaultLayoutContextType | null>;
9
+ export declare const useDefaultLayoutContext: () => DefaultLayoutContextType | null;
@@ -0,0 +1,34 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/components/XAdkProvider/context/DefaultLayoutContext.tsx
20
+ var DefaultLayoutContext_exports = {};
21
+ __export(DefaultLayoutContext_exports, {
22
+ DefaultLayoutContext: () => DefaultLayoutContext,
23
+ useDefaultLayoutContext: () => useDefaultLayoutContext
24
+ });
25
+ module.exports = __toCommonJS(DefaultLayoutContext_exports);
26
+ var import_react = require("react");
27
+ var DefaultLayoutContext = (0, import_react.createContext)(null);
28
+ var useDefaultLayoutContext = () => (0, import_react.useContext)(DefaultLayoutContext);
29
+ // Annotate the CommonJS export names for ESM import in node:
30
+ 0 && (module.exports = {
31
+ DefaultLayoutContext,
32
+ useDefaultLayoutContext
33
+ });
34
+ //# sourceMappingURL=DefaultLayoutContext.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/components/XAdkProvider/context/DefaultLayoutContext.tsx"],
4
+ "sourcesContent": ["import { createContext, useContext } from \"react\";\nimport type { XAdkSenderHandle } from \"@/types\";\n\n/** DefaultLayout 与自定义 footer Sender 之间的内部协作信息。 */\nexport interface DefaultLayoutContextType {\n allowUpload?: boolean;\n registerSender?: (sender: XAdkSenderHandle | null) => void;\n}\n\nexport const DefaultLayoutContext =\n createContext<DefaultLayoutContextType | null>(null);\n\nexport const useDefaultLayoutContext = () => useContext(DefaultLayoutContext);\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA0C;AASnC,IAAM,2BACX,4BAA+C,IAAI;AAE9C,IAAM,0BAA0B,UAAM,yBAAW,oBAAoB;",
6
+ "names": []
7
+ }
@@ -2,7 +2,8 @@
2
2
  * XAdkProvider Context 导出
3
3
  * 提供拆分的 Context 和对应的 Hooks
4
4
  */
5
- export * from './ChatStateContext';
6
- export * from './ChatActionContext';
7
- export * from './SessionContext';
8
- export * from './ChatSenderStateContext';
5
+ export * from "./ChatStateContext";
6
+ export * from "./ChatActionContext";
7
+ export * from "./SessionContext";
8
+ export * from "./ChatSenderStateContext";
9
+ export * from "./DefaultLayoutContext";
@@ -20,11 +20,13 @@ __reExport(context_exports, require("./ChatStateContext"), module.exports);
20
20
  __reExport(context_exports, require("./ChatActionContext"), module.exports);
21
21
  __reExport(context_exports, require("./SessionContext"), module.exports);
22
22
  __reExport(context_exports, require("./ChatSenderStateContext"), module.exports);
23
+ __reExport(context_exports, require("./DefaultLayoutContext"), module.exports);
23
24
  // Annotate the CommonJS export names for ESM import in node:
24
25
  0 && (module.exports = {
25
26
  ...require("./ChatStateContext"),
26
27
  ...require("./ChatActionContext"),
27
28
  ...require("./SessionContext"),
28
- ...require("./ChatSenderStateContext")
29
+ ...require("./ChatSenderStateContext"),
30
+ ...require("./DefaultLayoutContext")
29
31
  });
30
32
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/components/XAdkProvider/context/index.ts"],
4
- "sourcesContent": ["/**\n * XAdkProvider Context 导出\n * 提供拆分的 Context 和对应的 Hooks\n */\n\nexport * from './ChatStateContext';\nexport * from './ChatActionContext';\nexport * from './SessionContext';\nexport * from './ChatSenderStateContext';\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;AAAA;AAAA;AAKA,4BAAc,+BALd;AAMA,4BAAc,gCANd;AAOA,4BAAc,6BAPd;AAQA,4BAAc,qCARd;",
4
+ "sourcesContent": ["/**\n * XAdkProvider Context 导出\n * 提供拆分的 Context 和对应的 Hooks\n */\n\nexport * from \"./ChatStateContext\";\nexport * from \"./ChatActionContext\";\nexport * from \"./SessionContext\";\nexport * from \"./ChatSenderStateContext\";\nexport * from \"./DefaultLayoutContext\";\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;AAAA;AAAA;AAKA,4BAAc,+BALd;AAMA,4BAAc,gCANd;AAOA,4BAAc,6BAPd;AAQA,4BAAc,qCARd;AASA,4BAAc,mCATd;",
6
6
  "names": []
7
7
  }
@@ -5,6 +5,10 @@ export interface InlineTagInputRef {
5
5
  getText: () => string;
6
6
  getParts: () => XAdkSenderSubmitPart[];
7
7
  getCursorOffset: () => number;
8
+ deleteTextRange: (range: {
9
+ start: number;
10
+ end: number;
11
+ }) => void;
8
12
  insertMention: (mention: MentionTag, replace?: {
9
13
  start: number;
10
14
  end: number;
@@ -574,10 +574,29 @@ var InlineTagInput = (0, import_react.forwardRef)(
574
574
  getText: getPlainText,
575
575
  getParts,
576
576
  getCursorOffset: getOffsetInEditor,
577
+ deleteTextRange: ({ start, end }) => {
578
+ const range = replaceTextRange(start, end);
579
+ cleanupCaretTextNodes();
580
+ if (range) {
581
+ const selection = window.getSelection();
582
+ selection == null ? void 0 : selection.removeAllRanges();
583
+ selection == null ? void 0 : selection.addRange(range);
584
+ savedRangeRef.current = range.cloneRange();
585
+ }
586
+ emitChange();
587
+ },
577
588
  insertMention,
578
589
  insertTag: insertMention
579
590
  }),
580
- [getOffsetInEditor, getParts, getPlainText, insertMention]
591
+ [
592
+ cleanupCaretTextNodes,
593
+ emitChange,
594
+ getOffsetInEditor,
595
+ getParts,
596
+ getPlainText,
597
+ insertMention,
598
+ replaceTextRange
599
+ ]
581
600
  );
582
601
  useIsomorphicLayoutEffect(() => {
583
602
  const editor = editorRef.current;
@@ -586,7 +605,15 @@ var InlineTagInput = (0, import_react.forwardRef)(
586
605
  if (!defaultInputPartsAppliedRef.current && (defaultInputParts == null ? void 0 : defaultInputParts.length) && !value && mentions.length === 0) {
587
606
  defaultInputPartsAppliedRef.current = true;
588
607
  skipEmptyCleanupOnceRef.current = true;
608
+ latestMentionsRef.current = defaultInputParts.flatMap((part) => {
609
+ if (part.type === "mention")
610
+ return [part.mention];
611
+ if (part.type === "tag")
612
+ return [part.tag];
613
+ return [];
614
+ });
589
615
  renderPartsToEditor(defaultInputParts);
616
+ setHasContent(true);
590
617
  emitChange();
591
618
  return;
592
619
  }