@meistrari/chat-nuxt 1.11.0 → 1.12.0

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.
Files changed (72) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +15 -0
  3. package/dist/runtime/components/chat/conversation-item.d.vue.ts +6 -1
  4. package/dist/runtime/components/chat/conversation-item.vue +30 -141
  5. package/dist/runtime/components/chat/conversation-item.vue.d.ts +6 -1
  6. package/dist/runtime/components/chat/conversation-list.d.vue.ts +1 -0
  7. package/dist/runtime/components/chat/conversation-list.vue +300 -72
  8. package/dist/runtime/components/chat/conversation-list.vue.d.ts +1 -0
  9. package/dist/runtime/components/chat/conversation-new-group-button.d.vue.ts +7 -0
  10. package/dist/runtime/components/chat/conversation-new-group-button.vue +90 -0
  11. package/dist/runtime/components/chat/conversation-new-group-button.vue.d.ts +7 -0
  12. package/dist/runtime/components/chat/conversation-new-group-popover-content.d.vue.ts +23 -0
  13. package/dist/runtime/components/chat/conversation-new-group-popover-content.vue +75 -0
  14. package/dist/runtime/components/chat/conversation-new-group-popover-content.vue.d.ts +23 -0
  15. package/dist/runtime/components/chat/mobile/shell/drawer.d.vue.ts +2 -2
  16. package/dist/runtime/components/chat/mobile/shell/drawer.vue +370 -41
  17. package/dist/runtime/components/chat/mobile/shell/drawer.vue.d.ts +2 -2
  18. package/dist/runtime/components/chat/mobile/shell/shell.d.vue.ts +6 -6
  19. package/dist/runtime/components/chat/mobile/shell/shell.vue +1 -1
  20. package/dist/runtime/components/chat/mobile/shell/shell.vue.d.ts +6 -6
  21. package/dist/runtime/components/chat/topbar.d.vue.ts +2 -2
  22. package/dist/runtime/components/chat/topbar.vue.d.ts +2 -2
  23. package/dist/runtime/composables/useConversationGroups.d.ts +12 -0
  24. package/dist/runtime/composables/useConversationGroups.js +160 -0
  25. package/dist/runtime/composables/useConversationItem.d.ts +48 -0
  26. package/dist/runtime/composables/useConversationItem.js +176 -0
  27. package/dist/runtime/composables/useConversationList.d.ts +128 -0
  28. package/dist/runtime/composables/useConversationList.js +553 -0
  29. package/dist/runtime/composables/useConversations.d.ts +2 -0
  30. package/dist/runtime/composables/useConversations.js +45 -1
  31. package/dist/runtime/composables/usePendingConversationGroup.d.ts +5 -0
  32. package/dist/runtime/composables/usePendingConversationGroup.js +33 -0
  33. package/dist/runtime/embed/components/ChatConfigurationModal.d.vue.ts +1 -1
  34. package/dist/runtime/embed/components/ChatConfigurationModal.vue.d.ts +1 -1
  35. package/dist/runtime/embed/components/ChatEmbedInner.vue +24 -5
  36. package/dist/runtime/server/api/chat/conversations/[id]/group.patch.d.ts +1 -0
  37. package/dist/runtime/server/api/chat/conversations/[id]/group.patch.js +1 -0
  38. package/dist/runtime/server/api/chat/conversations/groups/[groupId]/index.delete.d.ts +1 -0
  39. package/dist/runtime/server/api/chat/conversations/groups/[groupId]/index.delete.js +1 -0
  40. package/dist/runtime/server/api/chat/conversations/groups/[groupId]/index.patch.d.ts +1 -0
  41. package/dist/runtime/server/api/chat/conversations/groups/[groupId]/index.patch.js +1 -0
  42. package/dist/runtime/server/api/chat/conversations/groups/index.get.d.ts +1 -0
  43. package/dist/runtime/server/api/chat/conversations/groups/index.get.js +1 -0
  44. package/dist/runtime/server/api/chat/conversations/groups/index.post.d.ts +1 -0
  45. package/dist/runtime/server/api/chat/conversations/groups/index.post.js +1 -0
  46. package/dist/runtime/server/api/conversations/[id]/duplicate.post.js +1 -0
  47. package/dist/runtime/server/api/conversations/[id]/group.patch.d.ts +2 -0
  48. package/dist/runtime/server/api/conversations/[id]/group.patch.js +46 -0
  49. package/dist/runtime/server/api/conversations/groups/[groupId]/index.delete.d.ts +4 -0
  50. package/dist/runtime/server/api/conversations/groups/[groupId]/index.delete.js +25 -0
  51. package/dist/runtime/server/api/conversations/groups/[groupId]/index.patch.d.ts +2 -0
  52. package/dist/runtime/server/api/conversations/groups/[groupId]/index.patch.js +30 -0
  53. package/dist/runtime/server/api/conversations/groups/index.get.d.ts +2 -0
  54. package/dist/runtime/server/api/conversations/groups/index.get.js +13 -0
  55. package/dist/runtime/server/api/conversations/groups/index.post.d.ts +2 -0
  56. package/dist/runtime/server/api/conversations/groups/index.post.js +26 -0
  57. package/dist/runtime/server/api/conversations/index.post.js +1 -0
  58. package/dist/runtime/server/db/schema/conversation-groups.d.ts +143 -0
  59. package/dist/runtime/server/db/schema/conversation-groups.js +20 -0
  60. package/dist/runtime/server/db/schema/conversations.d.ts +17 -0
  61. package/dist/runtime/server/db/schema/conversations.js +3 -0
  62. package/dist/runtime/server/db/schema/index.d.ts +1 -0
  63. package/dist/runtime/server/db/schema/index.js +1 -0
  64. package/dist/runtime/server/utils/conversation-group.d.ts +4 -0
  65. package/dist/runtime/server/utils/conversation-group.js +48 -0
  66. package/dist/runtime/types/chat.d.ts +2 -1
  67. package/dist/runtime/utils/conversation-groups.d.ts +18 -0
  68. package/dist/runtime/utils/conversation-groups.js +30 -0
  69. package/drizzle/0016_dry_aaron_stack.sql +16 -0
  70. package/drizzle/meta/0016_snapshot.json +887 -0
  71. package/drizzle/meta/_journal.json +7 -0
  72. package/package.json +1 -1
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meistrari/chat-nuxt",
3
3
  "configKey": "chatNuxt",
