brutalism design
This commit is contained in:
@@ -20,6 +20,7 @@
|
|||||||
"@vueuse/core": "^14.3.0",
|
"@vueuse/core": "^14.3.0",
|
||||||
"@zag-js/avatar": "^1.40.0",
|
"@zag-js/avatar": "^1.40.0",
|
||||||
"@zag-js/collapsible": "^1.40.0",
|
"@zag-js/collapsible": "^1.40.0",
|
||||||
|
"@zag-js/file-upload": "^1.41.0",
|
||||||
"@zag-js/file-utils": "^1.40.0",
|
"@zag-js/file-utils": "^1.40.0",
|
||||||
"@zag-js/password-input": "^1.40.0",
|
"@zag-js/password-input": "^1.40.0",
|
||||||
"@zag-js/toggle": "^1.40.0",
|
"@zag-js/toggle": "^1.40.0",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<ChadButton full type="submit" :disabled="!valid" :loading="submitting">
|
<ChadButton full native-type="submit" :disabled="!valid" :loading="submitting">
|
||||||
Let's go
|
Let's go
|
||||||
</ChadButton>
|
</ChadButton>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<ChadButton full type="submit" :disabled="!valid" :loading="submitting">
|
<ChadButton full native-type="submit" :disabled="!valid" :loading="submitting">
|
||||||
Create an account
|
Create an account
|
||||||
</ChadButton>
|
</ChadButton>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,37 +1,53 @@
|
|||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
class="chad-button"
|
:class="[
|
||||||
:data-loading="loading || undefined"
|
bem.b(),
|
||||||
:data-disabled="disabled || undefined"
|
bem.exp(!!type, bem.m(type!)),
|
||||||
|
bem.is('loading', loading),
|
||||||
|
bem.is('disabled', disabled),
|
||||||
|
bem.is('full', full),
|
||||||
|
]"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:type="type"
|
:type="nativeType"
|
||||||
:data-full="full || undefined"
|
|
||||||
>
|
>
|
||||||
<ChadSpinner v-if="loading" class="chad-button__spinner" />
|
<ChadSpinner v-if="loading" class="chad-button__spinner" />
|
||||||
<slot v-else />
|
|
||||||
|
<template v-else>
|
||||||
|
<Component :is="icon" v-if="icon" class="chad-button__icon" />
|
||||||
|
|
||||||
|
<span v-if="$slots.default">
|
||||||
|
<slot />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { Component } from 'vue'
|
||||||
import ChadSpinner from '@shared/components/ui/Spinner.vue'
|
import ChadSpinner from '@shared/components/ui/Spinner.vue'
|
||||||
|
import useBem from '@shared/composables/use-bem.ts'
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'ChadButton',
|
name: 'ChadButton',
|
||||||
})
|
})
|
||||||
|
|
||||||
withDefaults(
|
withDefaults(
|
||||||
defineProps<Props>(),
|
defineProps<ChadButtonProps>(),
|
||||||
{
|
{
|
||||||
type: 'button',
|
nativeType: 'button',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
interface Props {
|
export interface ChadButtonProps {
|
||||||
loading?: boolean
|
loading?: boolean
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
type?: 'button' | 'submit'
|
type?: 'secondary'
|
||||||
|
nativeType?: 'button' | 'submit'
|
||||||
|
icon?: Component
|
||||||
full?: boolean
|
full?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bem = useBem('chad-button')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@@ -41,7 +57,7 @@ interface Props {
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
border: none;
|
border: none;
|
||||||
color: var(--ink);
|
color: var(--ink);
|
||||||
padding-inline: var(--space-3);
|
padding: 0 var(--space-3);
|
||||||
height: 44px;
|
height: 44px;
|
||||||
background-color: var(--yellow);
|
background-color: var(--yellow);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
@@ -50,7 +66,7 @@ interface Props {
|
|||||||
outline: var(--border-w) solid var(--ink);
|
outline: var(--border-w) solid var(--ink);
|
||||||
outline-offset: calc(var(--border-w) * -1);
|
outline-offset: calc(var(--border-w) * -1);
|
||||||
|
|
||||||
&[data-full] {
|
&.is-full {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,16 +80,35 @@ interface Props {
|
|||||||
color: var(--yellow);
|
color: var(--yellow);
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-disabled],
|
&--secondary {
|
||||||
|
background-color: var(--grey-1);
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
background-color: var(--grey-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: var(--grey-3);
|
||||||
|
color: var(--ink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
background-color: var(--grey-1);
|
background-color: var(--grey-1);
|
||||||
color: var(--grey-3);
|
color: var(--grey-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-loading] {
|
&.is-loading {
|
||||||
background-color: var(--grey-1);
|
background-color: var(--grey-1);
|
||||||
cursor: wait;
|
cursor: wait;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__icon {
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-right: var(--space-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
{{ label }}
|
{{ label }}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<input :id="inputId" v-model="modelValue" class="chad-input__input" :placeholder="placeholder" type="text">
|
<input :id="inputId" v-model="modelValue" class="chad-input__input" :placeholder="placeholder" type="text" autocomplete="off">
|
||||||
|
|
||||||
<p v-if="helper" class="chad-input__helper">
|
<p v-if="helper" class="chad-input__helper">
|
||||||
{{ helper }}
|
{{ helper }}
|
||||||
|
|||||||
25
new-client/src/shared/components/ui/NotificationBadge.vue
Normal file
25
new-client/src/shared/components/ui/NotificationBadge.vue
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<template>
|
||||||
|
<div class="chad-notification-badge">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.chad-notification-badge {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 12px;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
background-color: var(--yellow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
38
new-client/src/shared/components/ui/ToBottom.vue
Normal file
38
new-client/src/shared/components/ui/ToBottom.vue
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<template>
|
||||||
|
<button class="chad-to-bottom">
|
||||||
|
<ArrowDown />
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ArrowDown } from '@lucide/vue'
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'ChadToBottom',
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.chad-to-bottom {
|
||||||
|
cursor: pointer;
|
||||||
|
width: 40px;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 40px;
|
||||||
|
outline: var(--border-w) solid var(--ink);
|
||||||
|
outline-offset: calc(var(--border-w) * -1);
|
||||||
|
border: none;
|
||||||
|
background-color: var(--grey-1);
|
||||||
|
padding: 0;
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
background-color: var(--grey-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: var(--grey-3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
68
new-client/src/shared/composables/use-bem.ts
Normal file
68
new-client/src/shared/composables/use-bem.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
interface Options {
|
||||||
|
block: string
|
||||||
|
blockSuffix?: string
|
||||||
|
element?: string
|
||||||
|
modifier?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function _bem(options: Options) {
|
||||||
|
const { block, blockSuffix, element, modifier } = options
|
||||||
|
|
||||||
|
let cls = block
|
||||||
|
|
||||||
|
if (blockSuffix)
|
||||||
|
cls += `-${blockSuffix}`
|
||||||
|
|
||||||
|
if (element)
|
||||||
|
cls += `__${element}`
|
||||||
|
|
||||||
|
if (modifier)
|
||||||
|
cls += `--${modifier}`
|
||||||
|
|
||||||
|
return cls
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTruthy(value: unknown): boolean {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value.length > 0
|
||||||
|
}
|
||||||
|
else if (typeof value === 'object' && value !== null) {
|
||||||
|
return Object.keys(value).length > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return !!value
|
||||||
|
}
|
||||||
|
|
||||||
|
export default (block: string) => {
|
||||||
|
const b = (blockSuffix?: string) => _bem({ block, blockSuffix })
|
||||||
|
const e = (element: string) => _bem({ block, element })
|
||||||
|
const m = (modifier: string) => _bem({ block, modifier })
|
||||||
|
|
||||||
|
const be = (blockSuffix: string, element: string) => _bem({ block, blockSuffix, element })
|
||||||
|
const em = (element: string, modifier: string) => _bem({ block, element, modifier })
|
||||||
|
const bm = (blockSuffix: string, modifier: string) => _bem({ block, blockSuffix, modifier })
|
||||||
|
|
||||||
|
const bem = (blockSuffix: string, element: string, modifier: string) => _bem({ block, blockSuffix, element, modifier })
|
||||||
|
|
||||||
|
const is = (name: string, state: unknown) => isTruthy(state) ? `is-${name}` : ''
|
||||||
|
const has = (name: string, state: unknown) => isTruthy(state) ? `has-${name}` : ''
|
||||||
|
|
||||||
|
const exp = (condition: boolean, trueState: string, falseState: string = '') => condition ? trueState : falseState
|
||||||
|
|
||||||
|
return {
|
||||||
|
b,
|
||||||
|
e,
|
||||||
|
m,
|
||||||
|
|
||||||
|
be,
|
||||||
|
em,
|
||||||
|
bm,
|
||||||
|
|
||||||
|
bem,
|
||||||
|
|
||||||
|
is,
|
||||||
|
has,
|
||||||
|
|
||||||
|
exp,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
--grey-2: #c9c6bd;
|
--grey-2: #c9c6bd;
|
||||||
--grey-3: #8a8a82;
|
--grey-3: #8a8a82;
|
||||||
|
|
||||||
|
--shadow-sm: 3px 3px 0 0 var(--ink);
|
||||||
--shadow: 6px 6px 0 0 var(--ink);
|
--shadow: 6px 6px 0 0 var(--ink);
|
||||||
|
|
||||||
--border-w: 2px;
|
--border-w: 2px;
|
||||||
|
|||||||
42
new-client/src/widgets/chat/composables/use-chat-history.ts
Normal file
42
new-client/src/widgets/chat/composables/use-chat-history.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import type { ChatMessage } from '@shared/api/generated-chad-api.ts'
|
||||||
|
import { useEventBus } from '@shared/composables/use-event-bus.ts'
|
||||||
|
import { createGlobalState } from '@vueuse/core'
|
||||||
|
import { computed, shallowRef, triggerRef } from 'vue'
|
||||||
|
import { qChatMessages } from '../api/qChatMessages.ts'
|
||||||
|
|
||||||
|
export interface MessageGroup {
|
||||||
|
senderUsername: string
|
||||||
|
messages: ChatMessage[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useChatHistory = createGlobalState(() => {
|
||||||
|
const eventBus = useEventBus()
|
||||||
|
|
||||||
|
const { data: messages, hasNextPage: hasMoreMessages, fetchNextPage: loadMoreMessages, isFetching } = qChatMessages()
|
||||||
|
|
||||||
|
const feedItems = shallowRef<ChatMessage[]>([])
|
||||||
|
|
||||||
|
eventBus.on('chat:new-message', (message: ChatMessage) => {
|
||||||
|
feedItems.value.push(message)
|
||||||
|
triggerRef(feedItems)
|
||||||
|
})
|
||||||
|
|
||||||
|
const messageGroups = computed<MessageGroup[]>(() => {
|
||||||
|
const all = [...(messages.value ?? []), ...feedItems.value]
|
||||||
|
return all.reduce((groups, msg) => {
|
||||||
|
const last = groups.at(-1)
|
||||||
|
if (last?.senderUsername === msg.senderUsername)
|
||||||
|
last.messages.push(msg)
|
||||||
|
else
|
||||||
|
groups.push({ senderUsername: msg.senderUsername, messages: [msg] })
|
||||||
|
return groups
|
||||||
|
}, [] as MessageGroup[])
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
messageGroups,
|
||||||
|
hasMoreMessages,
|
||||||
|
loadMoreMessages,
|
||||||
|
isFetching,
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -15,9 +15,7 @@ export function useChatScroll(target: TemplateRef<HTMLElement>, options?: MaybeR
|
|||||||
end: false,
|
end: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(arrivedState, () => {
|
let lastScrollHeight = 0
|
||||||
console.log('arrived state', arrivedState)
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(el, (el) => {
|
watch(el, (el) => {
|
||||||
if (!el)
|
if (!el)
|
||||||
@@ -31,14 +29,22 @@ export function useChatScroll(target: TemplateRef<HTMLElement>, options?: MaybeR
|
|||||||
if (arrivedState.start) {
|
if (arrivedState.start) {
|
||||||
scrollToStart(true)
|
scrollToStart(true)
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
const heightDiff = el.value!.scrollHeight - lastScrollHeight
|
||||||
|
|
||||||
|
el.value!.scrollTop += heightDiff
|
||||||
|
}
|
||||||
|
|
||||||
getArrivedState()
|
getArrivedState()
|
||||||
|
|
||||||
|
lastScrollHeight = el.value!.scrollHeight
|
||||||
}, {
|
}, {
|
||||||
childList: true,
|
childList: true,
|
||||||
subtree: true,
|
subtree: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
useEventListener(el, 'scroll', () => {
|
useEventListener(el, 'scroll', () => {
|
||||||
|
console.log('scroll', el.value!.scrollTop)
|
||||||
getArrivedState()
|
getArrivedState()
|
||||||
}, { passive: true })
|
}, { passive: true })
|
||||||
|
|
||||||
|
|||||||
@@ -1,41 +1,18 @@
|
|||||||
import type { ChatMessage } from '@shared/api/generated-chad-api.ts'
|
import type { NewChatMessagePayload } from '@shared/api/generated-chad-api.ts'
|
||||||
import { useSignaling } from '@shared/composables/use-signaling'
|
import api from '@shared/api/client.ts'
|
||||||
import { createGlobalState } from '@vueuse/core'
|
|
||||||
import { computed, shallowRef, triggerRef, watch } from 'vue'
|
|
||||||
import { qChatMessages } from '../api/qChatMessages.ts'
|
|
||||||
|
|
||||||
export interface MessageGroup {
|
export function useChat() {
|
||||||
senderUsername: string
|
async function sendMessage(newMessage: NewChatMessagePayload) {
|
||||||
messages: ChatMessage[]
|
newMessage.text = newMessage.text.trim()
|
||||||
}
|
|
||||||
|
|
||||||
export const useChat = createGlobalState(() => {
|
if (newMessage.attachments?.length === 0 && newMessage.text.length === 0) {
|
||||||
const { data: messages, hasNextPage: hasMoreMessages, fetchNextPage, isFetching } = qChatMessages()
|
|
||||||
|
|
||||||
const { socket, connected } = useSignaling()
|
|
||||||
const feedItems = shallowRef<ChatMessage[]>([])
|
|
||||||
|
|
||||||
watch(connected, async (isConnected) => {
|
|
||||||
if (!isConnected)
|
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
socket.value!.on('chat:new-message', (message: ChatMessage) => {
|
await api.chad.chatSend(newMessage)
|
||||||
feedItems.value.push(message)
|
}
|
||||||
triggerRef(feedItems)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const messageGroups = computed<MessageGroup[]>(() => {
|
return {
|
||||||
const all = [...(messages.value ?? []), ...feedItems.value]
|
sendMessage,
|
||||||
return all.reduce((groups, msg) => {
|
}
|
||||||
const last = groups.at(-1)
|
}
|
||||||
if (last?.senderUsername === msg.senderUsername)
|
|
||||||
last.messages.push(msg)
|
|
||||||
else
|
|
||||||
groups.push({ senderUsername: msg.senderUsername, messages: [msg] })
|
|
||||||
return groups
|
|
||||||
}, [] as MessageGroup[])
|
|
||||||
})
|
|
||||||
|
|
||||||
return { messageGroups, hasMoreMessages, fetchNextPage, isFetching }
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -6,8 +6,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useChatHistory } from '@widgets/chat/composables/use-chat-history.ts'
|
||||||
import ChatInput from '@widgets/chat/ui/ChatInput.vue'
|
import ChatInput from '@widgets/chat/ui/ChatInput.vue'
|
||||||
import ChatMessages from '@widgets/chat/ui/ChatMessages.vue'
|
import ChatMessages from '@widgets/chat/ui/ChatMessages.vue'
|
||||||
|
|
||||||
|
const { loadMoreMessages } = useChatHistory()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@@ -1,16 +1,138 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="chat-input">
|
<div class="chat-input" v-bind="fileUploadApi.getRootProps()">
|
||||||
<ChadInput placeholder="Write a message..." />
|
<div class="chat-input__input-row">
|
||||||
|
<ChadButton
|
||||||
|
class="chat-input__add-attachment"
|
||||||
|
type="secondary"
|
||||||
|
:icon="Plus"
|
||||||
|
@click="fileUploadApi.openFilePicker()"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ChadInput
|
||||||
|
v-model="message.text"
|
||||||
|
class="chat-input__input"
|
||||||
|
placeholder="Write a message..."
|
||||||
|
@keydown.enter="sendMessage()"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ChadButton
|
||||||
|
class="chat-input__send"
|
||||||
|
@click="sendMessage()"
|
||||||
|
>
|
||||||
|
Send
|
||||||
|
</ChadButton>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul v-if="fileUploadApi.acceptedFiles.length > 0" class="chat-input__attachments" v-bind="fileUploadApi.getItemGroupProps()">
|
||||||
|
<li
|
||||||
|
v-for="file in fileUploadApi.acceptedFiles"
|
||||||
|
:key="file.name"
|
||||||
|
class="chat-input__attachment"
|
||||||
|
v-bind="fileUploadApi.getItemProps({ file })"
|
||||||
|
@click="fileUploadApi.deleteFile(file)"
|
||||||
|
>
|
||||||
|
{{ file.name }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<input v-bind="fileUploadApi.getHiddenInputProps()">
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { NewChatMessagePayload } from '@shared/api/generated-chad-api.ts'
|
||||||
|
import { Plus } from '@lucide/vue'
|
||||||
|
import ChadButton from '@shared/components/ui/Button.vue'
|
||||||
import ChadInput from '@shared/components/ui/Input.vue'
|
import ChadInput from '@shared/components/ui/Input.vue'
|
||||||
|
import { useEventListener } from '@vueuse/core'
|
||||||
|
import { useChat } from '@widgets/chat/composables/use-chat.ts'
|
||||||
|
import * as fileUpload from '@zag-js/file-upload'
|
||||||
|
import { normalizeProps, useMachine } from '@zag-js/vue'
|
||||||
|
import { computed, reactive, useId } from 'vue'
|
||||||
|
|
||||||
|
const id = useId()
|
||||||
|
const chat = useChat()
|
||||||
|
|
||||||
|
const message: NewChatMessagePayload = reactive({
|
||||||
|
text: '',
|
||||||
|
attachments: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
const service = useMachine(fileUpload.machine, {
|
||||||
|
id,
|
||||||
|
maxFiles: 10,
|
||||||
|
maxFileSize: 100 * 1024 * 1024,
|
||||||
|
name: 'chat-input',
|
||||||
|
capture: 'environment',
|
||||||
|
allowDrop: false,
|
||||||
|
onFileAccept: (details) => {
|
||||||
|
console.log('onFileAccept', details)
|
||||||
|
},
|
||||||
|
// transformFiles: async (files) => {
|
||||||
|
// console.log(files)
|
||||||
|
//
|
||||||
|
// return files
|
||||||
|
// },
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
const fileUploadApi = computed(() => fileUpload.connect(service, normalizeProps))
|
||||||
|
|
||||||
|
useEventListener(document, 'paste', (event) => {
|
||||||
|
fileUploadApi.value.setClipboardFiles(event.clipboardData)
|
||||||
|
})
|
||||||
|
|
||||||
|
function sendMessage() {
|
||||||
|
chat.sendMessage(message)
|
||||||
|
|
||||||
|
reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset() {
|
||||||
|
message.text = ''
|
||||||
|
message.attachments = []
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.chat-input {
|
.chat-input {
|
||||||
padding: var(--space-3) var(--space-6);
|
padding: var(--space-3) var(--space-6);
|
||||||
border-top: var(--border-w) solid var(--ink);
|
border-top: var(--border-w) solid var(--ink);
|
||||||
|
|
||||||
|
&__input-row {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__add-attachment {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: calc(var(--border-w) * -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__input {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__send {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-left: calc(var(--border-w) * -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__attachments {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: var(--space-2);
|
||||||
|
padding: var(--space-2);
|
||||||
|
margin-top: var(--space-2);
|
||||||
|
outline: var(--border-w) dashed var(--ink);
|
||||||
|
outline-offset: calc(var(--border-w) * -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__attachment {
|
||||||
|
padding: var(--space-1) var(--space-2);
|
||||||
|
background-color: var(--grey-1);
|
||||||
|
outline: 1px solid var(--ink);
|
||||||
|
outline-offset: -1px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { MessageGroup } from '@widgets/chat/composables/use-chat.ts'
|
import type { MessageGroup } from '@widgets/chat/composables/use-chat-history.js'
|
||||||
import ChadAvatar from '@shared/components/ui/Avatar.vue'
|
import ChadAvatar from '@shared/components/ui/Avatar.vue'
|
||||||
import { useAuth } from '@shared/composables/use-auth.ts'
|
import { useAuth } from '@shared/composables/use-auth.ts'
|
||||||
import ChatMessage from '@widgets/chat/ui/ChatMessage.vue'
|
import ChatMessage from '@widgets/chat/ui/ChatMessage.vue'
|
||||||
|
|||||||
@@ -10,26 +10,33 @@
|
|||||||
|
|
||||||
<ChadSpinner v-if="isFetching" class="chat-messages__spinner" />
|
<ChadSpinner v-if="isFetching" class="chat-messages__spinner" />
|
||||||
|
|
||||||
<button v-if="!arrivedState.start" class="chat-messages__scroll-to-bottom" @click="scrollToStart()">
|
<div v-if="!arrivedState.start" class="chat-messages__floating-actions">
|
||||||
<ArrowDown />
|
<div v-if="hasUnreadMessages" class="chat-messages__has-unread-messages">
|
||||||
</button>
|
New messages
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ChadToBottom
|
||||||
|
class="chat-messages__scroll-to-bottom"
|
||||||
|
@click="scrollToStart()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ArrowDown } from '@lucide/vue'
|
|
||||||
import ChadSpinner from '@shared/components/ui/Spinner.vue'
|
import ChadSpinner from '@shared/components/ui/Spinner.vue'
|
||||||
|
import ChadToBottom from '@shared/components/ui/ToBottom.vue'
|
||||||
import { useEventBus } from '@shared/composables/use-event-bus.ts'
|
import { useEventBus } from '@shared/composables/use-event-bus.ts'
|
||||||
import { useChatScroll } from '@widgets/chat/composables/use-chat-scroll.ts'
|
import { useChatScroll } from '@widgets/chat/composables/use-chat-scroll.ts'
|
||||||
import ChatMessageGroup from '@widgets/chat/ui/ChatMessageGroup.vue'
|
import ChatMessageGroup from '@widgets/chat/ui/ChatMessageGroup.vue'
|
||||||
import { onUnmounted, ref, useTemplateRef, watch } from 'vue'
|
import { onUnmounted, ref, useTemplateRef, watch } from 'vue'
|
||||||
import { useChat } from '../composables/use-chat'
|
import { useChatHistory } from '../composables/use-chat-history'
|
||||||
|
|
||||||
const eventBus = useEventBus()
|
const eventBus = useEventBus()
|
||||||
|
|
||||||
const scrollRef = useTemplateRef('scroll')
|
const scrollRef = useTemplateRef('scroll')
|
||||||
|
|
||||||
const { messageGroups, hasMoreMessages, fetchNextPage, isFetching } = useChat()
|
const { messageGroups, hasMoreMessages, loadMoreMessages, isFetching } = useChatHistory()
|
||||||
|
|
||||||
const hasUnreadMessages = ref(false)
|
const hasUnreadMessages = ref(false)
|
||||||
|
|
||||||
@@ -43,7 +50,7 @@ watch(() => arrivedState.end, (arrived) => {
|
|||||||
return
|
return
|
||||||
|
|
||||||
if (hasMoreMessages.value) {
|
if (hasMoreMessages.value) {
|
||||||
fetchNextPage()
|
loadMoreMessages()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -81,31 +88,32 @@ function onNewChatMessage() {
|
|||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-y: overlay;
|
overflow-y: overlay;
|
||||||
|
overflow-anchor: none;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__scroll-to-bottom {
|
&__floating-actions {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
cursor: pointer;
|
display: inline-flex;
|
||||||
width: 40px;
|
align-items: flex-end;
|
||||||
aspect-ratio: 1;
|
gap: var(--space-2);
|
||||||
text-align: center;
|
|
||||||
line-height: 40px;
|
|
||||||
bottom: var(--space-4);
|
bottom: var(--space-4);
|
||||||
right: var(--space-4);
|
right: var(--space-4);
|
||||||
outline: var(--border-w) solid var(--ink);
|
pointer-events: none;
|
||||||
outline-offset: calc(var(--border-w) * -1);
|
|
||||||
border: none;
|
|
||||||
background-color: var(--grey-1);
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus,
|
|
||||||
&:active {
|
|
||||||
background-color: var(--grey-2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__has-unread-messages {
|
||||||
|
@include font-micro;
|
||||||
|
|
||||||
|
background-color: var(--yellow);
|
||||||
|
padding: var(--space-1) var(--space-2);
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__scroll-to-bottom {
|
||||||
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1200,112 +1200,125 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-14.3.0.tgz#a3e7e6391f9ed7f363cbb28c32c4a278efaacbd0"
|
resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-14.3.0.tgz#a3e7e6391f9ed7f363cbb28c32c4a278efaacbd0"
|
||||||
integrity sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==
|
integrity sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==
|
||||||
|
|
||||||
"@zag-js/anatomy@1.40.0":
|
"@zag-js/anatomy@1.41.0":
|
||||||
version "1.40.0"
|
version "1.41.0"
|
||||||
resolved "https://registry.yarnpkg.com/@zag-js/anatomy/-/anatomy-1.40.0.tgz#df087ed1a287d14bc99eca1e4a580fb68db04c5a"
|
resolved "https://registry.yarnpkg.com/@zag-js/anatomy/-/anatomy-1.41.0.tgz#af0d132a4470dcea93f857b1a12b6cc9c6d3b847"
|
||||||
integrity sha512-oiB4uAaV//L38JluLVPtOHO3xvqambrfrXVOoq4kmNrBv1LLlCmFvrXA2HOR9lakn4ExK27XSUrKhUN7YlKjfQ==
|
integrity sha512-0M/bWcYbWgM09HEhfU0GvpKgPt3I4vakjr21FHcjTNK2vYRC1oz2GHc/y9ArJa4jXe0piTiPbACzMK1/z2ukRw==
|
||||||
|
|
||||||
"@zag-js/avatar@^1.40.0":
|
"@zag-js/avatar@^1.40.0":
|
||||||
version "1.40.0"
|
version "1.41.0"
|
||||||
resolved "https://registry.yarnpkg.com/@zag-js/avatar/-/avatar-1.40.0.tgz#6d412fe7f7726f7924fcb6a46da397650f07987c"
|
resolved "https://registry.yarnpkg.com/@zag-js/avatar/-/avatar-1.41.0.tgz#2505e32cba85d815845c7f5c07431e57a1b60d8a"
|
||||||
integrity sha512-DayZDsNXbipT+1GUkX29tVhO4hZonDnidwE3SjEQv9Ic9vCdnwP95+B0FPEuaca03F5ZXFqVXjnPmRVbRMyDYQ==
|
integrity sha512-vsXNCyb7mDSSYELQ4MDwvtKKu8JhdF9FiC2bwbWxD8ubUUQscajPJ6Y6fLTIpxEx8h4B5St66RRDNuuirVRrXw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@zag-js/anatomy" "1.40.0"
|
"@zag-js/anatomy" "1.41.0"
|
||||||
"@zag-js/core" "1.40.0"
|
"@zag-js/core" "1.41.0"
|
||||||
"@zag-js/dom-query" "1.40.0"
|
"@zag-js/dom-query" "1.41.0"
|
||||||
"@zag-js/types" "1.40.0"
|
"@zag-js/types" "1.41.0"
|
||||||
"@zag-js/utils" "1.40.0"
|
"@zag-js/utils" "1.41.0"
|
||||||
|
|
||||||
"@zag-js/collapsible@^1.40.0":
|
"@zag-js/collapsible@^1.40.0":
|
||||||
version "1.40.0"
|
version "1.41.0"
|
||||||
resolved "https://registry.yarnpkg.com/@zag-js/collapsible/-/collapsible-1.40.0.tgz#a8cf143963df8be1421ec5b3f3cbd76581c36f62"
|
resolved "https://registry.yarnpkg.com/@zag-js/collapsible/-/collapsible-1.41.0.tgz#b9c0be046fb5df4b0915ed9522c1f1f037605878"
|
||||||
integrity sha512-xDLY4j9D3gdoTirkwzMaCtelfCjnMhBzPyY6c/mh4oPvD3RB6dr3V3kI80i3yxHaUUeDCIUm/XAxK0InPsRBug==
|
integrity sha512-Zdo1RiwxzjuM3ZElpgSxsHAej3dRnCP6Jti0rIyM+EEE3CvKeFpprJFh0sjE7TW5PEuhey69Q9QhMjJbHFfNpg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@zag-js/anatomy" "1.40.0"
|
"@zag-js/anatomy" "1.41.0"
|
||||||
"@zag-js/core" "1.40.0"
|
"@zag-js/core" "1.41.0"
|
||||||
"@zag-js/dom-query" "1.40.0"
|
"@zag-js/dom-query" "1.41.0"
|
||||||
"@zag-js/types" "1.40.0"
|
"@zag-js/types" "1.41.0"
|
||||||
"@zag-js/utils" "1.40.0"
|
"@zag-js/utils" "1.41.0"
|
||||||
|
|
||||||
"@zag-js/core@1.40.0":
|
"@zag-js/core@1.41.0":
|
||||||
version "1.40.0"
|
version "1.41.0"
|
||||||
resolved "https://registry.yarnpkg.com/@zag-js/core/-/core-1.40.0.tgz#0640fdda8611417fb88d5d2df65048dd2bd2b84b"
|
resolved "https://registry.yarnpkg.com/@zag-js/core/-/core-1.41.0.tgz#cba13f582b74ee221aca51686bb4e9b34843443e"
|
||||||
integrity sha512-0YcqCh7TmhSonkbKM/7NWolxlaQgvvXgqedocW9oeRYiDJIpBZyRqnHPoGAS2XwbBPkCnrqSosxSF5yBjhZpgw==
|
integrity sha512-CkX9xjNCTlOLwJNRZs4+Rse+bPVQWaNmfSTGa7m0FRR4XWf66/bx5YTpHNTKKmPL8KWjHCvlvSeN6uHDeSBs/w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@zag-js/dom-query" "1.40.0"
|
"@zag-js/dom-query" "1.41.0"
|
||||||
"@zag-js/utils" "1.40.0"
|
"@zag-js/utils" "1.41.0"
|
||||||
|
|
||||||
"@zag-js/dom-query@1.40.0":
|
"@zag-js/dom-query@1.41.0":
|
||||||
version "1.40.0"
|
version "1.41.0"
|
||||||
resolved "https://registry.yarnpkg.com/@zag-js/dom-query/-/dom-query-1.40.0.tgz#f35d1de3d7050da2b758aee35cb42f9c1332d920"
|
resolved "https://registry.yarnpkg.com/@zag-js/dom-query/-/dom-query-1.41.0.tgz#5f434cf6cb6ccf524f479d4597c7b4f5ab3c561c"
|
||||||
integrity sha512-4J3EO2gHpZ1VZiGLuMlH6G1Tsp4gKB8PPt2yKeNQWYGEXyrHUXrvMhRUzv7Z4/2I1s1tnxlFG4F8ovB3kTpz/Q==
|
integrity sha512-10KVw1sZNKsiGcR9nC+xazn6r2hAijrJFcMJWWmtrXuskezV04/axCaWdEGHkPloddaoADecWwCAsD4+kOmKFg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@zag-js/types" "1.40.0"
|
"@zag-js/types" "1.41.0"
|
||||||
|
|
||||||
"@zag-js/file-utils@^1.40.0":
|
"@zag-js/file-upload@^1.41.0":
|
||||||
version "1.40.0"
|
version "1.41.0"
|
||||||
resolved "https://registry.yarnpkg.com/@zag-js/file-utils/-/file-utils-1.40.0.tgz#65bfea43ff88c3534b79c1d880de9a6fc382fc8a"
|
resolved "https://registry.yarnpkg.com/@zag-js/file-upload/-/file-upload-1.41.0.tgz#6ad2deb4d5edc9db1c46fda6823be3a9d404b625"
|
||||||
integrity sha512-BGny4rafiBQ5TPCBXfzbH7lSyFdnoix7brq/+FllKpDqpWPQz0tIsgSZueF/Z8GPTrAkwMKOFI99P7OVhAhRig==
|
integrity sha512-zIAD1cx3zCa25G/nkHSH+VimU8YWAZYe+qYx+e/DSMUuebvkKRtBLXok4useKtxqLnn1rbX6GU7kLyC1ZSqgRQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@zag-js/i18n-utils" "1.40.0"
|
"@zag-js/anatomy" "1.41.0"
|
||||||
|
"@zag-js/core" "1.41.0"
|
||||||
|
"@zag-js/dom-query" "1.41.0"
|
||||||
|
"@zag-js/file-utils" "1.41.0"
|
||||||
|
"@zag-js/i18n-utils" "1.41.0"
|
||||||
|
"@zag-js/types" "1.41.0"
|
||||||
|
"@zag-js/utils" "1.41.0"
|
||||||
|
|
||||||
"@zag-js/i18n-utils@1.40.0":
|
"@zag-js/file-utils@1.41.0", "@zag-js/file-utils@^1.40.0":
|
||||||
version "1.40.0"
|
version "1.41.0"
|
||||||
resolved "https://registry.yarnpkg.com/@zag-js/i18n-utils/-/i18n-utils-1.40.0.tgz#c85c5e6327715dc3a86fc2d677e15905c3b1f3aa"
|
resolved "https://registry.yarnpkg.com/@zag-js/file-utils/-/file-utils-1.41.0.tgz#1139d15b98db3463cead76bf7bf303428dac8f46"
|
||||||
integrity sha512-8D3ki9V81gMKZvtRfNVoHCBDVYjr+WJLBvdfSv3cdOsVM2/E8//xAfYbYzl5Fdmeny3H71fxBNqOX05GN4K6OA==
|
integrity sha512-ZNdMOFt6+pSB0dl4fbepWPDJX1KUqDxRTIDz78obzpdLdIrQazsRqdGDN3WG71ul6hYDXMuzphEj9HYyRENzaA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@zag-js/dom-query" "1.40.0"
|
"@zag-js/i18n-utils" "1.41.0"
|
||||||
|
|
||||||
|
"@zag-js/i18n-utils@1.41.0":
|
||||||
|
version "1.41.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@zag-js/i18n-utils/-/i18n-utils-1.41.0.tgz#da493ffac2482df38668a99d542d85a568516cc4"
|
||||||
|
integrity sha512-+Ov6MJRSquHSFnUnCAWI/G5Xxaf0d64BsV+vzEFV0JPkLFT/2+ePzTwaVyYa+R55erHuMbpIxK/5PoxiLfEYkg==
|
||||||
|
dependencies:
|
||||||
|
"@zag-js/dom-query" "1.41.0"
|
||||||
|
|
||||||
"@zag-js/password-input@^1.40.0":
|
"@zag-js/password-input@^1.40.0":
|
||||||
version "1.40.0"
|
version "1.41.0"
|
||||||
resolved "https://registry.yarnpkg.com/@zag-js/password-input/-/password-input-1.40.0.tgz#8d70e938ad5646aef8869d967741a58608d0a16f"
|
resolved "https://registry.yarnpkg.com/@zag-js/password-input/-/password-input-1.41.0.tgz#c55b8f15170bb5b7a86169623cc2277ec4788e96"
|
||||||
integrity sha512-mD4tbA4m82oV+0NbJ+P00Q4Gwz+zf1kZEZ3Z48ohICfK/WO1KhCgviY7vu/7bCMnRiD3dbi+nEeym8Kb29wRHw==
|
integrity sha512-glJuzeUJxsBuXiJJ/RSr01mXKoxo6cvLcUbUrNdVGE1pnRMWdEJgVfItpmIZ+TrkUBzf88nru+MBuVeM0OKIAw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@zag-js/anatomy" "1.40.0"
|
"@zag-js/anatomy" "1.41.0"
|
||||||
"@zag-js/core" "1.40.0"
|
"@zag-js/core" "1.41.0"
|
||||||
"@zag-js/dom-query" "1.40.0"
|
"@zag-js/dom-query" "1.41.0"
|
||||||
"@zag-js/types" "1.40.0"
|
"@zag-js/types" "1.41.0"
|
||||||
"@zag-js/utils" "1.40.0"
|
"@zag-js/utils" "1.41.0"
|
||||||
|
|
||||||
"@zag-js/store@1.40.0":
|
"@zag-js/store@1.41.0":
|
||||||
version "1.40.0"
|
version "1.41.0"
|
||||||
resolved "https://registry.yarnpkg.com/@zag-js/store/-/store-1.40.0.tgz#d27ed18e9bd8bf979315ab672d6481b71b482f1d"
|
resolved "https://registry.yarnpkg.com/@zag-js/store/-/store-1.41.0.tgz#97a3ecc1bbb5fe8de51083e4dafaa0d0d3c2d741"
|
||||||
integrity sha512-EmgYIdbNZ4TN4Qht/jugY4UVkaWx69l8P1qiX23U4YwqNLq10tyOJmcXWbvsrprU1dGb24B+xq0WBm/RIjw4WA==
|
integrity sha512-hnXqp1HrpP4pfn86NlI1i9yFo236sjhyMErIA2gxm/6L0FpcP3V/ooVSoQgKE9rTSurpDAmVqg6jBb+DxXzaIQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
proxy-compare "3.0.1"
|
proxy-compare "3.0.1"
|
||||||
|
|
||||||
"@zag-js/toggle@^1.40.0":
|
"@zag-js/toggle@^1.40.0":
|
||||||
version "1.40.0"
|
version "1.41.0"
|
||||||
resolved "https://registry.yarnpkg.com/@zag-js/toggle/-/toggle-1.40.0.tgz#8c2a757e51acca6ebd25385db8fb70217c51269b"
|
resolved "https://registry.yarnpkg.com/@zag-js/toggle/-/toggle-1.41.0.tgz#3245e651fc6f7ae2a2c4f86ae244ae90f3d3b517"
|
||||||
integrity sha512-DW7682lzTP2eDlMvrS7tUX3zAm7ufrrKr7VDiX8BB6oXBRETXrVIxCYNuoIdqjwXebdjAoxaCiUZEreRVucYQg==
|
integrity sha512-x5r12kTBKpAzMaKA9MQDEf1yo7bYByalw3BfRuEWfbclGfWehHKVjbyoM7iQxeUjwvWE0kbB/213AyS1/0eoOQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@zag-js/anatomy" "1.40.0"
|
"@zag-js/anatomy" "1.41.0"
|
||||||
"@zag-js/core" "1.40.0"
|
"@zag-js/core" "1.41.0"
|
||||||
"@zag-js/dom-query" "1.40.0"
|
"@zag-js/dom-query" "1.41.0"
|
||||||
"@zag-js/types" "1.40.0"
|
"@zag-js/types" "1.41.0"
|
||||||
"@zag-js/utils" "1.40.0"
|
"@zag-js/utils" "1.41.0"
|
||||||
|
|
||||||
"@zag-js/types@1.40.0":
|
"@zag-js/types@1.41.0":
|
||||||
version "1.40.0"
|
version "1.41.0"
|
||||||
resolved "https://registry.yarnpkg.com/@zag-js/types/-/types-1.40.0.tgz#6bd98a399d58724e6e81c11f4cbd0bb3501cc6fa"
|
resolved "https://registry.yarnpkg.com/@zag-js/types/-/types-1.41.0.tgz#6bfe6a776a753af2178e256b7c5d1066ebe368be"
|
||||||
integrity sha512-LVvxEyqFv/u9SEe5xdivvG2vYb9cCmbkD+5r6s+IGljpDLaRgv4BYyxEh40ri1ai070tL08ZKmoLfx2/xfvY/A==
|
integrity sha512-CNTzGNjJU1e7VAzucjcjqBzpU7e1EBwRH29hCdyoigB4e4uDb+NrKUBHyAkfBVeNMLhpmXxnQfMDlvYt7K3W1A==
|
||||||
dependencies:
|
dependencies:
|
||||||
csstype "3.2.3"
|
csstype "3.2.3"
|
||||||
|
|
||||||
"@zag-js/utils@1.40.0":
|
"@zag-js/utils@1.41.0":
|
||||||
version "1.40.0"
|
version "1.41.0"
|
||||||
resolved "https://registry.yarnpkg.com/@zag-js/utils/-/utils-1.40.0.tgz#cf590c4b6ac294f74a369e8cda40ca7eec754400"
|
resolved "https://registry.yarnpkg.com/@zag-js/utils/-/utils-1.41.0.tgz#61639369aeadf26f91fe009b4ddce926c5ba607c"
|
||||||
integrity sha512-XUpqDtXfHe7CySjOhLPLj9H8rxbiFUJAGgmBzNdpsGPP4wx12cpOXrpSjRXZ2kMwooMPz/P7RPDBteto8sqhAQ==
|
integrity sha512-WUCIw+W4MYKYfyKad0LLNNqhL58/cRAAAVjLqDch05c1dZ0yhZq3t81jWeYUwiPnprt9V+BtGJEFMnWhdfxsBA==
|
||||||
|
|
||||||
"@zag-js/vue@^1.40.0":
|
"@zag-js/vue@^1.40.0":
|
||||||
version "1.40.0"
|
version "1.41.0"
|
||||||
resolved "https://registry.yarnpkg.com/@zag-js/vue/-/vue-1.40.0.tgz#f5d7f3ff68b6062ecab5611cc846fe39ddf08524"
|
resolved "https://registry.yarnpkg.com/@zag-js/vue/-/vue-1.41.0.tgz#7e5649c1d5e7979493987de66d25d3deda90976e"
|
||||||
integrity sha512-sUkJfuESY42yNnSXszpkz4PCreW0rvEWir1s01zhow1rDi7WCNO1P7Jc9VrS5goVyzqsfInedUX2nzOO7XV5Iw==
|
integrity sha512-K3Fi7oMKpqUqm8lvL7RuWK3c9nyIlokxElEgrhh6MLEWbbmm6mXQ3BBGyWVjl58QWhHEluXvqrI8BVOg12Mpgg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@zag-js/core" "1.40.0"
|
"@zag-js/core" "1.41.0"
|
||||||
"@zag-js/store" "1.40.0"
|
"@zag-js/store" "1.41.0"
|
||||||
"@zag-js/types" "1.40.0"
|
"@zag-js/types" "1.41.0"
|
||||||
"@zag-js/utils" "1.40.0"
|
"@zag-js/utils" "1.41.0"
|
||||||
|
|
||||||
acorn-jsx@^5.3.2:
|
acorn-jsx@^5.3.2:
|
||||||
version "5.3.2"
|
version "5.3.2"
|
||||||
|
|||||||
Reference in New Issue
Block a user