-
+
\ No newline at end of file
+
+provide(TAB_STYLE_INJECTION_KEY, props.variant)
+
+const slots = useSlots()
+const defaultSlot = slots.default
+
+const tabsChildren = computed(() => {
+ return defaultSlot
+ ? flatten(defaultSlot()).filter((v) => {
+ return (v.type as { __FLOWBITE_TAB__?: true }).__FLOWBITE_TAB__
+ })
+ : []
+})
+
+const modelValueRef = computed({
+ get: () => props.modelValue,
+ set: (value: string) => emit('update:modelValue', value),
+})
+
+const onActivate = (value: string) => {
+ modelValueRef.value = value
+}
+
+provide(TAB_ACTIVATE_INJECTION_KEY, onActivate)
+
diff --git a/src/components/Tabs/components/Tab/Tab.vue b/src/components/Tabs/components/Tab/Tab.vue
index 38597d5..c3b7845 100644
--- a/src/components/Tabs/components/Tab/Tab.vue
+++ b/src/components/Tabs/components/Tab/Tab.vue
@@ -1,28 +1,27 @@
+
\ No newline at end of file
diff --git a/src/components/Tabs/components/Tab/useTabClasses.ts b/src/components/Tabs/components/Tab/useTabClasses.ts
deleted file mode 100644
index e69de29..0000000
diff --git a/src/components/Tabs/components/TabPane/TabPane.vue b/src/components/Tabs/components/TabPane/TabPane.vue
new file mode 100644
index 0000000..f762cc5
--- /dev/null
+++ b/src/components/Tabs/components/TabPane/TabPane.vue
@@ -0,0 +1,53 @@
+
+
+
+ {{ title }}
+
+
+
+
\ No newline at end of file
diff --git a/src/components/Tabs/components/TabPane/useTabClasses.ts b/src/components/Tabs/components/TabPane/useTabClasses.ts
new file mode 100644
index 0000000..204e6cf
--- /dev/null
+++ b/src/components/Tabs/components/TabPane/useTabClasses.ts
@@ -0,0 +1,48 @@
+import type { Ref } from 'vue'
+import { computed } from 'vue'
+import type { TabsVariant } from '../../Tabs.vue'
+
+export type TabClassMap = { disabled: string, default: string, active: string }
+
+export type UseTabClassesProps = {
+ variant?: TabsVariant
+ active: Ref
+ disabled: Ref
+}
+
+const defaultTabClasses: TabClassMap = {
+ default: 'cursor-pointer inline-block p-4 rounded-t-lg hover:text-gray-600 hover:bg-gray-50 dark:hover:bg-gray-800 dark:hover:text-gray-300',
+ active: 'cursor-pointer inline-block p-4 text-blue-600 bg-gray-100 rounded-t-lg active dark:bg-gray-800 dark:text-blue-500',
+ disabled: 'inline-block p-4 text-gray-400 rounded-t-lg cursor-not-allowed dark:text-gray-500',
+}
+const underlineTabClasses: TabClassMap = {
+ default: 'cursor-pointer inline-block p-4 rounded-t-lg border-b-2 border-transparent hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300',
+ active: 'cursor-pointer inline-block p-4 text-blue-600 rounded-t-lg border-b-2 border-blue-600 active dark:text-blue-500 dark:border-blue-500',
+ disabled: 'inline-block p-4 text-gray-400 rounded-t-lg cursor-not-allowed dark:text-gray-500',
+}
+const pillsTabClasses: TabClassMap = {
+ default: 'cursor-pointer inline-block py-3 px-4 rounded-lg hover:text-gray-900 hover:bg-gray-100 dark:hover:bg-gray-800 dark:hover:text-white',
+ active: 'cursor-pointer inline-block py-3 px-4 text-white bg-blue-600 rounded-lg active',
+ disabled: 'inline-block py-3 px-4 text-gray-400 cursor-not-allowed dark:text-gray-500',
+}
+
+export function useTabClasses(props: UseTabClassesProps): {
+ tabClasses: Ref,
+} {
+
+ const tabClasses = computed(() => {
+ const tabClassType: keyof TabClassMap = props.active.value ? 'active' : props.disabled.value ? 'disabled' : 'default'
+
+ if(props.variant === 'default')
+ return defaultTabClasses[tabClassType]
+ else if(props.variant === 'underline')
+ return underlineTabClasses[tabClassType]
+ else if (props.variant === 'pills')
+ return pillsTabClasses[tabClassType]
+ return ''
+ })
+
+ return {
+ tabClasses,
+ }
+}
\ No newline at end of file
diff --git a/src/components/Tabs/config.ts b/src/components/Tabs/config.ts
new file mode 100644
index 0000000..76d42b0
--- /dev/null
+++ b/src/components/Tabs/config.ts
@@ -0,0 +1,2 @@
+export const TAB_STYLE_INJECTION_KEY = 'flowbite-tab-style-injection'
+export const TAB_ACTIVATE_INJECTION_KEY = 'flowbite-tab-activate-func-injection'
\ No newline at end of file
diff --git a/src/utils/flatten.ts b/src/utils/flatten.ts
new file mode 100644
index 0000000..268b460
--- /dev/null
+++ b/src/utils/flatten.ts
@@ -0,0 +1,33 @@
+import { Fragment, createTextVNode, Comment } from 'vue'
+import type { VNodeChild, VNode } from 'vue'
+
+// o(n) flatten
+export function flatten (
+ vNodes: VNodeChild[],
+ filterCommentNode = true,
+ result: VNode[] = [],
+): VNode[] {
+ vNodes.forEach((vNode) => {
+ if (vNode === null) return
+ if (typeof vNode !== 'object') {
+ if (typeof vNode === 'string' || typeof vNode === 'number') {
+ result.push(createTextVNode(String(vNode)))
+ }
+ return
+ }
+ if (Array.isArray(vNode)) {
+ flatten(vNode, filterCommentNode, result)
+ return
+ }
+ if (vNode.type === Fragment) {
+ if (vNode.children === null) return
+ if (Array.isArray(vNode.children)) {
+ flatten(vNode.children, filterCommentNode, result)
+ }
+ // rawSlot
+ } else if (vNode.type !== Comment) {
+ result.push(vNode)
+ }
+ })
+ return result
+}
\ No newline at end of file