Merge branch 'develop' into feat/contacts-redesign

This commit is contained in:
Sivin Varghese
2024-11-20 20:26:27 +05:30
committed by GitHub
19 changed files with 369 additions and 344 deletions
@@ -83,61 +83,55 @@ const inboxIcon = computed(() => {
<template>
<CardLayout layout="row">
<template #header>
<div class="flex flex-col items-start justify-between flex-1 min-w-0 gap-2">
<div class="flex justify-between gap-3 w-fit">
<span
class="text-base font-medium capitalize text-n-slate-12 line-clamp-1"
>
{{ title }}
</span>
<span
class="text-xs font-medium inline-flex items-center h-6 px-2 py-0.5 rounded-md bg-n-alpha-2"
:class="statusTextColor"
>
{{ campaignStatus }}
</span>
</div>
<div
class="flex flex-col items-start justify-between flex-1 min-w-0 gap-2"
>
<div class="flex justify-between gap-3 w-fit">
<span
class="text-base font-medium capitalize text-n-slate-12 line-clamp-1"
>
{{ title }}
</span>
<span
class="text-xs font-medium inline-flex items-center h-6 px-2 py-0.5 rounded-md bg-n-alpha-2"
:class="statusTextColor"
>
{{ campaignStatus }}
</span>
</div>
<div
v-dompurify-html="formatMessage(message)"
class="text-sm text-n-slate-11 line-clamp-1 [&>p]:mb-0 h-6"
/>
<div class="flex items-center w-full h-6 gap-2 overflow-hidden">
<LiveChatCampaignDetails
v-if="isLiveChatType"
:sender="sender"
:inbox-name="inboxName"
:inbox-icon="inboxIcon"
/>
<SMSCampaignDetails
v-else
:inbox-name="inboxName"
:inbox-icon="inboxIcon"
:scheduled-at="scheduledAt"
/>
</div>
</div>
</template>
<template #footer>
<div class="flex items-center justify-end w-20 gap-2">
<Button
v-dompurify-html="formatMessage(message)"
class="text-sm text-n-slate-11 line-clamp-1 [&>p]:mb-0 h-6"
/>
<div class="flex items-center w-full h-6 gap-2 overflow-hidden">
<LiveChatCampaignDetails
v-if="isLiveChatType"
variant="faded"
size="sm"
color="slate"
icon="i-lucide-sliders-vertical"
@click="emit('edit')"
:sender="sender"
:inbox-name="inboxName"
:inbox-icon="inboxIcon"
/>
<Button
variant="faded"
color="ruby"
size="sm"
icon="i-lucide-trash"
@click="emit('delete')"
<SMSCampaignDetails
v-else
:inbox-name="inboxName"
:inbox-icon="inboxIcon"
:scheduled-at="scheduledAt"
/>
</div>
</template>
</div>
<div class="flex items-center justify-end w-20 gap-2">
<Button
v-if="isLiveChatType"
variant="faded"
size="sm"
color="slate"
icon="i-lucide-sliders-vertical"
@click="emit('edit')"
/>
<Button
variant="faded"
color="ruby"
size="sm"
icon="i-lucide-trash"
@click="emit('delete')"
/>
</div>
</CardLayout>
</template>
@@ -63,14 +63,12 @@ defineExpose({ dialogRef });
overflow-y-auto
@confirm="handleSubmit"
>
<template #form>
<LiveChatCampaignForm
ref="liveChatCampaignFormRef"
mode="edit"
:selected-campaign="selectedCampaign"
:show-action-buttons="false"
@submit="handleSubmit"
/>
</template>
<LiveChatCampaignForm
ref="liveChatCampaignFormRef"
mode="edit"
:selected-campaign="selectedCampaign"
:show-action-buttons="false"
@submit="handleSubmit"
/>
</Dialog>
</template>
@@ -15,7 +15,7 @@ const handleClick = () => {
<template>
<div
class="relative flex flex-col w-full shadow outline-1 outline outline-n-container group/cardLayout rounded-2xl bg-n-solid-2"
class="flex flex-col w-full shadow outline-1 outline outline-n-container group/cardLayout rounded-2xl bg-n-solid-2"
>
<div
class="flex w-full gap-3 px-6 py-5"
@@ -24,10 +24,9 @@ const handleClick = () => {
"
@click="handleClick"
>
<slot name="header" />
<slot name="footer" />
<slot />
</div>
<slot name="expanded" />
<slot name="after" />
</div>
</template>
@@ -124,76 +124,72 @@ const handleClick = id => {
<template>
<CardLayout>
<template #header>
<div class="flex justify-between w-full gap-1">
<div class="flex justify-between w-full gap-1">
<span
class="text-base cursor-pointer hover:underline underline-offset-2 hover:text-n-blue-text text-n-slate-12 line-clamp-1"
@click="handleClick(id)"
>
{{ title }}
</span>
<div class="flex items-center gap-2">
<span
class="text-base cursor-pointer hover:underline underline-offset-2 hover:text-n-blue-text text-n-slate-12 line-clamp-1"
@click="handleClick(id)"
class="text-xs font-medium inline-flex items-center h-6 px-2 py-0.5 rounded-md bg-n-alpha-2"
:class="statusTextColor"
>
{{ title }}
{{ statusText }}
</span>
<div class="flex items-center gap-2">
<span
class="text-xs font-medium inline-flex items-center h-6 px-2 py-0.5 rounded-md bg-n-alpha-2"
:class="statusTextColor"
>
{{ statusText }}
</span>
<div
v-on-clickaway="() => toggleDropdown(false)"
class="relative flex items-center group"
>
<Button
icon="i-lucide-ellipsis-vertical"
color="slate"
size="xs"
class="rounded-md group-hover:bg-n-alpha-2"
@click="toggleDropdown()"
/>
<DropdownMenu
v-if="showActionsDropdown"
:menu-items="articleMenuItems"
class="mt-1 ltr:right-0 rtl:left-0 xl:ltr:left-0 xl:rtl:right-0 top-full"
@action="handleArticleAction($event)"
/>
</div>
<div
v-on-clickaway="() => toggleDropdown(false)"
class="relative flex items-center group"
>
<Button
icon="i-lucide-ellipsis-vertical"
color="slate"
size="xs"
class="rounded-md group-hover:bg-n-alpha-2"
@click="toggleDropdown()"
/>
<DropdownMenu
v-if="showActionsDropdown"
:menu-items="articleMenuItems"
class="mt-1 ltr:right-0 rtl:left-0 xl:ltr:left-0 xl:rtl:right-0 top-full"
@action="handleArticleAction($event)"
/>
</div>
</div>
</template>
<template #footer>
<div class="flex items-center justify-between w-full gap-4">
<div class="flex items-center gap-4">
<div class="flex items-center gap-1">
<Avatar
:name="authorName"
:src="authorThumbnailSrc"
:size="16"
rounded-full
/>
<span class="text-sm truncate text-n-slate-11">
{{ authorName || '-' }}
</span>
</div>
<span class="block text-sm whitespace-nowrap text-n-slate-11">
{{ categoryName }}
</div>
<div class="flex items-center justify-between w-full gap-4">
<div class="flex items-center gap-4">
<div class="flex items-center gap-1">
<Avatar
:name="authorName"
:src="authorThumbnailSrc"
:size="16"
rounded-full
/>
<span class="text-sm truncate text-n-slate-11">
{{ authorName || '-' }}
</span>
<div
class="inline-flex items-center gap-1 text-n-slate-11 whitespace-nowrap"
>
<Icon icon="i-lucide-eye" class="size-4" />
<span class="text-sm">
{{
t('HELP_CENTER.ARTICLES_PAGE.ARTICLE_CARD.CARD.VIEWS', {
count: views,
})
}}
</span>
</div>
</div>
<span class="text-sm text-n-slate-11 line-clamp-1">
{{ lastUpdatedAt }}
<span class="block text-sm whitespace-nowrap text-n-slate-11">
{{ categoryName }}
</span>
<div
class="inline-flex items-center gap-1 text-n-slate-11 whitespace-nowrap"
>
<Icon icon="i-lucide-eye" class="size-4" />
<span class="text-sm">
{{
t('HELP_CENTER.ARTICLES_PAGE.ARTICLE_CARD.CARD.VIEWS', {
count: views,
})
}}
</span>
</div>
</div>
</template>
<span class="text-sm text-n-slate-11 line-clamp-1">
{{ lastUpdatedAt }}
</span>
</div>
</CardLayout>
</template>
@@ -79,59 +79,55 @@ const handleAction = ({ action, value }) => {
<template>
<CardLayout>
<template #header>
<div class="flex w-full gap-2">
<div class="flex justify-between w-full gap-2">
<div class="flex items-center justify-start w-full min-w-0 gap-2">
<span
class="text-base truncate cursor-pointer hover:underline underline-offset-2 hover:text-n-blue-text text-n-slate-12"
@click="handleClick(slug)"
>
{{ categoryTitleWithIcon }}
</span>
<span
class="inline-flex items-center justify-center h-6 px-2 py-1 text-xs text-center border rounded-lg bg-n-slate-1 whitespace-nowrap shrink-0 text-n-slate-11 border-n-slate-4"
>
{{
t('HELP_CENTER.CATEGORY_PAGE.CATEGORY_CARD.ARTICLES_COUNT', {
count: articlesCount,
})
}}
</span>
</div>
<div
v-on-clickaway="() => toggleDropdown(false)"
class="relative group"
<div class="flex w-full gap-2">
<div class="flex justify-between w-full gap-2">
<div class="flex items-center justify-start w-full min-w-0 gap-2">
<span
class="text-base truncate cursor-pointer hover:underline underline-offset-2 hover:text-n-blue-text text-n-slate-12"
@click="handleClick(slug)"
>
<Button
icon="i-lucide-ellipsis-vertical"
color="slate"
size="xs"
variant="ghost"
class="rounded-md group-hover:bg-n-alpha-2"
@click="toggleDropdown()"
/>
<DropdownMenu
v-if="showActionsDropdown"
:menu-items="categoryMenuItems"
class="mt-1 ltr:right-0 rtl:left-0 xl:ltr:left-0 xl:rtl:right-0 top-full z-60"
@action="handleAction"
/>
</div>
{{ categoryTitleWithIcon }}
</span>
<span
class="inline-flex items-center justify-center h-6 px-2 py-1 text-xs text-center border rounded-lg bg-n-slate-1 whitespace-nowrap shrink-0 text-n-slate-11 border-n-slate-4"
>
{{
t('HELP_CENTER.CATEGORY_PAGE.CATEGORY_CARD.ARTICLES_COUNT', {
count: articlesCount,
})
}}
</span>
</div>
<div
v-on-clickaway="() => toggleDropdown(false)"
class="relative group"
>
<Button
icon="i-lucide-ellipsis-vertical"
color="slate"
size="xs"
variant="ghost"
class="rounded-md group-hover:bg-n-alpha-2"
@click="toggleDropdown()"
/>
<DropdownMenu
v-if="showActionsDropdown"
:menu-items="categoryMenuItems"
class="mt-1 ltr:right-0 rtl:left-0 xl:ltr:left-0 xl:rtl:right-0 top-full z-60"
@action="handleAction"
/>
</div>
</div>
</template>
<template #footer>
<span
class="text-sm line-clamp-3"
:class="
hasDescription
? 'text-slate-500 dark:text-slate-400'
: 'text-slate-400 dark:text-slate-700'
"
>
{{ description }}
</span>
</template>
</div>
<span
class="text-sm line-clamp-3"
:class="
hasDescription
? 'text-slate-500 dark:text-slate-400'
: 'text-slate-400 dark:text-slate-700'
"
>
{{ description }}
</span>
</CardLayout>
</template>
@@ -53,66 +53,64 @@ const handleAction = ({ action, value }) => {
<template>
<CardLayout>
<template #header>
<div class="flex justify-between gap-2">
<div class="flex items-center justify-start gap-2">
<div class="flex justify-between gap-2">
<div class="flex items-center justify-start gap-2">
<span
class="text-sm font-medium text-slate-900 dark:text-slate-50 line-clamp-1"
>
{{ locale }} ({{ localeCode }})
</span>
<span
v-if="isDefault"
class="bg-n-alpha-2 h-6 inline-flex items-center justify-center rounded-md text-xs border-px border-transparent text-n-blue-text px-2 py-0.5"
>
{{ $t('HELP_CENTER.LOCALES_PAGE.LOCALE_CARD.DEFAULT') }}
</span>
</div>
<div class="flex items-center justify-end gap-4">
<div class="flex items-center gap-4">
<span
class="text-sm font-medium text-slate-900 dark:text-slate-50 line-clamp-1"
class="text-sm text-slate-500 dark:text-slate-400 whitespace-nowrap"
>
{{ locale }} ({{ localeCode }})
{{
$t(
'HELP_CENTER.LOCALES_PAGE.LOCALE_CARD.ARTICLES_COUNT',
articleCount
)
}}
</span>
<div class="w-px h-3 bg-slate-75 dark:bg-slate-800" />
<span
v-if="isDefault"
class="bg-n-alpha-2 h-6 inline-flex items-center justify-center rounded-md text-xs border-px border-transparent text-n-blue-text px-2 py-0.5"
class="text-sm text-slate-500 dark:text-slate-400 whitespace-nowrap"
>
{{ $t('HELP_CENTER.LOCALES_PAGE.LOCALE_CARD.DEFAULT') }}
{{
$t(
'HELP_CENTER.LOCALES_PAGE.LOCALE_CARD.CATEGORIES_COUNT',
categoryCount
)
}}
</span>
</div>
<div class="flex items-center justify-end gap-4">
<div class="flex items-center gap-4">
<span
class="text-sm text-slate-500 dark:text-slate-400 whitespace-nowrap"
>
{{
$t(
'HELP_CENTER.LOCALES_PAGE.LOCALE_CARD.ARTICLES_COUNT',
articleCount
)
}}
</span>
<div class="w-px h-3 bg-slate-75 dark:bg-slate-800" />
<span
class="text-sm text-slate-500 dark:text-slate-400 whitespace-nowrap"
>
{{
$t(
'HELP_CENTER.LOCALES_PAGE.LOCALE_CARD.CATEGORIES_COUNT',
categoryCount
)
}}
</span>
</div>
<div
v-on-clickaway="() => toggleDropdown(false)"
class="relative group"
>
<Button
icon="i-lucide-ellipsis-vertical"
color="slate"
size="xs"
class="rounded-md group-hover:bg-n-alpha-2"
@click="toggleDropdown()"
/>
<div
v-on-clickaway="() => toggleDropdown(false)"
class="relative group"
>
<Button
icon="i-lucide-ellipsis-vertical"
color="slate"
size="xs"
class="rounded-md group-hover:bg-n-alpha-2"
@click="toggleDropdown()"
/>
<DropdownMenu
v-if="showDropdownMenu"
:menu-items="localeMenuItems"
class="ltr:right-0 rtl:left-0 mt-1 xl:ltr:left-0 xl:rtl:right-0 top-full z-60 min-w-[150px]"
@action="handleAction"
/>
</div>
<DropdownMenu
v-if="showDropdownMenu"
:menu-items="localeMenuItems"
class="ltr:right-0 rtl:left-0 mt-1 xl:ltr:left-0 xl:rtl:right-0 top-full z-60 min-w-[150px]"
@action="handleAction"
/>
</div>
</div>
</template>
</div>
</CardLayout>
</template>
@@ -97,16 +97,14 @@ defineExpose({ dialogRef });
:disable-confirm-button="isUpdatingCategory || isInvalidForm"
@confirm="onUpdateCategory"
>
<template #form>
<CategoryForm
ref="categoryFormRef"
mode="edit"
:selected-category="selectedCategory"
:active-locale-code="activeLocaleCode"
:portal-name="route.params.portalSlug"
:active-locale-name="activeLocaleName"
:show-action-buttons="false"
/>
</template>
<CategoryForm
ref="categoryFormRef"
mode="edit"
:selected-category="selectedCategory"
:active-locale-code="activeLocaleCode"
:portal-name="route.params.portalSlug"
:active-locale-name="activeLocaleName"
:show-action-buttons="false"
/>
</Dialog>
</template>
@@ -85,17 +85,15 @@ defineExpose({ dialogRef });
:description="t('HELP_CENTER.LOCALES_PAGE.ADD_LOCALE_DIALOG.DESCRIPTION')"
@confirm="onCreate"
>
<template #form>
<div class="flex flex-col gap-6">
<ComboBox
v-model="selectedLocale"
:options="locales"
:placeholder="
t('HELP_CENTER.LOCALES_PAGE.ADD_LOCALE_DIALOG.COMBOBOX.PLACEHOLDER')
"
class="[&>div>button]:!border-n-slate-5 [&>div>button]:dark:!border-n-slate-5"
/>
</div>
</template>
<div class="flex flex-col gap-6">
<ComboBox
v-model="selectedLocale"
:options="locales"
:placeholder="
t('HELP_CENTER.LOCALES_PAGE.ADD_LOCALE_DIALOG.COMBOBOX.PLACEHOLDER')
"
class="[&>div>button]:!border-n-slate-5 [&>div>button]:dark:!border-n-slate-5"
/>
</div>
</Dialog>
</template>
@@ -55,20 +55,18 @@ defineExpose({ dialogRef });
"
@confirm="handleDialogConfirm"
>
<template #form>
<Input
v-model="formState.customDomain"
:label="
t(
'HELP_CENTER.PORTAL_SETTINGS.CONFIGURATION_FORM.CUSTOM_DOMAIN.DIALOG.LABEL'
)
"
:placeholder="
t(
'HELP_CENTER.PORTAL_SETTINGS.CONFIGURATION_FORM.CUSTOM_DOMAIN.DIALOG.PLACEHOLDER'
)
"
/>
</template>
<Input
v-model="formState.customDomain"
:label="
t(
'HELP_CENTER.PORTAL_SETTINGS.CONFIGURATION_FORM.CUSTOM_DOMAIN.DIALOG.LABEL'
)
"
:placeholder="
t(
'HELP_CENTER.PORTAL_SETTINGS.CONFIGURATION_FORM.CUSTOM_DOMAIN.DIALOG.PLACEHOLDER'
)
"
/>
</Dialog>
</template>
@@ -59,21 +59,20 @@ defineExpose({ dialogRef });
}}
</p>
</template>
<template #form>
<div class="flex flex-col gap-6">
<span
class="h-10 px-3 py-2.5 text-sm select-none bg-transparent border rounded-lg text-n-slate-11 border-n-strong"
>
{{ subdomainCNAME }}
</span>
<p class="text-sm text-n-slate-12">
{{
t(
'HELP_CENTER.PORTAL_SETTINGS.CONFIGURATION_FORM.CUSTOM_DOMAIN.DNS_CONFIGURATION_DIALOG.HELP_TEXT'
)
}}
</p>
</div>
</template>
<div class="flex flex-col gap-6">
<span
class="h-10 px-3 py-2.5 text-sm select-none bg-transparent border rounded-lg text-n-slate-11 border-n-strong"
>
{{ subdomainCNAME }}
</span>
<p class="text-sm text-n-slate-12">
{{
t(
'HELP_CENTER.PORTAL_SETTINGS.CONFIGURATION_FORM.CUSTOM_DOMAIN.DNS_CONFIGURATION_DIALOG.HELP_TEXT'
)
}}
</p>
</div>
</Dialog>
</template>
@@ -120,29 +120,27 @@ defineExpose({ dialogRef });
:is-loading="isCreatingPortal"
@confirm="handleDialogConfirm"
>
<template #form>
<div class="flex flex-col gap-6">
<Input
id="portal-name"
v-model="state.name"
type="text"
:placeholder="t('HELP_CENTER.CREATE_PORTAL_DIALOG.NAME.PLACEHOLDER')"
:label="t('HELP_CENTER.CREATE_PORTAL_DIALOG.NAME.LABEL')"
:message-type="nameError ? 'error' : 'info'"
:message="
nameError || t('HELP_CENTER.CREATE_PORTAL_DIALOG.NAME.MESSAGE')
"
/>
<Input
id="portal-slug"
v-model="state.slug"
type="text"
:placeholder="t('HELP_CENTER.CREATE_PORTAL_DIALOG.SLUG.PLACEHOLDER')"
:label="t('HELP_CENTER.CREATE_PORTAL_DIALOG.SLUG.LABEL')"
:message-type="slugError ? 'error' : 'info'"
:message="slugError || buildPortalURL(state.slug)"
/>
</div>
</template>
<div class="flex flex-col gap-6">
<Input
id="portal-name"
v-model="state.name"
type="text"
:placeholder="t('HELP_CENTER.CREATE_PORTAL_DIALOG.NAME.PLACEHOLDER')"
:label="t('HELP_CENTER.CREATE_PORTAL_DIALOG.NAME.LABEL')"
:message-type="nameError ? 'error' : 'info'"
:message="
nameError || t('HELP_CENTER.CREATE_PORTAL_DIALOG.NAME.MESSAGE')
"
/>
<Input
id="portal-slug"
v-model="state.slug"
type="text"
:placeholder="t('HELP_CENTER.CREATE_PORTAL_DIALOG.SLUG.PLACEHOLDER')"
:label="t('HELP_CENTER.CREATE_PORTAL_DIALOG.SLUG.LABEL')"
:message-type="slugError ? 'error' : 'info'"
:message="slugError || buildPortalURL(state.slug)"
/>
</div>
</Dialog>
</template>
@@ -118,13 +118,12 @@ watch(
<ComboBoxDropdown
ref="dropdownRef"
v-model:search-value="search"
:open="open"
:options="filteredOptions"
:search-value="search"
:search-placeholder="searchPlaceholder"
:empty-state="emptyState"
:selected-values="selectedValue"
@update:search-value="search = $event"
@search="emit('search', $event)"
@select="selectOption"
/>
@@ -11,10 +11,6 @@ const props = defineProps({
type: Array,
required: true,
},
searchValue: {
type: String,
required: true,
},
searchPlaceholder: {
type: String,
default: '',
@@ -33,10 +29,15 @@ const props = defineProps({
},
});
const emit = defineEmits(['update:searchValue', 'select', 'search']);
const emit = defineEmits(['select', 'search']);
const { t } = useI18n();
const searchValue = defineModel('searchValue', {
type: String,
default: '',
});
const searchInput = ref(null);
const isSelected = option => {
@@ -47,7 +48,7 @@ const isSelected = option => {
};
const onInputSearch = event => {
emit('update:searchValue', event.target.value);
searchValue.value = event.target.value;
emit('search', event.target.value);
};
@@ -7,6 +7,7 @@ import Input from 'dashboard/components-next/input/Input.vue';
const alertDialog = ref(null);
const editDialog = ref(null);
const confirmDialog = ref(null);
const confirmDialogWithCustomFooter = ref(null);
const openAlertDialog = () => {
alertDialog.value.open();
@@ -17,6 +18,9 @@ const openEditDialog = () => {
const openConfirmDialog = () => {
confirmDialog.value.open();
};
const openConfirmDialogWithCustomFooter = () => {
confirmDialogWithCustomFooter.value.open();
};
// eslint-disable-next-line no-unused-vars
const onConfirm = dialog => {};
@@ -44,24 +48,22 @@ const onConfirm = dialog => {};
confirm-button-label="Save"
@confirm="onConfirm()"
>
<template #form>
<div class="flex flex-col gap-6">
<Input
id="portal-name"
type="text"
placeholder="User Guide | Chatwoot"
label="Name"
message="This will be the name of your public facing portal"
/>
<Input
id="portal-slug"
type="text"
placeholder="user-guide"
label="Slug"
message="app.chatwoot.com/hc/my-portal/en-US/categories/my-slug"
/>
</div>
</template>
<div class="flex flex-col gap-6">
<Input
id="portal-name"
type="text"
placeholder="User Guide | Chatwoot"
label="Name"
message="This will be the name of your public facing portal"
/>
<Input
id="portal-slug"
type="text"
placeholder="user-guide"
label="Slug"
message="app.chatwoot.com/hc/my-portal/en-US/categories/my-slug"
/>
</div>
</Dialog>
</Variant>
@@ -77,5 +79,21 @@ const onConfirm = dialog => {};
@confirm="onConfirm()"
/>
</Variant>
<Variant title="With custom footer">
<Button
label="Open Confirm Dialog with custom footer"
@click="openConfirmDialogWithCustomFooter"
/>
<Dialog
ref="confirmDialogWithCustomFooter"
title="Confirm Action"
description="Are you sure you want to perform this action?"
>
<template #footer>
<Button label="Custom Button" @click="onConfirm()" />
</template>
</Dialog>
</Variant>
</Story>
</template>
@@ -1,12 +1,12 @@
<script setup>
import { ref } from 'vue';
import { ref, computed } from 'vue';
import { OnClickOutside } from '@vueuse/components';
import { useI18n } from 'vue-i18n';
import { useMapGetter } from 'dashboard/composables/store.js';
import Button from 'dashboard/components-next/button/Button.vue';
defineProps({
const props = defineProps({
type: {
type: String,
default: 'edit',
@@ -48,9 +48,10 @@ defineProps({
type: Boolean,
default: false,
},
maxWidth: {
width: {
type: String,
default: 'max-w-lg',
default: 'lg',
validator: value => ['3xl', '2xl', 'xl', 'lg', 'md', 'sm'].includes(value),
},
});
@@ -63,6 +64,19 @@ const isRTL = useMapGetter('accounts/isRTL');
const dialogRef = ref(null);
const dialogContentRef = ref(null);
const maxWidthClass = computed(() => {
const classesMap = {
'3xl': 'max-w-3xl',
'2xl': 'max-w-2xl',
xl: 'max-w-xl',
lg: 'max-w-lg',
md: 'max-w-md',
sm: 'max-w-sm',
};
return classesMap[props.width] ?? 'max-w-md';
});
const open = () => {
dialogRef.value?.showModal();
};
@@ -83,7 +97,7 @@ defineExpose({ open, close });
ref="dialogRef"
class="w-full transition-all duration-300 ease-in-out shadow-xl rounded-xl"
:class="[
maxWidth,
maxWidthClass,
overflowYAuto ? 'overflow-y-auto' : 'overflow-visible',
]"
:dir="isRTL ? 'rtl' : 'ltr'"
@@ -105,9 +119,8 @@ defineExpose({ open, close });
</p>
</slot>
</div>
<slot name="form">
<!-- Form content will be injected here -->
</slot>
<slot />
<!-- Dialog content will be injected here -->
<slot name="footer">
<div class="flex items-center justify-between w-full gap-3">
<Button
@@ -51,5 +51,19 @@ const handleAction = () => {
/>
</div>
</Variant>
<Variant title="With search">
<div class="p-4 bg-white h-72 dark:bg-slate-900">
<DropdownMenu
:menu-items="[
{ label: 'Custom 1', action: 'custom1', icon: 'file-upload' },
{ label: 'Custom 2', action: 'custom2', icon: 'document' },
{ label: 'Danger', action: 'delete', icon: 'delete' },
]"
show-search
@action="handleAction"
/>
</div>
</Variant>
</Story>
</template>
@@ -46,6 +46,13 @@ const handleClickOutside = () => {
}
};
const handleKeydown = event => {
if (event.key === ',') {
event.preventDefault();
addTag();
}
};
watch(
() => props.modelValue,
newValue => {
@@ -81,6 +88,7 @@ watch(
:placeholder="placeholder"
custom-input-class="flex-grow"
@enter-press="addTag"
@keydown="handleKeydown"
/>
</div>
</OnClickOutside>