Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow toggling CTRL+Enter vs Enter to send ChatAreaInput #6592

Merged
merged 44 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
870a8fa
incomplete
ea42gh Mar 27, 2024
96a3157
fixed spelling, better log message, weird update behavior
ea42gh Mar 27, 2024
d8ead2f
update log messages
ea42gh Mar 27, 2024
1aac3c5
update log messages
ea42gh Mar 27, 2024
f388857
update log messages
ea42gh Mar 27, 2024
db51616
Merge branch 'main' into chat_shift_enter_to_send
ea42gh Mar 27, 2024
841453b
update shift_enter_sends variable name
ea42gh Mar 27, 2024
2856bea
working code
ea42gh Mar 27, 2024
fd68671
Merge branch 'main' into chat_shift_enter_to_send
ea42gh Mar 27, 2024
f135b22
Merge branch 'chat_shift_enter_to_send' of https://github.com/ea42gh/…
ea42gh Mar 27, 2024
ded25f4
fixed lint complaints
ea42gh Mar 27, 2024
4d23950
fixed lint complaints
ea42gh Mar 27, 2024
bad16a3
Merge branch 'main' into chat_shift_enter_to_send
ea42gh Mar 28, 2024
76a5331
Merge branch 'main' into chat_shift_enter_to_send
ea42gh Mar 30, 2024
2ea2879
removed comma
ea42gh Mar 30, 2024
72f7dfb
Merge branch 'chat_shift_enter_to_send' of https://github.com/ea42gh/…
ea42gh Mar 30, 2024
7aa3130
removed comma
ea42gh Mar 30, 2024
bcb2531
removed comma
ea42gh Mar 30, 2024
03a9399
Merge branch 'main' into chat_shift_enter_to_send
ea42gh Apr 1, 2024
3b39d09
Update examples/reference/chat/ChatAreaInput.ipynb
ea42gh Apr 4, 2024
528ff84
Update panel/models/chatarea_input.ts
ea42gh Apr 4, 2024
c684579
Merge branch 'main' into chat_shift_enter_to_send
ea42gh Apr 4, 2024
98e1b8c
Merge branch 'main' into chat_shift_enter_to_send
ea42gh Apr 4, 2024
2f456b9
Merge branch 'holoviz:main' into chat_shift_enter_to_send
ea42gh Apr 5, 2024
5401598
added enter_sends test
ea42gh Apr 6, 2024
53dcfbc
modified newline/send behavior
ea42gh Apr 6, 2024
cf5fe61
removed extra spaces
ea42gh Apr 6, 2024
1914924
added Ctrl-Enter handling when enter_sends=True
ea42gh Apr 6, 2024
4ec6027
removed space in if statement
ea42gh Apr 6, 2024
dd0d50c
Merge branch 'main' into chat_shift_enter_to_send
ea42gh Apr 8, 2024
ca218e2
Merge branch 'main' into chat_shift_enter_to_send
ea42gh Apr 8, 2024
3559d6b
Merge branch 'main' into chat_shift_enter_to_send
ea42gh Apr 9, 2024
8a91014
Update examples/reference/chat/ChatAreaInput.ipynb
ea42gh Apr 9, 2024
40732d6
Update examples/reference/chat/ChatAreaInput.ipynb
ea42gh Apr 9, 2024
20841e2
Update panel/chat/input.py
ea42gh Apr 9, 2024
e8a82ae
Update examples/reference/chat/ChatAreaInput.ipynb
ea42gh Apr 9, 2024
82db2ef
Update examples/reference/chat/ChatAreaInput.ipynb
ea42gh Apr 9, 2024
06a37e8
Update panel/chat/input.py
ea42gh Apr 9, 2024
c31bd75
Update panel/models/chatarea_input.py
ea42gh Apr 9, 2024
ec31e88
Update panel/models/chatarea_input.py
ea42gh Apr 9, 2024
9ebbd2d
Update examples/reference/chat/ChatAreaInput.ipynb
ahuang11 Apr 9, 2024
003c44f
Update examples/reference/chat/ChatAreaInput.ipynb
ahuang11 Apr 9, 2024
34c13fa
Update examples/reference/chat/ChatAreaInput.ipynb
ahuang11 Apr 9, 2024
149c4bd
Update examples/reference/chat/ChatAreaInput.ipynb
ahuang11 Apr 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 19 additions & 14 deletions examples/reference/chat/ChatAreaInput.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,17 @@
"metadata": {},
"source": [
"The `ChatAreaInput` inherits from `TextAreaInput`, allowing entering any multiline string using a text input\n",
"box, with the ability to click the \"Enter\" key to submit the message.\n",
"box, with the ability to click the \"Enter\" key or optionally the \"Ctrl-Enter\" key to submit the message.\n",
"\n",
"Whether \"Enter\" or \"Ctrl-Enter\" sends the message depends on whether the `enter_sends` parameter is set to True (the default) or False.\n",
"\n",
"Unlike TextAreaInput, the `ChatAreaInput` defaults to auto_grow=True and\n",
"max_rows=10, and the `value` is not synced to the server until the \"Enter\" key\n",
"is pressed so watch `value_input` if you need to access what's currently\n",
"max_rows=10, and the `value` is not synced to the server until the message is actually sent, so watch `value_input` if you need to access what's currently\n",
"available in the text input box.\n",
"\n",
"Lines are joined with the newline character `\\n`.\n",
"\n",
"It's primary purpose is use within the [`ChatInterface`](ChatInterface.ipynb) for a high-level, *easy to use*, *ChatGPT like* interface.\n",
"The primary purpose of `ChatAreaInput` is its use with [`ChatInterface`](ChatInterface.ipynb) for a high-level, *easy to use*, *ChatGPT like* interface.\n",
"\n",
"<img alt=\"Chat Design Specification\" src=\"../../assets/ChatDesignSpecification.png\"></img>\n",
"\n",
Expand All @@ -35,20 +36,21 @@
"\n",
"##### Core\n",
"\n",
"* **``disabled_enter``** (bool): If True, the enter key will not submit the message (clear the value).\n",
"* **``value``** (str): The value when the \"Enter\" key is pressed. Only to be used with `watch` or `bind` because the `value` resets to `\"\"` after the \"Enter\" key is pressed; use `value_input` instead to access what's currently available in the text input box.\n",
"* **``disabled_enter``** (bool): If True, disables sending the message by pressing the `enter_sends` key.\n",
"* **``enter_sends``** (bool): If True, pressing the Enter key sends the message, if False it is sent by pressing the Ctrl-Enter. Defaults to True.
ahuang11 marked this conversation as resolved.
Show resolved Hide resolved
"* **``value``** (str): The value when the \"Enter\" or \"Ctrl-Enter\" key is pressed. Only to be used with `watch` or `bind` because the `value` resets to `\"\"` after the message is sent; use `value_input` instead to access what's currently available in the text input box.\n",
"* **``value_input``** (str): The current value updated on every key press.\n",
"\n",
"##### Display\n",
"\n",
"* **`auto_grow`** (boolean, default=True): Whether the TextArea should automatically grow in height to fit the content.\n",
"* **`cols`** (int, default=2): The number of columns in the text input field. \n",
"* **`cols`** (int, default=2): The number of columns in the text input field.\n",
"* **`disabled`** (boolean, default=False): Whether the widget is editable\n",
"* **`max_length`** (int, default=5000): Max character length of the input field. Defaults to 5000\n",
"* **`max_rows`** (int, default=10): The maximum number of rows in the text input field when `auto_grow=True`. \n",
"* **`max_rows`** (int, default=10): The maximum number of rows in the text input field when `auto_grow=True`.\n",
"* **`name`** (str): The title of the widget\n",
"* **`placeholder`** (str): A placeholder string displayed when no value is entered\n",
"* **`rows`** (int, default=2): The number of rows in the text input field. \n",
"* **`rows`** (int, default=2): The number of rows in the text input field.\n",
"* **`resizable`** (boolean | str, default='both'): Whether the layout is interactively resizable, and if so in which dimensions: `width`, `height`, or `both`.\n",
"\n",
"___"
Expand All @@ -60,7 +62,7 @@
"source": [
"#### Basics\n",
"\n",
"To submit a message, press the Enter key."
"To submit a message, press the \"Enter\" key if **``enter_sends``** is True (the default), else press \"Ctrl-Enter\"."
]
},
{
Expand Down Expand Up @@ -97,7 +99,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"To see what's currently typed in, use `value_input` instead because `value` will be `\"\"` besides during submission."
"To see what's currently typed in, use `value_input` instead because `value` will only be set during submission and be `\"\"` otherwise."
]
},
{
Expand All @@ -106,8 +108,11 @@
"metadata": {},
"outputs": [],
"source": [
"chat_area_input = pn.chat.ChatAreaInput(placeholder=\"Type something, leave it, and run the next cell\")\n",
"chat_area_input"
"chat_area_input = pn.chat.ChatAreaInput(enter_sends=False, # To submit a message, press Ctrl-Enter\n",
" placeholder=\"Type something, do not submit it, and run the next cell\",)\n",
"output_markdown = pn.bind(output, chat_area_input.param.value)\n",
"\n",
"pn.Row(chat_area_input, output_markdown)"
]
},
{
Expand All @@ -116,7 +121,7 @@
"metadata": {},
"outputs": [],
"source": [
"print(chat_area_input.value_input, chat_area_input.value)"
"print(f"value_input: {chat_area_input.value_input!r}\nvalue: {chat_area_input.value!r})"
ahuang11 marked this conversation as resolved.
Show resolved Hide resolved
]
}
],
Expand Down
7 changes: 6 additions & 1 deletion panel/chat/input.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,12 @@ class ChatAreaInput(_PnTextAreaInput):

