daisy-ui-kit 0.4.4

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 (131) hide show
  1. package/README.md +80 -0
  2. package/components/-utils.ts +41 -0
  3. package/components/.DS_Store +0 -0
  4. package/components/Alert.vue +27 -0
  5. package/components/Artboard.vue +33 -0
  6. package/components/Avatar.vue +85 -0
  7. package/components/AvatarGroup.vue +19 -0
  8. package/components/Badge.vue +45 -0
  9. package/components/BottomNav.vue +27 -0
  10. package/components/Breadcrumbs.vue +7 -0
  11. package/components/Button.config.ts +26 -0
  12. package/components/Button.vue +112 -0
  13. package/components/ButtonGroup.vue +5 -0
  14. package/components/Card.vue +31 -0
  15. package/components/CardActions.vue +16 -0
  16. package/components/CardBody.vue +16 -0
  17. package/components/CardTitle.vue +16 -0
  18. package/components/Carousel.vue +26 -0
  19. package/components/CarouselItem.vue +5 -0
  20. package/components/Checkbox.vue +47 -0
  21. package/components/Code.vue +91 -0
  22. package/components/CodePreview.vue +28 -0
  23. package/components/CodeWrapper.vue +10 -0
  24. package/components/Collapse.vue +33 -0
  25. package/components/CollapseContent.vue +5 -0
  26. package/components/CollapseTitle.vue +5 -0
  27. package/components/Countdown.vue +16 -0
  28. package/components/CountdownTimers.vue +66 -0
  29. package/components/Counter.vue +15 -0
  30. package/components/Crumb.vue +5 -0
  31. package/components/DarkToggle.vue +11 -0
  32. package/components/DemoElement.vue +32 -0
  33. package/components/DemoExample.vue +23 -0
  34. package/components/Divider.vue +25 -0
  35. package/components/Drawer.vue +19 -0
  36. package/components/DrawerLayout.vue +35 -0
  37. package/components/DrawerLayoutContent.vue +11 -0
  38. package/components/Dropdown.vue +30 -0
  39. package/components/DropdownContent.vue +3 -0
  40. package/components/Flex.vue +146 -0
  41. package/components/FlexItem.vue +146 -0
  42. package/components/Footer.vue +25 -0
  43. package/components/FooterTitle.vue +17 -0
  44. package/components/FormControl.vue +5 -0
  45. package/components/Hero.vue +17 -0
  46. package/components/HeroContent.vue +17 -0
  47. package/components/HeroOverlay.vue +5 -0
  48. package/components/Home/AlternatingFeatureSections.vue +217 -0
  49. package/components/Home/CTA.vue +27 -0
  50. package/components/Home/Footer.vue +210 -0
  51. package/components/Home/GradientFeatureSections.vue +98 -0
  52. package/components/Home/Header.vue +174 -0
  53. package/components/Home/Hero.vue +52 -0
  54. package/components/Home/LogoCloud.vue +49 -0
  55. package/components/Home/StatsSection.vue +51 -0
  56. package/components/Home/Testimonial.vue +23 -0
  57. package/components/Indicator.vue +16 -0
  58. package/components/IndicatorItem.vue +37 -0
  59. package/components/InputGroup.vue +33 -0
  60. package/components/Kbd.vue +26 -0
  61. package/components/Label.vue +17 -0
  62. package/components/LabelText.vue +17 -0
  63. package/components/LabelTextAlt.vue +17 -0
  64. package/components/Link.vue +32 -0
  65. package/components/Logo.vue +8 -0
  66. package/components/Mask.config.ts +77 -0
  67. package/components/Mask.vue +15 -0
  68. package/components/Menu.vue +26 -0
  69. package/components/MenuItem.vue +17 -0
  70. package/components/MenuTitle.vue +14 -0
  71. package/components/MobileSidebar.vue +92 -0
  72. package/components/MockupCode.vue +4 -0
  73. package/components/Modal.vue +16 -0
  74. package/components/ModalAction.vue +5 -0
  75. package/components/ModalBox.vue +5 -0
  76. package/components/ModalWrapper.vue +32 -0
  77. package/components/NavButton.vue +22 -0
  78. package/components/Navbar.vue +17 -0
  79. package/components/NavbarCenter.vue +16 -0
  80. package/components/NavbarEnd.vue +16 -0
  81. package/components/NavbarStart.vue +16 -0
  82. package/components/Phone.vue +8 -0
  83. package/components/Progress.vue +44 -0
  84. package/components/Prose.vue +36 -0
  85. package/components/RadialProgress.vue +42 -0
  86. package/components/Radio.vue +63 -0
  87. package/components/RadioGroup.vue +41 -0
  88. package/components/Range.vue +49 -0
  89. package/components/RangeMeasure.vue +71 -0
  90. package/components/RangeMeasureTick.vue +62 -0
  91. package/components/Rating.vue +152 -0
  92. package/components/Select.vue +104 -0
  93. package/components/Sidebar.vue +89 -0
  94. package/components/SidebarMenuSection.vue +35 -0
  95. package/components/SigninForm.vue +47 -0
  96. package/components/Stack.vue +16 -0
  97. package/components/Stat.vue +5 -0
  98. package/components/StatActions.vue +5 -0
  99. package/components/StatDesc.vue +5 -0
  100. package/components/StatFigure.vue +5 -0
  101. package/components/StatTitle.vue +5 -0
  102. package/components/StatValue.vue +5 -0
  103. package/components/Stats.vue +5 -0
  104. package/components/Step.vue +36 -0
  105. package/components/Steps.vue +22 -0
  106. package/components/Swap.vue +60 -0
  107. package/components/Tab.vue +49 -0
  108. package/components/TabContent.vue +28 -0
  109. package/components/Tabs.vue +71 -0
  110. package/components/TabsManager.vue +37 -0
  111. package/components/Text.vue +179 -0
  112. package/components/TextArea.vue +53 -0
  113. package/components/TextInput.vue +64 -0
  114. package/components/Toast.vue +33 -0
  115. package/components/Toggle.vue +48 -0
  116. package/components/Tooltip.vue +49 -0
  117. package/components/UserMenu.vue +62 -0
  118. package/components/Window.vue +5 -0
  119. package/components/fixtures.ts +62 -0
  120. package/components/theme/Builder.vue +284 -0
  121. package/components/theme/Output.vue +70 -0
  122. package/components/theme/Picker.vue +39 -0
  123. package/components/theme/Preview.vue +1684 -0
  124. package/components/theme/Provider.vue +43 -0
  125. package/components/theme/Snooper.vue +41 -0
  126. package/components/theme/Swatch.vue +47 -0
  127. package/components/theme/custom-themes.ts +34 -0
  128. package/components/theme/theme-utils.ts +164 -0
  129. package/components/types.ts +7 -0
  130. package/index.ts +96 -0
  131. package/package.json +55 -0
