kempo-ui 0.4.4 → 0.4.6
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/dist/components/Chat.js +201 -0
- package/dist/components/CodeEditor.js +21 -2
- package/dist/components/Dropdown.js +1 -1
- package/dist/components/HtmlEditor.js +42 -3
- package/dist/components/MarkdownEditor.js +173 -0
- package/dist/components/Resize.js +12 -2
- package/dist/components/TextToSpeech.js +4 -4
- package/dist/components/VoiceSelector.js +49 -0
- package/dist/components/markdownEditorControls/Bold.js +11 -0
- package/dist/components/markdownEditorControls/BulletList.js +11 -0
- package/dist/components/markdownEditorControls/Code.js +11 -0
- package/dist/components/markdownEditorControls/FormatBlock.js +30 -0
- package/dist/components/markdownEditorControls/Heading.js +11 -0
- package/dist/components/markdownEditorControls/Image.js +93 -0
- package/dist/components/markdownEditorControls/Italic.js +11 -0
- package/dist/components/markdownEditorControls/Link.js +11 -0
- package/dist/components/markdownEditorControls/MarkdownEditorControl.js +39 -0
- package/dist/components/markdownEditorControls/Menu.js +30 -0
- package/dist/components/markdownEditorControls/NumberedList.js +11 -0
- package/dist/components/markdownEditorControls/Quote.js +11 -0
- package/dist/components/markdownEditorControls/SpeechToText.js +16 -0
- package/dist/components/markdownEditorControls/Strikethrough.js +11 -0
- package/dist/components/markdownEditorControls/Table.js +80 -0
- package/dist/utils/marked.esm.js +1 -0
- package/dist/utils/renderMarkdown.js +1 -0
- package/dist/utils/sanitizeHtml.js +1 -0
- package/dist/utils/voice.js +1 -0
- package/docs/components/accordion.html +19 -0
- package/docs/components/aside.html +19 -0
- package/docs/components/calendar.html +19 -0
- package/docs/components/card.html +19 -0
- package/docs/components/chat.html +715 -0
- package/docs/components/code-editor.html +55 -0
- package/docs/components/color-picker.html +19 -0
- package/docs/components/combobox.html +19 -0
- package/docs/components/content-slider.html +19 -0
- package/docs/components/context.html +19 -0
- package/docs/components/dialog.html +19 -0
- package/docs/components/dropdown.html +19 -0
- package/docs/components/filter-list.html +19 -0
- package/docs/components/focus-capture.html +19 -0
- package/docs/components/html-editor.html +60 -0
- package/docs/components/hybrid-component.html +19 -0
- package/docs/components/icon.html +19 -0
- package/docs/components/import.html +19 -0
- package/docs/components/light-component.html +19 -0
- package/docs/components/markdown-editor.html +924 -0
- package/docs/components/nav-spacer.html +19 -0
- package/docs/components/nav.html +19 -0
- package/docs/components/photo-viewer.html +19 -0
- package/docs/components/progress.html +19 -0
- package/docs/components/resize.html +22 -0
- package/docs/components/rich-textarea.html +650 -0
- package/docs/components/shadow-component.html +19 -0
- package/docs/components/show-more.html +19 -0
- package/docs/components/slider.html +19 -0
- package/docs/components/sortable.html +19 -0
- package/docs/components/speech-to-text.html +19 -0
- package/docs/components/spinner.html +19 -0
- package/docs/components/split.html +19 -0
- package/docs/components/table.html +19 -0
- package/docs/components/tableControls.html +19 -0
- package/docs/components/tableCustomFields.html +19 -0
- package/docs/components/tableFetchRecords.html +19 -0
- package/docs/components/tableFieldSortHide.html +19 -0
- package/docs/components/tablePagination.html +19 -0
- package/docs/components/tablePlaceholder.html +19 -0
- package/docs/components/tableRecordEditing.html +19 -0
- package/docs/components/tableRecordFiltering.html +19 -0
- package/docs/components/tableRecordHiding.html +19 -0
- package/docs/components/tableRecordSearching.html +19 -0
- package/docs/components/tableRecordSelection.html +19 -0
- package/docs/components/tableRowControls.html +19 -0
- package/docs/components/tableServerSync.html +19 -0
- package/docs/components/tableSorting.html +19 -0
- package/docs/components/tabs.html +19 -0
- package/docs/components/tags.html +19 -0
- package/docs/components/text-to-speech.html +63 -1
- package/docs/components/theme-select.html +19 -0
- package/docs/components/theme-switcher.html +19 -0
- package/docs/components/time.html +19 -0
- package/docs/components/timestamp.html +19 -0
- package/docs/components/toast.html +19 -0
- package/docs/components/toggle.html +19 -0
- package/docs/components/tree.html +19 -0
- package/docs/components/voice-selector.html +610 -0
- package/docs/icons/done_all.svg +1 -0
- package/docs/icons/format_quote.svg +1 -0
- package/docs/icons/format_strikethrough.svg +1 -0
- package/docs/icons/send.svg +1 -0
- package/docs/icons/text_fields.svg +1 -0
- package/docs/index.html +49 -0
- package/docs/src/components/Chat.js +201 -0
- package/docs/src/components/CodeEditor.js +21 -2
- package/docs/src/components/Dropdown.js +1 -1
- package/docs/src/components/HtmlEditor.js +42 -3
- package/docs/src/components/MarkdownEditor.js +173 -0
- package/docs/src/components/Resize.js +12 -2
- package/docs/src/components/TextToSpeech.js +4 -4
- package/docs/src/components/VoiceSelector.js +49 -0
- package/docs/src/components/markdownEditorControls/Bold.js +11 -0
- package/docs/src/components/markdownEditorControls/BulletList.js +11 -0
- package/docs/src/components/markdownEditorControls/Code.js +11 -0
- package/docs/src/components/markdownEditorControls/FormatBlock.js +30 -0
- package/docs/src/components/markdownEditorControls/Heading.js +11 -0
- package/docs/src/components/markdownEditorControls/Image.js +93 -0
- package/docs/src/components/markdownEditorControls/Italic.js +11 -0
- package/docs/src/components/markdownEditorControls/Link.js +11 -0
- package/docs/src/components/markdownEditorControls/MarkdownEditorControl.js +39 -0
- package/docs/src/components/markdownEditorControls/Menu.js +30 -0
- package/docs/src/components/markdownEditorControls/NumberedList.js +11 -0
- package/docs/src/components/markdownEditorControls/Quote.js +11 -0
- package/docs/src/components/markdownEditorControls/SpeechToText.js +16 -0
- package/docs/src/components/markdownEditorControls/Strikethrough.js +11 -0
- package/docs/src/components/markdownEditorControls/Table.js +80 -0
- package/docs/src/utils/marked.esm.js +1 -0
- package/docs/src/utils/renderMarkdown.js +1 -0
- package/docs/src/utils/sanitizeHtml.js +1 -0
- package/docs/src/utils/voice.js +1 -0
- package/docs/utils/context.html +19 -0
- package/docs/utils/cookie.html +19 -0
- package/docs/utils/debounce.html +19 -0
- package/docs/utils/drag.html +19 -0
- package/docs/utils/elevation.html +23 -10
- package/docs/utils/formatTimestamp.html +19 -0
- package/docs/utils/object.html +19 -0
- package/docs/utils/propConverters.html +19 -0
- package/docs/utils/sanitizeHtml.html +555 -0
- package/docs/utils/string.html +19 -0
- package/docs/utils/theme.html +19 -0
- package/docs/utils/toTitleCase.html +19 -0
- package/docs/utils/type.html +19 -0
- package/docs/utils/voice.html +548 -0
- package/docs/utils/wait.html +19 -0
- package/docs-src/components/chat.page.html +230 -0
- package/docs-src/components/code-editor.page.html +36 -0
- package/docs-src/components/html-editor.page.html +41 -0
- package/docs-src/components/markdown-editor.page.html +439 -0
- package/docs-src/components/resize.page.html +3 -0
- package/docs-src/components/text-to-speech.page.html +44 -1
- package/docs-src/components/voice-selector.page.html +125 -0
- package/docs-src/index.page.html +30 -0
- package/docs-src/nav.fragment.html +19 -0
- package/docs-src/utils/elevation.page.html +4 -10
- package/docs-src/utils/sanitizeHtml.page.html +73 -0
- package/docs-src/utils/voice.page.html +66 -0
- package/icons/done_all.svg +1 -0
- package/icons/format_quote.svg +1 -0
- package/icons/format_strikethrough.svg +1 -0
- package/icons/send.svg +1 -0
- package/icons/text_fields.svg +1 -0
- package/llms.txt +7 -2
- package/package.json +3 -2
- package/src/components/Chat.js +435 -0
- package/src/components/CodeEditor.js +58 -2
- package/src/components/Dropdown.js +1 -1
- package/src/components/HtmlEditor.js +84 -4
- package/src/components/MarkdownEditor.js +654 -0
- package/src/components/Resize.js +17 -1
- package/src/components/TextToSpeech.js +13 -2
- package/src/components/VoiceSelector.js +271 -0
- package/src/components/markdownEditorControls/Bold.js +30 -0
- package/src/components/markdownEditorControls/BulletList.js +30 -0
- package/src/components/markdownEditorControls/Code.js +39 -0
- package/src/components/markdownEditorControls/FormatBlock.js +102 -0
- package/src/components/markdownEditorControls/Heading.js +45 -0
- package/src/components/markdownEditorControls/Image.js +250 -0
- package/src/components/markdownEditorControls/Italic.js +30 -0
- package/src/components/markdownEditorControls/Link.js +74 -0
- package/src/components/markdownEditorControls/MarkdownEditorControl.js +158 -0
- package/src/components/markdownEditorControls/Menu.js +86 -0
- package/src/components/markdownEditorControls/NumberedList.js +69 -0
- package/src/components/markdownEditorControls/Quote.js +30 -0
- package/src/components/markdownEditorControls/SpeechToText.js +65 -0
- package/src/components/markdownEditorControls/Strikethrough.js +35 -0
- package/src/components/markdownEditorControls/Table.js +164 -0
- package/src/utils/marked.esm.js +77 -0
- package/src/utils/renderMarkdown.js +29 -0
- package/src/utils/sanitizeHtml.js +137 -0
- package/src/utils/voice.js +103 -0
- package/tests/components/Chat.browser-test.js +540 -0
- package/tests/components/TextToSpeech.browser-test.js +150 -1
- package/tests/components/VoiceSelector.browser-test.js +374 -0
- package/tests/utils/sanitizeHtml.browser-test.js +179 -0
- package/tests/utils/voice.browser-test.js +128 -0
package/docs/index.html
CHANGED
|
@@ -67,6 +67,9 @@
|
|
|
67
67
|
>Calendar<br><small>Component</small></a></k-filter-item>
|
|
68
68
|
<k-filter-item filter-keywords="card components"><a
|
|
69
69
|
href="./components/card.html">Card<br><small>Component</small></a></k-filter-item>
|
|
70
|
+
<k-filter-item filter-keywords="chat message conversation messaging components"><a
|
|
71
|
+
href="./components/chat.html"
|
|
72
|
+
>Chat<br><small>Component</small></a></k-filter-item>
|
|
70
73
|
<k-filter-item filter-keywords="code editor codeeditor monaco components"><a
|
|
71
74
|
href="./components/code-editor.html"
|
|
72
75
|
>Code Editor<br><small>Component</small></a></k-filter-item>
|
|
@@ -95,6 +98,9 @@
|
|
|
95
98
|
<k-filter-item filter-keywords="html editor components"><a
|
|
96
99
|
href="./components/html-editor.html">HTML
|
|
97
100
|
Editor<br><small>Component</small></a></k-filter-item>
|
|
101
|
+
<k-filter-item filter-keywords="markdown editor markdowneditor write preview marked gfm tables components"><a
|
|
102
|
+
href="./components/markdown-editor.html"
|
|
103
|
+
>Markdown Editor<br><small>Component</small></a></k-filter-item>
|
|
98
104
|
<k-filter-item filter-keywords="icon components"><a
|
|
99
105
|
href="./components/icon.html">Icon<br><small>Component</small></a></k-filter-item>
|
|
100
106
|
<k-filter-item filter-keywords="import components"><a
|
|
@@ -198,6 +204,9 @@
|
|
|
198
204
|
>Toggle<br><small>Component</small></a></k-filter-item>
|
|
199
205
|
<k-filter-item filter-keywords="tree treeview components"><a
|
|
200
206
|
href="./components/tree.html">Tree<br><small>Component</small></a></k-filter-item>
|
|
207
|
+
<k-filter-item filter-keywords="voice selector dropdown speech synthesis preference components"><a
|
|
208
|
+
href="./components/voice-selector.html"
|
|
209
|
+
>Voice Selector<br><small>Component</small></a></k-filter-item>
|
|
201
210
|
<k-filter-item filter-keywords="shadow component base"><a
|
|
202
211
|
href="./components/shadow-component.html"
|
|
203
212
|
>Shadow Component<br><small>Base Component</small></a></k-filter-item>
|
|
@@ -225,12 +234,17 @@
|
|
|
225
234
|
<k-filter-item filter-keywords="propconverters prop converters utils utility"><a
|
|
226
235
|
href="./utils/propConverters.html"
|
|
227
236
|
>propConverters<br><small>Utility</small></a></k-filter-item>
|
|
237
|
+
<k-filter-item filter-keywords="sanitizehtml sanitize html xss security utils utility"><a
|
|
238
|
+
href="./utils/sanitizeHtml.html"
|
|
239
|
+
>sanitizeHtml<br><small>Utility</small></a></k-filter-item>
|
|
228
240
|
<k-filter-item filter-keywords="string utils utility"><a
|
|
229
241
|
href="./utils/string.html">string<br><small>Utility</small></a></k-filter-item>
|
|
230
242
|
<k-filter-item filter-keywords="theme utils utility"><a
|
|
231
243
|
href="./utils/theme.html">theme<br><small>Utility</small></a></k-filter-item>
|
|
232
244
|
<k-filter-item filter-keywords="type utils utility"><a
|
|
233
245
|
href="./utils/type.html">type<br><small>Utility</small></a></k-filter-item>
|
|
246
|
+
<k-filter-item filter-keywords="voice speech synthesis preference utils utility"><a
|
|
247
|
+
href="./utils/voice.html">voice<br><small>Utility</small></a></k-filter-item>
|
|
234
248
|
<k-filter-item filter-keywords="wait async utils utility"><a
|
|
235
249
|
href="./utils/wait.html">wait<br><small>Utility</small></a></k-filter-item>
|
|
236
250
|
</k-filter-list>
|
|
@@ -283,6 +297,7 @@
|
|
|
283
297
|
<a href="./components/aside.html">Aside</a>
|
|
284
298
|
<a href="./components/calendar.html">Calendar</a>
|
|
285
299
|
<a href="./components/card.html">Card</a>
|
|
300
|
+
<a href="./components/chat.html">Chat</a>
|
|
286
301
|
<a href="./components/code-editor.html">Code Editor</a>
|
|
287
302
|
<a href="./components/combobox.html">Combobox</a>
|
|
288
303
|
<a href="./components/color-picker.html">ColorPicker</a>
|
|
@@ -293,6 +308,7 @@
|
|
|
293
308
|
<a href="./components/filter-list.html">Filter List</a>
|
|
294
309
|
<a href="./components/focus-capture.html">FocusCapture</a>
|
|
295
310
|
<a href="./components/html-editor.html">HTML Editor</a>
|
|
311
|
+
<a href="./components/markdown-editor.html">Markdown Editor</a>
|
|
296
312
|
<a href="./components/icon.html">Icon</a>
|
|
297
313
|
<a href="./components/import.html">Import</a>
|
|
298
314
|
<a href="./components/nav.html">Nav</a>
|
|
@@ -317,6 +333,7 @@
|
|
|
317
333
|
<a href="./components/toast.html">Toast</a>
|
|
318
334
|
<a href="./components/toggle.html">Toggle</a>
|
|
319
335
|
<a href="./components/tree.html">Tree</a>
|
|
336
|
+
<a href="./components/voice-selector.html">Voice Selector</a>
|
|
320
337
|
</div>
|
|
321
338
|
|
|
322
339
|
<h5 class="mb0">Base Components</h5>
|
|
@@ -336,9 +353,11 @@
|
|
|
336
353
|
<a href="./utils/formatTimestamp.html">formatTimestamp</a>
|
|
337
354
|
<a href="./utils/object.html">object</a>
|
|
338
355
|
<a href="./utils/propConverters.html">propConverters</a>
|
|
356
|
+
<a href="./utils/sanitizeHtml.html">sanitizeHtml</a>
|
|
339
357
|
<a href="./utils/string.html">string</a>
|
|
340
358
|
<a href="./utils/theme.html">theme</a>
|
|
341
359
|
<a href="./utils/type.html">type</a>
|
|
360
|
+
<a href="./utils/voice.html">voice</a>
|
|
342
361
|
<a href="./utils/wait.html">wait</a>
|
|
343
362
|
</div>
|
|
344
363
|
</menu>
|
|
@@ -518,6 +537,12 @@
|
|
|
518
537
|
<p class="tc-muted">Container component with optional labels and border styling.</p>
|
|
519
538
|
</a>
|
|
520
539
|
</div>
|
|
540
|
+
<div class="span-12 t-span-6 d-span-4 px">
|
|
541
|
+
<a href="./components/chat.html" class="card mb no-link d-b">
|
|
542
|
+
<h3 class="tc-primary">Chat</h3>
|
|
543
|
+
<p class="tc-muted">Chat-room widget with rich-text input, send-on-enter option, and per-message state tracking.</p>
|
|
544
|
+
</a>
|
|
545
|
+
</div>
|
|
521
546
|
<div class="span-12 t-span-6 d-span-4 px">
|
|
522
547
|
<a href="./components/code-editor.html" class="card mb no-link d-b">
|
|
523
548
|
<h3 class="tc-primary">Code Editor</h3>
|
|
@@ -578,6 +603,12 @@
|
|
|
578
603
|
<p class="tc-muted">WYSIWYG editor with formatting tools and dual editing modes.</p>
|
|
579
604
|
</a>
|
|
580
605
|
</div>
|
|
606
|
+
<div class="span-12 t-span-6 d-span-4 px">
|
|
607
|
+
<a href="./components/markdown-editor.html" class="card mb no-link d-b">
|
|
608
|
+
<h3 class="tc-primary">Markdown Editor</h3>
|
|
609
|
+
<p class="tc-muted">Markdown editor with Write/Preview tabs, slot-based toolbars, and a tiny safe parser (no inline HTML).</p>
|
|
610
|
+
</a>
|
|
611
|
+
</div>
|
|
581
612
|
<div class="span-12 t-span-6 d-span-4 px">
|
|
582
613
|
<a href="./components/icon.html" class="card mb no-link d-b">
|
|
583
614
|
<h3 class="tc-primary">Icon</h3>
|
|
@@ -722,6 +753,12 @@
|
|
|
722
753
|
<p class="tc-muted">Hierarchical data visualization with collapsible branches and custom leaf types.</p>
|
|
723
754
|
</a>
|
|
724
755
|
</div>
|
|
756
|
+
<div class="span-12 t-span-6 d-span-4 px">
|
|
757
|
+
<a href="./components/voice-selector.html" class="card mb no-link d-b">
|
|
758
|
+
<h3 class="tc-primary">Voice Selector</h3>
|
|
759
|
+
<p class="tc-muted">Dropdown of available speech-synthesis voices, persisted via the voice utility for site-wide use.</p>
|
|
760
|
+
</a>
|
|
761
|
+
</div>
|
|
725
762
|
</div>
|
|
726
763
|
|
|
727
764
|
<h2>Base Components</h2>
|
|
@@ -784,6 +821,12 @@
|
|
|
784
821
|
<p class="tc-muted">Type converters for Lit component properties and attributes.</p>
|
|
785
822
|
</a>
|
|
786
823
|
</div>
|
|
824
|
+
<div class="span-12 t-span-6 d-span-4 px">
|
|
825
|
+
<a href="./utils/sanitizeHtml.html" class="card mb no-link d-b">
|
|
826
|
+
<h3 class="tc-primary">sanitizeHtml</h3>
|
|
827
|
+
<p class="tc-muted">Whitelist HTML sanitizer for user-submitted rich text. Strips unsafe tags, attributes, and URL schemes.</p>
|
|
828
|
+
</a>
|
|
829
|
+
</div>
|
|
787
830
|
<div class="span-12 t-span-6 d-span-4 px">
|
|
788
831
|
<a href="./utils/string.html" class="card mb no-link d-b">
|
|
789
832
|
<h3 class="tc-primary">string</h3>
|
|
@@ -808,6 +851,12 @@
|
|
|
808
851
|
<p class="tc-muted">Functions for manipulating and analyzing JavaScript objects.</p>
|
|
809
852
|
</a>
|
|
810
853
|
</div>
|
|
854
|
+
<div class="span-12 t-span-6 d-span-4 px">
|
|
855
|
+
<a href="./utils/voice.html" class="card mb no-link d-b">
|
|
856
|
+
<h3 class="tc-primary">voice</h3>
|
|
857
|
+
<p class="tc-muted">Persisted speech-synthesis voice preference with pub/sub, mirroring the theme utility.</p>
|
|
858
|
+
</a>
|
|
859
|
+
</div>
|
|
811
860
|
<div class="span-12 t-span-6 d-span-4 px">
|
|
812
861
|
<a href="./utils/wait.html" class="card mb no-link d-b">
|
|
813
862
|
<h3 class="tc-primary">wait</h3>
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import{html as e,css as t,nothing as s}from"../lit-all.min.js";import i from"./ShadowComponent.js";import o from"../utils/sanitizeHtml.js";import a from"../utils/renderMarkdown.js";import"./MarkdownEditor.js";import"./markdownEditorControls/Bold.js";import"./markdownEditorControls/Italic.js";import"./markdownEditorControls/Code.js";import"./markdownEditorControls/Link.js";import"./markdownEditorControls/BulletList.js";import"./markdownEditorControls/NumberedList.js";import"./markdownEditorControls/Quote.js";import"./Spinner.js";import"./Icon.js";const r=new Set(["sending","delivered","read","failed"]);export default class n extends i{static properties={enterNewline:{type:Boolean,reflect:!0,attribute:"enter-newline"},showStatus:{type:String,reflect:!0,attribute:"show-status"},placeholder:{type:String,reflect:!0},disabled:{type:Boolean,reflect:!0},messages:{state:!0}};constructor(){super(),this.enterNewline=!1,this.showStatus=null,this.placeholder="Type a message...",this.disabled=!1,this.messages=[]}updated(e){super.updated(e),e.has("messages")&&this.#e()}addMessage(e={}){const t="outgoing"===e.type?"outgoing":"incoming",s=e.id||("undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID?crypto.randomUUID():`msg-${Date.now()}-${Math.random().toString(36).slice(2,10)}`),i={id:s,type:t,html:o(e.html||""),status:r.has(e.status)?e.status:"outgoing"===t?"delivered":"read",sender:e.sender||"",timestamp:e.timestamp instanceof Date?e.timestamp:new Date};return this.messages=[...this.messages,i],s}updateMessage(e,t={}){let s=!1;return this.messages=this.messages.map(i=>{if(i.id!==e)return i;s=!0;const a={...i};return void 0!==t.html&&(a.html=o(t.html)),void 0!==t.status&&r.has(t.status)&&(a.status=t.status),void 0!==t.sender&&(a.sender=t.sender),t.timestamp instanceof Date&&(a.timestamp=t.timestamp),a}),s}removeMessage(e){const t=this.messages.length;return this.messages=this.messages.filter(t=>t.id!==e),this.messages.length!==t}clear(){this.messages=[]}send(){if(this.disabled)return null;const e=this.shadowRoot?.querySelector("k-markdown-editor");if(!e)return null;const t=(e.value||"").trim();if(!t)return null;const s=o(a(t,{breaks:!0})),i=this.addMessage({type:"outgoing",html:s,status:this.#t?"sending":"delivered"});return e.clear(),this.dispatchEvent(new CustomEvent("send",{detail:{id:i,html:s,markdown:t},bubbles:!0})),i}handleSendClick=()=>this.send();handleEditorKeydown=e=>{if(this.disabled)return;if("Enter"!==e.key||e.ctrlKey||e.metaKey||e.altKey)return;(this.enterNewline?e.shiftKey:!e.shiftKey)&&(e.preventDefault(),this.send())};#e=()=>{this.updateComplete.then(()=>{const e=this.shadowRoot?.querySelector(".window");e&&(e.scrollTop=e.scrollHeight)})};get#s(){for(let e=this.messages.length-1;e>=0;e--)if("outgoing"===this.messages[e].type)return this.messages[e].id;return null}get#t(){return null!=this.showStatus&&"false"!==this.showStatus}get#i(){return"icons"===this.showStatus?"icons":"text"}#o(e,t){return!!this.#t&&("outgoing"===e.type&&("sending"===e.status||"failed"===e.status||e.id===t))}#a(e){return"icons"===this.#i?this.#r(e):this.#n(e)}#n(t){return"sending"===t?e`<span class="status sending"><k-spinner size="xs"></k-spinner> Sending…</span>`:"delivered"===t?e`<span class="status">Delivered</span>`:"read"===t?e`<span class="status">Read</span>`:"failed"===t?e`<span class="status failed"><k-icon name="error"></k-icon> Not Delivered</span>`:s}#r(t){return"sending"===t?e`<span class="status status-icon-only"><k-spinner size="xs" title="Sending"></k-spinner></span>`:"delivered"===t?e`<span class="status status-icon-only"><k-icon name="check" title="Delivered"></k-icon></span>`:"read"===t?e`<span class="status status-icon-only"><k-icon name="done_all" title="Read"></k-icon></span>`:"failed"===t?e`<span class="status status-icon-only failed"><k-icon name="error" title="Not Delivered"></k-icon></span>`:s}#d(t,i){const o=this.#o(t,i);return e`
|
|
2
|
+
<div
|
|
3
|
+
class="message ${t.type} ${t.status}"
|
|
4
|
+
data-id=${t.id}
|
|
5
|
+
>
|
|
6
|
+
${t.sender?e`<div class="sender">${t.sender}</div>`:s}
|
|
7
|
+
<div class="bubble">
|
|
8
|
+
<div class="content" .innerHTML=${t.html}></div>
|
|
9
|
+
</div>
|
|
10
|
+
${o?this.#a(t.status):s}
|
|
11
|
+
</div>
|
|
12
|
+
`}render(){const t=this.#s;return e`
|
|
13
|
+
<div class="window" role="log" aria-live="polite">
|
|
14
|
+
${this.messages.map(e=>this.#d(e,t))}
|
|
15
|
+
</div>
|
|
16
|
+
<div class="input-area">
|
|
17
|
+
<k-markdown-editor
|
|
18
|
+
class="editor"
|
|
19
|
+
placeholder=${this.placeholder}
|
|
20
|
+
?disabled=${this.disabled}
|
|
21
|
+
@keydown=${this.handleEditorKeydown}
|
|
22
|
+
>
|
|
23
|
+
<div slot="controls-top" class="controls-top">
|
|
24
|
+
<slot name="controls-top">
|
|
25
|
+
<k-md-bold></k-md-bold>
|
|
26
|
+
<k-md-italic></k-md-italic>
|
|
27
|
+
<k-md-code></k-md-code>
|
|
28
|
+
<k-md-link></k-md-link>
|
|
29
|
+
<k-md-bullet-list></k-md-bullet-list>
|
|
30
|
+
<k-md-numbered-list></k-md-numbered-list>
|
|
31
|
+
<k-md-quote></k-md-quote>
|
|
32
|
+
</slot>
|
|
33
|
+
</div>
|
|
34
|
+
<div slot="controls-bottom" class="controls-bottom">
|
|
35
|
+
<slot name="controls-bottom"></slot>
|
|
36
|
+
<button
|
|
37
|
+
type="button"
|
|
38
|
+
class="send-btn primary"
|
|
39
|
+
?disabled=${this.disabled}
|
|
40
|
+
@click=${this.handleSendClick}
|
|
41
|
+
aria-label="Send message"
|
|
42
|
+
title="Send message"
|
|
43
|
+
>
|
|
44
|
+
<k-icon name="send"></k-icon>
|
|
45
|
+
</button>
|
|
46
|
+
</div>
|
|
47
|
+
</k-markdown-editor>
|
|
48
|
+
</div>
|
|
49
|
+
`}static styles=t`
|
|
50
|
+
:host {
|
|
51
|
+
--window_min_height: 16rem;
|
|
52
|
+
--window_max_height: 32rem;
|
|
53
|
+
--chat_padding: 0.5rem;
|
|
54
|
+
--chat_gap: 0.5rem;
|
|
55
|
+
--message_radius: 1rem;
|
|
56
|
+
--message_max_width: 75%;
|
|
57
|
+
--bubble_padding: 0.5rem 0.75rem;
|
|
58
|
+
--bubble_bg__incoming: var(--c_bg__alt);
|
|
59
|
+
--bubble_bg__outgoing: var(--c_primary);
|
|
60
|
+
--bubble_tc__outgoing: white;
|
|
61
|
+
--send_btn_bg: var(--c_primary);
|
|
62
|
+
--send_btn_tc: white;
|
|
63
|
+
|
|
64
|
+
display: flex;
|
|
65
|
+
flex-direction: column;
|
|
66
|
+
border: 1px solid var(--c_border);
|
|
67
|
+
border-radius: var(--radius);
|
|
68
|
+
background: var(--c_bg);
|
|
69
|
+
/* Note: NO overflow:hidden on the host — that would clip the input
|
|
70
|
+
area's focus shadow. Each child clips its own content against the
|
|
71
|
+
shared rounded corners instead. */
|
|
72
|
+
}
|
|
73
|
+
:host([disabled]) {
|
|
74
|
+
opacity: 0.6;
|
|
75
|
+
}
|
|
76
|
+
.window {
|
|
77
|
+
flex: 1 1 auto;
|
|
78
|
+
min-height: var(--window_min_height);
|
|
79
|
+
max-height: var(--window_max_height);
|
|
80
|
+
overflow-y: auto;
|
|
81
|
+
padding: var(--chat_padding);
|
|
82
|
+
display: flex;
|
|
83
|
+
flex-direction: column;
|
|
84
|
+
gap: var(--chat_gap);
|
|
85
|
+
scroll-behavior: smooth;
|
|
86
|
+
/* Match the chat's outer rounded corners on the top edge so messages
|
|
87
|
+
don't render past them. */
|
|
88
|
+
border-top-left-radius: var(--radius);
|
|
89
|
+
border-top-right-radius: var(--radius);
|
|
90
|
+
}
|
|
91
|
+
.message {
|
|
92
|
+
display: flex;
|
|
93
|
+
flex-direction: column;
|
|
94
|
+
max-width: var(--message_max_width);
|
|
95
|
+
gap: 0.125rem;
|
|
96
|
+
}
|
|
97
|
+
.message.outgoing {
|
|
98
|
+
align-self: flex-end;
|
|
99
|
+
align-items: flex-end;
|
|
100
|
+
}
|
|
101
|
+
.message.incoming {
|
|
102
|
+
align-self: flex-start;
|
|
103
|
+
align-items: flex-start;
|
|
104
|
+
}
|
|
105
|
+
.sender {
|
|
106
|
+
font-size: 0.75rem;
|
|
107
|
+
color: var(--tc_muted);
|
|
108
|
+
}
|
|
109
|
+
.bubble {
|
|
110
|
+
padding: var(--bubble_padding);
|
|
111
|
+
border-radius: var(--message_radius);
|
|
112
|
+
background: var(--bubble_bg__incoming);
|
|
113
|
+
color: var(--tc);
|
|
114
|
+
word-wrap: break-word;
|
|
115
|
+
overflow-wrap: anywhere;
|
|
116
|
+
}
|
|
117
|
+
.message.outgoing .bubble {
|
|
118
|
+
background: var(--bubble_bg__outgoing);
|
|
119
|
+
color: var(--bubble_tc__outgoing);
|
|
120
|
+
}
|
|
121
|
+
.message.outgoing.sending .bubble {
|
|
122
|
+
opacity: 0.7;
|
|
123
|
+
}
|
|
124
|
+
.message.outgoing.failed .bubble {
|
|
125
|
+
background: var(--c_danger, #d32f2f);
|
|
126
|
+
}
|
|
127
|
+
.content {
|
|
128
|
+
line-height: 1.4;
|
|
129
|
+
}
|
|
130
|
+
.content p:first-child { margin-top: 0; }
|
|
131
|
+
.content p:last-child { margin-bottom: 0; }
|
|
132
|
+
/* iMessage-style small grey label below the message bubble. */
|
|
133
|
+
.status {
|
|
134
|
+
display: inline-flex;
|
|
135
|
+
align-items: center;
|
|
136
|
+
gap: 0.25rem;
|
|
137
|
+
font-size: 0.7rem;
|
|
138
|
+
color: var(--tc_muted);
|
|
139
|
+
margin-top: 0.125rem;
|
|
140
|
+
}
|
|
141
|
+
.status.failed {
|
|
142
|
+
color: var(--c_danger, #d32f2f);
|
|
143
|
+
}
|
|
144
|
+
.status k-spinner,
|
|
145
|
+
.status k-icon {
|
|
146
|
+
font-size: 0.8rem;
|
|
147
|
+
}
|
|
148
|
+
.status-icon-only {
|
|
149
|
+
font-size: 0.95rem;
|
|
150
|
+
}
|
|
151
|
+
.input-area {
|
|
152
|
+
position: relative;
|
|
153
|
+
border-top: 1px solid var(--c_border);
|
|
154
|
+
border-bottom-left-radius: var(--radius);
|
|
155
|
+
border-bottom-right-radius: var(--radius);
|
|
156
|
+
}
|
|
157
|
+
.editor {
|
|
158
|
+
/* Markdown editor fills the bottom of the chat. CSS custom properties
|
|
159
|
+
pierce shadow boundaries -- '--height' sets the initial size of the
|
|
160
|
+
editor's internal Resize wrapper. */
|
|
161
|
+
--height: 13rem;
|
|
162
|
+
display: block;
|
|
163
|
+
width: 100%;
|
|
164
|
+
}
|
|
165
|
+
.controls-top,
|
|
166
|
+
.controls-bottom {
|
|
167
|
+
display: flex;
|
|
168
|
+
align-items: center;
|
|
169
|
+
flex-wrap: wrap;
|
|
170
|
+
gap: 0.125rem;
|
|
171
|
+
}
|
|
172
|
+
.controls-bottom {
|
|
173
|
+
width: 100%;
|
|
174
|
+
}
|
|
175
|
+
.send-btn {
|
|
176
|
+
margin-left: auto;
|
|
177
|
+
display: inline-flex;
|
|
178
|
+
align-items: center;
|
|
179
|
+
justify-content: center;
|
|
180
|
+
width: 2rem;
|
|
181
|
+
height: 2rem;
|
|
182
|
+
padding: 0;
|
|
183
|
+
border: 1px solid transparent;
|
|
184
|
+
border-radius: 50%;
|
|
185
|
+
background: var(--c_primary);
|
|
186
|
+
color: white;
|
|
187
|
+
cursor: pointer;
|
|
188
|
+
transition: opacity var(--animation_ms);
|
|
189
|
+
}
|
|
190
|
+
.send-btn:hover:not(:disabled) {
|
|
191
|
+
opacity: 0.9;
|
|
192
|
+
}
|
|
193
|
+
.send-btn:focus-visible {
|
|
194
|
+
outline: none;
|
|
195
|
+
box-shadow: var(--focus_shadow);
|
|
196
|
+
}
|
|
197
|
+
.send-btn:disabled {
|
|
198
|
+
cursor: not-allowed;
|
|
199
|
+
opacity: 0.5;
|
|
200
|
+
}
|
|
201
|
+
`}customElements.define("k-chat",n);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{html as t,css as e}from"../lit-all.min.js";import o from"./ShadowComponent.js";import i from"../utils/formatCode.js";import{getCalculatedTheme as s,subscribeToTheme as
|
|
1
|
+
import{html as t,css as e}from"../lit-all.min.js";import o from"./ShadowComponent.js";import i from"../utils/formatCode.js";import{getCalculatedTheme as s,subscribeToTheme as a}from"../utils/theme.js";export default class r extends o{static formAssociated=!0;static properties={name:{type:String,reflect:!0},value:{type:String,reflect:!0},language:{type:String,reflect:!0},monacoSrc:{type:String,attribute:"monaco-src"},controls:{type:String,reflect:!0},editorTheme:{type:String,attribute:"editor-theme",reflect:!0},hasTopToolbar:{type:Boolean,state:!0},hasBottomToolbar:{type:Boolean,state:!0},fullscreen:{type:Boolean,reflect:!0},wordWrap:{type:Boolean},minimapEnabled:{type:Boolean},disabled:{type:Boolean,reflect:!0},readonly:{type:Boolean,reflect:!0},required:{type:Boolean,reflect:!0}};constructor(){super(),this.internals=this.attachInternals(),this.name="",this.value="",this.language="javascript",this.monacoSrc="",this.controls="",this.controlsLoaded=!1,this.hasTopToolbar=!1,this.hasBottomToolbar=!1,this.monacoEditor=null,this.skipValueSync=!1,this.editorTheme="auto",this.wordWrap=!0,this.minimapEnabled=!1,this.fontSize=14,this.fullscreen=!1,this.disabled=!1,this.readonly=!1,this.required=!1}connectedCallback(){super.connectedCallback(),this.hasAttribute("value")&&(this.value=this.getAttribute("value")),this.slotObserver=new MutationObserver(()=>this.updateToolbarVisibility()),this.slotObserver.observe(this,{childList:!0,subtree:!0}),this.updateToolbarVisibility()}disconnectedCallback(){super.disconnectedCallback(),this.slotObserver?.disconnect(),this.monacoEditor?.dispose(),this.unsubscribeTheme?.(),this.fullscreen&&this.exitFullscreen()}updateToolbarVisibility(){const t=new Set(Array.from(this.children).map(t=>t.getAttribute("slot"))),e=this.constructor.controlSets[this.controls]??null;this.hasTopToolbar=!(!e?.topLeft&&!e?.topRight)||["toolbar-top","toolbar-top-left","toolbar-top-right"].some(e=>t.has(e)),this.hasBottomToolbar=!(!e?.bottomLeft&&!e?.bottomRight)||["toolbar-bottom","toolbar-bottom-left","toolbar-bottom-right"].some(e=>t.has(e))}updated(t){if(super.updated(t),t.has("controls")&&(this.updateToolbarVisibility(),this.controls&&"none"!==this.controls&&this.loadControls()),t.has("value")&&!this.skipValueSync&&(this.monacoEditor&&this.monacoEditor.getValue()!==this.value&&this.monacoEditor.setValue(this.value),this.updateFormValue(),this.dispatchEvent(new CustomEvent("change",{detail:{value:this.value},bubbles:!0}))),t.has("language")&&this.monacoEditor){const t=this.monacoEditor.getModel();t&&window.monaco.editor.setModelLanguage(t,this.language),this.dispatchEvent(new CustomEvent("language-changed",{detail:{language:this.language},bubbles:!0}))}t.has("editorTheme")&&this.monacoEditor&&(window.monaco.editor.setTheme(this.resolveMonacoTheme()),this.dispatchEvent(new CustomEvent("editor-theme-changed",{detail:{editorTheme:this.editorTheme},bubbles:!0}))),t.has("wordWrap")&&(this.monacoEditor?.updateOptions({wordWrap:this.wordWrap?"on":"off"}),this.dispatchEvent(new CustomEvent("word-wrap-changed",{detail:{wordWrap:this.wordWrap},bubbles:!0}))),t.has("minimapEnabled")&&(this.monacoEditor?.updateOptions({minimap:{enabled:this.minimapEnabled}}),this.dispatchEvent(new CustomEvent("minimap-changed",{detail:{minimapEnabled:this.minimapEnabled},bubbles:!0}))),t.has("fullscreen")&&(this.fullscreen||this.monacoEditor?.layout({width:0,height:0}),requestAnimationFrame(()=>this.monacoEditor?.layout())),(t.has("disabled")||t.has("readonly"))&&this.monacoEditor?.updateOptions({readOnly:this.disabled||this.readonly}),(t.has("value")||t.has("required")||t.has("disabled"))&&this.#t()}#t=()=>{this.disabled?this.internals.setValidity({}):this.required&&!(this.getValue()||"").trim()?this.internals.setValidity({valueMissing:!0},"Please fill out this field.",this.monacoContainer||this):this.internals.setValidity({})};async firstUpdated(){this.monacoContainer=this.shadowRoot.querySelector(".monaco-editor-container"),await this.initMonaco(),this.dispatchEvent(new CustomEvent("ready",{detail:{value:this.value},bubbles:!0}))}async loadControls(){if(this.controlsLoaded)return;this.controlsLoaded=!0;const t=new URL("./codeEditorControls/",import.meta.url).href;await Promise.all([import(`${t}FormatCode.js`),import(`${t}CopyCode.js`),import(`${t}EditorTheme.js`),import(`${t}Undo.js`),import(`${t}Redo.js`),import(`${t}WordWrap.js`),import(`${t}Minimap.js`),import(`${t}FindReplace.js`),import(`${t}FontSize.js`),import(`${t}FoldAll.js`),import(`${t}LanguageSelect.js`),import(`${t}Fullscreen.js`),import(`${t}ControlGroup.js`),import(`${t}ControlSpacer.js`)]),this.requestUpdate()}async initMonaco(){if(!this.monacoEditor){if(this.monacoInitPromise)return this.monacoInitPromise;this.monacoInitPromise=this._initMonaco(),await this.monacoInitPromise,this.monacoInitPromise=null}}async _initMonaco(){const t=this.monacoSrc||window.kempo?.monacoUrl||"https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min";await new Promise((e,o)=>{if(window.monaco)return void e();if(window.require?.defined?.("vs/editor/editor.main"))return void e();const i=document.querySelector(`script[src="${t}/vs/loader.js"]`);if(i)return void i.addEventListener("load",()=>{window.require.config({paths:{vs:`${t}/vs`}}),window.require(["vs/editor/editor.main"],()=>e(),o)});const s=document.createElement("script");s.src=`${t}/vs/loader.js`,s.onload=()=>{window.require.config({paths:{vs:`${t}/vs`}}),window.require(["vs/editor/editor.main"],()=>e(),o)},s.onerror=o,document.head.appendChild(s)}),this.monacoEditor=window.monaco.editor.create(this.monacoContainer,{value:this.value,language:this.language,theme:this.resolveMonacoTheme(),minimap:{enabled:!1},wordWrap:"on",fontSize:14,scrollBeyondLastLine:!1,automaticLayout:!0,tabSize:2,padding:{top:8},readOnly:this.disabled||this.readonly});const e=document.querySelector('link[href*="monaco"][href*="editor.main.css"]');if(e){const t=document.createElement("link");t.rel="stylesheet",t.href=e.href,this.shadowRoot.appendChild(t)}this.unsubscribeTheme=a(()=>{this.monacoEditor&&"auto"===this.editorTheme&&window.monaco.editor.setTheme(this.resolveMonacoTheme())}),this.monacoEditor.onDidChangeModelContent(()=>{this.skipValueSync=!0,this.value=this.monacoEditor.getValue(),this.skipValueSync=!1,this.updateFormValue(),this.dispatchEvent(new CustomEvent("change",{detail:{value:this.value},bubbles:!0})),this.dispatchEvent(new CustomEvent("input",{detail:{value:this.value},bubbles:!0}))})}updateFormValue(){this.internals.setFormValue(this.getValue())}formResetCallback(){this.value=""}formStateRestoreCallback(t){this.value=t}formDisabledCallback(t){this.disabled=t}getValue(){return this.monacoEditor?this.monacoEditor.getValue():this.value}setValue(t){return this.skipValueSync=!0,this.value=t,this.monacoEditor&&this.monacoEditor.setValue(t),this.updateFormValue(),this.skipValueSync=!1,this}clear(){return this.setValue("")}formatCode(){return this.monacoEditor?.getAction("editor.action.formatDocument")?.run(),this}selectAll(){if(!this.monacoEditor)return this;const t=this.monacoEditor.getModel();return t&&this.monacoEditor.setSelection(t.getFullModelRange()),this}getSelectedText(){return this.monacoEditor&&this.monacoEditor.getModel()?.getValueInRange(this.monacoEditor.getSelection())||""}focus(){return this.monacoEditor?.focus(),this}setLanguage(t){return this.language=t,this}setEditorTheme(t){return["auto","light","dark"].includes(t)&&(this.editorTheme=t),this}copyToClipboard(){return navigator.clipboard.writeText(this.getValue()),this}undo(){return this.monacoEditor?.trigger("toolbar","undo"),this}redo(){return this.monacoEditor?.trigger("toolbar","redo"),this}setWordWrap(t){return this.wordWrap=t,this}setMinimap(t){return this.minimapEnabled=t,this}toggleWordWrap(){return this.setWordWrap(!this.wordWrap)}toggleMinimap(){return this.setMinimap(!this.minimapEnabled)}openFind(){return this.monacoEditor?.getAction("actions.find")?.run(),this}increaseFontSize(){return this.fontSize=Math.min(this.fontSize+2,40),this.monacoEditor?.updateOptions({fontSize:this.fontSize}),this}decreaseFontSize(){return this.fontSize=Math.max(this.fontSize-2,8),this.monacoEditor?.updateOptions({fontSize:this.fontSize}),this}foldAll(){return this.monacoEditor?.getAction("editor.foldAll")?.run(),this}unfoldAll(){return this.monacoEditor?.getAction("editor.unfoldAll")?.run(),this}enterFullscreen(){return this.fullscreen=!0,document.body.classList.add("no-scroll"),this.dispatchEvent(new CustomEvent("fullscreen-changed",{detail:{fullscreen:!0},bubbles:!0})),this}exitFullscreen(){return this.fullscreen=!1,document.body.classList.remove("no-scroll"),this.dispatchEvent(new CustomEvent("fullscreen-changed",{detail:{fullscreen:!1},bubbles:!0})),this}toggleFullscreen(){return this.fullscreen?this.exitFullscreen():this.enterFullscreen()}resolveMonacoTheme(){return"dark"===this.editorTheme?"vs-dark":"light"===this.editorTheme?"vs":"dark"===s()?"vs-dark":"vs"}static controlSets={full:{topLeft:t`
|
|
2
2
|
<k-cec-group>
|
|
3
3
|
<k-cec-undo></k-cec-undo>
|
|
4
4
|
<k-cec-redo></k-cec-redo>
|
|
@@ -69,6 +69,25 @@ import{html as t,css as e}from"../lit-all.min.js";import o from"./ShadowComponen
|
|
|
69
69
|
[hidden] {
|
|
70
70
|
display: none !important;
|
|
71
71
|
}
|
|
72
|
+
:host([disabled]) {
|
|
73
|
+
opacity: 0.6;
|
|
74
|
+
}
|
|
75
|
+
/* disabled blocks all interaction -- toolbar AND editor. Monaco's
|
|
76
|
+
readOnly already prevents typing; pointer-events: none also stops
|
|
77
|
+
focus / cursor placement, matching native form control semantics. */
|
|
78
|
+
:host([disabled]) .toolbar-top,
|
|
79
|
+
:host([disabled]) .toolbar-bottom,
|
|
80
|
+
:host([disabled]) .editor-container {
|
|
81
|
+
pointer-events: none;
|
|
82
|
+
}
|
|
83
|
+
/* readonly keeps the editor interactive (so users can place a cursor
|
|
84
|
+
to select / copy) but mutes the toolbar so its buttons can't
|
|
85
|
+
mutate the document. */
|
|
86
|
+
:host([readonly]) .toolbar-top,
|
|
87
|
+
:host([readonly]) .toolbar-bottom {
|
|
88
|
+
pointer-events: none;
|
|
89
|
+
opacity: 0.5;
|
|
90
|
+
}
|
|
72
91
|
`;render(){const e=this.constructor.controlSets[this.controls]??{};return t`
|
|
73
92
|
${this.hasTopToolbar?t`
|
|
74
93
|
<div class="toolbar-top bb">
|
|
@@ -93,4 +112,4 @@ import{html as t,css as e}from"../lit-all.min.js";import o from"./ShadowComponen
|
|
|
93
112
|
</div>
|
|
94
113
|
</div>
|
|
95
114
|
`:""}
|
|
96
|
-
`}}customElements.define("k-code-editor",
|
|
115
|
+
`}}customElements.define("k-code-editor",r);
|
|
@@ -14,7 +14,7 @@ import{html as e,css as t}from"../lit-all.min.js";import o from"./ShadowComponen
|
|
|
14
14
|
display: none;
|
|
15
15
|
position: fixed;
|
|
16
16
|
position-anchor: --dropdown-trigger;
|
|
17
|
-
z-index:
|
|
17
|
+
z-index: 30;
|
|
18
18
|
min-width: anchor-size(width);
|
|
19
19
|
background: var(--c_bg);
|
|
20
20
|
border: 1px solid var(--c_border);
|