@copilotkit/react-textarea 1.51.4 → 1.51.5-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.attw.json +3 -0
- package/CHANGELOG.md +18 -0
- package/dist/index.cjs +1918 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +10 -639
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +318 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +318 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +1879 -61
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +1900 -123
- package/dist/index.umd.js.map +1 -1
- package/package.json +18 -16
- package/src/components/copilot-textarea/copilot-textarea.tsx +1 -1
- package/tsdown.config.ts +60 -0
- package/vitest.config.mjs +11 -0
- package/dist/chunk-2C7O2EVM.mjs +0 -27
- package/dist/chunk-2C7O2EVM.mjs.map +0 -1
- package/dist/chunk-2X3CZVEP.mjs +0 -32
- package/dist/chunk-2X3CZVEP.mjs.map +0 -1
- package/dist/chunk-3WLGLZTY.mjs +0 -232
- package/dist/chunk-3WLGLZTY.mjs.map +0 -1
- package/dist/chunk-5UNJXFUO.mjs +0 -29
- package/dist/chunk-5UNJXFUO.mjs.map +0 -1
- package/dist/chunk-7GZWOXE4.mjs +0 -70
- package/dist/chunk-7GZWOXE4.mjs.map +0 -1
- package/dist/chunk-7V4ORVQX.mjs +0 -17
- package/dist/chunk-7V4ORVQX.mjs.map +0 -1
- package/dist/chunk-A6YGJFQI.mjs +0 -111
- package/dist/chunk-A6YGJFQI.mjs.map +0 -1
- package/dist/chunk-AHNPJMBR.mjs +0 -90
- package/dist/chunk-AHNPJMBR.mjs.map +0 -1
- package/dist/chunk-ARLBRSB7.mjs +0 -140
- package/dist/chunk-ARLBRSB7.mjs.map +0 -1
- package/dist/chunk-AZ7RF6ED.mjs +0 -120
- package/dist/chunk-AZ7RF6ED.mjs.map +0 -1
- package/dist/chunk-CFCMZVQ2.mjs +0 -136
- package/dist/chunk-CFCMZVQ2.mjs.map +0 -1
- package/dist/chunk-CMKGYQFX.mjs +0 -45
- package/dist/chunk-CMKGYQFX.mjs.map +0 -1
- package/dist/chunk-DE5K76I2.mjs +0 -1
- package/dist/chunk-DE5K76I2.mjs.map +0 -1
- package/dist/chunk-DZMQBOPG.mjs +0 -36
- package/dist/chunk-DZMQBOPG.mjs.map +0 -1
- package/dist/chunk-E7C63KQP.mjs +0 -64
- package/dist/chunk-E7C63KQP.mjs.map +0 -1
- package/dist/chunk-EGBZSVLK.mjs +0 -25
- package/dist/chunk-EGBZSVLK.mjs.map +0 -1
- package/dist/chunk-FTG7P3NP.mjs +0 -25
- package/dist/chunk-FTG7P3NP.mjs.map +0 -1
- package/dist/chunk-H4VKQGVU.mjs +0 -1
- package/dist/chunk-H4VKQGVU.mjs.map +0 -1
- package/dist/chunk-IBZTDP72.mjs +0 -56
- package/dist/chunk-IBZTDP72.mjs.map +0 -1
- package/dist/chunk-IU3WTXLQ.mjs +0 -1
- package/dist/chunk-IU3WTXLQ.mjs.map +0 -1
- package/dist/chunk-KNQIEOFP.mjs +0 -19
- package/dist/chunk-KNQIEOFP.mjs.map +0 -1
- package/dist/chunk-L7VVZH4Q.mjs +0 -1
- package/dist/chunk-L7VVZH4Q.mjs.map +0 -1
- package/dist/chunk-LYNGBKJR.mjs +0 -58
- package/dist/chunk-LYNGBKJR.mjs.map +0 -1
- package/dist/chunk-M7GTVHFB.mjs +0 -188
- package/dist/chunk-M7GTVHFB.mjs.map +0 -1
- package/dist/chunk-MCNXIA4Q.mjs +0 -75
- package/dist/chunk-MCNXIA4Q.mjs.map +0 -1
- package/dist/chunk-MMVDU6DF.mjs +0 -1
- package/dist/chunk-MMVDU6DF.mjs.map +0 -1
- package/dist/chunk-MQBPYOOZ.mjs +0 -97
- package/dist/chunk-MQBPYOOZ.mjs.map +0 -1
- package/dist/chunk-MQXYWOE2.mjs +0 -32
- package/dist/chunk-MQXYWOE2.mjs.map +0 -1
- package/dist/chunk-MRXNTQOX.mjs +0 -59
- package/dist/chunk-MRXNTQOX.mjs.map +0 -1
- package/dist/chunk-NFMCLTJU.mjs +0 -39
- package/dist/chunk-NFMCLTJU.mjs.map +0 -1
- package/dist/chunk-O4WCM57A.mjs +0 -30
- package/dist/chunk-O4WCM57A.mjs.map +0 -1
- package/dist/chunk-PDFIUPCS.mjs +0 -108
- package/dist/chunk-PDFIUPCS.mjs.map +0 -1
- package/dist/chunk-QFXR6DOA.mjs +0 -64
- package/dist/chunk-QFXR6DOA.mjs.map +0 -1
- package/dist/chunk-RUV6NBIF.mjs +0 -1
- package/dist/chunk-RUV6NBIF.mjs.map +0 -1
- package/dist/chunk-SWX3MRZ4.mjs +0 -278
- package/dist/chunk-SWX3MRZ4.mjs.map +0 -1
- package/dist/chunk-TGN3YVSO.mjs +0 -85
- package/dist/chunk-TGN3YVSO.mjs.map +0 -1
- package/dist/chunk-UB4Y22EF.mjs +0 -21
- package/dist/chunk-UB4Y22EF.mjs.map +0 -1
- package/dist/chunk-UIBUYQPG.mjs +0 -79
- package/dist/chunk-UIBUYQPG.mjs.map +0 -1
- package/dist/chunk-VBPZTMXB.mjs +0 -13
- package/dist/chunk-VBPZTMXB.mjs.map +0 -1
- package/dist/chunk-VH7INUR5.mjs +0 -82
- package/dist/chunk-VH7INUR5.mjs.map +0 -1
- package/dist/chunk-VVRGAA43.mjs +0 -59
- package/dist/chunk-VVRGAA43.mjs.map +0 -1
- package/dist/chunk-VYLLLBUP.mjs +0 -50
- package/dist/chunk-VYLLLBUP.mjs.map +0 -1
- package/dist/chunk-WADHCMPK.mjs +0 -1
- package/dist/chunk-WADHCMPK.mjs.map +0 -1
- package/dist/chunk-WJHSY5T6.mjs +0 -1
- package/dist/chunk-WJHSY5T6.mjs.map +0 -1
- package/dist/chunk-WXKPRNNO.mjs +0 -32
- package/dist/chunk-WXKPRNNO.mjs.map +0 -1
- package/dist/chunk-YINY56BI.mjs +0 -49
- package/dist/chunk-YINY56BI.mjs.map +0 -1
- package/dist/chunk-ZBP4SABT.mjs +0 -117
- package/dist/chunk-ZBP4SABT.mjs.map +0 -1
- package/dist/chunk-ZWI5KPQ5.mjs +0 -31
- package/dist/chunk-ZWI5KPQ5.mjs.map +0 -1
- package/dist/components/base-copilot-textarea/base-copilot-textarea.css +0 -9
- package/dist/components/base-copilot-textarea/base-copilot-textarea.css.map +0 -1
- package/dist/components/base-copilot-textarea/base-copilot-textarea.d.ts +0 -43
- package/dist/components/base-copilot-textarea/base-copilot-textarea.js +0 -1849
- package/dist/components/base-copilot-textarea/base-copilot-textarea.js.map +0 -1
- package/dist/components/base-copilot-textarea/base-copilot-textarea.mjs +0 -40
- package/dist/components/base-copilot-textarea/base-copilot-textarea.mjs.map +0 -1
- package/dist/components/base-copilot-textarea/render-element.d.ts +0 -7
- package/dist/components/base-copilot-textarea/render-element.js +0 -75
- package/dist/components/base-copilot-textarea/render-element.js.map +0 -1
- package/dist/components/base-copilot-textarea/render-element.mjs +0 -8
- package/dist/components/base-copilot-textarea/render-element.mjs.map +0 -1
- package/dist/components/base-copilot-textarea/render-placeholder.d.ts +0 -7
- package/dist/components/base-copilot-textarea/render-placeholder.js +0 -72
- package/dist/components/base-copilot-textarea/render-placeholder.js.map +0 -1
- package/dist/components/base-copilot-textarea/render-placeholder.mjs +0 -8
- package/dist/components/base-copilot-textarea/render-placeholder.mjs.map +0 -1
- package/dist/components/base-copilot-textarea/track-cursor-moved-since-last-text-change.d.ts +0 -8
- package/dist/components/base-copilot-textarea/track-cursor-moved-since-last-text-change.js +0 -112
- package/dist/components/base-copilot-textarea/track-cursor-moved-since-last-text-change.js.map +0 -1
- package/dist/components/base-copilot-textarea/track-cursor-moved-since-last-text-change.mjs +0 -9
- package/dist/components/base-copilot-textarea/track-cursor-moved-since-last-text-change.mjs.map +0 -1
- package/dist/components/base-copilot-textarea/use-add-branding-css.d.ts +0 -3
- package/dist/components/base-copilot-textarea/use-add-branding-css.js +0 -83
- package/dist/components/base-copilot-textarea/use-add-branding-css.js.map +0 -1
- package/dist/components/base-copilot-textarea/use-add-branding-css.mjs +0 -8
- package/dist/components/base-copilot-textarea/use-add-branding-css.mjs.map +0 -1
- package/dist/components/copilot-textarea/copilot-textarea.css +0 -9
- package/dist/components/copilot-textarea/copilot-textarea.css.map +0 -1
- package/dist/components/copilot-textarea/copilot-textarea.d.ts +0 -171
- package/dist/components/copilot-textarea/copilot-textarea.js +0 -2356
- package/dist/components/copilot-textarea/copilot-textarea.js.map +0 -1
- package/dist/components/copilot-textarea/copilot-textarea.mjs +0 -49
- package/dist/components/copilot-textarea/copilot-textarea.mjs.map +0 -1
- package/dist/components/hovering-toolbar/hovering-editor-provider.d.ts +0 -18
- package/dist/components/hovering-toolbar/hovering-editor-provider.js +0 -46
- package/dist/components/hovering-toolbar/hovering-editor-provider.js.map +0 -1
- package/dist/components/hovering-toolbar/hovering-editor-provider.mjs +0 -10
- package/dist/components/hovering-toolbar/hovering-editor-provider.mjs.map +0 -1
- package/dist/components/hovering-toolbar/hovering-toolbar-components.d.ts +0 -18
- package/dist/components/hovering-toolbar/hovering-toolbar-components.js +0 -158
- package/dist/components/hovering-toolbar/hovering-toolbar-components.js.map +0 -1
- package/dist/components/hovering-toolbar/hovering-toolbar-components.mjs +0 -16
- package/dist/components/hovering-toolbar/hovering-toolbar-components.mjs.map +0 -1
- package/dist/components/hovering-toolbar/hovering-toolbar.d.ts +0 -12
- package/dist/components/hovering-toolbar/hovering-toolbar.js +0 -934
- package/dist/components/hovering-toolbar/hovering-toolbar.js.map +0 -1
- package/dist/components/hovering-toolbar/hovering-toolbar.mjs +0 -23
- package/dist/components/hovering-toolbar/hovering-toolbar.mjs.map +0 -1
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/hovering-insertion-prompt-box-core.d.ts +0 -16
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/hovering-insertion-prompt-box-core.js +0 -649
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/hovering-insertion-prompt-box-core.js.map +0 -1
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/hovering-insertion-prompt-box-core.mjs +0 -18
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/hovering-insertion-prompt-box-core.mjs.map +0 -1
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/hovering-insertion-prompt-box.d.ts +0 -13
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/hovering-insertion-prompt-box.js +0 -672
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/hovering-insertion-prompt-box.js.map +0 -1
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/hovering-insertion-prompt-box.mjs +0 -19
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/hovering-insertion-prompt-box.mjs.map +0 -1
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/included-files-preview.d.ts +0 -16
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/included-files-preview.js +0 -144
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/included-files-preview.js.map +0 -1
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/included-files-preview.mjs +0 -12
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/included-files-preview.mjs.map +0 -1
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/index.d.ts +0 -4
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/index.js +0 -672
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/index.js.map +0 -1
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/index.mjs +0 -20
- package/dist/components/hovering-toolbar/text-insertion-prompt-box/index.mjs.map +0 -1
- package/dist/components/index.css +0 -9
- package/dist/components/index.css.map +0 -1
- package/dist/components/index.d.ts +0 -15
- package/dist/components/index.js +0 -2360
- package/dist/components/index.js.map +0 -1
- package/dist/components/index.mjs +0 -53
- package/dist/components/index.mjs.map +0 -1
- package/dist/components/manual-ui/chip-with-icon.d.ts +0 -10
- package/dist/components/manual-ui/chip-with-icon.js +0 -49
- package/dist/components/manual-ui/chip-with-icon.js.map +0 -1
- package/dist/components/manual-ui/chip-with-icon.mjs +0 -26
- package/dist/components/manual-ui/chip-with-icon.mjs.map +0 -1
- package/dist/components/source-search-box/source-search-box.d.ts +0 -16
- package/dist/components/source-search-box/source-search-box.js +0 -263
- package/dist/components/source-search-box/source-search-box.js.map +0 -1
- package/dist/components/source-search-box/source-search-box.mjs +0 -13
- package/dist/components/source-search-box/source-search-box.mjs.map +0 -1
- package/dist/components/ui/button.d.ts +0 -14
- package/dist/components/ui/button.js +0 -120
- package/dist/components/ui/button.js.map +0 -1
- package/dist/components/ui/button.mjs +0 -11
- package/dist/components/ui/button.mjs.map +0 -1
- package/dist/components/ui/command.d.ts +0 -53
- package/dist/components/ui/command.js +0 -323
- package/dist/components/ui/command.js.map +0 -1
- package/dist/components/ui/command.mjs +0 -26
- package/dist/components/ui/command.mjs.map +0 -1
- package/dist/components/ui/dialog.d.ts +0 -19
- package/dist/components/ui/dialog.js +0 -205
- package/dist/components/ui/dialog.js.map +0 -1
- package/dist/components/ui/dialog.mjs +0 -21
- package/dist/components/ui/dialog.mjs.map +0 -1
- package/dist/components/ui/label.d.ts +0 -8
- package/dist/components/ui/label.js +0 -93
- package/dist/components/ui/label.js.map +0 -1
- package/dist/components/ui/label.mjs +0 -9
- package/dist/components/ui/label.mjs.map +0 -1
- package/dist/context/index.d.ts +0 -2
- package/dist/context/index.js +0 -19
- package/dist/context/index.js.map +0 -1
- package/dist/context/index.mjs +0 -2
- package/dist/context/index.mjs.map +0 -1
- package/dist/hooks/base-copilot-textarea-implementation/use-autosuggestions.d.ts +0 -15
- package/dist/hooks/base-copilot-textarea-implementation/use-autosuggestions.js +0 -194
- package/dist/hooks/base-copilot-textarea-implementation/use-autosuggestions.js.map +0 -1
- package/dist/hooks/base-copilot-textarea-implementation/use-autosuggestions.mjs +0 -11
- package/dist/hooks/base-copilot-textarea-implementation/use-autosuggestions.mjs.map +0 -1
- package/dist/hooks/base-copilot-textarea-implementation/use-copilot-textarea-editor.d.ts +0 -8
- package/dist/hooks/base-copilot-textarea-implementation/use-copilot-textarea-editor.js +0 -194
- package/dist/hooks/base-copilot-textarea-implementation/use-copilot-textarea-editor.js.map +0 -1
- package/dist/hooks/base-copilot-textarea-implementation/use-copilot-textarea-editor.mjs +0 -9
- package/dist/hooks/base-copilot-textarea-implementation/use-copilot-textarea-editor.mjs.map +0 -1
- package/dist/hooks/base-copilot-textarea-implementation/use-populate-copilot-textarea-ref.d.ts +0 -7
- package/dist/hooks/base-copilot-textarea-implementation/use-populate-copilot-textarea-ref.js +0 -180
- package/dist/hooks/base-copilot-textarea-implementation/use-populate-copilot-textarea-ref.js.map +0 -1
- package/dist/hooks/base-copilot-textarea-implementation/use-populate-copilot-textarea-ref.mjs +0 -10
- package/dist/hooks/base-copilot-textarea-implementation/use-populate-copilot-textarea-ref.mjs.map +0 -1
- package/dist/hooks/index.d.ts +0 -2
- package/dist/hooks/index.js +0 -19
- package/dist/hooks/index.js.map +0 -1
- package/dist/hooks/index.mjs +0 -2
- package/dist/hooks/index.mjs.map +0 -1
- package/dist/hooks/make-autosuggestions-function/use-make-standard-autosuggestions-function.d.ts +0 -22
- package/dist/hooks/make-autosuggestions-function/use-make-standard-autosuggestions-function.js +0 -142
- package/dist/hooks/make-autosuggestions-function/use-make-standard-autosuggestions-function.js.map +0 -1
- package/dist/hooks/make-autosuggestions-function/use-make-standard-autosuggestions-function.mjs +0 -9
- package/dist/hooks/make-autosuggestions-function/use-make-standard-autosuggestions-function.mjs.map +0 -1
- package/dist/hooks/make-autosuggestions-function/use-make-standard-insertion-function.d.ts +0 -23
- package/dist/hooks/make-autosuggestions-function/use-make-standard-insertion-function.js +0 -248
- package/dist/hooks/make-autosuggestions-function/use-make-standard-insertion-function.js.map +0 -1
- package/dist/hooks/make-autosuggestions-function/use-make-standard-insertion-function.mjs +0 -9
- package/dist/hooks/make-autosuggestions-function/use-make-standard-insertion-function.mjs.map +0 -1
- package/dist/hooks/misc/use-autosize-textarea.d.ts +0 -5
- package/dist/hooks/misc/use-autosize-textarea.js +0 -37
- package/dist/hooks/misc/use-autosize-textarea.js.map +0 -1
- package/dist/hooks/misc/use-autosize-textarea.mjs +0 -8
- package/dist/hooks/misc/use-autosize-textarea.mjs.map +0 -1
- package/dist/index.d.ts +0 -15
- package/dist/index.js +0 -2365
- package/dist/index.js.map +0 -1
- package/dist/lib/debouncer.d.ts +0 -11
- package/dist/lib/debouncer.js +0 -76
- package/dist/lib/debouncer.js.map +0 -1
- package/dist/lib/debouncer.mjs +0 -8
- package/dist/lib/debouncer.mjs.map +0 -1
- package/dist/lib/editor-to-text.d.ts +0 -7
- package/dist/lib/editor-to-text.js +0 -69
- package/dist/lib/editor-to-text.js.map +0 -1
- package/dist/lib/editor-to-text.mjs +0 -8
- package/dist/lib/editor-to-text.mjs.map +0 -1
- package/dist/lib/get-text-around-cursor.d.ts +0 -15
- package/dist/lib/get-text-around-cursor.js +0 -131
- package/dist/lib/get-text-around-cursor.js.map +0 -1
- package/dist/lib/get-text-around-cursor.mjs +0 -14
- package/dist/lib/get-text-around-cursor.mjs.map +0 -1
- package/dist/lib/retry.d.ts +0 -3
- package/dist/lib/retry.js +0 -43
- package/dist/lib/retry.js.map +0 -1
- package/dist/lib/retry.mjs +0 -8
- package/dist/lib/retry.mjs.map +0 -1
- package/dist/lib/slatejs-edits/add-autocompletions.d.ts +0 -8
- package/dist/lib/slatejs-edits/add-autocompletions.js +0 -51
- package/dist/lib/slatejs-edits/add-autocompletions.js.map +0 -1
- package/dist/lib/slatejs-edits/add-autocompletions.mjs +0 -8
- package/dist/lib/slatejs-edits/add-autocompletions.mjs.map +0 -1
- package/dist/lib/slatejs-edits/clear-autocompletions.d.ts +0 -8
- package/dist/lib/slatejs-edits/clear-autocompletions.js +0 -49
- package/dist/lib/slatejs-edits/clear-autocompletions.js.map +0 -1
- package/dist/lib/slatejs-edits/clear-autocompletions.mjs +0 -8
- package/dist/lib/slatejs-edits/clear-autocompletions.mjs.map +0 -1
- package/dist/lib/slatejs-edits/replace-text.d.ts +0 -5
- package/dist/lib/slatejs-edits/replace-text.js +0 -53
- package/dist/lib/slatejs-edits/replace-text.js.map +0 -1
- package/dist/lib/slatejs-edits/replace-text.mjs +0 -8
- package/dist/lib/slatejs-edits/replace-text.mjs.map +0 -1
- package/dist/lib/slatejs-edits/with-partial-history.d.ts +0 -8
- package/dist/lib/slatejs-edits/with-partial-history.js +0 -133
- package/dist/lib/slatejs-edits/with-partial-history.js.map +0 -1
- package/dist/lib/slatejs-edits/with-partial-history.mjs +0 -10
- package/dist/lib/slatejs-edits/with-partial-history.mjs.map +0 -1
- package/dist/lib/stream-promise-flatten.d.ts +0 -12
- package/dist/lib/stream-promise-flatten.js +0 -72
- package/dist/lib/stream-promise-flatten.js.map +0 -1
- package/dist/lib/stream-promise-flatten.mjs +0 -8
- package/dist/lib/stream-promise-flatten.mjs.map +0 -1
- package/dist/lib/utils.d.ts +0 -9
- package/dist/lib/utils.js +0 -94
- package/dist/lib/utils.js.map +0 -1
- package/dist/lib/utils.mjs +0 -16
- package/dist/lib/utils.mjs.map +0 -1
- package/dist/types/autosuggestions-config/autosuggestions-config-user-specified.d.ts +0 -23
- package/dist/types/autosuggestions-config/autosuggestions-config-user-specified.js +0 -19
- package/dist/types/autosuggestions-config/autosuggestions-config-user-specified.js.map +0 -1
- package/dist/types/autosuggestions-config/autosuggestions-config-user-specified.mjs +0 -1
- package/dist/types/autosuggestions-config/autosuggestions-config-user-specified.mjs.map +0 -1
- package/dist/types/autosuggestions-config/autosuggestions-config.d.ts +0 -20
- package/dist/types/autosuggestions-config/autosuggestions-config.js +0 -287
- package/dist/types/autosuggestions-config/autosuggestions-config.js.map +0 -1
- package/dist/types/autosuggestions-config/autosuggestions-config.mjs +0 -13
- package/dist/types/autosuggestions-config/autosuggestions-config.mjs.map +0 -1
- package/dist/types/autosuggestions-config/editing-api-config.d.ts +0 -15
- package/dist/types/autosuggestions-config/editing-api-config.js +0 -108
- package/dist/types/autosuggestions-config/editing-api-config.js.map +0 -1
- package/dist/types/autosuggestions-config/editing-api-config.mjs +0 -12
- package/dist/types/autosuggestions-config/editing-api-config.mjs.map +0 -1
- package/dist/types/autosuggestions-config/index.d.ts +0 -10
- package/dist/types/autosuggestions-config/index.js +0 -287
- package/dist/types/autosuggestions-config/index.js.map +0 -1
- package/dist/types/autosuggestions-config/index.mjs +0 -14
- package/dist/types/autosuggestions-config/index.mjs.map +0 -1
- package/dist/types/autosuggestions-config/insertions-api-config.d.ts +0 -15
- package/dist/types/autosuggestions-config/insertions-api-config.js +0 -101
- package/dist/types/autosuggestions-config/insertions-api-config.js.map +0 -1
- package/dist/types/autosuggestions-config/insertions-api-config.mjs +0 -12
- package/dist/types/autosuggestions-config/insertions-api-config.mjs.map +0 -1
- package/dist/types/autosuggestions-config/subtypes/make-system-prompt.d.ts +0 -3
- package/dist/types/autosuggestions-config/subtypes/make-system-prompt.js +0 -19
- package/dist/types/autosuggestions-config/subtypes/make-system-prompt.js.map +0 -1
- package/dist/types/autosuggestions-config/subtypes/make-system-prompt.mjs +0 -1
- package/dist/types/autosuggestions-config/subtypes/make-system-prompt.mjs.map +0 -1
- package/dist/types/autosuggestions-config/suggestions-api-config.d.ts +0 -15
- package/dist/types/autosuggestions-config/suggestions-api-config.js +0 -90
- package/dist/types/autosuggestions-config/suggestions-api-config.js.map +0 -1
- package/dist/types/autosuggestions-config/suggestions-api-config.mjs +0 -12
- package/dist/types/autosuggestions-config/suggestions-api-config.mjs.map +0 -1
- package/dist/types/base/autosuggestion-state.d.ts +0 -8
- package/dist/types/base/autosuggestion-state.js +0 -19
- package/dist/types/base/autosuggestion-state.js.map +0 -1
- package/dist/types/base/autosuggestion-state.mjs +0 -1
- package/dist/types/base/autosuggestion-state.mjs.map +0 -1
- package/dist/types/base/autosuggestions-bare-function.d.ts +0 -19
- package/dist/types/base/autosuggestions-bare-function.js +0 -19
- package/dist/types/base/autosuggestions-bare-function.js.map +0 -1
- package/dist/types/base/autosuggestions-bare-function.mjs +0 -1
- package/dist/types/base/autosuggestions-bare-function.mjs.map +0 -1
- package/dist/types/base/base-autosuggestions-config.d.ts +0 -87
- package/dist/types/base/base-autosuggestions-config.js +0 -54
- package/dist/types/base/base-autosuggestions-config.js.map +0 -1
- package/dist/types/base/base-autosuggestions-config.mjs +0 -8
- package/dist/types/base/base-autosuggestions-config.mjs.map +0 -1
- package/dist/types/base/base-copilot-textarea-props.d.ts +0 -5
- package/dist/types/base/base-copilot-textarea-props.js +0 -19
- package/dist/types/base/base-copilot-textarea-props.js.map +0 -1
- package/dist/types/base/base-copilot-textarea-props.mjs +0 -1
- package/dist/types/base/base-copilot-textarea-props.mjs.map +0 -1
- package/dist/types/base/custom-editor.d.ts +0 -29
- package/dist/types/base/custom-editor.js +0 -19
- package/dist/types/base/custom-editor.js.map +0 -1
- package/dist/types/base/custom-editor.mjs +0 -1
- package/dist/types/base/custom-editor.mjs.map +0 -1
- package/dist/types/base/editor-autocomplete-state.d.ts +0 -10
- package/dist/types/base/editor-autocomplete-state.js +0 -40
- package/dist/types/base/editor-autocomplete-state.js.map +0 -1
- package/dist/types/base/editor-autocomplete-state.mjs +0 -9
- package/dist/types/base/editor-autocomplete-state.mjs.map +0 -1
- package/dist/types/base/index.d.ts +0 -54
- package/dist/types/base/index.js +0 -56
- package/dist/types/base/index.js.map +0 -1
- package/dist/types/base/index.mjs +0 -9
- package/dist/types/base/index.mjs.map +0 -1
- package/dist/types/html-copilot-textarea-element.d.ts +0 -7
- package/dist/types/html-copilot-textarea-element.js +0 -19
- package/dist/types/html-copilot-textarea-element.js.map +0 -1
- package/dist/types/html-copilot-textarea-element.mjs +0 -2
- package/dist/types/html-copilot-textarea-element.mjs.map +0 -1
- package/dist/types/index.d.ts +0 -13
- package/dist/types/index.js +0 -289
- package/dist/types/index.js.map +0 -1
- package/dist/types/index.mjs +0 -19
- package/dist/types/index.mjs.map +0 -1
- package/jest.config.js +0 -5
- package/rollup.config.mjs +0 -64
- package/tsup.config.ts +0 -15
package/dist/index.mjs
CHANGED
|
@@ -1,64 +1,1882 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
|
|
3
|
-
import "
|
|
4
|
-
import "
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
} from "
|
|
8
|
-
import "
|
|
9
|
-
import "
|
|
10
|
-
import "
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
} from "
|
|
14
|
-
import "
|
|
15
|
-
import "
|
|
16
|
-
import "
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
import "
|
|
21
|
-
import "
|
|
22
|
-
import "
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
import "./chunk-FTG7P3NP.mjs";
|
|
50
|
-
import "./chunk-YINY56BI.mjs";
|
|
51
|
-
import "./chunk-IU3WTXLQ.mjs";
|
|
52
|
-
import "./chunk-H4VKQGVU.mjs";
|
|
53
|
-
import "./chunk-DZMQBOPG.mjs";
|
|
54
|
-
import "./chunk-CMKGYQFX.mjs";
|
|
55
|
-
import "./chunk-A6YGJFQI.mjs";
|
|
56
|
-
import "./chunk-KNQIEOFP.mjs";
|
|
57
|
-
import "./chunk-MRXNTQOX.mjs";
|
|
58
|
-
export {
|
|
59
|
-
BaseCopilotTextarea,
|
|
60
|
-
CopilotTextarea,
|
|
61
|
-
defaultAutosuggestionsConfig,
|
|
62
|
-
defaultBaseAutosuggestionsConfig
|
|
2
|
+
|
|
3
|
+
import * as React$1 from "react";
|
|
4
|
+
import React, { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { Editor, Element, Node, Operation, Path, Point, Range, Text, Transforms, createEditor } from "slate";
|
|
6
|
+
import { Editable, ReactEditor, Slate, useSlate, useSlateSelection, useSlateSelector, withReact } from "slate-react";
|
|
7
|
+
import { twMerge } from "tailwind-merge";
|
|
8
|
+
import { clsx } from "clsx";
|
|
9
|
+
import { HistoryEditor } from "slate-history";
|
|
10
|
+
import { defaultCopilotContextCategories, useCopilotContext } from "@copilotkit/react-core";
|
|
11
|
+
import { COPILOT_CLOUD_PUBLIC_API_KEY_HEADER, isMacOS } from "@copilotkit/shared";
|
|
12
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
+
import { css, cx } from "@emotion/css";
|
|
14
|
+
import ReactDOM from "react-dom";
|
|
15
|
+
import { Command } from "cmdk";
|
|
16
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
17
|
+
import { cva } from "class-variance-authority";
|
|
18
|
+
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
19
|
+
import Chip from "@mui/material/Chip/Chip.js";
|
|
20
|
+
import Avatar from "@mui/material/Avatar/Avatar.js";
|
|
21
|
+
import { CopilotRequestType, Role, TextMessage, convertGqlOutputToMessages, convertMessagesToGqlInput, filterAgentStateMessages } from "@copilotkit/runtime-client-gql";
|
|
22
|
+
import merge from "lodash.merge";
|
|
23
|
+
|
|
24
|
+
//#region src/lib/debouncer.ts
|
|
25
|
+
var Debouncer = class {
|
|
26
|
+
constructor(wait) {
|
|
27
|
+
this.wait = wait;
|
|
28
|
+
this.debounce = async (func, ...args) => {
|
|
29
|
+
this.cancel();
|
|
30
|
+
this.timeoutId = setTimeout(async () => {
|
|
31
|
+
try {
|
|
32
|
+
this.activeAbortController = new AbortController();
|
|
33
|
+
await func(...args, this.activeAbortController.signal);
|
|
34
|
+
this.activeAbortController = void 0;
|
|
35
|
+
} catch (error) {}
|
|
36
|
+
}, this.wait);
|
|
37
|
+
};
|
|
38
|
+
this.cancel = () => {
|
|
39
|
+
if (this.activeAbortController) {
|
|
40
|
+
this.activeAbortController.abort();
|
|
41
|
+
this.activeAbortController = void 0;
|
|
42
|
+
}
|
|
43
|
+
if (this.timeoutId !== void 0) {
|
|
44
|
+
clearTimeout(this.timeoutId);
|
|
45
|
+
this.timeoutId = void 0;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
63
49
|
};
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/lib/utils.ts
|
|
53
|
+
function cn(...inputs) {
|
|
54
|
+
return twMerge(clsx(inputs));
|
|
55
|
+
}
|
|
56
|
+
const arraysAreEqual = (arr1, arr2) => arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]);
|
|
57
|
+
function nullableCompatibleEqualityCheck(naiveEqualityCheck, a, b) {
|
|
58
|
+
if (a === null || a === void 0 || b === null || b === void 0) return a === b;
|
|
59
|
+
return naiveEqualityCheck(a, b);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/types/base/editor-autocomplete-state.ts
|
|
64
|
+
function areEqual_autocompleteState(prev, next) {
|
|
65
|
+
return prev.cursorPoint.offset === next.cursorPoint.offset && arraysAreEqual(prev.cursorPoint.path, next.cursorPoint.path) && prev.textBeforeCursor === next.textBeforeCursor && prev.textAfterCursor === next.textAfterCursor;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/hooks/base-copilot-textarea-implementation/use-autosuggestions.ts
|
|
70
|
+
function useAutosuggestions(debounceTime, shouldAcceptAutosuggestionOnKeyPress, shouldAcceptAutosuggestionOnTouch, autosuggestionFunction, insertAutocompleteSuggestion, disableWhenEmpty, disabled) {
|
|
71
|
+
const [previousAutocompleteState, setPreviousAutocompleteState] = useState(null);
|
|
72
|
+
const [currentAutocompleteSuggestion, setCurrentAutocompleteSuggestion] = useState(null);
|
|
73
|
+
const awaitForAndAppendSuggestion = useCallback(async (editorAutocompleteState, abortSignal) => {
|
|
74
|
+
if (disabled) return;
|
|
75
|
+
if (disableWhenEmpty && editorAutocompleteState.textBeforeCursor === "" && editorAutocompleteState.textAfterCursor === "") return;
|
|
76
|
+
const suggestion = await autosuggestionFunction(editorAutocompleteState, abortSignal);
|
|
77
|
+
if (!suggestion || abortSignal.aborted) throw new DOMException("Aborted", "AbortError");
|
|
78
|
+
setCurrentAutocompleteSuggestion({
|
|
79
|
+
text: suggestion,
|
|
80
|
+
point: editorAutocompleteState.cursorPoint
|
|
81
|
+
});
|
|
82
|
+
}, [
|
|
83
|
+
autosuggestionFunction,
|
|
84
|
+
setCurrentAutocompleteSuggestion,
|
|
85
|
+
disableWhenEmpty,
|
|
86
|
+
disabled
|
|
87
|
+
]);
|
|
88
|
+
const debouncedFunction = useMemo(() => new Debouncer(debounceTime), [debounceTime]);
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
return () => {
|
|
91
|
+
debouncedFunction.cancel();
|
|
92
|
+
setCurrentAutocompleteSuggestion(null);
|
|
93
|
+
};
|
|
94
|
+
}, [debouncedFunction, disabled]);
|
|
95
|
+
const onChange = useCallback((newEditorState) => {
|
|
96
|
+
const editorStateHasChanged = !nullableCompatibleEqualityCheck(areEqual_autocompleteState, previousAutocompleteState, newEditorState);
|
|
97
|
+
setPreviousAutocompleteState(newEditorState);
|
|
98
|
+
if (!editorStateHasChanged) return;
|
|
99
|
+
setCurrentAutocompleteSuggestion(null);
|
|
100
|
+
if (newEditorState) debouncedFunction.debounce(awaitForAndAppendSuggestion, newEditorState);
|
|
101
|
+
else debouncedFunction.cancel();
|
|
102
|
+
}, [
|
|
103
|
+
previousAutocompleteState,
|
|
104
|
+
setPreviousAutocompleteState,
|
|
105
|
+
debouncedFunction,
|
|
106
|
+
awaitForAndAppendSuggestion,
|
|
107
|
+
setCurrentAutocompleteSuggestion
|
|
108
|
+
]);
|
|
109
|
+
const keyDownOrTouchHandler = useCallback((event) => {
|
|
110
|
+
if (currentAutocompleteSuggestion) {
|
|
111
|
+
if (event.type === "touchstart" ? shouldAcceptAutosuggestionOnTouch(event) : shouldAcceptAutosuggestionOnKeyPress(event)) {
|
|
112
|
+
event.preventDefault();
|
|
113
|
+
insertAutocompleteSuggestion(currentAutocompleteSuggestion);
|
|
114
|
+
setCurrentAutocompleteSuggestion(null);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}, [
|
|
118
|
+
currentAutocompleteSuggestion,
|
|
119
|
+
setCurrentAutocompleteSuggestion,
|
|
120
|
+
insertAutocompleteSuggestion,
|
|
121
|
+
shouldAcceptAutosuggestionOnKeyPress
|
|
122
|
+
]);
|
|
123
|
+
return {
|
|
124
|
+
currentAutocompleteSuggestion,
|
|
125
|
+
onChangeHandler: onChange,
|
|
126
|
+
onKeyDownHandler: keyDownOrTouchHandler,
|
|
127
|
+
onTouchStartHandler: keyDownOrTouchHandler
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
//#endregion
|
|
132
|
+
//#region src/lib/slatejs-edits/with-partial-history.ts
|
|
133
|
+
const withPartialHistory = (editor, shouldSave) => {
|
|
134
|
+
const e = editor;
|
|
135
|
+
const { apply } = e;
|
|
136
|
+
e.history = {
|
|
137
|
+
undos: [],
|
|
138
|
+
redos: []
|
|
139
|
+
};
|
|
140
|
+
e.redo = () => {
|
|
141
|
+
const { history } = e;
|
|
142
|
+
const { redos } = history;
|
|
143
|
+
if (redos.length > 0) {
|
|
144
|
+
const batch = redos[redos.length - 1];
|
|
145
|
+
if (batch.selectionBefore) Transforms.setSelection(e, batch.selectionBefore);
|
|
146
|
+
HistoryEditor.withoutSaving(e, () => {
|
|
147
|
+
Editor.withoutNormalizing(e, () => {
|
|
148
|
+
for (const op of batch.operations) e.apply(op);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
history.redos.pop();
|
|
152
|
+
e.writeHistory("undos", batch);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
e.undo = () => {
|
|
156
|
+
const { history } = e;
|
|
157
|
+
const { undos } = history;
|
|
158
|
+
if (undos.length > 0) {
|
|
159
|
+
const batch = undos[undos.length - 1];
|
|
160
|
+
HistoryEditor.withoutSaving(e, () => {
|
|
161
|
+
Editor.withoutNormalizing(e, () => {
|
|
162
|
+
const inverseOps = batch.operations.map(Operation.inverse).reverse();
|
|
163
|
+
for (const op of inverseOps) e.apply(op);
|
|
164
|
+
if (batch.selectionBefore) Transforms.setSelection(e, batch.selectionBefore);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
e.writeHistory("redos", batch);
|
|
168
|
+
history.undos.pop();
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
e.apply = (op) => {
|
|
172
|
+
const { operations, history } = e;
|
|
173
|
+
const { undos } = history;
|
|
174
|
+
const lastBatch = undos[undos.length - 1];
|
|
175
|
+
const lastOp = lastBatch && lastBatch.operations[lastBatch.operations.length - 1];
|
|
176
|
+
let save = HistoryEditor.isSaving(e);
|
|
177
|
+
let merge = HistoryEditor.isMerging(e);
|
|
178
|
+
if (save == null) save = shouldSave(op, lastOp);
|
|
179
|
+
if (save) {
|
|
180
|
+
if (merge == null) if (lastBatch == null) merge = false;
|
|
181
|
+
else if (operations.length !== 0) merge = true;
|
|
182
|
+
else merge = shouldMerge(op, lastOp);
|
|
183
|
+
if (lastBatch && merge) lastBatch.operations.push(op);
|
|
184
|
+
else {
|
|
185
|
+
const batch = {
|
|
186
|
+
operations: [op],
|
|
187
|
+
selectionBefore: e.selection
|
|
188
|
+
};
|
|
189
|
+
e.writeHistory("undos", batch);
|
|
190
|
+
}
|
|
191
|
+
while (undos.length > 100) undos.shift();
|
|
192
|
+
history.redos = [];
|
|
193
|
+
}
|
|
194
|
+
apply(op);
|
|
195
|
+
};
|
|
196
|
+
e.writeHistory = (stack, batch) => {
|
|
197
|
+
e.history[stack].push(batch);
|
|
198
|
+
};
|
|
199
|
+
return e;
|
|
200
|
+
};
|
|
201
|
+
/**
|
|
202
|
+
* Check whether to merge an operation into the previous operation.
|
|
203
|
+
*/
|
|
204
|
+
const shouldMerge = (op, prev) => {
|
|
205
|
+
if (prev && op.type === "insert_text" && prev.type === "insert_text" && op.offset === prev.offset + prev.text.length && Path.equals(op.path, prev.path)) return true;
|
|
206
|
+
if (prev && op.type === "remove_text" && prev.type === "remove_text" && op.offset + op.text.length === prev.offset && Path.equals(op.path, prev.path)) return true;
|
|
207
|
+
return false;
|
|
208
|
+
};
|
|
209
|
+
const defaultShouldSave = (op, prev) => {
|
|
210
|
+
if (op.type === "set_selection") return false;
|
|
211
|
+
return true;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
//#endregion
|
|
215
|
+
//#region src/hooks/base-copilot-textarea-implementation/use-copilot-textarea-editor.tsx
|
|
216
|
+
const shouldSave = (op, prev) => {
|
|
217
|
+
const excludedNodeType = "suggestion";
|
|
218
|
+
if (op.type === "insert_node" && Element.isElement(op.node) && op.node.type === excludedNodeType) return false;
|
|
219
|
+
if (op.type === "remove_node" && Element.isElement(op.node) && op.node.type === excludedNodeType) return false;
|
|
220
|
+
if (op.type === "set_node" && "type" in op.newProperties && op.newProperties.type === excludedNodeType) return false;
|
|
221
|
+
if (op.type == "set_node" && "type" in op.properties && op.properties.type === excludedNodeType) return false;
|
|
222
|
+
if (op.type === "merge_node" && "type" in op.properties && op.properties.type === excludedNodeType) return false;
|
|
223
|
+
if (op.type === "split_node" && "type" in op.properties && op.properties.type === excludedNodeType) return false;
|
|
224
|
+
return defaultShouldSave(op, prev);
|
|
225
|
+
};
|
|
226
|
+
function useCopilotTextareaEditor() {
|
|
227
|
+
return useMemo(() => {
|
|
228
|
+
const editor = withPartialHistory(withReact(createEditor()), shouldSave);
|
|
229
|
+
const { isVoid } = editor;
|
|
230
|
+
editor.isVoid = (element) => {
|
|
231
|
+
switch (element.type) {
|
|
232
|
+
case "suggestion": return true;
|
|
233
|
+
default: return isVoid(element);
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
const { markableVoid } = editor;
|
|
237
|
+
editor.markableVoid = (element) => {
|
|
238
|
+
switch (element.type) {
|
|
239
|
+
case "suggestion": return true;
|
|
240
|
+
default: return markableVoid(element);
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
const { isInline } = editor;
|
|
244
|
+
editor.isInline = (element) => {
|
|
245
|
+
switch (element.type) {
|
|
246
|
+
case "suggestion": return element.inline;
|
|
247
|
+
default: return isInline(element);
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
return editor;
|
|
251
|
+
}, []);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
//#endregion
|
|
255
|
+
//#region src/lib/get-text-around-cursor.ts
|
|
256
|
+
function getTextAroundCollapsedCursor(editor) {
|
|
257
|
+
const { selection } = editor;
|
|
258
|
+
if (!selection || !Range.isCollapsed(selection)) return null;
|
|
259
|
+
const cursorPoint = selection.anchor;
|
|
260
|
+
const beforeRange = {
|
|
261
|
+
anchor: Editor.start(editor, []),
|
|
262
|
+
focus: cursorPoint
|
|
263
|
+
};
|
|
264
|
+
const afterRange = {
|
|
265
|
+
anchor: cursorPoint,
|
|
266
|
+
focus: Editor.end(editor, [])
|
|
267
|
+
};
|
|
268
|
+
return {
|
|
269
|
+
cursorPoint,
|
|
270
|
+
textBeforeCursor: extractTextWithNewlines(editor, beforeRange),
|
|
271
|
+
textAfterCursor: extractTextWithNewlines(editor, afterRange)
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
function getTextAroundSelection(editor) {
|
|
275
|
+
const { selection } = editor;
|
|
276
|
+
if (!selection) return null;
|
|
277
|
+
const wellOrderedSelection = wellOrderedRange(selection);
|
|
278
|
+
const beforeRange = {
|
|
279
|
+
anchor: Editor.start(editor, []),
|
|
280
|
+
focus: wellOrderedSelection.anchor
|
|
281
|
+
};
|
|
282
|
+
const afterRange = {
|
|
283
|
+
anchor: wellOrderedSelection.focus,
|
|
284
|
+
focus: Editor.end(editor, [])
|
|
285
|
+
};
|
|
286
|
+
const before = extractTextWithNewlines(editor, beforeRange);
|
|
287
|
+
const after = extractTextWithNewlines(editor, afterRange);
|
|
288
|
+
return {
|
|
289
|
+
selection: wellOrderedSelection,
|
|
290
|
+
textBeforeCursor: before,
|
|
291
|
+
selectedText: extractTextWithNewlines(editor, wellOrderedSelection),
|
|
292
|
+
textAfterCursor: after
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
function getFullEditorTextWithNewlines(editor) {
|
|
296
|
+
return extractTextWithNewlines(editor, {
|
|
297
|
+
anchor: Editor.start(editor, []),
|
|
298
|
+
focus: Editor.end(editor, [])
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
function extractTextWithNewlines(editor, range) {
|
|
302
|
+
const voids = false;
|
|
303
|
+
const [start, end] = Range.edges(range);
|
|
304
|
+
let text = "";
|
|
305
|
+
let lastBlock = null;
|
|
306
|
+
for (const [node, path] of Editor.nodes(editor, {
|
|
307
|
+
at: range,
|
|
308
|
+
match: Text.isText,
|
|
309
|
+
voids
|
|
310
|
+
})) {
|
|
311
|
+
let t = node.text;
|
|
312
|
+
const [block] = Editor.above(editor, {
|
|
313
|
+
at: path,
|
|
314
|
+
match: (n) => Element.isElement(n) && n.type === "paragraph"
|
|
315
|
+
}) || [null];
|
|
316
|
+
if (lastBlock !== block && block) {
|
|
317
|
+
if (lastBlock) text += "\n";
|
|
318
|
+
lastBlock = block;
|
|
319
|
+
}
|
|
320
|
+
if (Path.equals(path, end.path)) t = t.slice(0, end.offset);
|
|
321
|
+
if (Path.equals(path, start.path)) t = t.slice(start.offset);
|
|
322
|
+
text += t;
|
|
323
|
+
}
|
|
324
|
+
return text;
|
|
325
|
+
}
|
|
326
|
+
function wellOrderedRange(range) {
|
|
327
|
+
const { anchor, focus } = range;
|
|
328
|
+
if (Point.isBefore(anchor, focus)) return range;
|
|
329
|
+
return {
|
|
330
|
+
anchor: focus,
|
|
331
|
+
focus: anchor
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
//#endregion
|
|
336
|
+
//#region src/lib/slatejs-edits/replace-text.ts
|
|
337
|
+
function replaceEditorText(editor, newText) {
|
|
338
|
+
Transforms.delete(editor, { at: {
|
|
339
|
+
anchor: Editor.start(editor, []),
|
|
340
|
+
focus: Editor.end(editor, [])
|
|
341
|
+
} });
|
|
342
|
+
if (newText && newText !== "") Transforms.insertNodes(editor, [{
|
|
343
|
+
type: "paragraph",
|
|
344
|
+
children: [{ text: newText }]
|
|
345
|
+
}], { at: [0] });
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
//#endregion
|
|
349
|
+
//#region src/hooks/base-copilot-textarea-implementation/use-populate-copilot-textarea-ref.ts
|
|
350
|
+
function usePopulateCopilotTextareaRef(editor, ref) {
|
|
351
|
+
React.useImperativeHandle(ref, () => {
|
|
352
|
+
class Combined {
|
|
353
|
+
constructor(customMethods, editorHtmlElement) {
|
|
354
|
+
this.customMethods = customMethods;
|
|
355
|
+
this.editorHtmlElement = editorHtmlElement;
|
|
356
|
+
}
|
|
357
|
+
get(target, propKey) {
|
|
358
|
+
if (this.isKeyOfCustomMethods(propKey)) {
|
|
359
|
+
const value = this.customMethods[propKey];
|
|
360
|
+
if (typeof value === "function") return value.bind(this.customMethods);
|
|
361
|
+
return value;
|
|
362
|
+
} else if (this.isKeyOfHTMLElement(propKey)) {
|
|
363
|
+
const value = this.editorHtmlElement[propKey];
|
|
364
|
+
if (typeof value === "function") return value.bind(this.editorHtmlElement);
|
|
365
|
+
return value;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
set(target, propKey, value) {
|
|
369
|
+
if (this.isKeyOfCustomMethods(propKey)) this.customMethods[propKey] = value;
|
|
370
|
+
else if (this.isKeyOfHTMLElement(propKey)) this.editorHtmlElement[propKey] = value;
|
|
371
|
+
else target[propKey] = value;
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
isKeyOfCustomMethods(key) {
|
|
375
|
+
return key in this.customMethods;
|
|
376
|
+
}
|
|
377
|
+
isKeyOfHTMLElement(key) {
|
|
378
|
+
return key in this.editorHtmlElement;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
const handler = {
|
|
382
|
+
get(target, propKey) {
|
|
383
|
+
return target.get(target, propKey);
|
|
384
|
+
},
|
|
385
|
+
set(target, propKey, value) {
|
|
386
|
+
return target.set(target, propKey, value);
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
class CustomMethods {
|
|
390
|
+
constructor(editor) {
|
|
391
|
+
this.editor = editor;
|
|
392
|
+
}
|
|
393
|
+
focus() {
|
|
394
|
+
ReactEditor.focus(this.editor);
|
|
395
|
+
}
|
|
396
|
+
blur() {
|
|
397
|
+
ReactEditor.blur(this.editor);
|
|
398
|
+
}
|
|
399
|
+
get value() {
|
|
400
|
+
return getFullEditorTextWithNewlines(this.editor);
|
|
401
|
+
}
|
|
402
|
+
set value(value) {
|
|
403
|
+
replaceEditorText(this.editor, value);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
const editorHtmlElement = ReactEditor.toDOMNode(editor, editor);
|
|
407
|
+
const combined = new Combined(new CustomMethods(editor), editorHtmlElement);
|
|
408
|
+
return new Proxy(combined, handler);
|
|
409
|
+
}, [editor]);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
//#endregion
|
|
413
|
+
//#region src/lib/slatejs-edits/add-autocompletions.ts
|
|
414
|
+
function addAutocompletionsToEditor(editor, newSuggestion, point) {
|
|
415
|
+
const editorPosition = editor.selection;
|
|
416
|
+
Transforms.insertNodes(editor, [{
|
|
417
|
+
type: "suggestion",
|
|
418
|
+
inline: true,
|
|
419
|
+
content: newSuggestion,
|
|
420
|
+
children: [{ text: "" }]
|
|
421
|
+
}], { at: point });
|
|
422
|
+
if (editorPosition) editor.selection = editorPosition;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
//#endregion
|
|
426
|
+
//#region src/lib/slatejs-edits/clear-autocompletions.ts
|
|
427
|
+
function clearAutocompletionsFromEditor(editor) {
|
|
428
|
+
const paths = [];
|
|
429
|
+
for (const [node, path] of Node.nodes(editor)) if (Element.isElement(node) && node.type === "suggestion") paths.push(path);
|
|
430
|
+
for (const path of paths) try {
|
|
431
|
+
Transforms.removeNodes(editor, { at: path });
|
|
432
|
+
} catch (e) {
|
|
433
|
+
console.log("CopilotTextarea.clearAutocompletionsFromEditor: error removing node", e);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
//#endregion
|
|
438
|
+
//#region src/types/base/base-autosuggestions-config.tsx
|
|
439
|
+
const defaultShouldToggleHoveringEditorOnKeyPress = (event, shortcut) => {
|
|
440
|
+
const isMetaKey = isMacOS() ? event.metaKey : event.ctrlKey;
|
|
441
|
+
return event.key === shortcut && isMetaKey;
|
|
442
|
+
};
|
|
443
|
+
const defaultShouldAcceptAutosuggestionOnKeyPress = (event) => {
|
|
444
|
+
if (event.key === "Tab") return true;
|
|
445
|
+
return false;
|
|
446
|
+
};
|
|
447
|
+
const defaultShouldAcceptAutosuggestionOnTouch = () => false;
|
|
448
|
+
/**
|
|
449
|
+
* Default configuration for the BaseAutosuggestions.
|
|
450
|
+
*
|
|
451
|
+
* @property {number} debounceTime - The amount of time to wait before triggering the autosuggestions API call.
|
|
452
|
+
* @property {string[]} contextCategories - The categories to use for context when making the autosuggestions API call.
|
|
453
|
+
* @property {boolean} disableWhenEmpty - Whether to disable the autosuggestions when the textarea is empty.
|
|
454
|
+
* @property {boolean} disabled - Whether to disable the autosuggestions feature entirely.
|
|
455
|
+
* @property {boolean} temporarilyDisableWhenMovingCursorWithoutChangingText - Whether to temporarily disable the autosuggestions when the cursor is moved without changing the text.
|
|
456
|
+
* @property {boolean} temporarilyDisableNotTrustedEvents - Temporarily disable the autosuggestions after change event from non-trusted sources (like text insertion from autocomplete plugins)
|
|
457
|
+
* @property {(event: React.KeyboardEvent<HTMLDivElement>) => boolean} shouldToggleHoveringEditorOnKeyPress - A function that determines whether to toggle the hovering editor based on a key press event.
|
|
458
|
+
* @property {(event: React.KeyboardEvent<HTMLDivElement>) => boolean} shouldAcceptAutosuggestionOnKeyPress - A function that determines whether to accept the autosuggestion based on a key press event.
|
|
459
|
+
* @property {() => boolean} defaultShouldAcceptAutosuggestionOnTouch - A function that determines whether to accept the autosuggestion based on a mobile touch event.
|
|
460
|
+
*/
|
|
461
|
+
const defaultBaseAutosuggestionsConfig = {
|
|
462
|
+
debounceTime: 250,
|
|
463
|
+
contextCategories: defaultCopilotContextCategories,
|
|
464
|
+
disableWhenEmpty: true,
|
|
465
|
+
disabled: false,
|
|
466
|
+
temporarilyDisableWhenMovingCursorWithoutChangingText: true,
|
|
467
|
+
temporarilyDisableNotTrustedEvents: true,
|
|
468
|
+
shouldToggleHoveringEditorOnKeyPress: defaultShouldToggleHoveringEditorOnKeyPress,
|
|
469
|
+
shouldAcceptAutosuggestionOnKeyPress: defaultShouldAcceptAutosuggestionOnKeyPress,
|
|
470
|
+
shouldAcceptAutosuggestionOnTouch: defaultShouldAcceptAutosuggestionOnTouch
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
//#endregion
|
|
474
|
+
//#region src/components/hovering-toolbar/hovering-editor-provider.tsx
|
|
475
|
+
const HoveringEditorContext = createContext({
|
|
476
|
+
isDisplayed: false,
|
|
477
|
+
setIsDisplayed: () => {}
|
|
478
|
+
});
|
|
479
|
+
/**
|
|
480
|
+
* A context provider for the hovering editor over the `CopilotTextarea`
|
|
481
|
+
* (used to edit and insert text into the `CopilotTextarea`).
|
|
482
|
+
*/
|
|
483
|
+
const HoveringEditorProvider = ({ children }) => {
|
|
484
|
+
const [isDisplayed, setIsDisplayed] = useState(false);
|
|
485
|
+
return /* @__PURE__ */ jsx(HoveringEditorContext.Provider, {
|
|
486
|
+
value: {
|
|
487
|
+
isDisplayed,
|
|
488
|
+
setIsDisplayed
|
|
489
|
+
},
|
|
490
|
+
children
|
|
491
|
+
});
|
|
492
|
+
};
|
|
493
|
+
const useHoveringEditorContext = () => useContext(HoveringEditorContext);
|
|
494
|
+
|
|
495
|
+
//#endregion
|
|
496
|
+
//#region src/components/hovering-toolbar/hovering-toolbar-components.tsx
|
|
497
|
+
const Button$1 = React.forwardRef(({ className, active, reversed, ...props }, ref) => /* @__PURE__ */ jsx("span", {
|
|
498
|
+
...props,
|
|
499
|
+
ref,
|
|
500
|
+
className: cx(className, css`
|
|
501
|
+
cursor: pointer;
|
|
502
|
+
color: ${reversed ? active ? "white" : "#aaa" : active ? "black" : "#ccc"};
|
|
503
|
+
`)
|
|
504
|
+
}));
|
|
505
|
+
const Icon = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("span", {
|
|
506
|
+
...props,
|
|
507
|
+
ref,
|
|
508
|
+
className: cx("material-icons", className, css`
|
|
509
|
+
font-size: 18px;
|
|
510
|
+
vertical-align: text-bottom;
|
|
511
|
+
`)
|
|
512
|
+
}));
|
|
513
|
+
const Menu = React.forwardRef(({ className, ...props }, ref) => {
|
|
514
|
+
return /* @__PURE__ */ jsx("div", {
|
|
515
|
+
...props,
|
|
516
|
+
"data-testid": "menu",
|
|
517
|
+
ref,
|
|
518
|
+
className: cx(className, css`
|
|
519
|
+
& > * {
|
|
520
|
+
display: inline-block;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
& > * + * {
|
|
524
|
+
margin-left: 15px;
|
|
525
|
+
}
|
|
526
|
+
`)
|
|
527
|
+
});
|
|
528
|
+
});
|
|
529
|
+
const Portal = ({ children }) => {
|
|
530
|
+
return typeof document === "object" ? ReactDOM.createPortal(children, document.body) : null;
|
|
531
|
+
};
|
|
532
|
+
const Toolbar = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(Menu, {
|
|
533
|
+
...props,
|
|
534
|
+
ref,
|
|
535
|
+
className: cx(className, css`
|
|
536
|
+
position: relative;
|
|
537
|
+
padding: 1px 18px 17px;
|
|
538
|
+
margin: 0 -20px;
|
|
539
|
+
border-bottom: 2px solid #eee;
|
|
540
|
+
margin-bottom: 20px;
|
|
541
|
+
`)
|
|
542
|
+
}));
|
|
543
|
+
|
|
544
|
+
//#endregion
|
|
545
|
+
//#region src/hooks/misc/use-autosize-textarea.tsx
|
|
546
|
+
const useAutosizeTextArea = (textAreaRef, value) => {
|
|
547
|
+
useEffect(() => {
|
|
548
|
+
if (textAreaRef.current !== null) {
|
|
549
|
+
textAreaRef.current.style.height = "0px";
|
|
550
|
+
const scrollHeight = textAreaRef.current.scrollHeight;
|
|
551
|
+
textAreaRef.current.style.height = scrollHeight + "px";
|
|
552
|
+
}
|
|
553
|
+
}, [textAreaRef, value]);
|
|
554
|
+
};
|
|
555
|
+
|
|
556
|
+
//#endregion
|
|
557
|
+
//#region src/components/ui/command.tsx
|
|
558
|
+
const Command$1 = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(Command, {
|
|
559
|
+
ref,
|
|
560
|
+
className: cn("flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground", className),
|
|
561
|
+
...props
|
|
562
|
+
}));
|
|
563
|
+
Command$1.displayName = Command.displayName;
|
|
564
|
+
const CommandInput = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", {
|
|
565
|
+
className: "flex items-center border-b px-3",
|
|
566
|
+
"cmdk-input-wrapper": "",
|
|
567
|
+
children: /* @__PURE__ */ jsx(Command.Input, {
|
|
568
|
+
ref,
|
|
569
|
+
className: cn("flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50", className),
|
|
570
|
+
...props
|
|
571
|
+
})
|
|
572
|
+
}));
|
|
573
|
+
CommandInput.displayName = Command.Input.displayName;
|
|
574
|
+
const CommandList = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(Command.List, {
|
|
575
|
+
ref,
|
|
576
|
+
className: cn("max-h-[300px] overflow-y-auto overflow-x-hidden pb-2", className),
|
|
577
|
+
...props
|
|
578
|
+
}));
|
|
579
|
+
CommandList.displayName = Command.List.displayName;
|
|
580
|
+
const CommandEmpty = React$1.forwardRef((props, ref) => /* @__PURE__ */ jsx(Command.Empty, {
|
|
581
|
+
ref,
|
|
582
|
+
className: "py-6 text-center text-sm",
|
|
583
|
+
...props
|
|
584
|
+
}));
|
|
585
|
+
CommandEmpty.displayName = Command.Empty.displayName;
|
|
586
|
+
const CommandGroup = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(Command.Group, {
|
|
587
|
+
ref,
|
|
588
|
+
className: cn("overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground", className),
|
|
589
|
+
...props
|
|
590
|
+
}));
|
|
591
|
+
CommandGroup.displayName = Command.Group.displayName;
|
|
592
|
+
const CommandSeparator = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(Command.Separator, {
|
|
593
|
+
ref,
|
|
594
|
+
className: cn("-mx-1 h-px bg-border", className),
|
|
595
|
+
...props
|
|
596
|
+
}));
|
|
597
|
+
CommandSeparator.displayName = Command.Separator.displayName;
|
|
598
|
+
const CommandItem = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(Command.Item, {
|
|
599
|
+
ref,
|
|
600
|
+
className: cn("relative flex cursor-default select-none items-center rounded-sm text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
|
|
601
|
+
...props
|
|
602
|
+
}));
|
|
603
|
+
CommandItem.displayName = Command.Item.displayName;
|
|
604
|
+
const CommandShortcut = ({ className, ...props }) => {
|
|
605
|
+
return /* @__PURE__ */ jsx("span", {
|
|
606
|
+
className: cn("ml-auto text-xs tracking-widest text-muted-foreground", className),
|
|
607
|
+
...props
|
|
608
|
+
});
|
|
609
|
+
};
|
|
610
|
+
CommandShortcut.displayName = "CommandShortcut";
|
|
611
|
+
|
|
612
|
+
//#endregion
|
|
613
|
+
//#region src/components/source-search-box/source-search-box.tsx
|
|
614
|
+
function SourceSearchBox(props) {
|
|
615
|
+
const [selectedValue, setSelectedValue] = useState("");
|
|
616
|
+
return /* @__PURE__ */ jsxs(Command$1, {
|
|
617
|
+
className: "rounded-lg border shadow-md",
|
|
618
|
+
value: selectedValue,
|
|
619
|
+
onValueChange: (value) => {
|
|
620
|
+
setSelectedValue(value);
|
|
621
|
+
},
|
|
622
|
+
filter: (value, search) => {
|
|
623
|
+
if (props.searchTerm === "") return 1;
|
|
624
|
+
if (value.startsWith(props.searchTerm)) return 1;
|
|
625
|
+
return 0;
|
|
626
|
+
},
|
|
627
|
+
children: [/* @__PURE__ */ jsx(CommandInput, {
|
|
628
|
+
value: props.searchTerm,
|
|
629
|
+
className: "rounded-t-lg hidden",
|
|
630
|
+
placeholder: "Search for a command..."
|
|
631
|
+
}), /* @__PURE__ */ jsxs(CommandList, { children: [
|
|
632
|
+
/* @__PURE__ */ jsx(CommandEmpty, { children: "No results found." }),
|
|
633
|
+
/* @__PURE__ */ jsx(CommandGroup, {
|
|
634
|
+
heading: "Available resources",
|
|
635
|
+
children: props.suggestedFiles.map((filePointer) => {
|
|
636
|
+
return /* @__PURE__ */ jsx(CommandItem, {
|
|
637
|
+
value: filePointer.name,
|
|
638
|
+
onSelect: (value) => {
|
|
639
|
+
props.onSelectedFile(filePointer);
|
|
640
|
+
},
|
|
641
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
642
|
+
className: " px-3 flex flex-row gap-1 items-center",
|
|
643
|
+
children: [/* @__PURE__ */ jsx(Logo, {
|
|
644
|
+
width: "20px",
|
|
645
|
+
height: "20px",
|
|
646
|
+
children: /* @__PURE__ */ jsx("img", {
|
|
647
|
+
src: filePointer.iconImageUri,
|
|
648
|
+
alt: filePointer.sourceApplication,
|
|
649
|
+
className: "w-full h-full"
|
|
650
|
+
})
|
|
651
|
+
}), filePointer.name]
|
|
652
|
+
})
|
|
653
|
+
}, `word-${filePointer.sourceApplication}.${filePointer.name}`);
|
|
654
|
+
})
|
|
655
|
+
}),
|
|
656
|
+
/* @__PURE__ */ jsx(CommandSeparator, {})
|
|
657
|
+
] })]
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
function Logo({ children, width, height }) {
|
|
661
|
+
return /* @__PURE__ */ jsx("div", {
|
|
662
|
+
className: "flex items-center justify-center",
|
|
663
|
+
style: {
|
|
664
|
+
width,
|
|
665
|
+
height
|
|
666
|
+
},
|
|
667
|
+
children
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
//#endregion
|
|
672
|
+
//#region src/components/ui/button.tsx
|
|
673
|
+
const buttonVariants = cva("inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", {
|
|
674
|
+
variants: {
|
|
675
|
+
variant: {
|
|
676
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
677
|
+
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
678
|
+
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
|
679
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
680
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
681
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
682
|
+
},
|
|
683
|
+
size: {
|
|
684
|
+
default: "h-10 px-4 py-2",
|
|
685
|
+
sm: "h-9 rounded-md px-3",
|
|
686
|
+
lg: "h-11 rounded-md px-8",
|
|
687
|
+
icon: "h-10 w-10"
|
|
688
|
+
}
|
|
689
|
+
},
|
|
690
|
+
defaultVariants: {
|
|
691
|
+
variant: "default",
|
|
692
|
+
size: "default"
|
|
693
|
+
}
|
|
694
|
+
});
|
|
695
|
+
const Button = React$1.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
696
|
+
return /* @__PURE__ */ jsx(asChild ? Slot : "button", {
|
|
697
|
+
className: cn(buttonVariants({
|
|
698
|
+
variant,
|
|
699
|
+
size,
|
|
700
|
+
className
|
|
701
|
+
})),
|
|
702
|
+
ref,
|
|
703
|
+
...props
|
|
704
|
+
});
|
|
705
|
+
});
|
|
706
|
+
Button.displayName = "Button";
|
|
707
|
+
|
|
708
|
+
//#endregion
|
|
709
|
+
//#region src/components/ui/label.tsx
|
|
710
|
+
const labelVariants = cva("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70");
|
|
711
|
+
const Label = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(LabelPrimitive.Root, {
|
|
712
|
+
ref,
|
|
713
|
+
className: cn(labelVariants(), className),
|
|
714
|
+
...props
|
|
715
|
+
}));
|
|
716
|
+
Label.displayName = LabelPrimitive.Root.displayName;
|
|
717
|
+
|
|
718
|
+
//#endregion
|
|
719
|
+
//#region src/lib/stream-promise-flatten.ts
|
|
720
|
+
/**
|
|
721
|
+
* Flatten a promise of a stream, into a stream.
|
|
722
|
+
*
|
|
723
|
+
* Useful because a stream already includes the notion of async value delivery,
|
|
724
|
+
* so it often makes sense to simply await the values rather than the generator of the values.
|
|
725
|
+
*
|
|
726
|
+
* @param {Promise<ReadableStream<A>>} promise - The promise to flatten.
|
|
727
|
+
* @returns {ReadableStream<A>} - The flattened stream.
|
|
728
|
+
*/
|
|
729
|
+
function streamPromiseFlatten(promise) {
|
|
730
|
+
return new ReadableStream({ async start(controller) {
|
|
731
|
+
try {
|
|
732
|
+
const reader = (await promise).getReader();
|
|
733
|
+
while (true) {
|
|
734
|
+
const { done, value } = await reader.read();
|
|
735
|
+
if (done) {
|
|
736
|
+
controller.close();
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
controller.enqueue(value);
|
|
740
|
+
}
|
|
741
|
+
} catch (error) {
|
|
742
|
+
controller.error(error);
|
|
743
|
+
}
|
|
744
|
+
} });
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
//#endregion
|
|
748
|
+
//#region src/components/hovering-toolbar/text-insertion-prompt-box/included-files-preview.tsx
|
|
749
|
+
const IncludedFilesPreview = ({ includedFiles, setIncludedFiles }) => {
|
|
750
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
751
|
+
className: "flex flex-col gap-2 mt-2",
|
|
752
|
+
children: [/* @__PURE__ */ jsx(Label, {
|
|
753
|
+
className: "",
|
|
754
|
+
children: "Included context:"
|
|
755
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
756
|
+
className: "flex flex-wrap gap-2",
|
|
757
|
+
children: includedFiles.map((filePointer, index) => {
|
|
758
|
+
return /* @__PURE__ */ jsx(FileChipPreview, {
|
|
759
|
+
filePointer,
|
|
760
|
+
onDelete: () => {
|
|
761
|
+
setIncludedFiles((prev) => prev.filter((fp) => fp !== filePointer));
|
|
762
|
+
}
|
|
763
|
+
}, `file-${filePointer.sourceApplication}.${filePointer.name}`);
|
|
764
|
+
})
|
|
765
|
+
})]
|
|
766
|
+
});
|
|
767
|
+
};
|
|
768
|
+
const FileChipPreview = ({ filePointer, onDelete }) => {
|
|
769
|
+
return /* @__PURE__ */ jsx(Chip, {
|
|
770
|
+
label: filePointer.name,
|
|
771
|
+
onDelete,
|
|
772
|
+
avatar: /* @__PURE__ */ jsx(Avatar, {
|
|
773
|
+
src: filePointer.iconImageUri,
|
|
774
|
+
alt: filePointer.sourceApplication,
|
|
775
|
+
sx: { backgroundColor: "transparent" }
|
|
776
|
+
})
|
|
777
|
+
});
|
|
778
|
+
};
|
|
779
|
+
|
|
780
|
+
//#endregion
|
|
781
|
+
//#region src/components/hovering-toolbar/text-insertion-prompt-box/hovering-insertion-prompt-box-core.tsx
|
|
782
|
+
const HoveringInsertionPromptBoxCore = ({ performInsertion, state, insertionOrEditingFunction, contextCategories }) => {
|
|
783
|
+
const { getDocumentsContext } = useCopilotContext();
|
|
784
|
+
const [editSuggestion, setEditSuggestion] = useState("");
|
|
785
|
+
const [suggestionIsLoading, setSuggestionIsLoading] = useState(false);
|
|
786
|
+
const [adjustmentPrompt, setAdjustmentPrompt] = useState("");
|
|
787
|
+
const [generatingSuggestion, setGeneratingSuggestion] = useState(null);
|
|
788
|
+
const adjustmentTextAreaRef = useRef(null);
|
|
789
|
+
const suggestionTextAreaRef = useRef(null);
|
|
790
|
+
const [filePointers, setFilePointers] = useState([]);
|
|
791
|
+
const [suggestedFiles, setSuggestedFiles] = useState([]);
|
|
792
|
+
useEffect(() => {
|
|
793
|
+
setSuggestedFiles(getDocumentsContext(contextCategories));
|
|
794
|
+
}, [contextCategories, getDocumentsContext]);
|
|
795
|
+
useAutosizeTextArea(suggestionTextAreaRef, editSuggestion || "");
|
|
796
|
+
useAutosizeTextArea(adjustmentTextAreaRef, adjustmentPrompt || "");
|
|
797
|
+
useEffect(() => {
|
|
798
|
+
adjustmentTextAreaRef.current?.focus();
|
|
799
|
+
}, []);
|
|
800
|
+
useEffect(() => {
|
|
801
|
+
if (!generatingSuggestion) return;
|
|
802
|
+
if (generatingSuggestion.locked) return;
|
|
803
|
+
setEditSuggestion("");
|
|
804
|
+
const reader = generatingSuggestion.getReader();
|
|
805
|
+
const read = async () => {
|
|
806
|
+
setSuggestionIsLoading(true);
|
|
807
|
+
while (true) {
|
|
808
|
+
const { done, value } = await reader.read();
|
|
809
|
+
if (done) break;
|
|
810
|
+
setEditSuggestion((prev) => {
|
|
811
|
+
const newSuggestion = prev + value;
|
|
812
|
+
if (suggestionTextAreaRef.current) suggestionTextAreaRef.current.scrollTop = suggestionTextAreaRef.current.scrollHeight;
|
|
813
|
+
return newSuggestion;
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
setSuggestionIsLoading(false);
|
|
817
|
+
};
|
|
818
|
+
read();
|
|
819
|
+
return () => {
|
|
820
|
+
const releaseLockIfNotClosed = async () => {
|
|
821
|
+
try {
|
|
822
|
+
await reader.closed;
|
|
823
|
+
} catch {
|
|
824
|
+
reader.releaseLock();
|
|
825
|
+
}
|
|
826
|
+
};
|
|
827
|
+
releaseLockIfNotClosed();
|
|
828
|
+
};
|
|
829
|
+
}, [generatingSuggestion]);
|
|
830
|
+
const beginGeneratingAdjustment = useCallback(async () => {
|
|
831
|
+
if (!adjustmentPrompt.trim()) return;
|
|
832
|
+
let modificationState = state.editorState;
|
|
833
|
+
if (editSuggestion !== "") modificationState.selectedText = editSuggestion;
|
|
834
|
+
setGeneratingSuggestion(streamPromiseFlatten(insertionOrEditingFunction(modificationState, adjustmentPrompt, filePointers, new AbortController().signal)));
|
|
835
|
+
}, [
|
|
836
|
+
adjustmentPrompt,
|
|
837
|
+
editSuggestion,
|
|
838
|
+
state.editorState,
|
|
839
|
+
insertionOrEditingFunction,
|
|
840
|
+
filePointers
|
|
841
|
+
]);
|
|
842
|
+
const isLoading = suggestionIsLoading;
|
|
843
|
+
const textToEdit = editSuggestion || state.editorState.selectedText;
|
|
844
|
+
const adjustmentLabel = textToEdit === "" ? "Describe the text you want to insert" : "Describe adjustments to the suggested text";
|
|
845
|
+
const placeholder = textToEdit === "" ? "e.g. 'summarize the client's top 3 pain-points from @CallTranscript'" : "e.g. 'make it more formal', 'be more specific', ...";
|
|
846
|
+
const { setIsDisplayed } = useHoveringEditorContext();
|
|
847
|
+
const AdjustmentPromptComponent = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Label, {
|
|
848
|
+
className: "",
|
|
849
|
+
children: adjustmentLabel
|
|
850
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
851
|
+
className: "relative w-full flex items-center",
|
|
852
|
+
children: [/* @__PURE__ */ jsx("textarea", {
|
|
853
|
+
"data-testid": "adjustment-prompt",
|
|
854
|
+
disabled: suggestionIsLoading,
|
|
855
|
+
ref: adjustmentTextAreaRef,
|
|
856
|
+
value: adjustmentPrompt,
|
|
857
|
+
onChange: (e) => setAdjustmentPrompt(e.target.value),
|
|
858
|
+
onKeyDown: (e) => {
|
|
859
|
+
if (e.key === "Enter" && e.shiftKey) {
|
|
860
|
+
e.preventDefault();
|
|
861
|
+
setAdjustmentPrompt(adjustmentPrompt + "\n");
|
|
862
|
+
} else if (e.key === "Enter") {
|
|
863
|
+
e.preventDefault();
|
|
864
|
+
beginGeneratingAdjustment();
|
|
865
|
+
}
|
|
866
|
+
},
|
|
867
|
+
placeholder,
|
|
868
|
+
style: { minHeight: "3rem" },
|
|
869
|
+
className: "w-full bg-slate-100 h-auto h-min-14 text-sm p-2 rounded-md resize-none overflow-visible focus:outline-none focus:ring-0 focus:border-non pr-[3rem]",
|
|
870
|
+
rows: 1
|
|
871
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
872
|
+
onClick: beginGeneratingAdjustment,
|
|
873
|
+
className: "absolute right-2 bg-blue-500 text-white w-8 h-8 rounded-full flex items-center justify-center",
|
|
874
|
+
"data-testid": "generate-button",
|
|
875
|
+
children: /* @__PURE__ */ jsx("i", {
|
|
876
|
+
className: "material-icons",
|
|
877
|
+
children: "arrow_forward"
|
|
878
|
+
})
|
|
879
|
+
})]
|
|
880
|
+
})] });
|
|
881
|
+
const SuggestionComponent = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
882
|
+
className: "flex justify-between items-end w-full",
|
|
883
|
+
children: [/* @__PURE__ */ jsx(Label, {
|
|
884
|
+
className: "mt-4",
|
|
885
|
+
children: "Suggested:"
|
|
886
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
887
|
+
className: "ml-auto",
|
|
888
|
+
children: isLoading && /* @__PURE__ */ jsx("div", {
|
|
889
|
+
className: "flex justify-center items-center",
|
|
890
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
891
|
+
className: "inline-block h-4 w-4 animate-spin rounded-full border-4 border-solid border-current border-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite]",
|
|
892
|
+
role: "status",
|
|
893
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
894
|
+
className: "!absolute !-m-px !h-px !w-px !overflow-hidden !whitespace-nowrap !border-0 !p-0 ![clip:rect(0,0,0,0)]",
|
|
895
|
+
children: "Loading..."
|
|
896
|
+
})
|
|
897
|
+
})
|
|
898
|
+
})
|
|
899
|
+
})]
|
|
900
|
+
}), /* @__PURE__ */ jsx("textarea", {
|
|
901
|
+
"data-testid": "suggestion-result",
|
|
902
|
+
ref: suggestionTextAreaRef,
|
|
903
|
+
value: editSuggestion,
|
|
904
|
+
disabled: suggestionIsLoading,
|
|
905
|
+
onChange: (e) => setEditSuggestion(e.target.value),
|
|
906
|
+
className: "w-full text-base p-2 border border-gray-300 rounded-md resize-none bg-green-50",
|
|
907
|
+
style: {
|
|
908
|
+
overflow: "auto",
|
|
909
|
+
maxHeight: "10em"
|
|
910
|
+
}
|
|
911
|
+
})] });
|
|
912
|
+
const SubmitComponent = /* @__PURE__ */ jsx("div", {
|
|
913
|
+
className: "flex w-full gap-4 justify-start",
|
|
914
|
+
children: /* @__PURE__ */ jsxs(Button, {
|
|
915
|
+
"data-testid": "insert-button",
|
|
916
|
+
className: " bg-green-700 text-white",
|
|
917
|
+
onClick: () => {
|
|
918
|
+
performInsertion(editSuggestion);
|
|
919
|
+
},
|
|
920
|
+
children: ["Insert ", /* @__PURE__ */ jsx("i", {
|
|
921
|
+
className: "material-icons",
|
|
922
|
+
children: "check"
|
|
923
|
+
})]
|
|
924
|
+
})
|
|
925
|
+
});
|
|
926
|
+
const sourceSearchCandidate = adjustmentPrompt.split(" ").pop();
|
|
927
|
+
const sourceSearchWord = sourceSearchCandidate?.startsWith("@") ? sourceSearchCandidate.slice(1) : void 0;
|
|
928
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
929
|
+
className: "w-full flex flex-col items-start relative gap-2",
|
|
930
|
+
children: [
|
|
931
|
+
AdjustmentPromptComponent,
|
|
932
|
+
filePointers.length > 0 && /* @__PURE__ */ jsx(IncludedFilesPreview, {
|
|
933
|
+
includedFiles: filePointers,
|
|
934
|
+
setIncludedFiles: setFilePointers
|
|
935
|
+
}),
|
|
936
|
+
sourceSearchWord !== void 0 && /* @__PURE__ */ jsx(SourceSearchBox, {
|
|
937
|
+
searchTerm: sourceSearchWord,
|
|
938
|
+
suggestedFiles,
|
|
939
|
+
onSelectedFile: (filePointer) => {
|
|
940
|
+
setAdjustmentPrompt(adjustmentPrompt.replace(new RegExp(`@${sourceSearchWord}$`), ""));
|
|
941
|
+
setFilePointers((prev) => [...prev, filePointer]);
|
|
942
|
+
adjustmentTextAreaRef.current?.focus();
|
|
943
|
+
}
|
|
944
|
+
}),
|
|
945
|
+
generatingSuggestion ? SuggestionComponent : null,
|
|
946
|
+
generatingSuggestion ? SubmitComponent : null
|
|
947
|
+
]
|
|
948
|
+
});
|
|
949
|
+
};
|
|
950
|
+
|
|
951
|
+
//#endregion
|
|
952
|
+
//#region src/components/hovering-toolbar/text-insertion-prompt-box/hovering-insertion-prompt-box.tsx
|
|
953
|
+
const HoveringInsertionPromptBox = (props) => {
|
|
954
|
+
return /* @__PURE__ */ jsx("div", {
|
|
955
|
+
className: "flex flex-col justify-center items-center space-y-4 rounded-md border shadow-lg p-4 border-gray- bg-white",
|
|
956
|
+
style: { width: "35rem" },
|
|
957
|
+
children: /* @__PURE__ */ jsx(HoveringInsertionPromptBoxCore, {
|
|
958
|
+
state: { editorState: props.editorState },
|
|
959
|
+
insertionOrEditingFunction: props.apiConfig.insertionOrEditingFunction,
|
|
960
|
+
performInsertion: props.performInsertion,
|
|
961
|
+
contextCategories: props.contextCategories
|
|
962
|
+
})
|
|
963
|
+
});
|
|
964
|
+
};
|
|
965
|
+
|
|
966
|
+
//#endregion
|
|
967
|
+
//#region src/components/hovering-toolbar/hovering-toolbar.tsx
|
|
968
|
+
const HoveringToolbar = (props) => {
|
|
969
|
+
const ref = useRef(null);
|
|
970
|
+
const editor = useSlate();
|
|
971
|
+
const selection = useSlateSelection();
|
|
972
|
+
const { isDisplayed, setIsDisplayed } = useHoveringEditorContext();
|
|
973
|
+
const [isClient, setIsClient] = useState(false);
|
|
974
|
+
useEffect(() => {
|
|
975
|
+
setIsClient(true);
|
|
976
|
+
}, []);
|
|
977
|
+
const isShown = isClient && isDisplayed && selection;
|
|
978
|
+
useLayoutEffect(() => {
|
|
979
|
+
const el = ref.current;
|
|
980
|
+
const { selection } = editor;
|
|
981
|
+
if (!el || !isShown) return;
|
|
982
|
+
if (!selection) {
|
|
983
|
+
el.removeAttribute("style");
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
const domSelection = window.getSelection();
|
|
987
|
+
if (!domSelection || domSelection.rangeCount === 0) return;
|
|
988
|
+
const rect = domSelection.getRangeAt(0).getBoundingClientRect();
|
|
989
|
+
if (rect.top === 0 && rect.left === 0 && rect.width === 0 && rect.height === 0) return;
|
|
990
|
+
const verticalOffsetFromCorner = 0;
|
|
991
|
+
const horizontalOffsetFromCorner = 0;
|
|
992
|
+
let top = rect.bottom + window.scrollY + verticalOffsetFromCorner;
|
|
993
|
+
if (rect.bottom + el.offsetHeight > window.innerHeight - verticalOffsetFromCorner) top = rect.top + window.scrollY - el.offsetHeight - verticalOffsetFromCorner;
|
|
994
|
+
let left = rect.left + window.scrollX - el.offsetWidth / 2 + rect.width / 2 + horizontalOffsetFromCorner;
|
|
995
|
+
if (left < horizontalOffsetFromCorner) left = horizontalOffsetFromCorner;
|
|
996
|
+
else if (left + el.offsetWidth > window.innerWidth - horizontalOffsetFromCorner) left = window.innerWidth - el.offsetWidth - horizontalOffsetFromCorner;
|
|
997
|
+
el.style.opacity = "1";
|
|
998
|
+
el.style.position = "absolute";
|
|
999
|
+
el.style.top = `${top}px`;
|
|
1000
|
+
el.style.left = `${left}px`;
|
|
1001
|
+
}, [isShown]);
|
|
1002
|
+
useEffect(() => {
|
|
1003
|
+
const handleClickOutside = (event) => {
|
|
1004
|
+
if (ref.current && !ref.current.contains(event.target)) setIsDisplayed(false);
|
|
1005
|
+
};
|
|
1006
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1007
|
+
return () => {
|
|
1008
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
1009
|
+
};
|
|
1010
|
+
}, [ref, setIsDisplayed]);
|
|
1011
|
+
if (!isShown) return null;
|
|
1012
|
+
return /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Menu, {
|
|
1013
|
+
ref,
|
|
1014
|
+
className: "copilot-kit-textarea-css-scope " + (props.hoverMenuClassname || "p-2 absolute z-10 top-[-10000px] left-[-10000px] mt-[-6px] opacity-0 transition-opacity duration-700"),
|
|
1015
|
+
"data-testid": "hovering-toolbar",
|
|
1016
|
+
children: /* @__PURE__ */ jsx(HoveringInsertionPromptBox, {
|
|
1017
|
+
editorState: editorState(editor, selection),
|
|
1018
|
+
apiConfig: props.apiConfig,
|
|
1019
|
+
performInsertion: (insertedText) => {
|
|
1020
|
+
Transforms.delete(editor, { at: selection });
|
|
1021
|
+
Transforms.insertText(editor, insertedText, { at: selection });
|
|
1022
|
+
setIsDisplayed(false);
|
|
1023
|
+
},
|
|
1024
|
+
contextCategories: props.contextCategories
|
|
1025
|
+
})
|
|
1026
|
+
}) });
|
|
1027
|
+
};
|
|
1028
|
+
function editorState(editor, selection) {
|
|
1029
|
+
const textAroundCursor = getTextAroundSelection(editor);
|
|
1030
|
+
if (textAroundCursor) return textAroundCursor;
|
|
1031
|
+
return {
|
|
1032
|
+
textBeforeCursor: getFullEditorTextWithNewlines(editor),
|
|
1033
|
+
textAfterCursor: "",
|
|
1034
|
+
selectedText: ""
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
//#endregion
|
|
1039
|
+
//#region src/components/base-copilot-textarea/render-element.tsx
|
|
1040
|
+
function makeRenderElementFunction(suggestionsStyle) {
|
|
1041
|
+
return (props) => {
|
|
1042
|
+
switch (props.element.type) {
|
|
1043
|
+
case "paragraph": return /* @__PURE__ */ jsx(DefaultElement, { ...props });
|
|
1044
|
+
case "suggestion": return /* @__PURE__ */ jsx(SuggestionElement, {
|
|
1045
|
+
...props,
|
|
1046
|
+
suggestionsStyle
|
|
1047
|
+
});
|
|
1048
|
+
}
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
const DefaultElement = (props) => {
|
|
1052
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1053
|
+
...props.attributes,
|
|
1054
|
+
children: props.children
|
|
1055
|
+
});
|
|
1056
|
+
};
|
|
1057
|
+
const SuggestionElement = (props) => {
|
|
1058
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
1059
|
+
...props.attributes,
|
|
1060
|
+
style: { ...props.suggestionsStyle },
|
|
1061
|
+
"data-testid": "suggestion",
|
|
1062
|
+
contentEditable: false,
|
|
1063
|
+
children: [props.children, props.element.type === "suggestion" && props.element.content]
|
|
1064
|
+
});
|
|
1065
|
+
};
|
|
1066
|
+
|
|
1067
|
+
//#endregion
|
|
1068
|
+
//#region src/components/base-copilot-textarea/render-placeholder.tsx
|
|
1069
|
+
function makeRenderPlaceholderFunction(placeholderStyle) {
|
|
1070
|
+
return (props) => {
|
|
1071
|
+
const { style, ...restAttributes } = props.attributes;
|
|
1072
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1073
|
+
...restAttributes,
|
|
1074
|
+
style: {
|
|
1075
|
+
...style,
|
|
1076
|
+
...placeholderStyle
|
|
1077
|
+
},
|
|
1078
|
+
children: props.children
|
|
1079
|
+
});
|
|
1080
|
+
};
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
//#endregion
|
|
1084
|
+
//#region src/components/base-copilot-textarea/use-add-branding-css.tsx
|
|
1085
|
+
function useAddBrandingCss(suggestionStyleAugmented, disableBranding) {
|
|
1086
|
+
const cssSelector = ".copilot-textarea.with-branding";
|
|
1087
|
+
useEffect(() => {
|
|
1088
|
+
if (disableBranding) return;
|
|
1089
|
+
const styleEl = document.createElement("style");
|
|
1090
|
+
styleEl.id = "dynamic-styles";
|
|
1091
|
+
let dynamicStyles = Object.entries(suggestionStyleAugmented).map(([key, value]) => {
|
|
1092
|
+
return `${key.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase()}: ${value};`;
|
|
1093
|
+
}).join(" ");
|
|
1094
|
+
dynamicStyles += `font-style: normal; font-size: x-small;`;
|
|
1095
|
+
dynamicStyles += `content: "CopilotKit";`;
|
|
1096
|
+
dynamicStyles += `bottom: 6px;`;
|
|
1097
|
+
dynamicStyles += `right: 6px;`;
|
|
1098
|
+
dynamicStyles += `pointer-events: none;`;
|
|
1099
|
+
dynamicStyles += `font-weight: 200;`;
|
|
1100
|
+
dynamicStyles += `padding: 0;`;
|
|
1101
|
+
dynamicStyles += `margin: 0;`;
|
|
1102
|
+
dynamicStyles += `border: 0;`;
|
|
1103
|
+
dynamicStyles += `line-height: 1;`;
|
|
1104
|
+
dynamicStyles += `position: absolute;`;
|
|
1105
|
+
styleEl.innerHTML = `
|
|
1106
|
+
${cssSelector}::after {
|
|
1107
|
+
${dynamicStyles}
|
|
1108
|
+
}
|
|
1109
|
+
`;
|
|
1110
|
+
document.head.appendChild(styleEl);
|
|
1111
|
+
const textarea = document.querySelector(cssSelector);
|
|
1112
|
+
const handleScroll = () => {
|
|
1113
|
+
const styleEl = document.getElementById("dynamic-styles");
|
|
1114
|
+
if (styleEl && textarea) {
|
|
1115
|
+
const offsetFromBottom = -textarea.scrollTop + 6;
|
|
1116
|
+
const offsetFromRight = -textarea.scrollLeft + 6;
|
|
1117
|
+
styleEl.innerHTML = `
|
|
1118
|
+
${cssSelector}::after {
|
|
1119
|
+
${dynamicStyles}
|
|
1120
|
+
bottom: ${offsetFromBottom}px;
|
|
1121
|
+
right: ${offsetFromRight}px;
|
|
1122
|
+
}
|
|
1123
|
+
`;
|
|
1124
|
+
}
|
|
1125
|
+
};
|
|
1126
|
+
textarea?.addEventListener("scroll", handleScroll);
|
|
1127
|
+
return () => {
|
|
1128
|
+
document.getElementById("dynamic-styles")?.remove();
|
|
1129
|
+
textarea?.removeEventListener("scroll", handleScroll);
|
|
1130
|
+
};
|
|
1131
|
+
}, [disableBranding, suggestionStyleAugmented]);
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
//#endregion
|
|
1135
|
+
//#region src/lib/editor-to-text.ts
|
|
1136
|
+
function nodeChildrenToTextComponents(editor, nodes) {
|
|
1137
|
+
const indeciesOfInlineElements = new Set(nodes.map((node, index) => {
|
|
1138
|
+
if (Element.isElement(node) && editor.isInline(node)) return index;
|
|
1139
|
+
return -1;
|
|
1140
|
+
}).filter((index) => index !== -1));
|
|
1141
|
+
return nodes.filter((node, index) => {
|
|
1142
|
+
if (indeciesOfInlineElements.has(index)) return false;
|
|
1143
|
+
if (indeciesOfInlineElements.has(index - 1) || indeciesOfInlineElements.has(index + 1)) return node.text !== "";
|
|
1144
|
+
return true;
|
|
1145
|
+
}).map((node) => {
|
|
1146
|
+
if (Element.isElement(node)) switch (node.type) {
|
|
1147
|
+
case "paragraph": return nodeChildrenToTextComponents(editor, node.children);
|
|
1148
|
+
case "suggestion": return [];
|
|
1149
|
+
}
|
|
1150
|
+
else return [node];
|
|
1151
|
+
}).reduce((acc, val) => acc.concat(val), []);
|
|
1152
|
+
}
|
|
1153
|
+
const editorToText = (editor) => {
|
|
1154
|
+
return nodeChildrenToTextComponents(editor, editor.children).map((textComponent) => textComponent.text).join("\n");
|
|
1155
|
+
};
|
|
1156
|
+
|
|
1157
|
+
//#endregion
|
|
1158
|
+
//#region src/components/base-copilot-textarea/track-cursor-moved-since-last-text-change.tsx
|
|
1159
|
+
function TrackerTextEditedSinceLastCursorMovement(props) {
|
|
1160
|
+
const cursorState = useSlateSelector((state) => ({
|
|
1161
|
+
selection: state.selection,
|
|
1162
|
+
text: editorToText(state)
|
|
1163
|
+
}));
|
|
1164
|
+
const previousState = usePrevious(cursorState);
|
|
1165
|
+
useEffect(() => {
|
|
1166
|
+
if (!previousState) return;
|
|
1167
|
+
if (cursorChangedWithoutTextChanged(previousState, cursorState)) props.setCursorMovedSinceLastTextChange(true);
|
|
1168
|
+
}, [props.setCursorMovedSinceLastTextChange, cursorState]);
|
|
1169
|
+
return /* @__PURE__ */ jsx(Fragment, {});
|
|
1170
|
+
}
|
|
1171
|
+
const cursorChangedWithoutTextChanged = (prev, next) => {
|
|
1172
|
+
const isSelectionChanged = !isSelectionEqual(prev.selection, next.selection);
|
|
1173
|
+
const isTextSame = prev.text === next.text;
|
|
1174
|
+
return isSelectionChanged && isTextSame;
|
|
1175
|
+
};
|
|
1176
|
+
const isSelectionEqual = (a, b) => {
|
|
1177
|
+
if (!a && !b) return true;
|
|
1178
|
+
if (!a || !b) return false;
|
|
1179
|
+
return Range.equals(a, b);
|
|
1180
|
+
};
|
|
1181
|
+
/**
|
|
1182
|
+
* Easily keep track of the *previous* value of a variable.
|
|
1183
|
+
*
|
|
1184
|
+
* Example:
|
|
1185
|
+
* ```
|
|
1186
|
+
* const [count, setCount] = useState(0);
|
|
1187
|
+
* const prevCount = usePrevious(count);
|
|
1188
|
+
*
|
|
1189
|
+
* useEffect(() => {
|
|
1190
|
+
* if (count > prevCount) {
|
|
1191
|
+
* console.log('Now I know that count is bigger than before');
|
|
1192
|
+
* }
|
|
1193
|
+
* }, [count, prevCount]);
|
|
1194
|
+
* ```
|
|
1195
|
+
*/
|
|
1196
|
+
function usePrevious(value) {
|
|
1197
|
+
const ref = useRef(void 0);
|
|
1198
|
+
useEffect(() => {
|
|
1199
|
+
ref.current = value;
|
|
1200
|
+
});
|
|
1201
|
+
return ref.current;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
//#endregion
|
|
1205
|
+
//#region src/components/base-copilot-textarea/base-copilot-textarea.tsx
|
|
1206
|
+
/**
|
|
1207
|
+
* Not intended for direct use. Use CopilotTextarea instead.
|
|
1208
|
+
*
|
|
1209
|
+
* The `BaseCopilotTextarea` includes the basic UX component,
|
|
1210
|
+
* without the business logic / AI logic that makes the content useful and coherent.
|
|
1211
|
+
*
|
|
1212
|
+
* It is useful if you want to build your own backend, with fully custom business logic
|
|
1213
|
+
* for figuring out which contnet to fill in.
|
|
1214
|
+
*/
|
|
1215
|
+
const BaseCopilotTextarea = React.forwardRef((props, ref) => {
|
|
1216
|
+
return /* @__PURE__ */ jsx(HoveringEditorProvider, { children: /* @__PURE__ */ jsx(BaseCopilotTextareaWithHoveringContext, {
|
|
1217
|
+
...props,
|
|
1218
|
+
ref
|
|
1219
|
+
}) });
|
|
1220
|
+
});
|
|
1221
|
+
/**
|
|
1222
|
+
* Not intended for direct use. Use `CopilotTextarea` instead.
|
|
1223
|
+
*
|
|
1224
|
+
* This is the private core of the `BaseCopilotTextarea` component.
|
|
1225
|
+
* For practical purposes the implementation is cleaner assuming containment in a `HoveringEditorProviderContext`.
|
|
1226
|
+
*
|
|
1227
|
+
* Therefore we separate the core logic into this component,
|
|
1228
|
+
* and wrap it in a `HoveringEditorProviderContext` in `BaseCopilotTextarea`.
|
|
1229
|
+
*/
|
|
1230
|
+
const BaseCopilotTextareaWithHoveringContext = React.forwardRef((props, ref) => {
|
|
1231
|
+
const autosuggestionsConfig = {
|
|
1232
|
+
...defaultBaseAutosuggestionsConfig,
|
|
1233
|
+
...props.baseAutosuggestionsConfig
|
|
1234
|
+
};
|
|
1235
|
+
const valueOnInitialRender = useMemo(() => props.value ?? "", []);
|
|
1236
|
+
const [lastKnownFullEditorText, setLastKnownFullEditorText] = useState(valueOnInitialRender);
|
|
1237
|
+
const [cursorMovedSinceLastTextChange, setCursorMovedSinceLastTextChange] = useState(false);
|
|
1238
|
+
const [isUserInputActive, setIsUserInputActive] = useState(false);
|
|
1239
|
+
const initialValue = useMemo(() => {
|
|
1240
|
+
return [{
|
|
1241
|
+
type: "paragraph",
|
|
1242
|
+
children: [{ text: valueOnInitialRender }]
|
|
1243
|
+
}];
|
|
1244
|
+
}, [valueOnInitialRender]);
|
|
1245
|
+
const editor = useCopilotTextareaEditor();
|
|
1246
|
+
const { isDisplayed: hoveringEditorIsDisplayed, setIsDisplayed: setHoveringEditorIsDisplayed } = useHoveringEditorContext();
|
|
1247
|
+
const insertText = useCallback((autosuggestion) => {
|
|
1248
|
+
Editor.insertText(editor, autosuggestion.text, { at: autosuggestion.point });
|
|
1249
|
+
}, [editor]);
|
|
1250
|
+
const shouldDisableAutosuggestions = autosuggestionsConfig.disabled || hoveringEditorIsDisplayed || cursorMovedSinceLastTextChange && autosuggestionsConfig.temporarilyDisableWhenMovingCursorWithoutChangingText || !isUserInputActive && autosuggestionsConfig.temporarilyDisableNotTrustedEvents;
|
|
1251
|
+
const { currentAutocompleteSuggestion, onChangeHandler: onChangeHandlerForAutocomplete, onKeyDownHandler: onKeyDownHandlerForAutocomplete, onTouchStartHandler: onTouchStartHandlerForAutocomplete } = useAutosuggestions(autosuggestionsConfig.debounceTime, autosuggestionsConfig.shouldAcceptAutosuggestionOnKeyPress, autosuggestionsConfig.shouldAcceptAutosuggestionOnTouch, autosuggestionsConfig.apiConfig.autosuggestionsFunction, insertText, autosuggestionsConfig.disableWhenEmpty, shouldDisableAutosuggestions);
|
|
1252
|
+
const onKeyDownHandlerForHoveringEditor = useCallback((event) => {
|
|
1253
|
+
if (autosuggestionsConfig.shouldToggleHoveringEditorOnKeyPress(event, props.shortcut ?? "k")) {
|
|
1254
|
+
event.preventDefault();
|
|
1255
|
+
setHoveringEditorIsDisplayed(!hoveringEditorIsDisplayed);
|
|
1256
|
+
}
|
|
1257
|
+
}, [
|
|
1258
|
+
hoveringEditorIsDisplayed,
|
|
1259
|
+
setHoveringEditorIsDisplayed,
|
|
1260
|
+
autosuggestionsConfig.shouldToggleHoveringEditorOnKeyPress
|
|
1261
|
+
]);
|
|
1262
|
+
useEffect(() => {
|
|
1263
|
+
clearAutocompletionsFromEditor(editor);
|
|
1264
|
+
if (currentAutocompleteSuggestion) addAutocompletionsToEditor(editor, currentAutocompleteSuggestion.text, currentAutocompleteSuggestion.point);
|
|
1265
|
+
}, [currentAutocompleteSuggestion]);
|
|
1266
|
+
const suggestionStyleAugmented = useMemo(() => {
|
|
1267
|
+
return {
|
|
1268
|
+
fontStyle: "italic",
|
|
1269
|
+
color: "gray",
|
|
1270
|
+
...props.suggestionsStyle
|
|
1271
|
+
};
|
|
1272
|
+
}, [props.suggestionsStyle]);
|
|
1273
|
+
const renderElementMemoized = useMemo(() => {
|
|
1274
|
+
return makeRenderElementFunction(suggestionStyleAugmented);
|
|
1275
|
+
}, [suggestionStyleAugmented]);
|
|
1276
|
+
const renderPlaceholderMemoized = useMemo(() => {
|
|
1277
|
+
return makeRenderPlaceholderFunction({
|
|
1278
|
+
top: void 0,
|
|
1279
|
+
...props.placeholderStyle
|
|
1280
|
+
});
|
|
1281
|
+
}, [props.placeholderStyle]);
|
|
1282
|
+
useEffect(() => {
|
|
1283
|
+
if (props.value === lastKnownFullEditorText) return;
|
|
1284
|
+
setLastKnownFullEditorText(props.value ?? "");
|
|
1285
|
+
replaceEditorText(editor, props.value ?? "");
|
|
1286
|
+
}, [props.value]);
|
|
1287
|
+
const { placeholderStyle, value, hoverMenuClassname, onValueChange, baseAutosuggestionsConfig: autosuggestionsConfigFromProps, className, onChange, onKeyDown, disableBranding, ...propsToForward } = props;
|
|
1288
|
+
useAddBrandingCss(suggestionStyleAugmented, disableBranding);
|
|
1289
|
+
usePopulateCopilotTextareaRef(editor, ref);
|
|
1290
|
+
const moddedClassName = `copilot-textarea ${disableBranding ? "no-branding" : "with-branding"} ${twMerge("bg-white overflow-y-auto resize-y", className ?? "")}`;
|
|
1291
|
+
return /* @__PURE__ */ jsxs(Slate, {
|
|
1292
|
+
editor,
|
|
1293
|
+
initialValue,
|
|
1294
|
+
onChange: (value) => {
|
|
1295
|
+
const newEditorState = getTextAroundCollapsedCursor(editor);
|
|
1296
|
+
const fullEditorText = newEditorState ? newEditorState.textBeforeCursor + newEditorState.textAfterCursor : getFullEditorTextWithNewlines(editor);
|
|
1297
|
+
setLastKnownFullEditorText((prev) => {
|
|
1298
|
+
if (prev !== fullEditorText) setCursorMovedSinceLastTextChange(false);
|
|
1299
|
+
return fullEditorText;
|
|
1300
|
+
});
|
|
1301
|
+
onChangeHandlerForAutocomplete(newEditorState);
|
|
1302
|
+
props.onValueChange?.(fullEditorText);
|
|
1303
|
+
props.onChange?.(makeSemiFakeReactTextAreaEvent(fullEditorText));
|
|
1304
|
+
},
|
|
1305
|
+
children: [
|
|
1306
|
+
/* @__PURE__ */ jsx(TrackerTextEditedSinceLastCursorMovement, { setCursorMovedSinceLastTextChange }),
|
|
1307
|
+
/* @__PURE__ */ jsx(HoveringToolbar, {
|
|
1308
|
+
apiConfig: autosuggestionsConfig.apiConfig,
|
|
1309
|
+
contextCategories: autosuggestionsConfig.contextCategories,
|
|
1310
|
+
hoverMenuClassname
|
|
1311
|
+
}),
|
|
1312
|
+
/* @__PURE__ */ jsx(Editable, {
|
|
1313
|
+
renderElement: renderElementMemoized,
|
|
1314
|
+
renderPlaceholder: renderPlaceholderMemoized,
|
|
1315
|
+
onKeyDown: (event) => {
|
|
1316
|
+
setIsUserInputActive(true);
|
|
1317
|
+
onKeyDownHandlerForHoveringEditor(event);
|
|
1318
|
+
onKeyDownHandlerForAutocomplete(event);
|
|
1319
|
+
props.onKeyDown?.(event);
|
|
1320
|
+
},
|
|
1321
|
+
onTouchStart: (event) => {
|
|
1322
|
+
onTouchStartHandlerForAutocomplete(event);
|
|
1323
|
+
},
|
|
1324
|
+
"data-testid": "copilot-textarea-editable",
|
|
1325
|
+
className: moddedClassName,
|
|
1326
|
+
onBlur: (ev) => {
|
|
1327
|
+
props.onBlur?.(ev);
|
|
1328
|
+
clearAutocompletionsFromEditor(editor);
|
|
1329
|
+
setIsUserInputActive(false);
|
|
1330
|
+
},
|
|
1331
|
+
...propsToForward
|
|
1332
|
+
})
|
|
1333
|
+
]
|
|
1334
|
+
});
|
|
1335
|
+
});
|
|
1336
|
+
function makeSemiFakeReactTextAreaEvent(currentText) {
|
|
1337
|
+
return {
|
|
1338
|
+
target: {
|
|
1339
|
+
value: currentText,
|
|
1340
|
+
type: "copilot-textarea"
|
|
1341
|
+
},
|
|
1342
|
+
currentTarget: {
|
|
1343
|
+
value: currentText,
|
|
1344
|
+
type: "copilot-textarea"
|
|
1345
|
+
}
|
|
1346
|
+
};
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
//#endregion
|
|
1350
|
+
//#region src/lib/retry.tsx
|
|
1351
|
+
function retry(fn, retriesLeft = 2, interval = 200, backoff = 1.5) {
|
|
1352
|
+
return new Promise((resolve, reject) => {
|
|
1353
|
+
fn().then(resolve).catch((error) => {
|
|
1354
|
+
if (retriesLeft === 1) {
|
|
1355
|
+
reject(error);
|
|
1356
|
+
return;
|
|
1357
|
+
}
|
|
1358
|
+
setTimeout(() => {
|
|
1359
|
+
retry(fn, retriesLeft - 1, interval * backoff, backoff).then(resolve).catch(reject);
|
|
1360
|
+
}, interval);
|
|
1361
|
+
});
|
|
1362
|
+
});
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
//#endregion
|
|
1366
|
+
//#region src/hooks/make-autosuggestions-function/use-make-standard-autosuggestions-function.tsx
|
|
1367
|
+
/**
|
|
1368
|
+
* Returns a memoized function that sends a request to the specified API endpoint to get an autosuggestion for the user's input.
|
|
1369
|
+
* The function takes in the text before and after the cursor, and an abort signal.
|
|
1370
|
+
* It sends a POST request to the API endpoint with the messages array containing the system message, few shot messages, and user messages.
|
|
1371
|
+
* The function returns the suggestion from the API response.
|
|
1372
|
+
*
|
|
1373
|
+
* @param textareaPurpose - The purpose of the textarea. This is included in the system message.
|
|
1374
|
+
* @param apiEndpoint - The API endpoint to send the autosuggestion request to.
|
|
1375
|
+
* @param makeSystemMessage - A function that takes in a context string and returns a system message to include in the autosuggestion request.
|
|
1376
|
+
* @param fewShotMessages - An array of few shot messages to include in the autosuggestion request.
|
|
1377
|
+
* @param contextCategories - The categories of context strings we want to include. By default, we include the (default) "global" context category.
|
|
1378
|
+
* @returns A memoized function that sends a request to the specified API endpoint to get an autosuggestion for the user's input.
|
|
1379
|
+
*/
|
|
1380
|
+
function useMakeStandardAutosuggestionFunction(textareaPurpose, contextCategories, apiConfig) {
|
|
1381
|
+
const { getContextString, copilotApiConfig } = useCopilotContext();
|
|
1382
|
+
const { chatApiEndpoint: url, publicApiKey, credentials, properties } = copilotApiConfig;
|
|
1383
|
+
({
|
|
1384
|
+
...copilotApiConfig.headers,
|
|
1385
|
+
...publicApiKey ? { [COPILOT_CLOUD_PUBLIC_API_KEY_HEADER]: publicApiKey } : {}
|
|
1386
|
+
});
|
|
1387
|
+
const { maxTokens, stop, temperature = 0 } = apiConfig;
|
|
1388
|
+
return useCallback(async (editorState, abortSignal) => {
|
|
1389
|
+
return await retry(async () => {
|
|
1390
|
+
[
|
|
1391
|
+
new TextMessage({
|
|
1392
|
+
role: Role.System,
|
|
1393
|
+
content: apiConfig.makeSystemPrompt(textareaPurpose, getContextString([], contextCategories))
|
|
1394
|
+
}),
|
|
1395
|
+
...apiConfig.fewShotMessages,
|
|
1396
|
+
editorState.textAfterCursor != "" ? new TextMessage({
|
|
1397
|
+
role: Role.User,
|
|
1398
|
+
content: editorState.textAfterCursor
|
|
1399
|
+
}) : null,
|
|
1400
|
+
new TextMessage({
|
|
1401
|
+
role: Role.User,
|
|
1402
|
+
content: `<TextAfterCursor>${editorState.textAfterCursor}</TextAfterCursor>`
|
|
1403
|
+
}),
|
|
1404
|
+
new TextMessage({
|
|
1405
|
+
role: Role.User,
|
|
1406
|
+
content: `<TextBeforeCursor>${editorState.textBeforeCursor}</TextBeforeCursor>`
|
|
1407
|
+
})
|
|
1408
|
+
].filter(Boolean);
|
|
1409
|
+
const response = {};
|
|
1410
|
+
let result = "";
|
|
1411
|
+
for (const message of convertGqlOutputToMessages(response.data?.generateCopilotResponse?.messages ?? [])) {
|
|
1412
|
+
if (abortSignal.aborted) break;
|
|
1413
|
+
if (message.isTextMessage()) result += message.content;
|
|
1414
|
+
}
|
|
1415
|
+
return result;
|
|
1416
|
+
});
|
|
1417
|
+
}, [
|
|
1418
|
+
apiConfig,
|
|
1419
|
+
getContextString,
|
|
1420
|
+
contextCategories,
|
|
1421
|
+
textareaPurpose
|
|
1422
|
+
]);
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
//#endregion
|
|
1426
|
+
//#region src/types/autosuggestions-config/suggestions-api-config.tsx
|
|
1427
|
+
const defaultSuggestionsMakeSystemPrompt = (textareaPurpose, contextString) => {
|
|
1428
|
+
return `You are a versatile writing assistant.
|
|
1429
|
+
|
|
1430
|
+
The user is writing some text.
|
|
1431
|
+
The purpose is: \"${textareaPurpose}\"
|
|
1432
|
+
|
|
1433
|
+
Your job is to guess what the user will write next AS BEST YOU CAN.
|
|
1434
|
+
Only guess a SHORT distance ahead. Usually 1 sentence, or at most 1 paragraph.
|
|
1435
|
+
|
|
1436
|
+
Adjust yourself to the user's style and implied intent.
|
|
1437
|
+
|
|
1438
|
+
The user will provide both the text before and after the cursor. You should use this to infer what the user is likely to write next.
|
|
1439
|
+
<TextAfterCursor>
|
|
1440
|
+
<TextBeforeCursor>
|
|
1441
|
+
<YourSuggestion>
|
|
1442
|
+
|
|
1443
|
+
If we need to add a whitespace character to the suggested text, make sure to explicitly add it in.
|
|
1444
|
+
Refrain from adding <YourSuggestion> tags when responding
|
|
1445
|
+
|
|
1446
|
+
The following external context is also provided. Use it to help you make better suggestions!!!
|
|
1447
|
+
\`\`\`
|
|
1448
|
+
${contextString}
|
|
1449
|
+
\`\`\`
|
|
1450
|
+
`;
|
|
1451
|
+
};
|
|
1452
|
+
const defaultSuggestionsFewShotMessages = [
|
|
1453
|
+
new TextMessage({
|
|
1454
|
+
role: Role.User,
|
|
1455
|
+
content: "<TextAfterCursor>While I was there I also picked up some apples, oranges, and bananas.</TextAfterCursor>"
|
|
1456
|
+
}),
|
|
1457
|
+
new TextMessage({
|
|
1458
|
+
role: Role.User,
|
|
1459
|
+
content: "This morning I woke up and went straight to the grocery store."
|
|
1460
|
+
}),
|
|
1461
|
+
new TextMessage({
|
|
1462
|
+
role: Role.Assistant,
|
|
1463
|
+
content: " When I arrived I went straight to the produce section and picked out a big watermelon. "
|
|
1464
|
+
}),
|
|
1465
|
+
new TextMessage({
|
|
1466
|
+
role: Role.User,
|
|
1467
|
+
content: "<TextAfterCursor>and (iii) to the appointment of the Equityholders' Representative pursuant to Section 10.7 of the Merger Agreement and to the provisions thereof.</TextAfterCursor>"
|
|
1468
|
+
}),
|
|
1469
|
+
new TextMessage({
|
|
1470
|
+
role: Role.User,
|
|
1471
|
+
content: "<TextBeforeCursor>The Optionholder, in the Optionholder's capacity as a holder of vested Options, hereby irrevocably and unconditionally agrees: (i) that the Optionholder shall be deemed an \"Equityholder\" under the Merger Agreement and shall be entitled to the rights and benefits, and subject to the obligations, of an \"Equityholder\" thereunder;</TextBeforeCursor>"
|
|
1472
|
+
}),
|
|
1473
|
+
new TextMessage({
|
|
1474
|
+
role: Role.Assistant,
|
|
1475
|
+
content: " (ii) that, for purposes of this Agreement and the Merger Agreement, the applicable percentage set forth opposite the name of the Optionholder in the Distribution Waterfall shall be such the Optionholder's \"Pro Rata Share\"; "
|
|
1476
|
+
})
|
|
1477
|
+
];
|
|
1478
|
+
const defaultSuggestionsApiConfig = {
|
|
1479
|
+
makeSystemPrompt: defaultSuggestionsMakeSystemPrompt,
|
|
1480
|
+
fewShotMessages: defaultSuggestionsFewShotMessages
|
|
1481
|
+
};
|
|
1482
|
+
|
|
1483
|
+
//#endregion
|
|
1484
|
+
//#region src/types/autosuggestions-config/insertions-api-config.tsx
|
|
1485
|
+
const defaultInsertionsMakeSystemPrompt = (textareaPurpose, contextString) => {
|
|
1486
|
+
return `You are a versatile writing assistant helping the user insert new text into their existing work.
|
|
1487
|
+
|
|
1488
|
+
The user is writing some text.
|
|
1489
|
+
The purpose is: \"${textareaPurpose}\"
|
|
1490
|
+
|
|
1491
|
+
The following external context is also provided. Use it to inform your suggestions when relevant!!!
|
|
1492
|
+
\`\`\`
|
|
1493
|
+
${contextString}
|
|
1494
|
+
\`\`\`
|
|
1495
|
+
|
|
1496
|
+
The user will provide you with a prompt for an INSERTION into the text they are writing.
|
|
1497
|
+
Your job is to come up with an INSERTION into the text that the user would like to use, AS BEST YOU CAN.
|
|
1498
|
+
Only insert a SHORT segment. Usually 1 sentence, or at most 1 paragraph.
|
|
1499
|
+
|
|
1500
|
+
Adjust yourself to the user's style and implied intent.
|
|
1501
|
+
|
|
1502
|
+
|
|
1503
|
+
The user will provide the text before and after the cursor, as well as the INSERTION prompt. You should use this to infer the best relevant insertion.
|
|
1504
|
+
The conversation will be structured as follows:
|
|
1505
|
+
<TextAfterCursor>
|
|
1506
|
+
<TextBeforeCursor>
|
|
1507
|
+
<InsertionPrompt>
|
|
1508
|
+
|
|
1509
|
+
<YourInsertionSuggestion>
|
|
1510
|
+
`;
|
|
1511
|
+
};
|
|
1512
|
+
const defaultInsertionsFewShotMessages = [
|
|
1513
|
+
new TextMessage({
|
|
1514
|
+
role: Role.User,
|
|
1515
|
+
content: "<TextAfterCursor>While I was there I also picked up some apples, oranges, and bananas.</TextAfterCursor>"
|
|
1516
|
+
}),
|
|
1517
|
+
new TextMessage({
|
|
1518
|
+
role: Role.User,
|
|
1519
|
+
content: "<TextBeforeCursor>This morning I woke up and went straight to the grocery store.</TextBeforeCursor>"
|
|
1520
|
+
}),
|
|
1521
|
+
new TextMessage({
|
|
1522
|
+
role: Role.User,
|
|
1523
|
+
content: "<InsertionPrompt>I bought a big watermelon</InsertionPrompt>"
|
|
1524
|
+
}),
|
|
1525
|
+
new TextMessage({
|
|
1526
|
+
role: Role.Assistant,
|
|
1527
|
+
content: "When I arrived I went straight to the produce section and picked out a big watermelon."
|
|
1528
|
+
}),
|
|
1529
|
+
new TextMessage({
|
|
1530
|
+
role: Role.User,
|
|
1531
|
+
content: "<TextAfterCursor>and (iii) to the appointment of the Equityholders' Representative pursuant to Section 10.7 of the Merger Agreement and to the provisions thereof.</TextAfterCursor>"
|
|
1532
|
+
}),
|
|
1533
|
+
new TextMessage({
|
|
1534
|
+
role: Role.User,
|
|
1535
|
+
content: "<TextBeforeCursor>The Optionholder, in the Optionholder's capacity as a holder of vested Options, hereby irrevocably and unconditionally agrees: (i) that the Optionholder shall be deemed an \"Equityholder\" under the Merger Agreement and shall be entitled to the rights and benefits, and subject to the obligations, of an \"Equityholder\" thereunder;</TextBeforeCursor>"
|
|
1536
|
+
}),
|
|
1537
|
+
new TextMessage({
|
|
1538
|
+
role: Role.User,
|
|
1539
|
+
content: "<InsertionPrompt>add section about the optionholder's pro rata share</InsertionPrompt>"
|
|
1540
|
+
}),
|
|
1541
|
+
new TextMessage({
|
|
1542
|
+
role: Role.Assistant,
|
|
1543
|
+
content: " (ii) that, for purposes of this Agreement and the Merger Agreement, the applicable percentage set forth opposite the name of the Optionholder in the Distribution Waterfall shall be such the Optionholder's \"Pro Rata Share\"; "
|
|
1544
|
+
})
|
|
1545
|
+
];
|
|
1546
|
+
const defaultInsertionsApiConfig = {
|
|
1547
|
+
makeSystemPrompt: defaultInsertionsMakeSystemPrompt,
|
|
1548
|
+
fewShotMessages: defaultInsertionsFewShotMessages,
|
|
1549
|
+
forwardedParams: void 0
|
|
1550
|
+
};
|
|
1551
|
+
|
|
1552
|
+
//#endregion
|
|
1553
|
+
//#region src/types/autosuggestions-config/editing-api-config.tsx
|
|
1554
|
+
const defaultEditingMakeSystemPrompt = (textareaPurpose, contextString) => {
|
|
1555
|
+
return `You are a versatile writing assistant helping the user edit a portion of their text.
|
|
1556
|
+
|
|
1557
|
+
The user is writing some text.
|
|
1558
|
+
The purpose is: \"${textareaPurpose}\"
|
|
1559
|
+
|
|
1560
|
+
The following external context is also provided. Use it when relevant.
|
|
1561
|
+
\`\`\`
|
|
1562
|
+
${contextString}
|
|
1563
|
+
\`\`\`
|
|
1564
|
+
|
|
1565
|
+
The user has provided you with a PROMPT for EDITING a PORTION of the text.
|
|
1566
|
+
Your job is to come up with a new EDITED version OF THE SEGMENT IN QUESTION - AS BEST YOU CAN.
|
|
1567
|
+
Only rewrite the portion of the text that the user has marked as "TextToEdit"!!!
|
|
1568
|
+
|
|
1569
|
+
Adjust yourself to the user's style and implied intent.
|
|
1570
|
+
|
|
1571
|
+
The conversation will be structured as follows:
|
|
1572
|
+
<TextBeforeCursor>
|
|
1573
|
+
<TextToEdit>
|
|
1574
|
+
<TextAfterCursor>
|
|
1575
|
+
<EditingPrompt>
|
|
1576
|
+
|
|
1577
|
+
<YourEditSuggestion>
|
|
1578
|
+
`;
|
|
1579
|
+
};
|
|
1580
|
+
const defaultEditingFewShotMessages = [
|
|
1581
|
+
new TextMessage({
|
|
1582
|
+
role: Role.User,
|
|
1583
|
+
content: "<TextBeforeCursor>This morning I woke up and went straight to the grocery store. </TextBeforeCursor>"
|
|
1584
|
+
}),
|
|
1585
|
+
new TextMessage({
|
|
1586
|
+
role: Role.User,
|
|
1587
|
+
content: "<TextToEdit>While I was there I picked up some apples, oranges, and bananas. </TextToEdit>"
|
|
1588
|
+
}),
|
|
1589
|
+
new TextMessage({
|
|
1590
|
+
role: Role.User,
|
|
1591
|
+
content: "<TextAfterCursor>The grocery store was having a sale on fruit, so I decided to stock up.</TextAfterCursor>"
|
|
1592
|
+
}),
|
|
1593
|
+
new TextMessage({
|
|
1594
|
+
role: Role.User,
|
|
1595
|
+
content: "<EditingPrompt>I also bought a big watermelon</EditingPrompt>"
|
|
1596
|
+
}),
|
|
1597
|
+
new TextMessage({
|
|
1598
|
+
role: Role.Assistant,
|
|
1599
|
+
content: "While I was there I picked up some apples, oranges, and bananas, and a big watermelon."
|
|
1600
|
+
}),
|
|
1601
|
+
new TextMessage({
|
|
1602
|
+
role: Role.User,
|
|
1603
|
+
content: "<TextBeforeCursor>Yesterday, I spent the afternoon working on my new project.</TextBeforeCursor>"
|
|
1604
|
+
}),
|
|
1605
|
+
new TextMessage({
|
|
1606
|
+
role: Role.User,
|
|
1607
|
+
content: "<TextToEdit>It's quite challenging and requires a lot of focus.</TextToEdit>"
|
|
1608
|
+
}),
|
|
1609
|
+
new TextMessage({
|
|
1610
|
+
role: Role.User,
|
|
1611
|
+
content: "<TextAfterCursor>I'm really excited about the potential outcomes of this project.</TextAfterCursor>"
|
|
1612
|
+
}),
|
|
1613
|
+
new TextMessage({
|
|
1614
|
+
role: Role.User,
|
|
1615
|
+
content: "<EditingPrompt>emphasize the complexity and my enthusiasm for the project</EditingPrompt>"
|
|
1616
|
+
}),
|
|
1617
|
+
new TextMessage({
|
|
1618
|
+
role: Role.Assistant,
|
|
1619
|
+
content: "It's a highly complex task that demands intense concentration, but I'm incredibly enthusiastic about the promising prospects of this project."
|
|
1620
|
+
})
|
|
1621
|
+
];
|
|
1622
|
+
const defaultEditingApiConfig = {
|
|
1623
|
+
makeSystemPrompt: defaultEditingMakeSystemPrompt,
|
|
1624
|
+
fewShotMessages: defaultEditingFewShotMessages,
|
|
1625
|
+
forwardedParams: void 0
|
|
1626
|
+
};
|
|
1627
|
+
|
|
1628
|
+
//#endregion
|
|
1629
|
+
//#region src/types/autosuggestions-config/autosuggestions-config.tsx
|
|
1630
|
+
const defaultAutosuggestionsConfig = {
|
|
1631
|
+
...defaultBaseAutosuggestionsConfig,
|
|
1632
|
+
contextCategories: defaultCopilotContextCategories,
|
|
1633
|
+
chatApiConfigs: {
|
|
1634
|
+
suggestionsApiConfig: defaultSuggestionsApiConfig,
|
|
1635
|
+
insertionApiConfig: defaultInsertionsApiConfig,
|
|
1636
|
+
editingApiConfig: defaultEditingApiConfig
|
|
1637
|
+
}
|
|
1638
|
+
};
|
|
1639
|
+
|
|
1640
|
+
//#endregion
|
|
1641
|
+
//#region src/hooks/make-autosuggestions-function/use-make-standard-insertion-function.tsx
|
|
1642
|
+
/**
|
|
1643
|
+
* Returns a memoized function that sends a request to the specified API endpoint to get an autosuggestion for the user's input.
|
|
1644
|
+
* The function takes in the text before and after the cursor, and an abort signal.
|
|
1645
|
+
* It sends a POST request to the API endpoint with the messages array containing the system message, few shot messages, and user messages.
|
|
1646
|
+
* The function returns the suggestion from the API response.
|
|
1647
|
+
*
|
|
1648
|
+
* @param textareaPurpose - The purpose of the textarea. This is included in the system message.
|
|
1649
|
+
* @param apiEndpoint - The API endpoint to send the autosuggestion request to.
|
|
1650
|
+
* @param makeSystemMessage - A function that takes in a context string and returns a system message to include in the autosuggestion request.
|
|
1651
|
+
* @param fewShotMessages - An array of few shot messages to include in the autosuggestion request.
|
|
1652
|
+
* @param contextCategories - The categories of context strings we want to include. By default, we include the (default) "global" context category.
|
|
1653
|
+
* @returns A memoized function that sends a request to the specified API endpoint to get an autosuggestion for the user's input.
|
|
1654
|
+
*/
|
|
1655
|
+
function useMakeStandardInsertionOrEditingFunction(textareaPurpose, contextCategories, insertionApiConfig, editingApiConfig) {
|
|
1656
|
+
const runtimeClient = { generateCopilotResponse: (...args) => {} };
|
|
1657
|
+
const { getContextString, copilotApiConfig } = useCopilotContext();
|
|
1658
|
+
({ ...copilotApiConfig.publicApiKey ? { [COPILOT_CLOUD_PUBLIC_API_KEY_HEADER]: copilotApiConfig.publicApiKey } : {} });
|
|
1659
|
+
async function runtimeClientResponseToStringStream(responsePromise) {
|
|
1660
|
+
const messagesStream = runtimeClient.asStream(responsePromise);
|
|
1661
|
+
return new ReadableStream({ async start(controller) {
|
|
1662
|
+
const reader = messagesStream.getReader();
|
|
1663
|
+
let sentContent = "";
|
|
1664
|
+
while (true) {
|
|
1665
|
+
const { done, value } = await reader.read();
|
|
1666
|
+
if (done) break;
|
|
1667
|
+
const messages = convertGqlOutputToMessages(value.generateCopilotResponse.messages);
|
|
1668
|
+
let newContent = "";
|
|
1669
|
+
for (const message of messages) if (message.isTextMessage()) newContent += message.content;
|
|
1670
|
+
if (newContent) {
|
|
1671
|
+
const contentToSend = newContent.slice(sentContent.length);
|
|
1672
|
+
controller.enqueue(contentToSend);
|
|
1673
|
+
sentContent += contentToSend;
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
controller.close();
|
|
1677
|
+
} });
|
|
1678
|
+
}
|
|
1679
|
+
const insertionFunction = useCallback(async (editorState, insertionPrompt, documents, abortSignal) => {
|
|
1680
|
+
return await retry(async () => {
|
|
1681
|
+
const messages = [
|
|
1682
|
+
new TextMessage({
|
|
1683
|
+
role: Role.System,
|
|
1684
|
+
content: insertionApiConfig.makeSystemPrompt(textareaPurpose, getContextString(documents, contextCategories))
|
|
1685
|
+
}),
|
|
1686
|
+
...insertionApiConfig.fewShotMessages,
|
|
1687
|
+
new TextMessage({
|
|
1688
|
+
role: Role.User,
|
|
1689
|
+
content: `<TextAfterCursor>${editorState.textAfterCursor}</TextAfterCursor>`
|
|
1690
|
+
}),
|
|
1691
|
+
new TextMessage({
|
|
1692
|
+
role: Role.User,
|
|
1693
|
+
content: `<TextBeforeCursor>${editorState.textBeforeCursor}</TextBeforeCursor>`
|
|
1694
|
+
}),
|
|
1695
|
+
new TextMessage({
|
|
1696
|
+
role: Role.User,
|
|
1697
|
+
content: `<InsertionPrompt>${insertionPrompt}</InsertionPrompt>`
|
|
1698
|
+
})
|
|
1699
|
+
];
|
|
1700
|
+
return runtimeClientResponseToStringStream(runtimeClient.generateCopilotResponse({
|
|
1701
|
+
data: {
|
|
1702
|
+
frontend: {
|
|
1703
|
+
actions: [],
|
|
1704
|
+
url: window.location.href
|
|
1705
|
+
},
|
|
1706
|
+
messages: convertMessagesToGqlInput(filterAgentStateMessages(messages)),
|
|
1707
|
+
metadata: { requestType: CopilotRequestType.TextareaCompletion }
|
|
1708
|
+
},
|
|
1709
|
+
properties: copilotApiConfig.properties,
|
|
1710
|
+
signal: abortSignal
|
|
1711
|
+
}));
|
|
1712
|
+
});
|
|
1713
|
+
}, [
|
|
1714
|
+
insertionApiConfig,
|
|
1715
|
+
getContextString,
|
|
1716
|
+
contextCategories,
|
|
1717
|
+
textareaPurpose
|
|
1718
|
+
]);
|
|
1719
|
+
const editingFunction = useCallback(async (editorState, editingPrompt, documents, abortSignal) => {
|
|
1720
|
+
return await retry(async () => {
|
|
1721
|
+
const messages = [
|
|
1722
|
+
new TextMessage({
|
|
1723
|
+
role: Role.System,
|
|
1724
|
+
content: editingApiConfig.makeSystemPrompt(textareaPurpose, getContextString(documents, contextCategories))
|
|
1725
|
+
}),
|
|
1726
|
+
...editingApiConfig.fewShotMessages,
|
|
1727
|
+
new TextMessage({
|
|
1728
|
+
role: Role.User,
|
|
1729
|
+
content: `<TextBeforeCursor>${editorState.textBeforeCursor}</TextBeforeCursor>`
|
|
1730
|
+
}),
|
|
1731
|
+
new TextMessage({
|
|
1732
|
+
role: Role.User,
|
|
1733
|
+
content: `<TextToEdit>${editorState.selectedText}</TextToEdit>`
|
|
1734
|
+
}),
|
|
1735
|
+
new TextMessage({
|
|
1736
|
+
role: Role.User,
|
|
1737
|
+
content: `<TextAfterCursor>${editorState.textAfterCursor}</TextAfterCursor>`
|
|
1738
|
+
}),
|
|
1739
|
+
new TextMessage({
|
|
1740
|
+
role: Role.User,
|
|
1741
|
+
content: `<EditingPrompt>${editingPrompt}</EditingPrompt>`
|
|
1742
|
+
})
|
|
1743
|
+
];
|
|
1744
|
+
return runtimeClientResponseToStringStream(runtimeClient.generateCopilotResponse({
|
|
1745
|
+
data: {
|
|
1746
|
+
frontend: {
|
|
1747
|
+
actions: [],
|
|
1748
|
+
url: window.location.href
|
|
1749
|
+
},
|
|
1750
|
+
messages: convertMessagesToGqlInput(filterAgentStateMessages(messages)),
|
|
1751
|
+
metadata: { requestType: CopilotRequestType.TextareaCompletion }
|
|
1752
|
+
},
|
|
1753
|
+
properties: copilotApiConfig.properties,
|
|
1754
|
+
signal: abortSignal
|
|
1755
|
+
}));
|
|
1756
|
+
});
|
|
1757
|
+
}, [
|
|
1758
|
+
editingApiConfig,
|
|
1759
|
+
getContextString,
|
|
1760
|
+
contextCategories,
|
|
1761
|
+
textareaPurpose
|
|
1762
|
+
]);
|
|
1763
|
+
return useCallback(async (editorState, insertionPrompt, documents, abortSignal) => {
|
|
1764
|
+
if (editorState.selectedText === "") return await insertionFunction(editorState, insertionPrompt, documents, abortSignal);
|
|
1765
|
+
else return await editingFunction(editorState, insertionPrompt, documents, abortSignal);
|
|
1766
|
+
}, [insertionFunction, editingFunction]);
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
//#endregion
|
|
1770
|
+
//#region src/components/copilot-textarea/copilot-textarea.tsx
|
|
1771
|
+
/**
|
|
1772
|
+
* <br/>
|
|
1773
|
+
* <img src="https://cdn.copilotkit.ai/docs/copilotkit/images/CopilotTextarea.gif" width="500" />
|
|
1774
|
+
*
|
|
1775
|
+
* `<CopilotTextarea>` is a React component that acts as a drop-in replacement for the standard `<textarea>`,
|
|
1776
|
+
* offering enhanced autocomplete features powered by AI. It is context-aware, integrating seamlessly with the
|
|
1777
|
+
* [`useCopilotReadable`](/reference/v1/hooks/useCopilotReadable) hook to provide intelligent suggestions based on the application context.
|
|
1778
|
+
*
|
|
1779
|
+
* In addition, it provides a hovering editor window (available by default via `Cmd + K` on Mac and `Ctrl + K` on Windows) that allows the user to
|
|
1780
|
+
* suggest changes to the text, for example providing a summary or rephrasing the text.
|
|
1781
|
+
*
|
|
1782
|
+
* ## Example
|
|
1783
|
+
*
|
|
1784
|
+
* ```tsx
|
|
1785
|
+
* import { CopilotTextarea } from '@copilotkit/react-textarea';
|
|
1786
|
+
* import "@copilotkit/react-textarea/styles.css";
|
|
1787
|
+
*
|
|
1788
|
+
* <CopilotTextarea
|
|
1789
|
+
* autosuggestionsConfig={{
|
|
1790
|
+
* textareaPurpose:
|
|
1791
|
+
* "the body of an email message",
|
|
1792
|
+
* chatApiConfigs: {},
|
|
1793
|
+
* }}
|
|
1794
|
+
* />
|
|
1795
|
+
* ```
|
|
1796
|
+
*
|
|
1797
|
+
* ## Usage
|
|
1798
|
+
*
|
|
1799
|
+
* ### Install Dependencies
|
|
1800
|
+
*
|
|
1801
|
+
* This component is part of the [@copilotkit/react-textarea](https://npmjs.com/package/@copilotkit/react-textarea) package.
|
|
1802
|
+
*
|
|
1803
|
+
* ```shell npm2yarn \"@copilotkit/react-textarea"\
|
|
1804
|
+
* npm install @copilotkit/react-core @copilotkit/react-textarea
|
|
1805
|
+
* ```
|
|
1806
|
+
*
|
|
1807
|
+
* ### Usage
|
|
1808
|
+
*
|
|
1809
|
+
* Use the CopilotTextarea component in your React application similarly to a standard `<textarea />`,
|
|
1810
|
+
* with additional configurations for AI-powered features.
|
|
1811
|
+
*
|
|
1812
|
+
* For example:
|
|
1813
|
+
*
|
|
1814
|
+
* ```tsx
|
|
1815
|
+
* import { useState } from "react";
|
|
1816
|
+
* import { CopilotTextarea } from "@copilotkit/react-textarea";
|
|
1817
|
+
* import "@copilotkit/react-textarea/styles.css";
|
|
1818
|
+
*
|
|
1819
|
+
* export function ExampleComponent() {
|
|
1820
|
+
* const [text, setText] = useState("");
|
|
1821
|
+
*
|
|
1822
|
+
* return (
|
|
1823
|
+
* <CopilotTextarea
|
|
1824
|
+
* className="custom-textarea-class"
|
|
1825
|
+
* value={text}
|
|
1826
|
+
* onValueChange={(value: string) => setText(value)}
|
|
1827
|
+
* placeholder="Enter your text here..."
|
|
1828
|
+
* autosuggestionsConfig={{
|
|
1829
|
+
* textareaPurpose: "Provide context or purpose of the textarea.",
|
|
1830
|
+
* chatApiConfigs: {
|
|
1831
|
+
* suggestionsApiConfig: {
|
|
1832
|
+
* maxTokens: 20,
|
|
1833
|
+
* stop: [".", "?", "!"],
|
|
1834
|
+
* },
|
|
1835
|
+
* },
|
|
1836
|
+
* }}
|
|
1837
|
+
* />
|
|
1838
|
+
* );
|
|
1839
|
+
* }
|
|
1840
|
+
* ```
|
|
1841
|
+
*
|
|
1842
|
+
* ### Look & Feel
|
|
1843
|
+
*
|
|
1844
|
+
* By default, CopilotKit components do not have any styles. You can import CopilotKit's stylesheet at the root of your project:
|
|
1845
|
+
* ```tsx title="YourRootComponent.tsx"
|
|
1846
|
+
* ...
|
|
1847
|
+
* import "@copilotkit/react-textarea/styles.css"; // [!code highlight]
|
|
1848
|
+
*
|
|
1849
|
+
* export function YourRootComponent() {
|
|
1850
|
+
* return (
|
|
1851
|
+
* <CopilotKit>
|
|
1852
|
+
* ...
|
|
1853
|
+
* </CopilotKit>
|
|
1854
|
+
* );
|
|
1855
|
+
* }
|
|
1856
|
+
* ```
|
|
1857
|
+
* For more information about how to customize the styles, check out the [Customize Look & Feel](/guides/custom-look-and-feel/customize-built-in-ui-components) guide.
|
|
1858
|
+
* */
|
|
1859
|
+
/**
|
|
1860
|
+
* A copilot textarea that uses the standard autosuggestions function.
|
|
1861
|
+
*/
|
|
1862
|
+
const CopilotTextarea = React.forwardRef((props, ref) => {
|
|
1863
|
+
const { autosuggestionsConfig: autosuggestionsConfigUserSpecified, ...forwardedProps } = props;
|
|
1864
|
+
const autosuggestionsConfig = merge(defaultAutosuggestionsConfig, autosuggestionsConfigUserSpecified);
|
|
1865
|
+
const autosuggestionsFunction = useMakeStandardAutosuggestionFunction(autosuggestionsConfig.textareaPurpose, autosuggestionsConfig.contextCategories, autosuggestionsConfig.chatApiConfigs.suggestionsApiConfig);
|
|
1866
|
+
const insertionOrEditingFunction = useMakeStandardInsertionOrEditingFunction(autosuggestionsConfig.textareaPurpose, autosuggestionsConfig.contextCategories, autosuggestionsConfig.chatApiConfigs.insertionApiConfig, autosuggestionsConfig.chatApiConfigs.editingApiConfig);
|
|
1867
|
+
return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(BaseCopilotTextarea, {
|
|
1868
|
+
ref,
|
|
1869
|
+
...forwardedProps,
|
|
1870
|
+
baseAutosuggestionsConfig: {
|
|
1871
|
+
...autosuggestionsConfig,
|
|
1872
|
+
apiConfig: {
|
|
1873
|
+
insertionOrEditingFunction,
|
|
1874
|
+
autosuggestionsFunction
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
}) });
|
|
1878
|
+
});
|
|
1879
|
+
|
|
1880
|
+
//#endregion
|
|
1881
|
+
export { BaseCopilotTextarea, CopilotTextarea, defaultAutosuggestionsConfig, defaultBaseAutosuggestionsConfig };
|
|
64
1882
|
//# sourceMappingURL=index.mjs.map
|