chainlit 0.4.0__py3-none-any.whl → 0.4.2__py3-none-any.whl

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.

Potentially problematic release.


This version of chainlit might be problematic. Click here for more details.

chainlit/types.py CHANGED
@@ -1,4 +1,4 @@
1
- from typing import List, TypedDict, Optional, Literal, Dict, Union
1
+ from typing import List, Any, TypedDict, Optional, Literal, Dict, Union
2
2
  from pydantic import BaseModel
3
3
  from pydantic.dataclasses import dataclass
4
4
  from dataclasses_json import dataclass_json
@@ -66,3 +66,28 @@ class CompletionRequest(BaseModel):
66
66
  prompt: str
67
67
  userEnv: Dict[str, str]
68
68
  settings: LLMSettings
69
+
70
+
71
+ class UpdateFeedbackRequest(BaseModel):
72
+ messageId: int
73
+ feedback: int
74
+
75
+
76
+ class DeleteConversationRequest(BaseModel):
77
+ conversationId: int
78
+
79
+
80
+ class Pagination(BaseModel):
81
+ first: int
82
+ cursor: Any
83
+
84
+
85
+ class ConversationFilter(BaseModel):
86
+ feedback: Optional[Literal[-1, 0, 1]]
87
+ authorEmail: Optional[str]
88
+ search: Optional[str]
89
+
90
+
91
+ class GetConversationsRequest(BaseModel):
92
+ pagination: Pagination
93
+ filter: ConversationFilter
chainlit/user_session.py CHANGED
@@ -1,5 +1,5 @@
1
1
  from typing import Dict
2
- from chainlit.emitter import get_emitter
2
+ from chainlit.context import get_emitter
3
3
 
4
4
  user_sessions: Dict[str, Dict] = {}
5
5
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: chainlit
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: A faster way to build chatbot UIs.
5
5
  Home-page: https://github.com/Chainlit/chainlit
6
6
  License: Apache-2.0 license
@@ -21,8 +21,8 @@ Requires-Dist: click (>=8.1.3,<9.0.0)
21
21
  Requires-Dist: dataclasses_json (>=0.5.7,<0.6.0)
22
22
  Requires-Dist: fastapi (>=0.96.0,<0.97.0)
23
23
  Requires-Dist: fastapi-socketio (>=0.0.10,<0.0.11)
24
- Requires-Dist: nest-asyncio (>=1.5.6,<2.0.0)
25
24
  Requires-Dist: openai (>=0.27.7,<0.28.0)
25
+ Requires-Dist: prisma (>=0.9.0,<0.10.0)
26
26
  Requires-Dist: pydantic (>=1.10.8,<2.0.0)
27
27
  Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
28
28
  Requires-Dist: python-graphql-client (>=0.4.3,<0.5.0)