disabled_enter = param.Boolean(
default=False,
doc="If True, the enter key will not submit the message (clear the value).",
doc="If True, disables sending the message by pressing the `enter_sends` key.",
)

enter_sends = param.Boolean(
default=True,
doc="If True, pressing the Enter key sends the message, if False it is sent by pressing the Ctrl+Enter.",
)

rows = param.Integer(default=1, doc="""
Expand Down
5 changes: 4 additions & 1 deletion panel/models/chatarea_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ def __init__(self, model, value=None):
class ChatAreaInput(TextAreaInput):

disabled_enter = Bool(default=False, help="""
If True, the enter key will not submit the message (clear the value).""")
If True, disables sending the message by pressing the `enter_sends` key.""")

enter_sends = Bool(default=True, help="""
If True, pressing the Enter key sends the message, if False it is sent by pressing Ctrl+Enter""")
17 changes: 12 additions & 5 deletions panel/models/chatarea_input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,17 @@ export class ChatAreaInputView extends PnTextAreaInputView {
super.render()

this.el.addEventListener("keydown", (event) => {
if (event.key === "Enter" && !event.shiftKey) {
if (!this.model.disabled_enter) {
this.model.trigger_event(new ChatMessageEvent(this.model.value_input))
this.model.value_input = ""
if (event.key === "Enter") {
if (!event.shiftKey && (event.ctrlKey != this.model.enter_sends)) {
if (!this.model.disabled_enter) {
this.model.trigger_event(new ChatMessageEvent(this.model.value_input))
this.model.value_input = ""
}
event.preventDefault()
} else if (event.ctrlKey && this.model.enter_sends) {
this.model.value_input += "\n"
event.preventDefault()
}
event.preventDefault()
}
})
}
Expand All @@ -46,6 +51,7 @@ export namespace ChatAreaInput {
export type Attrs = p.AttrsOf<Props>
export type Props = PnTextAreaInput.Props & {
disabled_enter: p.Property<boolean>
enter_sends: p.Property<boolean>
}
}

Expand All @@ -65,6 +71,7 @@ export class ChatAreaInput extends PnTextAreaInput {
this.define<ChatAreaInput.Props>(({Bool}) => {
return {
disabled_enter: [ Bool, false ],
enter_sends: [ Bool, true ],
}
})
}
Expand Down
39 changes: 39 additions & 0 deletions panel/tests/ui/chat/test_input_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def test_chat_area_input_resets_to_row(page):
# find chat area input and type a message
textbox = page.locator(".bk-input")
textbox.fill("Hello World!")

# click shift_enter 3 times
textbox.press("Shift+Enter")
textbox.press("Shift+Enter")
Expand All @@ -69,3 +70,41 @@ def test_chat_area_input_resets_to_row(page):
assert chat_area_input.value == ""
textbox_rows = textbox.evaluate("el => el.rows")
assert textbox_rows == 2


def test_chat_area_enter_sends(page):

chat_area_input = ChatAreaInput()
serve_component(page, chat_area_input)

# find chat area input
textbox = page.locator(".bk-input")

# Case enter_sends is True
chat_area_input.enter_sends = True
textbox.fill("enter_sends: True")
wait_until(lambda: chat_area_input.value_input == "enter_sends: True", page)
textbox.press("Shift+Enter")
wait_until(lambda: chat_area_input.value_input == "enter_sends: True\n", page)
textbox.press("Control+Enter")
wait_until(lambda: chat_area_input.value_input == "enter_sends: True\n\n", page)
textbox_rows = textbox.evaluate("el => el.rows")
assert textbox_rows == 3

textbox.press("Enter")
wait_until(lambda: chat_area_input.value_input == "", page)
assert chat_area_input.value == ""

# Case enter_sends is False
chat_area_input.enter_sends = False
textbox.fill("enter_sends: False")
wait_until(lambda: chat_area_input.value_input == "enter_sends: False", page)
textbox.press("Enter")
wait_until(lambda: chat_area_input.value_input == "enter_sends: False\n", page)
textbox.press("Shift+Enter")
wait_until(lambda: chat_area_input.value_input == "enter_sends: False\n\n", page)
textbox_rows = textbox.evaluate("el => el.rows")
assert textbox_rows == 3
textbox.press("Control+Enter")
wait_until(lambda: chat_area_input.value_input == "", page)
assert chat_area_input.value == ""