4
- "version": "1.11.0",
4
+ "version": "1.12.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
package/dist/module.mjs CHANGED
@@ -180,6 +180,10 @@ const DEFAULT_FEATURES = {
180
180
  credentials: false
181
181
  };
182
182
  const VUE_COMPONENT_EXTENSIONS = [".vue"];
183
+ const DYNAMIC_ICON_SAFELIST = [
184
+ "i-ph-folder-minus",
185
+ "i-ph-folder-open"
186
+ ];
183
187
  function resolveChatAuthMode(runtimeConfig) {
184
188
  const publicConfig = runtimeConfig.public;
185
189
  const telaAuth = publicConfig?.telaAuth;
@@ -283,6 +287,16 @@ function ensureIconifyPackages(consumerRoot) {
283
287
  }
284
288
  }
285
289
  }
290
+ function ensureDynamicIconSafelist(nuxtOptions) {
291
+ const unocssOptions = nuxtOptions.unocss ||= {};
292
+ const currentSafelist = Array.isArray(unocssOptions.safelist) ? unocssOptions.safelist : unocssOptions.safelist ? [unocssOptions.safelist] : [];
293
+ for (const icon of DYNAMIC_ICON_SAFELIST) {
294
+ if (!currentSafelist.includes(icon)) {
295
+ currentSafelist.push(icon);
296
+ }
297
+ }
298
+ unocssOptions.safelist = currentSafelist;
299
+ }
286
300
  function validateRuntimeConfig(runtimeConfig, mode, features) {
287
301
  if (!mode) {
288
302
  return;
@@ -326,6 +340,7 @@ const module$1 = defineNuxtModule({
326
340
  );
327
341
  }
328
342
  ensureIconifyPackages(nuxt.options.rootDir);
343
+ ensureDynamicIconSafelist(nuxt.options);
329
344
  const resolver = createResolver(import.meta.url);
330
345
  const builtRuntimeDir = resolver.resolve("./runtime");
331
346
  const sourceRuntimeDir = resolver.resolve("../src/runtime");
@@ -1,8 +1,9 @@
1
- import type { Conversation } from '../../types/chat.js';
2
1
  import type { DeepReadonly } from 'vue';
2
+ import type { Conversation } from '../../types/chat.js';
3
3
  type __VLS_Props = {
4
4
  conversation: DeepReadonly<Conversation>;
5
5
  active: boolean;
6
+ draggable?: boolean;
6
7
  userImage?: string;
7
8
  selectConversation?: (id: string) => void | Promise<void>;
8
9
  };
@@ -11,11 +12,15 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
11
12
  rename: (id: string, title: string) => any;
12
13
  duplicate: (id: string) => any;
13
14
  export: (id: string) => any;
15
+ dragStart: (id: string) => any;
16
+ dragEnd: () => any;
14
17
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
18
  onDelete?: ((id: string) => any) | undefined;
16
19
  onRename?: ((id: string, title: string) => any) | undefined;
17
20
  onDuplicate?: ((id: string) => any) | undefined;
18
21
  onExport?: ((id: string) => any) | undefined;
22
+ onDragStart?: ((id: string) => any) | undefined;
23
+ onDragEnd?: (() => any) | undefined;
19
24
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
20
25
  declare const _default: typeof __VLS_export;
21
26
  export default _default;
@@ -1,148 +1,33 @@
1
1
  <script setup>
2
- import { useMagicKeys, useMutationObserver } from "@vueuse/core";
3
- import { resolveConversationRenameTitle } from "../../utils/conversation-title";
4
- import { capitalizeFirst } from "../../utils/string";
2
+ import { useConversationItem } from "../../composables/useConversationItem";
5
3
  const props = defineProps({
6
4
  conversation: { type: null, required: true },
7
5
  active: { type: Boolean, required: true },
6
+ draggable: { type: Boolean, required: false },
8
7
  userImage: { type: String, required: false },
9
8
  selectConversation: { type: Function, required: false }
10
9
  });
11
- const emit = defineEmits(["delete", "rename", "duplicate", "export"]);
12
- const isRenamingInline = ref(false);
13
- const renameTitle = ref("");
14
- const renameInputRef = ref(null);
15
- const isIgnoringInitialRenameBlur = ref(false);
16
- const showDeleteModal = ref(false);
17
- const { escape } = useMagicKeys();
18
- watch(() => escape?.value, (pressed) => {
19
- if (pressed && isRenamingInline.value) {
20
- cancelRename();
21
- }
22
- if (pressed && showDeleteModal.value) {
23
- showDeleteModal.value = false;
24
- }
25
- });
26
- function confirmDelete() {
27
- showDeleteModal.value = false;
28
- emit("delete", props.conversation.id);
29
- }
30
- const menuButtonRef = ref(null);
31
- const isMenuOpen = ref(false);
32
- useMutationObserver(menuButtonRef, (mutations) => {
33
- for (const mutation of mutations) {
34
- if (mutation.attributeName === "data-state") {
35
- isMenuOpen.value = menuButtonRef.value?.getAttribute("data-state") === "open";
36
- }
37
- }
38
- }, { attributes: true });
39
- const conversationPath = computed(() => `/${props.conversation.id}`);
40
- const conversationNavigationDelayMs = 250;
41
- let conversationNavigationTimer = null;
42
- let renameBlurTimer = null;
43
- function clearPendingConversationNavigation() {
44
- if (conversationNavigationTimer === null)
45
- return;
46
- clearTimeout(conversationNavigationTimer);
47
- conversationNavigationTimer = null;
48
- }
49
- function clearRenameBlurTimer() {
50
- if (renameBlurTimer === null)
51
- return;
52
- clearTimeout(renameBlurTimer);
53
- renameBlurTimer = null;
54
- }
55
- function allowRenameBlurSoon() {
56
- clearRenameBlurTimer();
57
- renameBlurTimer = setTimeout(() => {
58
- isIgnoringInitialRenameBlur.value = false;
59
- renameBlurTimer = null;
60
- }, 100);
61
- }
62
- function handleConversationClick(event) {
63
- if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)
64
- return;
65
- event.preventDefault();
66
- clearPendingConversationNavigation();
67
- if (event.detail > 1)
68
- return;
69
- conversationNavigationTimer = setTimeout(() => {
70
- if (props.selectConversation) {
71
- void props.selectConversation(props.conversation.id);
72
- } else {
73
- navigateTo(conversationPath.value);
74
- }
75
- conversationNavigationTimer = null;
76
- }, conversationNavigationDelayMs);
77
- }
78
- async function focusRenameInput() {
79
- await nextTick();
80
- renameInputRef.value?.focus();
81
- renameInputRef.value?.select();
82
- allowRenameBlurSoon();
83
- }
84
- function startRename() {
85
- isMenuOpen.value = false;
86
- clearPendingConversationNavigation();
87
- clearRenameBlurTimer();
88
- renameTitle.value = props.conversation.title;
89
- isIgnoringInitialRenameBlur.value = true;
90
- isRenamingInline.value = true;
91
- void focusRenameInput();
92
- }
93
- function handleConversationDoubleClick() {
94
- clearPendingConversationNavigation();
95
- startRename();
96
- }
97
- function cancelRename() {
98
- isRenamingInline.value = false;
99
- isIgnoringInitialRenameBlur.value = false;
100
- renameTitle.value = "";
101
- clearRenameBlurTimer();
102
- }
103
- function submitRename() {
104
- if (!isRenamingInline.value)
105
- return;
106
- const title = resolveConversationRenameTitle(renameTitle.value, props.conversation.title);
107
- if (!title) {
108
- cancelRename();
109
- return;
110
- }
111
- emit("rename", props.conversation.id, title);
112
- cancelRename();
113
- }
114
- function handleRenameBlur() {
115
- if (isIgnoringInitialRenameBlur.value)
116
- return;
117
- submitRename();
118
- }
119
- const menuItems = [
120
- {
121
- label: "Renomear",
122
- icon: "i-ph-pencil-simple",
123
- click: () => startRename()
124
- },
125
- {
126
- label: "Duplicar",
127
- icon: "i-ph-copy",
128
- click: () => emit("duplicate", props.conversation.id)
129
- },
130
- {
131
- label: "Exportar",
132
- icon: "i-ph-download-simple",
133
- click: () => emit("export", props.conversation.id)
134
- },
135
- {
136
- label: "Excluir",
137
- icon: "i-ph-trash",
138
- color: "negative",
139
- click: () => showDeleteModal.value = true
140
- }
141
- ];
142
- onBeforeUnmount(() => {
143
- clearPendingConversationNavigation();
144
- clearRenameBlurTimer();
145
- });
10
+ const emit = defineEmits(["delete", "rename", "duplicate", "export", "dragStart", "dragEnd"]);
11
+ const {
12
+ isRenamingInline,
13
+ renameTitle,
14
+ renameInputRef,
15
+ showDeleteModal,
16
+ menuButtonRef,
17
+ isMenuOpen,
18
+ conversationPath,
19
+ displayTitle,
20
+ menuItems,
21
+ confirmDelete,
22
+ cancelDelete,
23
+ handleConversationClick,
24
+ handleConversationDoubleClick,
25
+ handleConversationDragStart,
26
+ handleConversationDragEnd,
27
+ cancelRename,
28
+ submitRename,
29
+ handleRenameBlur
30
+ } = useConversationItem(props, emit);
146
31
  </script>
147
32
 
148
33
  <template>
@@ -189,6 +74,7 @@ onBeforeUnmount(() => {
189
74
  <a
190
75
  v-else
191
76
  :href="conversationPath"
77
+ :draggable="draggable"
192
78
  block
193
79
  px-12px
194
80
  h-32px
@@ -201,6 +87,8 @@ onBeforeUnmount(() => {
201
87
  ]"
202
88
  @click="handleConversationClick"
203
89
  @dblclick.prevent.stop="handleConversationDoubleClick"
90
+ @dragstart="handleConversationDragStart"
91
+ @dragend="handleConversationDragEnd"
204
92
  >
205
93
  <div flex items-center justify-between gap-12px h-full>
206
94
  <!-- User Avatar -->
@@ -220,7 +108,7 @@ onBeforeUnmount(() => {
220
108
  truncate
221
109
  tracking="-.15px"
222
110
  >
223
- {{ capitalizeFirst(conversation.title) }}
111
+ {{ displayTitle }}
224
112
  </span>
225
113
  </div>
226
114
 
@@ -231,7 +119,7 @@ onBeforeUnmount(() => {
231
119
  class="opacity-0 group-hover:opacity-100 transition-opacity"
232
120
  :class="isMenuOpen && 'opacity-100'"
233
121
  >
234
- <TelaDropdownMenu :items="menuItems">
122
+ <TelaDropdownMenu :items="menuItems" content-class="chat-sidebar-floating">
235
123
  <button
236
124
  ref="menuButtonRef"
237
125
  p-4px
@@ -253,10 +141,11 @@ onBeforeUnmount(() => {
253
141
  v-model:open="showDeleteModal"
254
142
  title="Excluir conversa"
255
143
  variant="danger"
144
+ class="chat-sidebar-floating"
256
145
  confirm-button-text="Excluir"
257
146
  cancel-button-text="Cancelar"
258
147
  @confirm="confirmDelete"
259
- @cancel="showDeleteModal = false"
148
+ @cancel="cancelDelete"
260
149
  >
261
150
  Tem certeza que deseja excluir esta conversa? Esta ação não pode ser desfeita.
262
151
  </TelaConfirmationModal>
@@ -1,8 +1,9 @@
1
- import type { Conversation } from '../../types/chat.js';
2
1
  import type { DeepReadonly } from 'vue';
2
+ import type { Conversation } from '../../types/chat.js';
3
3
  type __VLS_Props = {
4
4
  conversation: DeepReadonly<Conversation>;
5
5
  active: boolean;
6
+ draggable?: boolean;
6
7
  userImage?: string;
7
8
  selectConversation?: (id: string) => void | Promise<void>;
8
9
  };
@@ -11,11 +12,15 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
11
12
  rename: (id: string, title: string) => any;
12
13
  duplicate: (id: string) => any;
13
14
  export: (id: string) => any;
15
+ dragStart: (id: string) => any;
16
+ dragEnd: () => any;
14
17
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
18
  onDelete?: ((id: string) => any) | undefined;
16
19
  onRename?: ((id: string, title: string) => any) | undefined;
17
20
  onDuplicate?: ((id: string) => any) | undefined;
18
21
  onExport?: ((id: string) => any) | undefined;
22
+ onDragStart?: ((id: string) => any) | undefined;
23
+ onDragEnd?: (() => any) | undefined;
19
24
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
20
25
  declare const _default: typeof __VLS_export;
21
26
  export default _default;
@@ -6,6 +6,7 @@ type __VLS_Props = {
6
6
  getMemberImage?: (userId: string) => string | undefined;
7
7
  selectConversation?: (id: string) => void | Promise<void>;
8
8
  resetConversation?: () => void | Promise<void>;
9
+ startConversation?: (groupId?: string | null) => void | Promise<void>;
9
10
  loading?: boolean;
10
11
  };
11
12
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;