We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Please replace MultiSelect widget with something more compact, effective and nicer looking
ORIGINALLY POSTED AS PANEL FEATURE REQUEST AT https://github.com/holoviz/panel/issues/874

#### My Pain

I know of experience that many of my dashboard have multiple multi-selections. 

The MultiSelect widget of panel is not compact so it takes up a lot of space.

Furthermore I find the MultiSelect not very nicely looking. I would like my dashboards to look appealing and fresh.

Futhermore I think navigating and selecting in the MultiSelect widget is slow as soon as you have to start scrolling in the MultiSelect

![image](https://user-images.githubusercontent.com/42288570/70967814-c2e29080-2097-11ea-97cd-e41d3b9e1bc7.png)

#### Solution

Implement compact, efficient and nicer looking MultiSelect. 

It should work as a dropdown with multiselect.

#### Additional Context

You can get inspiration from Dash, Streamlit and Tableau that all have a much more compact and modern looking widget.

![image](https://user-images.githubusercontent.com/42288570/70967921-240a6400-2098-11ea-9d99-cefe44ed27dc.png)

![image](https://user-images.githubusercontent.com/42288570/70967964-3d131500-2098-11ea-8991-3ff2f1c29fc8.png)

FYI. Tableau has both a more compact Dropdown and something similar to the MultiSelect.

Here it's used an that's where I have my evaluation from. You can find it in the Gallery at awesome-panel.org.

![kickstarter_dashboard](https://user-images.githubusercontent.com/42288570/70968057-72b7fe00-2098-11ea-8680-73de1f2bf843.gif)

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `bokeh/models/widgets/inputs.py`
Content:
```
1 #-----------------------------------------------------------------------------
2 # Copyright (c) 2012 - 2020, Anaconda, Inc., and Bokeh Contributors.
3 # All rights reserved.
4 #
5 # The full license is in the file LICENSE.txt, distributed with this software.
6 #-----------------------------------------------------------------------------
7 ''' Various kinds of input widgets and form controls.
8 
9 '''
10 
11 #-----------------------------------------------------------------------------
12 # Boilerplate
13 #-----------------------------------------------------------------------------
14 import logging # isort:skip
15 log = logging.getLogger(__name__)
16 
17 #-----------------------------------------------------------------------------
18 # Imports
19 #-----------------------------------------------------------------------------
20 
21 # Bokeh imports
22 from ...core.enums import CalendarPosition
23 from ...core.has_props import abstract
24 from ...core.properties import (
25     Bool,
26     ColorHex,
27     Date,
28     Dict,
29     Either,
30     Enum,
31     Float,
32     Int,
33     List,
34     PositiveInt,
35     String,
36     Tuple,
37 )
38 from .widget import Widget
39 
40 #-----------------------------------------------------------------------------
41 # Globals and constants
42 #-----------------------------------------------------------------------------
43 
44 __all__ = (
45     'AutocompleteInput',
46     'ColorPicker',
47     'DatePicker',
48     'FileInput',
49     'InputWidget',
50     'MultiSelect',
51     'PasswordInput',
52     'Select',
53     'Spinner',
54     'TextInput',
55     'TextAreaInput'
56 )
57 
58 #-----------------------------------------------------------------------------
59 # Dev API
60 #-----------------------------------------------------------------------------
61 
62 
63 @abstract
64 class InputWidget(Widget):
65     ''' Abstract base class for input widgets.
66 
67     '''
68 
69     title = String(default="", help="""
70     Widget's label.
71     """)
72 
73     @classmethod
74     def coerce_value(cls, val):
75         prop_obj = cls.lookup('value')
76         if isinstance(prop_obj, Float):
77             return float(val)
78         elif isinstance(prop_obj, Int):
79             return int(val)
80         elif isinstance(prop_obj, String):
81             return str(val)
82         else:
83             return val
84 
85 #-----------------------------------------------------------------------------
86 # General API
87 #-----------------------------------------------------------------------------
88 
89 class FileInput(Widget):
90     ''' Present a file-chooser dialog to users and return the contents of a
91     selected file.
92 
93     '''
94 
95     value = String(default="", readonly=True, help="""
96     A base64-encoded string of the contents of the selected file.
97     """)
98 
99     mime_type = String(default="", readonly=True, help="""
100     The mime type of the selected file.
101     """)
102 
103     filename = String(default="", readonly=True, help="""
104     The filename of the selected file.
105 
106     .. note::
107         The full file path is not included since browsers will not provide
108         access to that information for security reasons.
109     """)
110 
111     accept = String(default="", help="""
112     Comma-separated list of standard HTML file input filters that restrict what
113     files the user can pick from. Values can be:
114 
115     `<file extension>`:
116         Specific file extension(s) (e.g: .gif, .jpg, .png, .doc) are pickable
117 
118     `audio/*`:
119         all sound files are pickable
120 
121     `video/*`:
122         all video files are pickable
123 
124     `image/*`:
125         all image files are pickable
126 
127     `<media type>`:
128         A valid `IANA Media Type`_, with no parameters.
129 
130     .. _IANA Media Type: https://www.iana.org/assignments/media-types/media-types.xhtml
131     """)
132 
133 
134 class TextInput(InputWidget):
135     ''' Single-line input widget.
136 
137     '''
138 
139     value = String(default="", help="""
140     Initial or entered text value.
141 
142     Change events are triggered whenever <enter> is pressed.
143     """)
144 
145     value_input = String(default="", help="""
146     Initial or current value.
147 
148     Change events are triggered whenever any update happens, i.e. on every
149     keypress.
150     """)
151 
152     placeholder = String(default="", help="""
153     Placeholder for empty input field.
154     """)
155 
156 
157 class TextAreaInput(TextInput):
158     ''' Multi-line input widget.
159 
160     '''
161 
162     cols = Int(default=20, help="""
163     Specifies the width of the text area (in average character width). Default: 20
164     """)
165 
166     rows = Int(default=2, help="""
167     Specifies the height of the text area (in lines). Default: 2
168     """)
169 
170     max_length = Int(default=500, help="""
171     Max count of characters in field
172     """)
173 
174 
175 class PasswordInput(TextInput):
176     ''' Single-line password input widget.
177 
178     This widget hides the input value so that it is not visible in the browser.
179 
180     .. warning::
181         Secure transmission of the password to Bokeh server application code
182         requires configuring the server for SSL (i.e. HTTPS) termination.
183 
184     '''
185 
186 
187 class AutocompleteInput(TextInput):
188     ''' Single-line input widget with auto-completion.
189 
190     '''
191 
192     completions = List(String, help="""
193     A list of completion strings. This will be used to guide the
194     user upon typing the beginning of a desired value.
195     """)
196 
197     min_characters = PositiveInt(default=2, help="""
198     The number of characters a user must type before completions are presented.
199     """)
200 
201 
202 class Select(InputWidget):
203     ''' Single-select widget.
204 
205     '''
206     options = Either(List(Either(String, Tuple(Either(Int, String), String))),
207         Dict(String, List(Either(String, Tuple(Either(Int, String), String)))), help="""
208     Available selection options. Options may be provided either as a list of
209     possible string values, or as a list of tuples, each of the form
210     ``(value, label)``. In the latter case, the visible widget text for each
211     value will be corresponding given label. Option groupings can be provided
212     by supplying a dictionary object whose values are in the aforementioned
213     list format
214     """)
215 
216     value = String(default="", help="""
217     Initial or selected value.
218     """)
219 
220 class MultiSelect(InputWidget):
221     ''' Multi-select widget.
222 
223     '''
224 
225     options = List(Either(String, Tuple(String, String)), help="""
226     Available selection options. Options may be provided either as a list of
227     possible string values, or as a list of tuples, each of the form
228     ``(value, label)``. In the latter case, the visible widget text for each
229     value will be corresponding given label.
230     """)
231 
232     value = List(String, help="""
233     Initial or selected values.
234     """)
235 
236     size = Int(default=4, help="""
237     The number of visible options in the dropdown list. (This uses the
238     ``select`` HTML element's ``size`` attribute. Some browsers might not
239     show less than 3 options.)
240     """)
241 
242 
243 class DatePicker(InputWidget):
244     ''' Calendar-based date picker widget.
245 
246     '''
247 
248     value = Date(help="""
249     The initial or picked date.
250     """)
251 
252     min_date = Date(default=None, help="""
253     Optional earliest allowable date.
254     """)
255 
256     max_date = Date(default=None, help="""
257     Optional latest allowable date.
258     """)
259 
260     disabled_dates = List(Either(Date, Tuple(Date, Date)), default=[], help="""
261     A list of dates of ``(start, end)`` date ranges to make unavailable for
262     selection. All other dates will be avalable.
263 
264     .. note::
265         Only one of ``disabled_dates`` and ``enabled_dates`` should be specified.
266     """)
267 
268     enabled_dates = List(Either(Date, Tuple(Date, Date)), default=[], help="""
269     A list of dates of ``(start, end)`` date ranges to make available for
270     selection. All other dates will be unavailable.
271 
272     .. note::
273         Only one of ``disabled_dates`` and ``enabled_dates`` should be specified.
274     """)
275 
276     position = Enum(CalendarPosition, default="auto", help="""
277     Where the calendar is rendered relative to the input when ``inline`` is False.
278     """)
279 
280     inline = Bool(default=False, help="""
281     Whether the calendar sholud be displayed inline.
282     """)
283 
284 class ColorPicker(InputWidget):
285     ''' Color picker widget
286 
287     .. warning::
288         This widget as a limited support on *Internet Explorer* (it will be displayed
289         as a simple text input).
290 
291     '''
292 
293     color = ColorHex(default='#000000', help="""
294     The initial color of the picked color (named or hexadecimal)
295     """)
296 
297 class Spinner(InputWidget):
298     ''' Spinner widget for numerical inputs
299 
300     '''
301 
302     value = Float(default=0, help="""
303     The initial value of the spinner
304     """)
305 
306     step = Float(default=1, help="""
307     The step added or subtracted to the current value
308     """)
309 
310     low = Float(help="""
311     Optional lowest allowable value.
312     """)
313 
314     high = Float(help="""
315     Optional highest allowable value.
316     """)
317 
318 #-----------------------------------------------------------------------------
319 # Private API
320 #-----------------------------------------------------------------------------
321 
322 #-----------------------------------------------------------------------------
323 # Code
324 #-----------------------------------------------------------------------------
325
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/bokeh/models/widgets/inputs.py b/bokeh/models/widgets/inputs.py
--- a/bokeh/models/widgets/inputs.py
+++ b/bokeh/models/widgets/inputs.py
@@ -47,6 +47,7 @@
     'DatePicker',
     'FileInput',
     'InputWidget',
+    'MultiChoice',
     'MultiSelect',
     'PasswordInput',
     'Select',
@@ -240,6 +241,42 @@
     """)
 
 
+class MultiChoice(InputWidget):
+    ''' MultiChoice widget.
+
+    '''
+
+    options = List(Either(String, Tuple(String, String)), help="""
+    Available selection options. Options may be provided either as a list of
+    possible string values, or as a list of tuples, each of the form
+    ``(value, label)``. In the latter case, the visible widget text for each
+    value will be corresponding given label.
+    """)
+
+    value = List(String, help="""
+    Initial or selected values.
+    """)
+
+    delete_button = Bool(default=True, help="""
+    Whether to add a button to remove a selected option.
+    """)
+
+    max_items = Int(default=None, help="""
+    The maximum number of items that can be selected.
+    """)
+
+    option_limit = Int(default=None, help="""
+    The number of choices that will be rendered in the dropdown.
+    """)
+
+    placeholder = String(default=None, help="""
+    A string that is displayed if not item is added.
+    """)
+
+    solid = Bool(default=True, help="""
+    Specify whether the choices should be solidly filled.""")
+
+
 class DatePicker(InputWidget):
     ''' Calendar-based date picker widget.

{"golden_diff": "diff --git a/bokeh/models/widgets/inputs.py b/bokeh/models/widgets/inputs.py\n--- a/bokeh/models/widgets/inputs.py\n+++ b/bokeh/models/widgets/inputs.py\n@@ -47,6 +47,7 @@\n     'DatePicker',\n     'FileInput',\n     'InputWidget',\n+    'MultiChoice',\n     'MultiSelect',\n     'PasswordInput',\n     'Select',\n@@ -240,6 +241,42 @@\n     \"\"\")\n \n \n+class MultiChoice(InputWidget):\n+    ''' MultiChoice widget.\n+\n+    '''\n+\n+    options = List(Either(String, Tuple(String, String)), help=\"\"\"\n+    Available selection options. Options may be provided either as a list of\n+    possible string values, or as a list of tuples, each of the form\n+    ``(value, label)``. In the latter case, the visible widget text for each\n+    value will be corresponding given label.\n+    \"\"\")\n+\n+    value = List(String, help=\"\"\"\n+    Initial or selected values.\n+    \"\"\")\n+\n+    delete_button = Bool(default=True, help=\"\"\"\n+    Whether to add a button to remove a selected option.\n+    \"\"\")\n+\n+    max_items = Int(default=None, help=\"\"\"\n+    The maximum number of items that can be selected.\n+    \"\"\")\n+\n+    option_limit = Int(default=None, help=\"\"\"\n+    The number of choices that will be rendered in the dropdown.\n+    \"\"\")\n+\n+    placeholder = String(default=None, help=\"\"\"\n+    A string that is displayed if not item is added.\n+    \"\"\")\n+\n+    solid = Bool(default=True, help=\"\"\"\n+    Specify whether the choices should be solidly filled.\"\"\")\n+\n+\n class DatePicker(InputWidget):\n     ''' Calendar-based date picker widget.\n", "issue": "Please replace MultiSelect widget with something more compact, effective and nicer looking\nORIGINALLY POSTED AS PANEL FEATURE REQUEST AT https://github.com/holoviz/panel/issues/874\r\n\r\n#### My Pain\r\n\r\nI know of experience that many of my dashboard have multiple multi-selections. \r\n\r\nThe MultiSelect widget of panel is not compact so it takes up a lot of space.\r\n\r\nFurthermore I find the MultiSelect not very nicely looking. I would like my dashboards to look appealing and fresh.\r\n\r\nFuthermore I think navigating and selecting in the MultiSelect widget is slow as soon as you have to start scrolling in the MultiSelect\r\n\r\n![image](https://user-images.githubusercontent.com/42288570/70967814-c2e29080-2097-11ea-97cd-e41d3b9e1bc7.png)\r\n\r\n#### Solution\r\n\r\nImplement compact, efficient and nicer looking MultiSelect. \r\n\r\nIt should work as a dropdown with multiselect.\r\n\r\n#### Additional Context\r\n\r\nYou can get inspiration from Dash, Streamlit and Tableau that all have a much more compact and modern looking widget.\r\n\r\n![image](https://user-images.githubusercontent.com/42288570/70967921-240a6400-2098-11ea-9d99-cefe44ed27dc.png)\r\n\r\n![image](https://user-images.githubusercontent.com/42288570/70967964-3d131500-2098-11ea-8991-3ff2f1c29fc8.png)\r\n\r\nFYI. Tableau has both a more compact Dropdown and something similar to the MultiSelect.\r\n\r\nHere it's used an that's where I have my evaluation from. You can find it in the Gallery at awesome-panel.org.\r\n\r\n![kickstarter_dashboard](https://user-images.githubusercontent.com/42288570/70968057-72b7fe00-2098-11ea-8680-73de1f2bf843.gif)\n", "before_files": [{"content": "#-----------------------------------------------------------------------------\n# Copyright (c) 2012 - 2020, Anaconda, Inc., and Bokeh Contributors.\n# All rights reserved.\n#\n# The full license is in the file LICENSE.txt, distributed with this software.\n#-----------------------------------------------------------------------------\n''' Various kinds of input widgets and form controls.\n\n'''\n\n#-----------------------------------------------------------------------------\n# Boilerplate\n#-----------------------------------------------------------------------------\nimport logging # isort:skip\nlog = logging.getLogger(__name__)\n\n#-----------------------------------------------------------------------------\n# Imports\n#-----------------------------------------------------------------------------\n\n# Bokeh imports\nfrom ...core.enums import CalendarPosition\nfrom ...core.has_props import abstract\nfrom ...core.properties import (\n    Bool,\n    ColorHex,\n    Date,\n    Dict,\n    Either,\n    Enum,\n    Float,\n    Int,\n    List,\n    PositiveInt,\n    String,\n    Tuple,\n)\nfrom .widget import Widget\n\n#-----------------------------------------------------------------------------\n# Globals and constants\n#-----------------------------------------------------------------------------\n\n__all__ = (\n    'AutocompleteInput',\n    'ColorPicker',\n    'DatePicker',\n    'FileInput',\n    'InputWidget',\n    'MultiSelect',\n    'PasswordInput',\n    'Select',\n    'Spinner',\n    'TextInput',\n    'TextAreaInput'\n)\n\n#-----------------------------------------------------------------------------\n# Dev API\n#-----------------------------------------------------------------------------\n\n\n@abstract\nclass InputWidget(Widget):\n    ''' Abstract base class for input widgets.\n\n    '''\n\n    title = String(default=\"\", help=\"\"\"\n    Widget's label.\n    \"\"\")\n\n    @classmethod\n    def coerce_value(cls, val):\n        prop_obj = cls.lookup('value')\n        if isinstance(prop_obj, Float):\n            return float(val)\n        elif isinstance(prop_obj, Int):\n            return int(val)\n        elif isinstance(prop_obj, String):\n            return str(val)\n        else:\n            return val\n\n#-----------------------------------------------------------------------------\n# General API\n#-----------------------------------------------------------------------------\n\nclass FileInput(Widget):\n    ''' Present a file-chooser dialog to users and return the contents of a\n    selected file.\n\n    '''\n\n    value = String(default=\"\", readonly=True, help=\"\"\"\n    A base64-encoded string of the contents of the selected file.\n    \"\"\")\n\n    mime_type = String(default=\"\", readonly=True, help=\"\"\"\n    The mime type of the selected file.\n    \"\"\")\n\n    filename = String(default=\"\", readonly=True, help=\"\"\"\n    The filename of the selected file.\n\n    .. note::\n        The full file path is not included since browsers will not provide\n        access to that information for security reasons.\n    \"\"\")\n\n    accept = String(default=\"\", help=\"\"\"\n    Comma-separated list of standard HTML file input filters that restrict what\n    files the user can pick from. Values can be:\n\n    `<file extension>`:\n        Specific file extension(s) (e.g: .gif, .jpg, .png, .doc) are pickable\n\n    `audio/*`:\n        all sound files are pickable\n\n    `video/*`:\n        all video files are pickable\n\n    `image/*`:\n        all image files are pickable\n\n    `<media type>`:\n        A valid `IANA Media Type`_, with no parameters.\n\n    .. _IANA Media Type: https://www.iana.org/assignments/media-types/media-types.xhtml\n    \"\"\")\n\n\nclass TextInput(InputWidget):\n    ''' Single-line input widget.\n\n    '''\n\n    value = String(default=\"\", help=\"\"\"\n    Initial or entered text value.\n\n    Change events are triggered whenever <enter> is pressed.\n    \"\"\")\n\n    value_input = String(default=\"\", help=\"\"\"\n    Initial or current value.\n\n    Change events are triggered whenever any update happens, i.e. on every\n    keypress.\n    \"\"\")\n\n    placeholder = String(default=\"\", help=\"\"\"\n    Placeholder for empty input field.\n    \"\"\")\n\n\nclass TextAreaInput(TextInput):\n    ''' Multi-line input widget.\n\n    '''\n\n    cols = Int(default=20, help=\"\"\"\n    Specifies the width of the text area (in average character width). Default: 20\n    \"\"\")\n\n    rows = Int(default=2, help=\"\"\"\n    Specifies the height of the text area (in lines). Default: 2\n    \"\"\")\n\n    max_length = Int(default=500, help=\"\"\"\n    Max count of characters in field\n    \"\"\")\n\n\nclass PasswordInput(TextInput):\n    ''' Single-line password input widget.\n\n    This widget hides the input value so that it is not visible in the browser.\n\n    .. warning::\n        Secure transmission of the password to Bokeh server application code\n        requires configuring the server for SSL (i.e. HTTPS) termination.\n\n    '''\n\n\nclass AutocompleteInput(TextInput):\n    ''' Single-line input widget with auto-completion.\n\n    '''\n\n    completions = List(String, help=\"\"\"\n    A list of completion strings. This will be used to guide the\n    user upon typing the beginning of a desired value.\n    \"\"\")\n\n    min_characters = PositiveInt(default=2, help=\"\"\"\n    The number of characters a user must type before completions are presented.\n    \"\"\")\n\n\nclass Select(InputWidget):\n    ''' Single-select widget.\n\n    '''\n    options = Either(List(Either(String, Tuple(Either(Int, String), String))),\n        Dict(String, List(Either(String, Tuple(Either(Int, String), String)))), help=\"\"\"\n    Available selection options. Options may be provided either as a list of\n    possible string values, or as a list of tuples, each of the form\n    ``(value, label)``. In the latter case, the visible widget text for each\n    value will be corresponding given label. Option groupings can be provided\n    by supplying a dictionary object whose values are in the aforementioned\n    list format\n    \"\"\")\n\n    value = String(default=\"\", help=\"\"\"\n    Initial or selected value.\n    \"\"\")\n\nclass MultiSelect(InputWidget):\n    ''' Multi-select widget.\n\n    '''\n\n    options = List(Either(String, Tuple(String, String)), help=\"\"\"\n    Available selection options. Options may be provided either as a list of\n    possible string values, or as a list of tuples, each of the form\n    ``(value, label)``. In the latter case, the visible widget text for each\n    value will be corresponding given label.\n    \"\"\")\n\n    value = List(String, help=\"\"\"\n    Initial or selected values.\n    \"\"\")\n\n    size = Int(default=4, help=\"\"\"\n    The number of visible options in the dropdown list. (This uses the\n    ``select`` HTML element's ``size`` attribute. Some browsers might not\n    show less than 3 options.)\n    \"\"\")\n\n\nclass DatePicker(InputWidget):\n    ''' Calendar-based date picker widget.\n\n    '''\n\n    value = Date(help=\"\"\"\n    The initial or picked date.\n    \"\"\")\n\n    min_date = Date(default=None, help=\"\"\"\n    Optional earliest allowable date.\n    \"\"\")\n\n    max_date = Date(default=None, help=\"\"\"\n    Optional latest allowable date.\n    \"\"\")\n\n    disabled_dates = List(Either(Date, Tuple(Date, Date)), default=[], help=\"\"\"\n    A list of dates of ``(start, end)`` date ranges to make unavailable for\n    selection. All other dates will be avalable.\n\n    .. note::\n        Only one of ``disabled_dates`` and ``enabled_dates`` should be specified.\n    \"\"\")\n\n    enabled_dates = List(Either(Date, Tuple(Date, Date)), default=[], help=\"\"\"\n    A list of dates of ``(start, end)`` date ranges to make available for\n    selection. All other dates will be unavailable.\n\n    .. note::\n        Only one of ``disabled_dates`` and ``enabled_dates`` should be specified.\n    \"\"\")\n\n    position = Enum(CalendarPosition, default=\"auto\", help=\"\"\"\n    Where the calendar is rendered relative to the input when ``inline`` is False.\n    \"\"\")\n\n    inline = Bool(default=False, help=\"\"\"\n    Whether the calendar sholud be displayed inline.\n    \"\"\")\n\nclass ColorPicker(InputWidget):\n    ''' Color picker widget\n\n    .. warning::\n        This widget as a limited support on *Internet Explorer* (it will be displayed\n        as a simple text input).\n\n    '''\n\n    color = ColorHex(default='#000000', help=\"\"\"\n    The initial color of the picked color (named or hexadecimal)\n    \"\"\")\n\nclass Spinner(InputWidget):\n    ''' Spinner widget for numerical inputs\n\n    '''\n\n    value = Float(default=0, help=\"\"\"\n    The initial value of the spinner\n    \"\"\")\n\n    step = Float(default=1, help=\"\"\"\n    The step added or subtracted to the current value\n    \"\"\")\n\n    low = Float(help=\"\"\"\n    Optional lowest allowable value.\n    \"\"\")\n\n    high = Float(help=\"\"\"\n    Optional highest allowable value.\n    \"\"\")\n\n#-----------------------------------------------------------------------------\n# Private API\n#-----------------------------------------------------------------------------\n\n#-----------------------------------------------------------------------------\n# Code\n#-----------------------------------------------------------------------------\n", "path": "bokeh/models/widgets/inputs.py"}], "after_files": [{"content": "#-----------------------------------------------------------------------------\n# Copyright (c) 2012 - 2020, Anaconda, Inc., and Bokeh Contributors.\n# All rights reserved.\n#\n# The full license is in the file LICENSE.txt, distributed with this software.\n#-----------------------------------------------------------------------------\n''' Various kinds of input widgets and form controls.\n\n'''\n\n#-----------------------------------------------------------------------------\n# Boilerplate\n#-----------------------------------------------------------------------------\nimport logging # isort:skip\nlog = logging.getLogger(__name__)\n\n#-----------------------------------------------------------------------------\n# Imports\n#-----------------------------------------------------------------------------\n\n# Bokeh imports\nfrom ...core.enums import CalendarPosition\nfrom ...core.has_props import abstract\nfrom ...core.properties import (\n    Bool,\n    ColorHex,\n    Date,\n    Dict,\n    Either,\n    Enum,\n    Float,\n    Int,\n    List,\n    PositiveInt,\n    String,\n    Tuple,\n)\nfrom .widget import Widget\n\n#-----------------------------------------------------------------------------\n# Globals and constants\n#-----------------------------------------------------------------------------\n\n__all__ = (\n    'AutocompleteInput',\n    'ColorPicker',\n    'DatePicker',\n    'FileInput',\n    'InputWidget',\n    'MultiChoice',\n    'MultiSelect',\n    'PasswordInput',\n    'Select',\n    'Spinner',\n    'TextInput',\n    'TextAreaInput'\n)\n\n#-----------------------------------------------------------------------------\n# Dev API\n#-----------------------------------------------------------------------------\n\n\n@abstract\nclass InputWidget(Widget):\n    ''' Abstract base class for input widgets.\n\n    '''\n\n    title = String(default=\"\", help=\"\"\"\n    Widget's label.\n    \"\"\")\n\n    @classmethod\n    def coerce_value(cls, val):\n        prop_obj = cls.lookup('value')\n        if isinstance(prop_obj, Float):\n            return float(val)\n        elif isinstance(prop_obj, Int):\n            return int(val)\n        elif isinstance(prop_obj, String):\n            return str(val)\n        else:\n            return val\n\n#-----------------------------------------------------------------------------\n# General API\n#-----------------------------------------------------------------------------\n\nclass FileInput(Widget):\n    ''' Present a file-chooser dialog to users and return the contents of a\n    selected file.\n\n    '''\n\n    value = String(default=\"\", readonly=True, help=\"\"\"\n    A base64-encoded string of the contents of the selected file.\n    \"\"\")\n\n    mime_type = String(default=\"\", readonly=True, help=\"\"\"\n    The mime type of the selected file.\n    \"\"\")\n\n    filename = String(default=\"\", readonly=True, help=\"\"\"\n    The filename of the selected file.\n\n    .. note::\n        The full file path is not included since browsers will not provide\n        access to that information for security reasons.\n    \"\"\")\n\n    accept = String(default=\"\", help=\"\"\"\n    Comma-separated list of standard HTML file input filters that restrict what\n    files the user can pick from. Values can be:\n\n    `<file extension>`:\n        Specific file extension(s) (e.g: .gif, .jpg, .png, .doc) are pickable\n\n    `audio/*`:\n        all sound files are pickable\n\n    `video/*`:\n        all video files are pickable\n\n    `image/*`:\n        all image files are pickable\n\n    `<media type>`:\n        A valid `IANA Media Type`_, with no parameters.\n\n    .. _IANA Media Type: https://www.iana.org/assignments/media-types/media-types.xhtml\n    \"\"\")\n\n\nclass TextInput(InputWidget):\n    ''' Single-line input widget.\n\n    '''\n\n    value = String(default=\"\", help=\"\"\"\n    Initial or entered text value.\n\n    Change events are triggered whenever <enter> is pressed.\n    \"\"\")\n\n    value_input = String(default=\"\", help=\"\"\"\n    Initial or current value.\n\n    Change events are triggered whenever any update happens, i.e. on every\n    keypress.\n    \"\"\")\n\n    placeholder = String(default=\"\", help=\"\"\"\n    Placeholder for empty input field.\n    \"\"\")\n\n\nclass TextAreaInput(TextInput):\n    ''' Multi-line input widget.\n\n    '''\n\n    cols = Int(default=20, help=\"\"\"\n    Specifies the width of the text area (in average character width). Default: 20\n    \"\"\")\n\n    rows = Int(default=2, help=\"\"\"\n    Specifies the height of the text area (in lines). Default: 2\n    \"\"\")\n\n    max_length = Int(default=500, help=\"\"\"\n    Max count of characters in field\n    \"\"\")\n\n\nclass PasswordInput(TextInput):\n    ''' Single-line password input widget.\n\n    This widget hides the input value so that it is not visible in the browser.\n\n    .. warning::\n        Secure transmission of the password to Bokeh server application code\n        requires configuring the server for SSL (i.e. HTTPS) termination.\n\n    '''\n\n\nclass AutocompleteInput(TextInput):\n    ''' Single-line input widget with auto-completion.\n\n    '''\n\n    completions = List(String, help=\"\"\"\n    A list of completion strings. This will be used to guide the\n    user upon typing the beginning of a desired value.\n    \"\"\")\n\n    min_characters = PositiveInt(default=2, help=\"\"\"\n    The number of characters a user must type before completions are presented.\n    \"\"\")\n\n\nclass Select(InputWidget):\n    ''' Single-select widget.\n\n    '''\n    options = Either(List(Either(String, Tuple(Either(Int, String), String))),\n        Dict(String, List(Either(String, Tuple(Either(Int, String), String)))), help=\"\"\"\n    Available selection options. Options may be provided either as a list of\n    possible string values, or as a list of tuples, each of the form\n    ``(value, label)``. In the latter case, the visible widget text for each\n    value will be corresponding given label. Option groupings can be provided\n    by supplying a dictionary object whose values are in the aforementioned\n    list format\n    \"\"\")\n\n    value = String(default=\"\", help=\"\"\"\n    Initial or selected value.\n    \"\"\")\n\nclass MultiSelect(InputWidget):\n    ''' Multi-select widget.\n\n    '''\n\n    options = List(Either(String, Tuple(String, String)), help=\"\"\"\n    Available selection options. Options may be provided either as a list of\n    possible string values, or as a list of tuples, each of the form\n    ``(value, label)``. In the latter case, the visible widget text for each\n    value will be corresponding given label.\n    \"\"\")\n\n    value = List(String, help=\"\"\"\n    Initial or selected values.\n    \"\"\")\n\n    size = Int(default=4, help=\"\"\"\n    The number of visible options in the dropdown list. (This uses the\n    ``select`` HTML element's ``size`` attribute. Some browsers might not\n    show less than 3 options.)\n    \"\"\")\n\n\nclass MultiChoice(InputWidget):\n    ''' MultiChoice widget.\n\n    '''\n\n    options = List(Either(String, Tuple(String, String)), help=\"\"\"\n    Available selection options. Options may be provided either as a list of\n    possible string values, or as a list of tuples, each of the form\n    ``(value, label)``. In the latter case, the visible widget text for each\n    value will be corresponding given label.\n    \"\"\")\n\n    value = List(String, help=\"\"\"\n    Initial or selected values.\n    \"\"\")\n\n    delete_button = Bool(default=True, help=\"\"\"\n    Whether to add a button to remove a selected option.\n    \"\"\")\n\n    max_items = Int(default=None, help=\"\"\"\n    The maximum number of items that can be selected.\n    \"\"\")\n\n    option_limit = Int(default=None, help=\"\"\"\n    The number of choices that will be rendered in the dropdown.\n    \"\"\")\n\n    placeholder = String(default=None, help=\"\"\"\n    A string that is displayed if not item is added.\n    \"\"\")\n\n    solid = Bool(default=True, help=\"\"\"\n    Specify whether the choices should be solidly filled.\"\"\")\n\n\nclass DatePicker(InputWidget):\n    ''' Calendar-based date picker widget.\n\n    '''\n\n    value = Date(help=\"\"\"\n    The initial or picked date.\n    \"\"\")\n\n    min_date = Date(default=None, help=\"\"\"\n    Optional earliest allowable date.\n    \"\"\")\n\n    max_date = Date(default=None, help=\"\"\"\n    Optional latest allowable date.\n    \"\"\")\n\n    disabled_dates = List(Either(Date, Tuple(Date, Date)), default=[], help=\"\"\"\n    A list of dates of ``(start, end)`` date ranges to make unavailable for\n    selection. All other dates will be avalable.\n\n    .. note::\n        Only one of ``disabled_dates`` and ``enabled_dates`` should be specified.\n    \"\"\")\n\n    enabled_dates = List(Either(Date, Tuple(Date, Date)), default=[], help=\"\"\"\n    A list of dates of ``(start, end)`` date ranges to make available for\n    selection. All other dates will be unavailable.\n\n    .. note::\n        Only one of ``disabled_dates`` and ``enabled_dates`` should be specified.\n    \"\"\")\n\n    position = Enum(CalendarPosition, default=\"auto\", help=\"\"\"\n    Where the calendar is rendered relative to the input when ``inline`` is False.\n    \"\"\")\n\n    inline = Bool(default=False, help=\"\"\"\n    Whether the calendar sholud be displayed inline.\n    \"\"\")\n\nclass ColorPicker(InputWidget):\n    ''' Color picker widget\n\n    .. warning::\n        This widget as a limited support on *Internet Explorer* (it will be displayed\n        as a simple text input).\n\n    '''\n\n    color = ColorHex(default='#000000', help=\"\"\"\n    The initial color of the picked color (named or hexadecimal)\n    \"\"\")\n\nclass Spinner(InputWidget):\n    ''' Spinner widget for numerical inputs\n\n    '''\n\n    value = Float(default=0, help=\"\"\"\n    The initial value of the spinner\n    \"\"\")\n\n    step = Float(default=1, help=\"\"\"\n    The step added or subtracted to the current value\n    \"\"\")\n\n    low = Float(help=\"\"\"\n    Optional lowest allowable value.\n    \"\"\")\n\n    high = Float(help=\"\"\"\n    Optional highest allowable value.\n    \"\"\")\n\n#-----------------------------------------------------------------------------\n# Private API\n#-----------------------------------------------------------------------------\n\n#-----------------------------------------------------------------------------\n# Code\n#-----------------------------------------------------------------------------\n", "path": "bokeh/models/widgets/inputs.py"}]}