@@ -44,6 +44,8 @@ Chainlit lets you create ChatGPT-like UIs on top of any Python code in minutes!
44
44
  [![Twitter](https://img.shields.io/twitter/url/https/twitter.com/chainlit_io.svg?style=social&label=Follow%20%40chainlit_io)](https://twitter.com/chainlit_io)
45
45
  [![CI](https://github.com/Chainlit/chainlit/actions/workflows/ci.yaml/badge.svg)](https://github.com/Chainlit/chainlit/actions/workflows/ci.yaml)
46
46
 
47
+ https://github.com/Chainlit/chainlit/assets/13104895/e347e52c-35b2-4c35-8a88-f8ac02dd198e
48
+
47
49
  ## Installation
48
50
 
49
51
  Open a terminal and run:
@@ -90,7 +92,10 @@ $ chainlit run demo.py -w
90
92
 
91
93
  ### 🔗 With LangChain
92
94
 
93
- Checkout our plug and play [integration](https://docs.chainlit.io/langchain) with LangChain!
95
+ Check out our plug-and-play [integration](https://docs.chainlit.io/langchain) with LangChain!
96
+
97
+ ### 📚 More Examples - Cookbook
98
+ You can find various examples of Chainlit apps [here](https://github.com/Chainlit/cookbook) that leverage tools and services such as OpenAI, Anthropiс, LangChain, LlamaIndex, ChromaDB, Pinecone and more.
94
99
 
95
100
  ## 🛣 Roadmap
96
101
  - [ ] New UI elements (spreadsheet, video, carousel...)
@@ -0,0 +1,44 @@
1
+ chainlit/__init__.py,sha256=0PqkxriXIHa1UsTGf_CWiHHQjC7Pc3tmIPT5yIJxOUQ,7956
2
+ chainlit/__main__.py,sha256=7Vg3w3T3qDuz4KDu5lQhLH6lQ3cYdume7gHH7Z1V97U,87
3
+ chainlit/action.py,sha256=dk-ymZXZPQlHjh77ivwmdzhAp3QN7ihPZVVVhoh2jMc,1209
4
+ chainlit/cache.py,sha256=HFieoVnhsJf36AT7nRL8wcEJ1jTgeTLju23WW2-vgp4,1343
5
+ chainlit/cli/__init__.py,sha256=OIlAc1Pe7JZ3owUXwT_UOmt1nVTqiGPY9UqlKXYUoI8,4535
6
+ chainlit/cli/auth.py,sha256=G437UK4BvLA4wWPz_KPDwN6_6dnchMtHWr4tqu5XN-M,4093
7
+ chainlit/cli/deploy.py,sha256=RyIzpjS3yuVjQpllDO2PzXb6VZAtTcOyuAfF75WKVJE,2594
8
+ chainlit/cli/mock.py,sha256=tWvkbPzm6TeBkAu6b1ia9gL6iTj9OS3YLyxmreTJU6o,1147
9
+ chainlit/cli/utils.py,sha256=Pn6ANnw9GgdUduiMphnb8RiGUPRbzDafkCHM2rOPBj4,716
10
+ chainlit/client/base.py,sha256=HtVS6mGm_Ik6W08nLdUPtdVxzxK6Au1K6QKz-HdBz2Q,3284
11
+ chainlit/client/cloud.py,sha256=OEUVVnvJK0ofQRoOkjxNniuyPtxZfVLqYXi8_0o6fS0,14109
12
+ chainlit/client/local.py,sha256=JTSBHVArt7aA-rkuFJrGvlKUGin-PO2VXoWd_AQUko0,7324
13
+ chainlit/client/utils.py,sha256=YARrA5XMpOpKhNjvIpve5H5CH2YekNP46aEYFvBjXlk,682
14
+ chainlit/config.py,sha256=67obJCmbFCuLNP-5N1D_TOFPFruPi1b-NISWn6zMS1g,8323
15
+ chainlit/context.py,sha256=m639AAk-bt7DWTStuW8s9FotohVonuW7veg5UwiKdKA,709
16
+ chainlit/db/__init__.py,sha256=kFk5a6SoDrq1U6X4EjvJLd-3YsuVV4cl9r8BFHUExlM,982
17
+ chainlit/db/prisma/schema.prisma,sha256=ZvhefSK_9D2Vck9SORaG9o-jQr6_BRpKNo-2YTlmgmg,1373
18
+ chainlit/element.py,sha256=15nfoeQYF-hkOC8eFWmUWUsLT-vhyyacmG3GkOE_QDk,6317
19
+ chainlit/emitter.py,sha256=SVgD6f9evY2IzanZ_ZHLd3qK_keDO20E_2fqv1Ka5JI,4142
20
+ chainlit/frontend/dist/assets/index-995e21ad.js,sha256=SUgCkhIZA7gX6f3_yjaDsiGimnIPTsUebIwZVIhtqkE,614554
21
+ chainlit/frontend/dist/assets/index-f93cc942.css,sha256=-TzJQmhWdpIg94Jv25YHMi9h-jSQmeERggrrlmYIflg,5697
22
+ chainlit/frontend/dist/assets/index-fb1e167a.js,sha256=m1BTWtvezgPLE4cYNGIwZV1YdQPy66msAITDfDnDUZ8,1334132
23
+ chainlit/frontend/dist/assets/logo_dark-bc7401f6.svg,sha256=vHQB9g-n5OqOmuH3Fduuc7ZMg0EmMsGyO9cEnYwLbHg,8889
24
+ chainlit/frontend/dist/assets/logo_light-f19fc2ea.svg,sha256=8Z_C6t-0V9QL9ldmLjaLfp2REcGDuaTeNynj6-6muNI,8891
25
+ chainlit/frontend/dist/favicon.svg,sha256=0Cy8x28obT5eWW3nxZRhsEvu6_zMqrqbg0y6hT3D0Q0,6455
26
+ chainlit/frontend/dist/index.html,sha256=BCPkjtPetaewRy4-rWXdMkjkziVH9yhGXxB6nCiiPFM,793
27
+ chainlit/hello.py,sha256=bqKP00i0FKHnZ9fdyVW1a2xDAA1g7IWT0EVzUNky7rA,417
28
+ chainlit/lc/__init__.py,sha256=AHceu8jfttx74FLLhr7TIk5ihOqFFqJde1M33Y_YEFA,292
29
+ chainlit/lc/agent.py,sha256=aC1BkKGN0WXkRLoU4H7DxsK7VffAYb1pF-9HlZ60duE,1121
30
+ chainlit/lc/callbacks.py,sha256=VcTV9HhuWy9WHmIiI4mSt-A-9y6Aq96bZV-_NK6f_Sw,12783
31
+ chainlit/logger.py,sha256=VFl6D0UbY7PH7gCl0HBXM_vfk7lK_bMEqiUxQBq_Vnw,374
32
+ chainlit/markdown.py,sha256=JRhaKb0BB1G2S1XEaGj95DH75y7jqWdeIPx4u0oDaxw,1623
33
+ chainlit/message.py,sha256=dyc_IKmz_AJK5eXcDV5MGVW3rXlcaJkY8MKmR_Zldl8,12198
34
+ chainlit/server.py,sha256=SV8x5eYcQ7BjWLTUd8GLUpKbrUAmjRtIQvS6WxHErDk,17267
35
+ chainlit/session.py,sha256=jP3x0-pRLi-ozCOoxiwV5t-x0IXDh-HzDTZDum8YyJA,812
36
+ chainlit/sync.py,sha256=AsC0wU577zD-1fuQfhEnv42SOfUR3sIpf3Vesuzzha4,539
37
+ chainlit/telemetry.py,sha256=yaRnmjjwLPbUa_wLQ--sp1VKPAKIHgTQP-MZo_W8AM8,2358
38
+ chainlit/types.py,sha256=py6vLmm_w43v7X_NNBvWtfi5rUc9owGNPdBO7L8Pto4,1981
39
+ chainlit/user_session.py,sha256=U4F1e9DBUhFoXvEdReRTq7Bu0Str4qsvSgAOeMobUzA,1213
40
+ chainlit/version.py,sha256=iosXhlXclBwBqlADFKEilxAC2wWKbtuBKi87AmPi7s8,196
41
+ chainlit-0.4.2.dist-info/METADATA,sha256=RjdADKuJNlzLcRMPoMkU9eHQkm3Yhi1aHSOz7EnpHVE,4280
42
+ chainlit-0.4.2.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
43
+ chainlit-0.4.2.dist-info/entry_points.txt,sha256=FrkqdjrFl8juSnvBndniyX7XuKojmUwO4ghRh-CFMQc,45
44
+ chainlit-0.4.2.dist-info/RECORD,,
chainlit/client.py DELETED
@@ -1,287 +0,0 @@
1
- from typing import Dict, Any, Optional
2
- from abc import ABC, abstractmethod
3
- import uuid
4
-
5
- import asyncio
6
- import aiohttp
7
- from python_graphql_client import GraphqlClient
8
-
9
- from chainlit.types import ElementType, ElementSize
10
- from chainlit.logger import logger
11
- from chainlit.config import config
12
-
13
-
14
- class BaseClient(ABC):
15
- project_id: str
16
- session_id: str
17
-
18
- @abstractmethod
19
- async def is_project_member(self, access_token: str) -> bool:
20
- pass
21
-
22
- @abstractmethod
23
- async def create_conversation(self, session_id: str) -> int:
24
- pass
25
-
26
- @abstractmethod
27
- async def create_message(self, variables: Dict[str, Any]) -> int:
28
- pass
29
-
30
- @abstractmethod
31
- async def update_message(self, message_id: int, variables: Dict[str, Any]) -> bool:
32
- pass
33
-
34
- @abstractmethod
35
- async def delete_message(self, message_id: int) -> bool:
36
- pass
37
-
38
- @abstractmethod
39
- async def upload_element(self, content: bytes, mime: str) -> str:
40
- pass
41
-
42
- @abstractmethod
43
- async def create_element(
44
- self,
45
- type: ElementType,
46
- url: str,
47
- name: str,
48
- display: str,
49
- size: ElementSize = None,
50
- language: str = None,
51
- for_id: str = None,
52
- ) -> Dict[str, Any]:
53
- pass
54
-
55
-
56
- conversation_lock = asyncio.Lock()
57
-
58
-
59
- class CloudClient(BaseClient):
60
- conversation_id: Optional[str] = None
61
-
62
- def __init__(self, project_id: str, session_id: str, access_token: str):
63
- self.project_id = project_id
64
- self.session_id = session_id
65
- self.headers = {
66
- "Authorization": access_token,
67
- "content-type": "application/json",
68
- }
69
- graphql_endpoint = f"{config.chainlit_server}/api/graphql"
70
- self.graphql_client = GraphqlClient(
71
- endpoint=graphql_endpoint, headers=self.headers
72
- )
73
-
74
- def query(self, query: str, variables: Dict[str, Any] = {}) -> Dict[str, Any]:
75
- """
76
- Execute a GraphQL query.
77
-
78
- :param query: The GraphQL query string.
79
- :param variables: A dictionary of variables for the query.
80
- :return: The response data as a dictionary.
81
- """
82
- return self.graphql_client.execute_async(query=query, variables=variables)
83
-
84
- def check_for_errors(self, response: Dict[str, Any]):
85
- if "errors" in response:
86
- logger.error(response["errors"])
87
- return True
88
- return False
89
-
90
- def mutation(self, mutation: str, variables: Dict[str, Any] = {}) -> Dict[str, Any]:
91
- """
92
- Execute a GraphQL mutation.
93
-
94
- :param mutation: The GraphQL mutation string.
95
- :param variables: A dictionary of variables for the mutation.
96
- :return: The response data as a dictionary.
97
- """
98
- return self.graphql_client.execute_async(query=mutation, variables=variables)
99
-
100
- async def is_project_member(self) -> bool:
101
- data = {"projectId": self.project_id}
102
- async with aiohttp.ClientSession() as session:
103
- async with session.post(
104
- f"{config.chainlit_server}/api/role",
105
- json=data,
106
- headers=self.headers,
107
- ) as r:
108
- if not r.ok:
109
- reason = await r.text()
110
- logger.error(f"Failed to get user role. {r.status}: {reason}")
111
- return False
112
- json = await r.json()
113
- role = json.get("role", "ANONYMOUS")
114
- return role != "ANONYMOUS"
115
-
116
- async def create_conversation(self, session_id: str) -> int:
117
- # If we run multiple send concurrently, we need to make sure we don't create multiple conversations.
118
- async with conversation_lock:
119
- if self.conversation_id:
120
- return self.conversation_id
121
-
122
- mutation = """
123
- mutation ($projectId: String!, $sessionId: String!) {
124
- createConversation(projectId: $projectId, sessionId: $sessionId) {
125
- id
126
- }
127
- }
128
- """
129
- variables = {"projectId": self.project_id, "sessionId": session_id}
130
- res = await self.mutation(mutation, variables)
131
-
132
- if self.check_for_errors(res):
133
- logger.warning("Could not create conversation.")
134
- return None
135
-
136
- return int(res["data"]["createConversation"]["id"])
137
-
138
- async def get_conversation_id(self):
139
- self.conversation_id = await self.create_conversation(self.session_id)
140
-
141
- return self.conversation_id
142
-
143
- async def create_message(self, variables: Dict[str, Any]) -> int:
144
- c_id = await self.get_conversation_id()
145
-
146
- if not c_id:
147
- logger.warning("Missing conversation ID, could not persist the message.")
148
- return None
149
-
150
- variables["conversationId"] = c_id
151
-
152
- mutation = """
153
- mutation ($conversationId: ID!, $author: String!, $content: String!, $language: String, $prompt: String, $llmSettings: Json, $isError: Boolean, $indent: Int, $authorIsUser: Boolean, $waitForAnswer: Boolean, $createdAt: Float) {
154
- createMessage(conversationId: $conversationId, author: $author, content: $content, language: $language, prompt: $prompt, llmSettings: $llmSettings, isError: $isError, indent: $indent, authorIsUser: $authorIsUser, waitForAnswer: $waitForAnswer, createdAt: $createdAt) {
155
- id
156
- }
157
- }
158
- """
159
- res = await self.mutation(mutation, variables)
160
- if self.check_for_errors(res):
161
- logger.warning("Could not create message.")
162
- return None
163
-
164
- return int(res["data"]["createMessage"]["id"])
165
-
166
- async def update_message(self, message_id: int, variables: Dict[str, Any]) -> bool:
167
- mutation = """
168
- mutation ($messageId: ID!, $author: String!, $content: String!, $language: String, $prompt: String, $llmSettings: Json) {
169
- updateMessage(messageId: $messageId, author: $author, content: $content, language: $language, prompt: $prompt, llmSettings: $llmSettings) {
170
- id
171
- }
172
- }
173
- """
174
- variables["messageId"] = message_id
175
- res = await self.mutation(mutation, variables)
176
-
177
- if self.check_for_errors(res):
178
- logger.warning("Could not update message.")
179
- return False
180
-
181
- return True
182
-
183
- async def delete_message(self, message_id: int) -> bool:
184
- mutation = """
185
- mutation ($messageId: ID!) {
186
- deleteMessage(messageId: $messageId) {
187
- id
188
- }
189
- }
190
- """
191
- res = await self.mutation(mutation, {"messageId": message_id})
192
-
193
- if self.check_for_errors(res):
194
- logger.warning("Could not delete message.")
195
- return False
196
-
197
- return True
198
-
199
- async def create_element(
200
- self,
201
- type: ElementType,
202
- url: str,
203
- name: str,
204
- display: str,
205
- size: ElementSize = None,
206
- language: str = None,
207
- for_id: str = None,
208
- ) -> Dict[str, Any]:
209
- c_id = await self.get_conversation_id()
210
-
211
- if not c_id:
212
- logger.warning("Missing conversation ID, could not persist the element.")
213
- return None
214
-
215
- mutation = """
216
- mutation ($conversationId: ID!, $type: String!, $url: String!, $name: String!, $display: String!, $size: String, $language: String, $forId: String) {
217
- createElement(conversationId: $conversationId, type: $type, url: $url, name: $name, display: $display, size: $size, language: $language, forId: $forId) {
218
- id,
219
- type,
220
- url,
221
- name,
222
- display,
223
- size,
224
- language,
225
- forId
226
- }
227
- }
228
- """
229
- variables = {
230
- "conversationId": c_id,
231
- "type": type,
232
- "url": url,
233
- "name": name,
234
- "display": display,
235
- "size": size,
236
- "language": language,
237
- "forId": for_id,
238
- }
239
- res = await self.mutation(mutation, variables)
240
-
241
- if self.check_for_errors(res):
242
- logger.warning("Could not persist element.")
243
- return None
244
-
245
- return res["data"]["createElement"]
246
-
247
- async def upload_element(self, content: bytes, mime: str) -> str:
248
- id = f"{uuid.uuid4()}"
249
- body = {"projectId": self.project_id, "fileName": id, "contentType": mime}
250
-
251
- path = f"/api/upload/file"
252
-
253
- async with aiohttp.ClientSession() as session:
254
- async with session.post(
255
- f"{config.chainlit_server}{path}",
256
- json=body,
257
- headers=self.headers,
258
- ) as r:
259
- if not r.ok:
260
- reason = await r.text()
261
- logger.error(f"Failed to upload file: {reason}")
262
- return ""
263
- json_res = await r.json()
264
-
265
- upload_details = json_res["post"]
266
- permanent_url = json_res["permanentUrl"]
267
-
268
- form_data = aiohttp.FormData()
269
-
270
- # Add fields to the form_data
271
- for field_name, field_value in upload_details["fields"].items():
272
- form_data.add_field(field_name, field_value)
273
-
274
- # Add file to the form_data
275
- form_data.add_field("file", content, content_type="multipart/form-data")
276
- async with aiohttp.ClientSession() as session:
277
- async with session.post(
278
- upload_details["url"],
279
- data=form_data,
280
- ) as upload_response:
281
- if not upload_response.ok:
282
- reason = await upload_response.text()
283
- logger.error(f"Failed to upload file: {reason}")
284
- return ""
285
-
286
- url = f'{upload_details["url"]}/{upload_details["fields"]["key"]}'
287
- return permanent_url
@@ -1 +0,0 @@
1
- body{margin:0;padding:0;font-family:Inter,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}.markdown-body *:first-child{margin-top:0}.markdown-body *:last-child{margin-bottom:0}.markdown-body p{white-space:break-spaces}.DraftEditor-editorContainer,.DraftEditor-root,.public-DraftEditor-content{height:inherit;text-align:initial}.public-DraftEditor-content[contenteditable=true]{-webkit-user-modify:read-write-plaintext-only}.DraftEditor-root{position:relative}.DraftEditor-editorContainer{background-color:#fff0;border-left:.1px solid transparent;position:relative;z-index:1}.public-DraftEditor-block{position:relative}.DraftEditor-alignLeft .public-DraftStyleDefault-block{text-align:left}.DraftEditor-alignLeft .public-DraftEditorPlaceholder-root{left:0;text-align:left}.DraftEditor-alignCenter .public-DraftStyleDefault-block{text-align:center}.DraftEditor-alignCenter .public-DraftEditorPlaceholder-root{margin:0 auto;text-align:center;width:100%}.DraftEditor-alignRight .public-DraftStyleDefault-block{text-align:right}.DraftEditor-alignRight .public-DraftEditorPlaceholder-root{right:0;text-align:right}.public-DraftEditorPlaceholder-root{color:#9197a3;position:absolute;width:100%;z-index:1}.public-DraftEditorPlaceholder-hasFocus{color:#bdc1c9}.DraftEditorPlaceholder-hidden{display:none}.public-DraftStyleDefault-block{position:relative;white-space:pre-wrap}.public-DraftStyleDefault-ltr{direction:ltr;text-align:left}.public-DraftStyleDefault-rtl{direction:rtl;text-align:right}.public-DraftStyleDefault-listLTR{direction:ltr}.public-DraftStyleDefault-listRTL{direction:rtl}.public-DraftStyleDefault-ol,.public-DraftStyleDefault-ul{margin:16px 0;padding:0}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listLTR{margin-left:1.5em}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listRTL{margin-right:1.5em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listLTR{margin-left:3em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listRTL{margin-right:3em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listLTR{margin-left:4.5em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listRTL{margin-right:4.5em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listLTR{margin-left:6em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listRTL{margin-right:6em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listLTR{margin-left:7.5em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listRTL{margin-right:7.5em}.public-DraftStyleDefault-unorderedListItem{list-style-type:square;position:relative}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth0{list-style-type:disc}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth1{list-style-type:circle}.public-DraftStyleDefault-orderedListItem{list-style-type:none;position:relative}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listLTR:before{left:-36px;position:absolute;text-align:right;width:30px}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listRTL:before{position:absolute;right:-36px;text-align:left;width:30px}.public-DraftStyleDefault-orderedListItem:before{content:counter(ol0) ". ";counter-increment:ol0}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth1:before{content:counter(ol1,lower-alpha) ". ";counter-increment:ol1}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth2:before{content:counter(ol2,lower-roman) ". ";counter-increment:ol2}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth3:before{content:counter(ol3) ". ";counter-increment:ol3}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth4:before{content:counter(ol4,lower-alpha) ". ";counter-increment:ol4}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-reset{counter-reset:ol0}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-reset{counter-reset:ol1}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-reset{counter-reset:ol2}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-reset{counter-reset:ol3}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-reset{counter-reset:ol4}.react-resizable{position:relative}.react-resizable-handle{position:absolute;width:20px;height:20px;background-repeat:no-repeat;background-origin:content-box;box-sizing:border-box;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2IDYiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiNmZmZmZmYwMCIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSI2cHgiIGhlaWdodD0iNnB4Ij48ZyBvcGFjaXR5PSIwLjMwMiI+PHBhdGggZD0iTSA2IDYgTCAwIDYgTCAwIDQuMiBMIDQgNC4yIEwgNC4yIDQuMiBMIDQuMiAwIEwgNiAwIEwgNiA2IEwgNiA2IFoiIGZpbGw9IiMwMDAwMDAiLz48L2c+PC9zdmc+);background-position:bottom right;padding:0 3px 3px 0}.react-resizable-handle-sw{bottom:0;left:0;cursor:sw-resize;transform:rotate(90deg)}.react-resizable-handle-se{bottom:0;right:0;cursor:se-resize}.react-resizable-handle-nw{top:0;left:0;cursor:nw-resize;transform:rotate(180deg)}.react-resizable-handle-ne{top:0;right:0;cursor:ne-resize;transform:rotate(270deg)}.react-resizable-handle-w,.react-resizable-handle-e{top:50%;margin-top:-10px;cursor:ew-resize}.react-resizable-handle-w{left:0;transform:rotate(135deg)}.react-resizable-handle-e{right:0;transform:rotate(315deg)}.react-resizable-handle-n,.react-resizable-handle-s{left:50%;margin-left:-10px;cursor:ns-resize}.react-resizable-handle-n{top:0;transform:rotate(225deg)}.react-resizable-handle-s{bottom:0;transform:rotate(45deg)}