@@ -0,0 +1,89 @@
1
+ <script setup>
2
+ const docsLinks = [{ label: 'Install', to: '/install' }]
3
+ const actions = [
4
+ { label: 'Button', to: '/daisy-button' },
5
+ { label: 'Dropdown', to: '/daisy-dropdown' },
6
+ { label: 'Modal', to: '/daisy-modal', pendingDocs: true },
7
+ { label: 'Swap', to: '/daisy-swap' },
8
+ ]
9
+ const dataDisplay = [
10
+ { label: 'Alert', to: '/daisy-alert' },
11
+ { label: 'Avatar', to: '/daisy-avatar' },
12
+ { label: 'AvatarGroup', to: '/daisy-avatar-group' },
13
+ { label: 'Badge', to: '/daisy-badge' },
14
+ { label: 'Card', to: '/daisy-card' },
15
+ { label: 'Carousel', to: '/daisy-carousel' },
16
+ { label: 'Collapse', to: '/daisy-collapse' },
17
+ { label: 'Countdown', to: '/daisy-countdown' },
18
+ { label: 'Kbd', to: '/daisy-kbd' },
19
+ { label: 'Progress', to: '/daisy-progress' },
20
+ { label: 'RadialProgress', to: '/daisy-radial-progress' },
21
+ { label: 'Stat', to: '/daisy-stat' },
22
+ { label: 'Table', to: '/daisy-table' },
23
+ { label: 'Text', to: '/daisy-text' },
24
+ { label: 'Tooltip', to: '/daisy-tooltip' },
25
+ { label: 'Prose', to: '/daisy-prose' },
26
+ ]
27
+ const dataInput = [
28
+ { label: 'FormControl', to: '/daisy-form-control' },
29
+ { label: 'Checkbox', to: '/daisy-form-checkbox' },
30
+ { label: 'TextInput', to: '/daisy-form-text-input' },
31
+ { label: 'Radio', to: '/daisy-form-radio' },
32
+ { label: 'RadioGroup', to: '/daisy-form-radio-group' },
33
+ { label: 'Range', to: '/daisy-form-range' },
34
+ { label: 'Rating', to: '/daisy-form-rating' },
35
+ { label: 'Select', to: '/daisy-form-select' },
36
+ { label: 'Textarea', to: '/daisy-form-textarea' },
37
+ { label: 'Toggle', to: '/daisy-form-toggle' },
38
+ ]
39
+ const layout = [
40
+ { label: 'Artboard', to: '/daisy-artboard' },
41
+ { label: 'ButtonGroup', to: '/daisy-button-group' },
42
+ { label: 'Divider', to: '/daisy-divider' },
43
+ { label: 'Drawer', to: '/daisy-drawer' },
44
+ { label: 'Flex', to: '/daisy-flex' },
45
+ { label: 'Footer', to: '/daisy-footer' },
46
+ { label: 'Hero', to: '/daisy-hero' },
47
+ { label: 'Indicator', to: '/daisy-indicator' },
48
+ { label: 'InputGroup', to: '/daisy-input-group' },
49
+ { label: 'Mask', to: '/daisy-mask' },
50
+ { label: 'Stack', to: '/daisy-stack' },
51
+ { label: 'Toast', to: '/daisy-toast' },
52
+ ]
53
+ const navigation = [
54
+ { label: 'Breadcrumbs', to: '/daisy-breadcrumbs' },
55
+ { label: 'BottomNav', to: '/daisy-bottom-nav' },
56
+ { label: 'Link', to: '/daisy-link' },
57
+ { label: 'Menu', to: '/daisy-menu' },
58
+ { label: 'Navbar', to: '/daisy-navbar' },
59
+ { label: 'Pagination', to: '/daisy-pagination' },
60
+ { label: 'Steps', to: '/daisy-steps' },
61
+ { label: 'Tabs', to: '/daisy-tabs' },
62
+ ]
63
+ const mockup = [
64
+ { label: 'Code', to: '/daisy-code' },
65
+ { label: 'Phone', to: '/daisy-phone' },
66
+ { label: 'Window', to: '/daisy-window' },
67
+ ]
68
+ </script>
69
+
70
+ <template>
71
+ <Drawer class="border-r border-r-base-300/30">
72
+ <!-- Sidebar component, swap this element with another sidebar if you like -->
73
+ <div class="relative pt-4 menu w-80 bg-base-100 text-base-content">
74
+ <NuxtLink to="/" class="fixed">
75
+ <Logo class="text-base-content" />
76
+ </NuxtLink>
77
+
78
+ <div class="pb-12 pl-2 mt-12 overflow-y-auto">
79
+ <SidebarMenuSection title="Docs" :links="docsLinks" />
80
+ <SidebarMenuSection title="Actions" :links="actions" />
81
+ <SidebarMenuSection title="Data Display" :links="dataDisplay" />
82
+ <SidebarMenuSection title="Data Input" :links="dataInput" />
83
+ <SidebarMenuSection title="Layout" :links="layout" />
84
+ <SidebarMenuSection title="Navigation" :links="navigation" />
85
+ <SidebarMenuSection title="Mockup" :links="mockup" />
86
+ </div>
87
+ </div>
88
+ </Drawer>
89
+ </template>
@@ -0,0 +1,35 @@
1
+ <script setup lang="ts">
2
+ import FileTextIcon from '~icons/feather/file-text'
3
+
4
+ interface Link {
5
+ label: string
6
+ to: string
7
+ pending: boolean
8
+ pendingDocs: boolean
9
+ }
10
+ defineProps<{
11
+ title: string
12
+ links: Link[]
13
+ }>()
14
+ </script>
15
+
16
+ <template>
17
+ <Menu compact class="p-2 mt-2">
18
+ <MenuTitle class="text-sm">
19
+ {{ title }}
20
+ </MenuTitle>
21
+
22
+ <MenuItem
23
+ v-for="link in links"
24
+ :key="link.label"
25
+ :class="{ 'opacity-30': link.pending }"
26
+ >
27
+ <NuxtLink :to="link.to" exact-active-class="active">
28
+ {{ link.label }}
29
+ <FileTextIcon v-if="link.pendingDocs" class="ml-2" />
30
+ </NuxtLink>
31
+ </MenuItem>
32
+ </Menu>
33
+
34
+ <hr class="opacity-10">
35
+ </template>
@@ -0,0 +1,47 @@
1
+ <script>
2
+ import { LockClosedIcon } from '@heroicons/vue/solid'
3
+
4
+ export default {
5
+ components: {
6
+ LockClosedIcon,
7
+ },
8
+ }
9
+ </script>
10
+
11
+ <template>
12
+ <div class="flex items-center justify-center min-h-full px-4 py-12 sm:px-6 lg:px-8">
13
+ <div class="w-full max-w-md space-y-8">
14
+ <div>
15
+ <img
16
+ class="w-auto h-24 mx-auto invert"
17
+ src="https://avatars.githubusercontent.com/u/85031756"
18
+ alt="Feathers Cloud"
19
+ >
20
+ <h2 class="mt-6 text-3xl font-extrabold text-center text-gray-900">
21
+ Sign in to your account
22
+ </h2>
23
+ </div>
24
+ <div class="mt-8 space-y-6">
25
+ <a
26
+ type="button"
27
+ class="relative flex justify-center w-full px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent rounded-md group hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
28
+ href="/api/auth/login"
29
+ >
30
+ <span class="absolute inset-y-0 left-0 flex items-center pl-3">
31
+ <LockClosedIcon
32
+ class="w-5 h-5 text-indigo-500 group-hover:text-indigo-400"
33
+ aria-hidden="true"
34
+ />
35
+ </span>
36
+ Sign in
37
+ </a>
38
+ <div class="text-center">
39
+ or
40
+ <RouterLink to="/" class="text-blue-500">
41
+ Return to Home
42
+ </RouterLink>
43
+ </div>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ </template>
@@ -0,0 +1,16 @@
1
+ <script setup lang="ts">
2
+ import { defineProps, withDefaults } from 'vue'
3
+
4
+ interface Props {
5
+ is?: string
6
+ }
7
+ withDefaults(defineProps<Props>(), {
8
+ is: 'div',
9
+ })
10
+ </script>
11
+
12
+ <template>
13
+ <component :is="is" class="stack">
14
+ <slot />
15
+ </component>
16
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <div class="stat">
3
+ <slot />
4
+ </div>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <div class="stat-actions">
3
+ <slot />
4
+ </div>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <div class="stat-desc">
3
+ <slot />
4
+ </div>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <div class="stat-figure">
3
+ <slot />
4
+ </div>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <div class="stat-title">
3
+ <slot />
4
+ </div>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <div class="stat-value">
3
+ <slot />
4
+ </div>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <div class="stats">
3
+ <slot />
4
+ </div>
5
+ </template>
@@ -0,0 +1,36 @@
1
+ <script setup lang="ts">
2
+ import { computed, defineProps } from 'vue'
3
+
4
+ const props = defineProps<{
5
+ glyph?: string
6
+
7
+ color?: string
8
+ primary?: boolean
9
+ secondary?: boolean
10
+ accent?: boolean
11
+ neutral?: boolean
12
+ info?: boolean
13
+ success?: boolean
14
+ warning?: boolean
15
+ error?: boolean
16
+ }>()
17
+
18
+ const classes = computed(() => {
19
+ return {
20
+ 'step-primary': props.primary || props.color === 'primary',
21
+ 'step-secondary': props.secondary || props.color === 'secondary',
22
+ 'step-accent': props.accent || props.color === 'accent',
23
+ 'step-neutral': props.neutral || props.color === 'neutral',
24
+ 'step-info': props.info || props.color === 'info',
25
+ 'step-success': props.success || props.color === 'success',
26
+ 'step-warning': props.warning || props.color === 'warning',
27
+ 'step-error': props.error || props.color === 'error',
28
+ }
29
+ })
30
+ </script>
31
+
32
+ <template>
33
+ <li class="step" :class="classes" :data-content="glyph">
34
+ <slot />
35
+ </li>
36
+ </template>
@@ -0,0 +1,22 @@
1
+ <script setup lang="ts">
2
+ import { computed, defineProps } from 'vue'
3
+
4
+ interface Props {
5
+ vertical?: boolean
6
+ horizontal?: boolean
7
+ }
8
+ const props = defineProps<Props>()
9
+
10
+ const classes = computed(() => {
11
+ return {
12
+ 'steps-vertical': props.vertical,
13
+ 'steps-horizontal': props.horizontal,
14
+ }
15
+ })
16
+ </script>
17
+
18
+ <template>
19
+ <ul class="steps" :class="classes">
20
+ <slot />
21
+ </ul>
22
+ </template>
@@ -0,0 +1,60 @@
1
+ <script setup lang="ts">
2
+ import { computed, defineEmits, defineProps, nextTick, ref, watch } from 'vue'
3
+
4
+ interface Props {
5
+ modelValue?: boolean | null
6
+ indeterminate?: boolean
7
+ rotate?: boolean
8
+ flip?: boolean
9
+ }
10
+
11
+ const props = defineProps<Props>()
12
+ const emit = defineEmits(['update:modelValue'])
13
+ const classes = computed(() => {
14
+ return {
15
+ 'swap-rotate': props.rotate,
16
+ 'swap-flip': props.flip,
17
+ }
18
+ })
19
+
20
+ const checkbox = ref(null)
21
+
22
+ // Allow internal or external control
23
+ const isChecked = ref<any>(false)
24
+ watch(isChecked, val => emit('update:modelValue', val))
25
+ watch(
26
+ () => props.modelValue,
27
+ (val) => {
28
+ if (isChecked.value !== val)
29
+ isChecked.value = val
30
+ },
31
+ )
32
+
33
+ // When the indeterminate prop updates, manually update the checkbox element.
34
+ watch(
35
+ () => [props.indeterminate, checkbox.value],
36
+ ([val]) => {
37
+ nextTick(() => {
38
+ if (checkbox.value != null)
39
+ (checkbox.value as any).indeterminate = val
40
+ isChecked.value = null
41
+ })
42
+ },
43
+ { immediate: true },
44
+ )
45
+ </script>
46
+
47
+ <template>
48
+ <label class="swap" :class="classes">
49
+ <input ref="checkbox" v-model="isChecked" type="checkbox">
50
+ <div class="swap-off">
51
+ <slot />
52
+ </div>
53
+ <div class="swap-on">
54
+ <slot name="swap" />
55
+ </div>
56
+ <div v-if="indeterminate" class="swap-indeterminate">
57
+ <slot name="indeterminate" />
58
+ </div>
59
+ </label>
60
+ </template>
@@ -0,0 +1,49 @@
1
+ <script setup lang="ts">
2
+ import { computed, defineProps, inject, withDefaults } from 'vue'
3
+
4
+ interface Props {
5
+ is?: string | Object | Function
6
+ name?: string
7
+ active?: boolean
8
+
9
+ variant?: 'bordered' | 'lifted'
10
+ bordered?: boolean
11
+ lifted?: boolean
12
+
13
+ size?: 'lg' | 'md' | 'sm' | 'xs'
14
+ lg?: boolean
15
+ md?: boolean
16
+ sm?: boolean
17
+ xs?: boolean
18
+ }
19
+ const props = withDefaults(defineProps<Props>(), {
20
+ is: 'a',
21
+ })
22
+
23
+ const manager: any = inject('tabManager')
24
+
25
+ const classes = computed(() => {
26
+ return {
27
+ 'tab-active': props.active || manager.currentTab === props.name,
28
+
29
+ 'tab-lg': props.size === 'lg' || props.lg,
30
+ 'tab-md': props.size === 'md' || props.md,
31
+ 'tab-sm': props.size === 'sm' || props.sm,
32
+ 'tab-xs': props.size === 'xs' || props.xs,
33
+
34
+ 'tab-bordered': props.variant === 'bordered' || props.bordered,
35
+ 'tab-lifted': props.variant === 'lifted' || props.lifted,
36
+ }
37
+ })
38
+ </script>
39
+
40
+ <template>
41
+ <component
42
+ :is="is" class="tab" :class="classes" tabindex="0"
43
+ @click="() => (manager.currentTab = name)"
44
+ @keypress.enter="() => (manager.currentTab = name)"
45
+ >
46
+ <slot v-if="$slots.default" />
47
+ <span v-else>{{ name }}</span>
48
+ </component>
49
+ </template>
@@ -0,0 +1,28 @@
1
+ <script setup lang="ts">
2
+ import { computed, defineProps, inject, withDefaults } from 'vue'
3
+
4
+ interface Props {
5
+ is?: any
6
+ name: string
7
+ }
8
+ const props = withDefaults(defineProps<Props>(), {
9
+ is: 'div',
10
+ })
11
+
12
+ const tabManager: any = inject('tabManager')
13
+
14
+ const isCurrentTab = computed(() => {
15
+ return tabManager.currentTab === props.name
16
+ })
17
+
18
+ if (!tabManager.currentTab) tabManager.currentTab = props.name
19
+
20
+ const existing = tabManager.tabs.find(t => t === props.name)
21
+ if (!existing) tabManager.tabs.push(props.name)
22
+ </script>
23
+
24
+ <template>
25
+ <component :is="is" v-show="isCurrentTab" class="tab-content">
26
+ <slot />
27
+ </component>
28
+ </template>
@@ -0,0 +1,71 @@
1
+ <script setup lang="ts">
2
+ import { computed, defineProps, inject, withDefaults } from 'vue'
3
+ import Tab from './Tab.vue'
4
+
5
+ interface Props {
6
+ is?: string | Object | Function
7
+ tabs: string[]
8
+
9
+ variant?: 'bordered' | 'lifted' | 'boxed' | 'inline-boxed'
10
+ bordered?: boolean
11
+ lifted?: boolean
12
+ boxed?: boolean
13
+ inlineBoxed?: boolean
14
+
15
+ size?: 'lg' | 'md' | 'sm' | 'xs'
16
+ lg?: boolean
17
+ md?: boolean
18
+ sm?: boolean
19
+ xs?: boolean
20
+ }
21
+ const props = withDefaults(defineProps<Props>(), {
22
+ is: 'a',
23
+ tabs: [] as any,
24
+ })
25
+
26
+ const tabManager: any = inject('tabManager')
27
+
28
+ const _variant = computed(() => {
29
+ if (props.bordered || props.variant === 'bordered') return 'bordered'
30
+ if (props.lifted || props.variant === 'lifted') return 'lifted'
31
+ return undefined
32
+ })
33
+ const _size = computed(() => {
34
+ if (props.size) return props.size
35
+ if (props.lg) return 'lg'
36
+ if (props.md) return 'md'
37
+ if (props.sm) return 'sm'
38
+ if (props.xs) return 'xs'
39
+ return 'md'
40
+ })
41
+
42
+ const classes = computed(() => {
43
+ return {
44
+ 'tabs-boxed':
45
+ props.variant === 'boxed'
46
+ || props.variant === 'inline-boxed'
47
+ || props.boxed
48
+ || props.inlineBoxed,
49
+ 'inline-block': props.variant === 'inline-boxed' || props.inlineBoxed,
50
+ }
51
+ })
52
+ </script>
53
+
54
+ <template>
55
+ <div class="tabs" :class="classes">
56
+ <slot v-if="$slots.default" />
57
+ <template v-for="tabName in tabs" v-else :key="tabName">
58
+ <Tab
59
+ :is="is"
60
+ :name="tabName"
61
+ :variant="_variant"
62
+ :size="_size"
63
+ :active="tabManager.currentTab === tabName"
64
+ @click="() => (tabManager.currentTab = tabName)"
65
+ >
66
+ {{ tabName }}
67
+ </Tab>
68
+ </template>
69
+ <div v-if="variant === 'lifted' || lifted" class="flex-1 cursor-default tab tab-lifted" />
70
+ </div>
71
+ </template>
@@ -0,0 +1,37 @@
1
+ <script setup lang="ts">
2
+ import { defineEmits, defineProps, provide, reactive, watch } from 'vue'
3
+
4
+ interface Props {
5
+ tab?: string
6
+ }
7
+ const props = defineProps<Props>()
8
+ const emit = defineEmits(['update:tab'])
9
+
10
+ const manager = reactive({
11
+ currentTab: props.tab,
12
+ tabs: [],
13
+ })
14
+ provide('tabManager', manager)
15
+
16
+ // If the tab changes from outside, update the internal value.
17
+ watch(
18
+ () => props.tab,
19
+ (val) => {
20
+ if (val !== manager.currentTab) manager.currentTab = val
21
+ },
22
+ )
23
+
24
+ // If the internal tab value changes, update the tab
25
+ watch(
26
+ () => manager.currentTab,
27
+ (val) => {
28
+ if (val !== props.tab) emit('update:tab', val)
29
+ },
30
+ )
31
+ </script>
32
+
33
+ <template>
34
+ <div class="tabs-manager">
35
+ <slot />
36
+ </div>
37
+ </template>