@rkosafo/cai.components 0.0.75 → 0.0.78
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/README.md +8 -8
- package/dist/baseEditor/index.svelte +32 -32
- package/dist/builders/filters/FilterBuilder.svelte +641 -641
- package/dist/forms/FormCheckbox/FormCheckbox.svelte +53 -53
- package/dist/forms/FormClEditor/ClEdito.svelte +68 -68
- package/dist/forms/FormDatepicker/FormDatepicker.svelte +159 -159
- package/dist/forms/FormFileUpload/FormFileUplad.svelte +134 -134
- package/dist/forms/FormInput/FormInput.svelte +87 -87
- package/dist/forms/FormRadio/FormRadio.svelte +53 -53
- package/dist/forms/FormSelect/FormSelect.svelte +88 -88
- package/dist/forms/FormTextarea/FormTextarea.svelte +78 -78
- package/dist/forms/button-toggle/ButtonToggle.svelte +119 -0
- package/dist/forms/button-toggle/ButtonToggle.svelte.d.ts +139 -0
- package/dist/forms/button-toggle/ButtonToggleGroup.svelte +0 -0
- package/dist/forms/button-toggle/ButtonToggleGroup.svelte.d.ts +26 -0
- package/dist/forms/button-toggle/CheckIcon.svelte +28 -0
- package/dist/forms/button-toggle/CheckIcon.svelte.d.ts +4 -0
- package/dist/forms/button-toggle/index.d.ts +4 -0
- package/dist/forms/button-toggle/index.js +4 -0
- package/dist/forms/button-toggle/theme.d.ts +347 -0
- package/dist/forms/button-toggle/theme.js +129 -0
- package/dist/forms/checkbox/Checkbox.svelte +82 -82
- package/dist/forms/checkbox/CheckboxButton.svelte +92 -92
- package/dist/forms/datepicker/Datepicker.svelte +707 -707
- package/dist/forms/form/Form.svelte +69 -69
- package/dist/forms/input/Input.svelte +363 -363
- package/dist/forms/label/Label.svelte +38 -38
- package/dist/forms/radio/Radio.svelte +48 -48
- package/dist/forms/radio/RadioButton.svelte +22 -22
- package/dist/forms/select/Select.svelte +56 -56
- package/dist/forms/textarea/Textarea.svelte +165 -165
- package/dist/forms/toggle/Toggle.svelte +70 -0
- package/dist/forms/toggle/Toggle.svelte.d.ts +3 -0
- package/dist/forms/toggle/index.d.ts +2 -0
- package/dist/forms/toggle/index.js +2 -0
- package/dist/forms/toggle/theme.d.ts +280 -0
- package/dist/forms/toggle/theme.js +97 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/layout/Chat/CategorySelector.svelte +52 -52
- package/dist/layout/Chat/ChatEntry.svelte +246 -246
- package/dist/layout/Chat/ChatEntrySkeleton.svelte +81 -81
- package/dist/layout/Chat/ChatHeader.svelte +172 -172
- package/dist/layout/Chat/ChatInput.svelte +207 -207
- package/dist/layout/Chat/DraggableWindow.svelte +230 -230
- package/dist/layout/Chat/PreviewPage.svelte +182 -182
- package/dist/layout/Chat/RichText.svelte +216 -216
- package/dist/layout/ComponentCanvas/Canvas.svelte +40 -40
- package/dist/layout/ComponentCanvas/ComponentRenderer.svelte +85 -85
- package/dist/layout/TF/Content/Content.svelte +21 -21
- package/dist/layout/TF/Header/Header.svelte +166 -166
- package/dist/layout/TF/Sidebar/Sidebar.svelte +148 -148
- package/dist/layout/TF/Wrapper/Wrapper.svelte +17 -17
- package/dist/layout/mailing/MailPaginator.svelte +36 -36
- package/dist/layout/mailing/MailSidebar.svelte +39 -39
- package/dist/layout/mailing/MailToolBar.svelte +174 -174
- package/dist/layout/mailing/MailingContent.svelte +10 -10
- package/dist/layout/mailing/MailingHeader.svelte +55 -55
- package/dist/layout/mailing/MailingMessageCard.svelte +112 -112
- package/dist/layout/mailing/MailingMessageViewer.svelte +87 -87
- package/dist/layout/mailing/MailingModule.svelte +448 -448
- package/dist/styles/docs.css +615 -615
- package/dist/styles/tf-layout.css +185 -185
- package/dist/themes/ThemeProvider.svelte +20 -20
- package/dist/themes/themes.d.ts +3 -0
- package/dist/themes/themes.js +3 -0
- package/dist/types/index.d.ts +57 -1
- package/dist/typography/heading/Heading.svelte +35 -35
- package/dist/ui/accordion/Accordion.svelte +49 -49
- package/dist/ui/accordion/AccordionItem.svelte +173 -173
- package/dist/ui/alert/Alert.svelte +83 -83
- package/dist/ui/alertDialog/AlertDialog.svelte +40 -40
- package/dist/ui/avatar/Avatar.svelte +77 -77
- package/dist/ui/box/Box.svelte +28 -28
- package/dist/ui/breadcrumb/Breadcrumb.svelte +39 -39
- package/dist/ui/buttons/ActionButton.svelte +234 -234
- package/dist/ui/buttons/Button.svelte +102 -102
- package/dist/ui/buttons/GradientButton.svelte +59 -59
- package/dist/ui/datatable/Datatable.svelte +525 -525
- package/dist/ui/drawer/Drawer.svelte +300 -300
- package/dist/ui/dropdown/Dropdown.svelte +36 -36
- package/dist/ui/dropdown/DropdownDivider.svelte +11 -11
- package/dist/ui/dropdown/DropdownGroup.svelte +14 -14
- package/dist/ui/dropdown/DropdownHeader.svelte +14 -14
- package/dist/ui/dropdown/DropdownItem.svelte +52 -52
- package/dist/ui/footer/Footer.svelte +15 -15
- package/dist/ui/footer/FooterBrand.svelte +37 -37
- package/dist/ui/footer/FooterCopyright.svelte +45 -45
- package/dist/ui/footer/FooterIcon.svelte +22 -22
- package/dist/ui/footer/FooterLink.svelte +33 -33
- package/dist/ui/footer/FooterLinkGroup.svelte +13 -13
- package/dist/ui/icons/IconifyIcon.svelte +7 -7
- package/dist/ui/indicator/Indicator.svelte +42 -42
- package/dist/ui/modal/Modal.svelte +265 -265
- package/dist/ui/modal/theme.d.ts +26 -26
- package/dist/ui/modal/theme.js +25 -25
- package/dist/ui/notificationList/NotificationList.svelte +123 -123
- package/dist/ui/pageLoader/PageLoader.svelte +14 -14
- package/dist/ui/paginate/Paginate.svelte +96 -96
- package/dist/ui/speedDial/SpeedDial.svelte +77 -0
- package/dist/ui/speedDial/SpeedDial.svelte.d.ts +21 -0
- package/dist/ui/speedDial/SpeedDialButton.svelte +75 -0
- package/dist/ui/speedDial/SpeedDialButton.svelte.d.ts +20 -0
- package/dist/ui/speedDial/SpeedDialTrigger.svelte +79 -0
- package/dist/ui/speedDial/SpeedDialTrigger.svelte.d.ts +18 -0
- package/dist/ui/speedDial/index.d.ts +4 -0
- package/dist/ui/speedDial/index.js +4 -0
- package/dist/ui/speedDial/theme.d.ts +75 -0
- package/dist/ui/speedDial/theme.js +35 -0
- package/dist/ui/tab/Tab.svelte +67 -67
- package/dist/ui/table/Table.svelte +396 -396
- package/dist/ui/tableLoader/TableLoader.svelte +24 -24
- package/dist/ui/toast/Toast.svelte +337 -337
- package/dist/ui/toast/Toast.svelte.d.ts +10 -10
- package/dist/ui/toast/index.d.ts +1 -2
- package/dist/ui/toast/index.js +3 -1
- package/dist/ui/toolbar/Toolbar.svelte +59 -59
- package/dist/ui/toolbar/ToolbarButton.svelte +56 -56
- package/dist/ui/toolbar/ToolbarGroup.svelte +43 -43
- package/dist/ui/tooltip/Tooltip.svelte +51 -51
- package/dist/utils/Popper.svelte +257 -257
- package/dist/utils/closeButton/CloseButton.svelte +88 -88
- package/dist/utils/index.d.ts +3 -2
- package/dist/utils/index.js +13 -3
- package/dist/utils/singleSelection.svelte.js +48 -48
- package/dist/youtube/index.svelte +12 -12
- package/package.json +2 -1
|
@@ -1,216 +1,216 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { clickOutsideAction, cn, IconifyIcon } from '../../index.js';
|
|
3
|
-
import type { CommandListType, IMentionableItem, ISlashCommand, RichTextProps } from './index.js';
|
|
4
|
-
|
|
5
|
-
let {
|
|
6
|
-
value = $bindable(''),
|
|
7
|
-
placeholder = 'Type a new message',
|
|
8
|
-
loading = false,
|
|
9
|
-
slashCommands = [],
|
|
10
|
-
mentionableItems = [],
|
|
11
|
-
onMention,
|
|
12
|
-
onSend,
|
|
13
|
-
onSlash,
|
|
14
|
-
class: className = ''
|
|
15
|
-
}: RichTextProps = $props();
|
|
16
|
-
|
|
17
|
-
let showCommandList = $state(false);
|
|
18
|
-
let commandListPosition = $state(0);
|
|
19
|
-
let commandListType = $state<CommandListType>('slash');
|
|
20
|
-
let filteredItems = $state<Array<ISlashCommand | IMentionableItem>>([]);
|
|
21
|
-
let textareaElement = $state<HTMLTextAreaElement | undefined>(undefined);
|
|
22
|
-
let lastTriggerPosition = $state(-1);
|
|
23
|
-
|
|
24
|
-
function onKeyUp(e: KeyboardEvent) {
|
|
25
|
-
if (e.code === 'Enter' && value && !e.shiftKey) {
|
|
26
|
-
if (showCommandList) {
|
|
27
|
-
e.preventDefault();
|
|
28
|
-
selectCommand();
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
onSend?.();
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (showCommandList) {
|
|
36
|
-
if (e.code === 'ArrowUp') {
|
|
37
|
-
e.preventDefault();
|
|
38
|
-
commandListPosition = Math.max(0, commandListPosition - 1);
|
|
39
|
-
} else if (e.code === 'ArrowDown') {
|
|
40
|
-
e.preventDefault();
|
|
41
|
-
commandListPosition = Math.min(filteredItems.length - 1, commandListPosition + 1);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function onKeyDown(e: KeyboardEvent) {
|
|
47
|
-
const cursorPos = textareaElement!.selectionStart;
|
|
48
|
-
const textBeforeCursor = value.substring(0, cursorPos);
|
|
49
|
-
|
|
50
|
-
if (e.key === '/' && !showCommandList) {
|
|
51
|
-
lastTriggerPosition = cursorPos;
|
|
52
|
-
showCommandList = true;
|
|
53
|
-
commandListType = 'slash';
|
|
54
|
-
filteredItems = slashCommands;
|
|
55
|
-
commandListPosition = 0;
|
|
56
|
-
} else if (e.key === '@' && !showCommandList) {
|
|
57
|
-
lastTriggerPosition = cursorPos;
|
|
58
|
-
showCommandList = true;
|
|
59
|
-
commandListType = 'mention';
|
|
60
|
-
filteredItems = mentionableItems;
|
|
61
|
-
commandListPosition = 0;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (e.key === 'Backspace') {
|
|
65
|
-
const textUntilCursor = value.substring(0, cursorPos);
|
|
66
|
-
const lastAtPos = textUntilCursor.lastIndexOf('@');
|
|
67
|
-
|
|
68
|
-
if (lastAtPos !== -1) {
|
|
69
|
-
const textAfterAt = value.substring(lastAtPos);
|
|
70
|
-
const spacePos = textAfterAt.indexOf(' ');
|
|
71
|
-
const mentionText = spacePos === -1 ? textAfterAt : textAfterAt.substring(0, spacePos);
|
|
72
|
-
|
|
73
|
-
const mentionMatch = mentionableItems.find(
|
|
74
|
-
(item) => `@${item.name.replaceAll(' ', '_')}` === mentionText
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
if (mentionMatch && cursorPos > lastAtPos && cursorPos <= lastAtPos + mentionText.length) {
|
|
78
|
-
e.preventDefault();
|
|
79
|
-
|
|
80
|
-
const textBeforeMention = value.substring(0, lastAtPos);
|
|
81
|
-
const textAfterMention = value.substring(lastAtPos + mentionText.length);
|
|
82
|
-
value = textBeforeMention + textAfterMention;
|
|
83
|
-
|
|
84
|
-
setTimeout(() => {
|
|
85
|
-
textareaElement!.setSelectionRange(lastAtPos, lastAtPos);
|
|
86
|
-
});
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (showCommandList && cursorPos <= lastTriggerPosition) {
|
|
92
|
-
showCommandList = false;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (showCommandList) {
|
|
97
|
-
const textAfterTrigger = textBeforeCursor.substring(lastTriggerPosition);
|
|
98
|
-
|
|
99
|
-
if (commandListType === 'slash') {
|
|
100
|
-
filteredItems = slashCommands.filter((cmd) =>
|
|
101
|
-
cmd.cmdK.includes(textAfterTrigger.toLowerCase())
|
|
102
|
-
);
|
|
103
|
-
} else {
|
|
104
|
-
filteredItems = mentionableItems.filter((item) =>
|
|
105
|
-
item.name.toLowerCase().includes(textAfterTrigger.toLowerCase())
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
commandListPosition = Math.min(commandListPosition, filteredItems.length - 1);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function selectCommand() {
|
|
114
|
-
if (filteredItems.length === 0) return;
|
|
115
|
-
|
|
116
|
-
const selectedItem = filteredItems[commandListPosition];
|
|
117
|
-
const cursorPos = textareaElement!.selectionStart;
|
|
118
|
-
const textBeforeTrigger = value.substring(0, lastTriggerPosition);
|
|
119
|
-
const textAfterSelection = value.substring(cursorPos);
|
|
120
|
-
|
|
121
|
-
if (commandListType === 'slash') {
|
|
122
|
-
value = '';
|
|
123
|
-
onSlash?.(selectedItem as ISlashCommand);
|
|
124
|
-
} else {
|
|
125
|
-
value =
|
|
126
|
-
textBeforeTrigger +
|
|
127
|
-
`@${(selectedItem as IMentionableItem).name.replaceAll(' ', '_')}` +
|
|
128
|
-
textAfterSelection;
|
|
129
|
-
onMention?.(selectedItem as IMentionableItem);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const newCursorPos =
|
|
133
|
-
textBeforeTrigger.length +
|
|
134
|
-
(commandListType === 'slash'
|
|
135
|
-
? (selectedItem as ISlashCommand).cmdK.length + 1
|
|
136
|
-
: `@${(selectedItem as IMentionableItem).name.replaceAll(' ', '_')}`.length);
|
|
137
|
-
|
|
138
|
-
setTimeout(() => {
|
|
139
|
-
textareaElement!.setSelectionRange(newCursorPos, newCursorPos);
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
showCommandList = false;
|
|
143
|
-
commandListPosition = 0;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
function closeCommandList() {
|
|
147
|
-
showCommandList = false;
|
|
148
|
-
commandListPosition = 0;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function autoExpandTextarea(event: any) {
|
|
152
|
-
event.target.style.height = 'auto';
|
|
153
|
-
event.target.style.height = event.target.scrollHeight + 'px';
|
|
154
|
-
}
|
|
155
|
-
</script>
|
|
156
|
-
|
|
157
|
-
<div class="flex flex-col gap-2" use:clickOutsideAction onclickoutside={closeCommandList}>
|
|
158
|
-
<div class="relative px-2">
|
|
159
|
-
<div class="flex">
|
|
160
|
-
<textarea
|
|
161
|
-
bind:value
|
|
162
|
-
bind:this={textareaElement}
|
|
163
|
-
oninput={autoExpandTextarea}
|
|
164
|
-
onkeyup={onKeyUp}
|
|
165
|
-
onkeydown={onKeyDown}
|
|
166
|
-
rows="1"
|
|
167
|
-
class={cn('mt-1 flex-grow rounded-md bg-transparent p-2 focus:outline-none', className)}
|
|
168
|
-
{placeholder}
|
|
169
|
-
></textarea>
|
|
170
|
-
{#if loading}
|
|
171
|
-
<div class="absolute right-5 pt-4">
|
|
172
|
-
<IconifyIcon icon="svg-spinners:3-dots-move" style="font-size: 20px;" />
|
|
173
|
-
</div>
|
|
174
|
-
{/if}
|
|
175
|
-
</div>
|
|
176
|
-
|
|
177
|
-
{#if showCommandList && filteredItems.length > 0}
|
|
178
|
-
<div
|
|
179
|
-
class="absolute bottom-12 left-2 z-[3500] w-64 rounded-md border border-gray-200 bg-white shadow-lg"
|
|
180
|
-
>
|
|
181
|
-
<ul class="py-1">
|
|
182
|
-
{#each filteredItems as item, index}
|
|
183
|
-
<li
|
|
184
|
-
class="cursor-pointer px-4 py-2 hover:bg-gray-100 {index === commandListPosition
|
|
185
|
-
? 'bg-gray-100'
|
|
186
|
-
: ''}"
|
|
187
|
-
onclick={() => {
|
|
188
|
-
commandListPosition = index;
|
|
189
|
-
selectCommand();
|
|
190
|
-
}}
|
|
191
|
-
>
|
|
192
|
-
{#if commandListType === 'slash'}
|
|
193
|
-
<div class="font-medium text-blue-600">{item?.name}</div>
|
|
194
|
-
<div class="text-xs text-gray-500">{item?.hint}</div>
|
|
195
|
-
{:else}
|
|
196
|
-
<div class="flex items-center gap-2">
|
|
197
|
-
{#if item?.avatar}
|
|
198
|
-
<img src={item?.avatar} alt={item?.name} class="h-6 w-6 rounded-full" />
|
|
199
|
-
{/if}
|
|
200
|
-
<div class="font-medium text-blue-600">{item?.name}</div>
|
|
201
|
-
</div>
|
|
202
|
-
{/if}
|
|
203
|
-
</li>
|
|
204
|
-
{/each}
|
|
205
|
-
</ul>
|
|
206
|
-
</div>
|
|
207
|
-
{/if}
|
|
208
|
-
</div>
|
|
209
|
-
</div>
|
|
210
|
-
|
|
211
|
-
<style>
|
|
212
|
-
textarea {
|
|
213
|
-
resize: none;
|
|
214
|
-
overflow: hidden;
|
|
215
|
-
}
|
|
216
|
-
</style>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { clickOutsideAction, cn, IconifyIcon } from '../../index.js';
|
|
3
|
+
import type { CommandListType, IMentionableItem, ISlashCommand, RichTextProps } from './index.js';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
value = $bindable(''),
|
|
7
|
+
placeholder = 'Type a new message',
|
|
8
|
+
loading = false,
|
|
9
|
+
slashCommands = [],
|
|
10
|
+
mentionableItems = [],
|
|
11
|
+
onMention,
|
|
12
|
+
onSend,
|
|
13
|
+
onSlash,
|
|
14
|
+
class: className = ''
|
|
15
|
+
}: RichTextProps = $props();
|
|
16
|
+
|
|
17
|
+
let showCommandList = $state(false);
|
|
18
|
+
let commandListPosition = $state(0);
|
|
19
|
+
let commandListType = $state<CommandListType>('slash');
|
|
20
|
+
let filteredItems = $state<Array<ISlashCommand | IMentionableItem>>([]);
|
|
21
|
+
let textareaElement = $state<HTMLTextAreaElement | undefined>(undefined);
|
|
22
|
+
let lastTriggerPosition = $state(-1);
|
|
23
|
+
|
|
24
|
+
function onKeyUp(e: KeyboardEvent) {
|
|
25
|
+
if (e.code === 'Enter' && value && !e.shiftKey) {
|
|
26
|
+
if (showCommandList) {
|
|
27
|
+
e.preventDefault();
|
|
28
|
+
selectCommand();
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
onSend?.();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (showCommandList) {
|
|
36
|
+
if (e.code === 'ArrowUp') {
|
|
37
|
+
e.preventDefault();
|
|
38
|
+
commandListPosition = Math.max(0, commandListPosition - 1);
|
|
39
|
+
} else if (e.code === 'ArrowDown') {
|
|
40
|
+
e.preventDefault();
|
|
41
|
+
commandListPosition = Math.min(filteredItems.length - 1, commandListPosition + 1);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function onKeyDown(e: KeyboardEvent) {
|
|
47
|
+
const cursorPos = textareaElement!.selectionStart;
|
|
48
|
+
const textBeforeCursor = value.substring(0, cursorPos);
|
|
49
|
+
|
|
50
|
+
if (e.key === '/' && !showCommandList) {
|
|
51
|
+
lastTriggerPosition = cursorPos;
|
|
52
|
+
showCommandList = true;
|
|
53
|
+
commandListType = 'slash';
|
|
54
|
+
filteredItems = slashCommands;
|
|
55
|
+
commandListPosition = 0;
|
|
56
|
+
} else if (e.key === '@' && !showCommandList) {
|
|
57
|
+
lastTriggerPosition = cursorPos;
|
|
58
|
+
showCommandList = true;
|
|
59
|
+
commandListType = 'mention';
|
|
60
|
+
filteredItems = mentionableItems;
|
|
61
|
+
commandListPosition = 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (e.key === 'Backspace') {
|
|
65
|
+
const textUntilCursor = value.substring(0, cursorPos);
|
|
66
|
+
const lastAtPos = textUntilCursor.lastIndexOf('@');
|
|
67
|
+
|
|
68
|
+
if (lastAtPos !== -1) {
|
|
69
|
+
const textAfterAt = value.substring(lastAtPos);
|
|
70
|
+
const spacePos = textAfterAt.indexOf(' ');
|
|
71
|
+
const mentionText = spacePos === -1 ? textAfterAt : textAfterAt.substring(0, spacePos);
|
|
72
|
+
|
|
73
|
+
const mentionMatch = mentionableItems.find(
|
|
74
|
+
(item) => `@${item.name.replaceAll(' ', '_')}` === mentionText
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
if (mentionMatch && cursorPos > lastAtPos && cursorPos <= lastAtPos + mentionText.length) {
|
|
78
|
+
e.preventDefault();
|
|
79
|
+
|
|
80
|
+
const textBeforeMention = value.substring(0, lastAtPos);
|
|
81
|
+
const textAfterMention = value.substring(lastAtPos + mentionText.length);
|
|
82
|
+
value = textBeforeMention + textAfterMention;
|
|
83
|
+
|
|
84
|
+
setTimeout(() => {
|
|
85
|
+
textareaElement!.setSelectionRange(lastAtPos, lastAtPos);
|
|
86
|
+
});
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (showCommandList && cursorPos <= lastTriggerPosition) {
|
|
92
|
+
showCommandList = false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (showCommandList) {
|
|
97
|
+
const textAfterTrigger = textBeforeCursor.substring(lastTriggerPosition);
|
|
98
|
+
|
|
99
|
+
if (commandListType === 'slash') {
|
|
100
|
+
filteredItems = slashCommands.filter((cmd) =>
|
|
101
|
+
cmd.cmdK.includes(textAfterTrigger.toLowerCase())
|
|
102
|
+
);
|
|
103
|
+
} else {
|
|
104
|
+
filteredItems = mentionableItems.filter((item) =>
|
|
105
|
+
item.name.toLowerCase().includes(textAfterTrigger.toLowerCase())
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
commandListPosition = Math.min(commandListPosition, filteredItems.length - 1);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function selectCommand() {
|
|
114
|
+
if (filteredItems.length === 0) return;
|
|
115
|
+
|
|
116
|
+
const selectedItem = filteredItems[commandListPosition];
|
|
117
|
+
const cursorPos = textareaElement!.selectionStart;
|
|
118
|
+
const textBeforeTrigger = value.substring(0, lastTriggerPosition);
|
|
119
|
+
const textAfterSelection = value.substring(cursorPos);
|
|
120
|
+
|
|
121
|
+
if (commandListType === 'slash') {
|
|
122
|
+
value = '';
|
|
123
|
+
onSlash?.(selectedItem as ISlashCommand);
|
|
124
|
+
} else {
|
|
125
|
+
value =
|
|
126
|
+
textBeforeTrigger +
|
|
127
|
+
`@${(selectedItem as IMentionableItem).name.replaceAll(' ', '_')}` +
|
|
128
|
+
textAfterSelection;
|
|
129
|
+
onMention?.(selectedItem as IMentionableItem);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const newCursorPos =
|
|
133
|
+
textBeforeTrigger.length +
|
|
134
|
+
(commandListType === 'slash'
|
|
135
|
+
? (selectedItem as ISlashCommand).cmdK.length + 1
|
|
136
|
+
: `@${(selectedItem as IMentionableItem).name.replaceAll(' ', '_')}`.length);
|
|
137
|
+
|
|
138
|
+
setTimeout(() => {
|
|
139
|
+
textareaElement!.setSelectionRange(newCursorPos, newCursorPos);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
showCommandList = false;
|
|
143
|
+
commandListPosition = 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function closeCommandList() {
|
|
147
|
+
showCommandList = false;
|
|
148
|
+
commandListPosition = 0;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function autoExpandTextarea(event: any) {
|
|
152
|
+
event.target.style.height = 'auto';
|
|
153
|
+
event.target.style.height = event.target.scrollHeight + 'px';
|
|
154
|
+
}
|
|
155
|
+
</script>
|
|
156
|
+
|
|
157
|
+
<div class="flex flex-col gap-2" use:clickOutsideAction onclickoutside={closeCommandList}>
|
|
158
|
+
<div class="relative px-2">
|
|
159
|
+
<div class="flex">
|
|
160
|
+
<textarea
|
|
161
|
+
bind:value
|
|
162
|
+
bind:this={textareaElement}
|
|
163
|
+
oninput={autoExpandTextarea}
|
|
164
|
+
onkeyup={onKeyUp}
|
|
165
|
+
onkeydown={onKeyDown}
|
|
166
|
+
rows="1"
|
|
167
|
+
class={cn('mt-1 flex-grow rounded-md bg-transparent p-2 focus:outline-none', className)}
|
|
168
|
+
{placeholder}
|
|
169
|
+
></textarea>
|
|
170
|
+
{#if loading}
|
|
171
|
+
<div class="absolute right-5 pt-4">
|
|
172
|
+
<IconifyIcon icon="svg-spinners:3-dots-move" style="font-size: 20px;" />
|
|
173
|
+
</div>
|
|
174
|
+
{/if}
|
|
175
|
+
</div>
|
|
176
|
+
|
|
177
|
+
{#if showCommandList && filteredItems.length > 0}
|
|
178
|
+
<div
|
|
179
|
+
class="absolute bottom-12 left-2 z-[3500] w-64 rounded-md border border-gray-200 bg-white shadow-lg"
|
|
180
|
+
>
|
|
181
|
+
<ul class="py-1">
|
|
182
|
+
{#each filteredItems as item, index}
|
|
183
|
+
<li
|
|
184
|
+
class="cursor-pointer px-4 py-2 hover:bg-gray-100 {index === commandListPosition
|
|
185
|
+
? 'bg-gray-100'
|
|
186
|
+
: ''}"
|
|
187
|
+
onclick={() => {
|
|
188
|
+
commandListPosition = index;
|
|
189
|
+
selectCommand();
|
|
190
|
+
}}
|
|
191
|
+
>
|
|
192
|
+
{#if commandListType === 'slash'}
|
|
193
|
+
<div class="font-medium text-blue-600">{item?.name}</div>
|
|
194
|
+
<div class="text-xs text-gray-500">{item?.hint}</div>
|
|
195
|
+
{:else}
|
|
196
|
+
<div class="flex items-center gap-2">
|
|
197
|
+
{#if item?.avatar}
|
|
198
|
+
<img src={item?.avatar} alt={item?.name} class="h-6 w-6 rounded-full" />
|
|
199
|
+
{/if}
|
|
200
|
+
<div class="font-medium text-blue-600">{item?.name}</div>
|
|
201
|
+
</div>
|
|
202
|
+
{/if}
|
|
203
|
+
</li>
|
|
204
|
+
{/each}
|
|
205
|
+
</ul>
|
|
206
|
+
</div>
|
|
207
|
+
{/if}
|
|
208
|
+
</div>
|
|
209
|
+
</div>
|
|
210
|
+
|
|
211
|
+
<style>
|
|
212
|
+
textarea {
|
|
213
|
+
resize: none;
|
|
214
|
+
overflow: hidden;
|
|
215
|
+
}
|
|
216
|
+
</style>
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { receive, type IComponentDescriptor, type IDocumentCanvasProps } from '../../index.js';
|
|
3
|
-
import { nanoid } from 'nanoid';
|
|
4
|
-
import ComponentRenderer from './ComponentRenderer.svelte';
|
|
5
|
-
|
|
6
|
-
let {
|
|
7
|
-
children = [],
|
|
8
|
-
close,
|
|
9
|
-
contextKey,
|
|
10
|
-
toggleCollapse,
|
|
11
|
-
showBackground
|
|
12
|
-
}: IDocumentCanvasProps = $props();
|
|
13
|
-
|
|
14
|
-
function updateChildren(children: IComponentDescriptor[]) {
|
|
15
|
-
return children.map((a) => {
|
|
16
|
-
if (!a.id) a.id = nanoid();
|
|
17
|
-
return a;
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
let toRender = $derived(updateChildren(children));
|
|
22
|
-
</script>
|
|
23
|
-
|
|
24
|
-
<div class="flex flex-grow flex-col gap-5">
|
|
25
|
-
{#each toRender as child (child.id)}
|
|
26
|
-
<div
|
|
27
|
-
class="flex p-3"
|
|
28
|
-
class:shadow={showBackground}
|
|
29
|
-
class:bg-white={showBackground}
|
|
30
|
-
in:receive={{ key: child.id }}
|
|
31
|
-
>
|
|
32
|
-
<ComponentRenderer descriptor={child} {contextKey} {close} {toggleCollapse} />
|
|
33
|
-
</div>
|
|
34
|
-
{/each}
|
|
35
|
-
{#if toRender.length === 0}
|
|
36
|
-
<!-- <Alert>
|
|
37
|
-
It is lonely here
|
|
38
|
-
</Alert> -->
|
|
39
|
-
{/if}
|
|
40
|
-
</div>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { receive, type IComponentDescriptor, type IDocumentCanvasProps } from '../../index.js';
|
|
3
|
+
import { nanoid } from 'nanoid';
|
|
4
|
+
import ComponentRenderer from './ComponentRenderer.svelte';
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
children = [],
|
|
8
|
+
close,
|
|
9
|
+
contextKey,
|
|
10
|
+
toggleCollapse,
|
|
11
|
+
showBackground
|
|
12
|
+
}: IDocumentCanvasProps = $props();
|
|
13
|
+
|
|
14
|
+
function updateChildren(children: IComponentDescriptor[]) {
|
|
15
|
+
return children.map((a) => {
|
|
16
|
+
if (!a.id) a.id = nanoid();
|
|
17
|
+
return a;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let toRender = $derived(updateChildren(children));
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<div class="flex flex-grow flex-col gap-5">
|
|
25
|
+
{#each toRender as child (child.id)}
|
|
26
|
+
<div
|
|
27
|
+
class="flex p-3"
|
|
28
|
+
class:shadow={showBackground}
|
|
29
|
+
class:bg-white={showBackground}
|
|
30
|
+
in:receive={{ key: child.id }}
|
|
31
|
+
>
|
|
32
|
+
<ComponentRenderer descriptor={child} {contextKey} {close} {toggleCollapse} />
|
|
33
|
+
</div>
|
|
34
|
+
{/each}
|
|
35
|
+
{#if toRender.length === 0}
|
|
36
|
+
<!-- <Alert>
|
|
37
|
+
It is lonely here
|
|
38
|
+
</Alert> -->
|
|
39
|
+
{/if}
|
|
40
|
+
</div>
|