@auronui/vue 1.0.5 → 1.0.7
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.
- package/dist/cjs/index.cjs +314 -45
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/components/autocomplete/AutocompleteContent.js.map +1 -1
- package/dist/components/autocomplete/AutocompleteContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/autocomplete/AutocompleteItem.js.map +1 -1
- package/dist/components/autocomplete/AutocompleteItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/combo-box/ComboBoxContent.js.map +1 -1
- package/dist/components/combo-box/ComboBoxContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/combo-box/ComboBoxItem.js.map +1 -1
- package/dist/components/combo-box/ComboBoxItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tabs/Tab.js.map +1 -1
- package/dist/components/tabs/Tab.vue_vue_type_script_setup_true_lang.js +2 -0
- package/dist/components/tabs/Tab.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tabs/TabList.js.map +1 -1
- package/dist/components/tabs/TabList.vue_vue_type_script_setup_true_lang.js +262 -3
- package/dist/components/tabs/TabList.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tabs/Tabs.js.map +1 -1
- package/dist/components/tabs/Tabs.vue_vue_type_script_setup_true_lang.js +14 -6
- package/dist/components/tabs/Tabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tabs/tabs.context.js.map +1 -1
- package/dist/index.d.ts +8972 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutocompleteContent.js","names":[],"sources":["../../../src/components/autocomplete/AutocompleteContent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { AutocompletePortal, AutocompleteContent, AutocompleteViewport, AutocompleteEmpty, injectComboboxRootContext } from 'reka-ui'\nimport { motion, AnimatePresence } from 'motion-v'\nimport { useSlots, watchEffect, type VNode } from 'vue'\nimport { useAutocompleteInject } from './Autocomplete.context'\n\nconst props = withDefaults(defineProps<{\n sideOffset?: number\n class?: string\n}>(), {\n sideOffset: 8,\n class: undefined,\n})\n\nconst ctx = useAutocompleteInject()\n// AutocompleteRoot internally provides the ComboboxRoot context\nconst rootContext = injectComboboxRootContext()\n\n// Pre-walk slot VNodes to extract value→label pairs synchronously.\n// This runs before the portal opens so the bridge can resolve labels on initial render.\nconst slots = useSlots()\n\nfunction extractNodeText(nodes: VNode[]): string {\n return nodes.map(n => {\n if (typeof n.children === 'string') return n.children\n if (Array.isArray(n.children)) return extractNodeText(n.children as VNode[])\n return ''\n }).join('')\n}\n\nfunction walkAndRegister(nodes: VNode[]) {\n for (const node of nodes) {\n // AutocompleteItem VNodes have a `value` prop; extract their text children\n if (node.props && typeof node.props.value === 'string') {\n const value = node.props.value as string\n const label = node.props.label as string | undefined\n if (label) {\n ctx.registerItem(value, label)\n } else {\n // Extract text from the default slot children of this VNode\n const children = node.children\n if (children && typeof children === 'object' && 'default' in children) {\n const slotFn = (children as Record<string, () => VNode[]>).default\n if (typeof slotFn === 'function') {\n const text = extractNodeText(slotFn()).trim()\n if (text) ctx.registerItem(value, text)\n }\n } else if (typeof children === 'string') {\n const text = children.trim()\n if (text) ctx.registerItem(value, text)\n } else if (Array.isArray(children)) {\n const text = extractNodeText(children as VNode[]).trim()\n if (text) ctx.registerItem(value, text)\n }\n }\n }\n // Recurse into children\n if (Array.isArray(node.children)) {\n walkAndRegister(node.children as VNode[])\n }\n }\n}\n\n// Run synchronously at setup time and whenever the slot content changes\nwatchEffect(() => {\n const vnodes = slots.default?.()\n if (vnodes) walkAndRegister(vnodes)\n})\n</script>\n\n<template>\n <AutocompletePortal>\n <AnimatePresence>\n <AutocompleteContent\n v-if=\"rootContext.open.value && (ctx.hasItems.value || (ctx.isFilled.value && !ctx.isLoading.value))\"\n position=\"popper\"\n :side-offset=\"props.sideOffset\"\n as-child\n data-slot=\"popover\"\n >\n <motion.div\n :class=\"['autocomplete__popover', 'relative']\"\n :data-loading=\"ctx.isLoading.value ? '' : undefined\"\n :data-truncate-items=\"ctx.truncateItems.value ? undefined : 'false'\"\n :aria-busy=\"ctx.isLoading.value || undefined\"\n :initial=\"{ opacity: 0, scale: 0.95 }\"\n :animate=\"{ opacity: 1, scale: 1 }\"\n :exit=\"{ opacity: 0, scale: 0.95 }\"\n :transition=\"{ duration: 0.15 }\"\n >\n <div\n :class=\"[\n 'transition-opacity duration-150',\n ctx.isLoading.value\n ? 'pointer-events-none opacity-50 grayscale cursor-not-allowed select-none'\n : '',\n ]\"\n :inert=\"ctx.isLoading.value || undefined\"\n :aria-disabled=\"ctx.isLoading.value || undefined\"\n :data-disabled=\"ctx.isLoading.value ? '' : undefined\"\n data-slot=\"list-wrapper\"\n >\n <AutocompleteViewport\n data-slot=\"list-box\"\n >\n <slot />\n <!-- Empty state: only show when the user has typed a query -->\n <AutocompleteEmpty\n v-if=\"ctx.isFilled.value && !ctx.isLoading.value\"\n class=\"py-3 text-center text-sm text-default-400\"\n data-slot=\"empty-content\"\n >\n <slot name=\"empty\">\n No results found\n </slot>\n </AutocompleteEmpty>\n </AutocompleteViewport>\n </div>\n </motion.div>\n </AutocompleteContent>\n </AnimatePresence>\n </AutocompletePortal>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"AutocompleteContent.js","names":[],"sources":["../../../src/components/autocomplete/AutocompleteContent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { AutocompletePortal, AutocompleteContent, AutocompleteViewport, AutocompleteEmpty, injectComboboxRootContext } from 'reka-ui'\nimport { motion, AnimatePresence } from 'motion-v'\nimport { useSlots, watchEffect, type VNode } from 'vue'\nimport { useAutocompleteInject } from './Autocomplete.context'\n\nconst props = withDefaults(defineProps<{\n sideOffset?: number\n class?: string\n}>(), {\n sideOffset: 8,\n class: undefined,\n})\n\nconst ctx = useAutocompleteInject()\n// AutocompleteRoot internally provides the ComboboxRoot context\nconst rootContext = injectComboboxRootContext()\n\n// Pre-walk slot VNodes to extract value→label pairs synchronously.\n// This runs before the portal opens so the bridge can resolve labels on initial render.\nconst slots = useSlots()\n\nfunction extractNodeText(nodes: VNode[]): string {\n return nodes.map(n => {\n if (typeof n.children === 'string') return n.children\n if (Array.isArray(n.children)) return extractNodeText(n.children as VNode[])\n return ''\n }).join('')\n}\n\nfunction walkAndRegister(nodes: VNode[]) {\n for (const node of nodes) {\n // AutocompleteItem VNodes have a `value` prop; extract their text children\n if (node.props && typeof node.props.value === 'string') {\n const value = node.props.value as string\n const label = node.props.label as string | undefined\n if (label) {\n ctx.registerItem(value, label)\n } else {\n // Extract text from the default slot children of this VNode\n const children = node.children\n if (children && typeof children === 'object' && 'default' in children) {\n const slotFn = (children as Record<string, () => VNode[]>).default\n if (typeof slotFn === 'function') {\n const text = extractNodeText(slotFn()).trim()\n if (text) ctx.registerItem(value, text)\n }\n } else if (typeof children === 'string') {\n const text = children.trim()\n if (text) ctx.registerItem(value, text)\n } else if (Array.isArray(children)) {\n const text = extractNodeText(children as VNode[]).trim()\n if (text) ctx.registerItem(value, text)\n }\n }\n }\n // Recurse into children\n if (Array.isArray(node.children)) {\n walkAndRegister(node.children as VNode[])\n }\n }\n}\n\n// Run synchronously at setup time and whenever the slot content changes\nwatchEffect(() => {\n const vnodes = (slots.default as (() => VNode[]) | undefined)?.()\n if (vnodes) walkAndRegister(vnodes)\n})\n</script>\n\n<template>\n <AutocompletePortal>\n <AnimatePresence>\n <AutocompleteContent\n v-if=\"rootContext.open.value && (ctx.hasItems.value || (ctx.isFilled.value && !ctx.isLoading.value))\"\n position=\"popper\"\n :side-offset=\"props.sideOffset\"\n as-child\n data-slot=\"popover\"\n >\n <motion.div\n :class=\"['autocomplete__popover', 'relative']\"\n :data-loading=\"ctx.isLoading.value ? '' : undefined\"\n :data-truncate-items=\"ctx.truncateItems.value ? undefined : 'false'\"\n :aria-busy=\"ctx.isLoading.value || undefined\"\n :initial=\"{ opacity: 0, scale: 0.95 }\"\n :animate=\"{ opacity: 1, scale: 1 }\"\n :exit=\"{ opacity: 0, scale: 0.95 }\"\n :transition=\"{ duration: 0.15 }\"\n >\n <div\n :class=\"[\n 'transition-opacity duration-150',\n ctx.isLoading.value\n ? 'pointer-events-none opacity-50 grayscale cursor-not-allowed select-none'\n : '',\n ]\"\n :inert=\"ctx.isLoading.value || undefined\"\n :aria-disabled=\"ctx.isLoading.value || undefined\"\n :data-disabled=\"ctx.isLoading.value ? '' : undefined\"\n data-slot=\"list-wrapper\"\n >\n <AutocompleteViewport\n data-slot=\"list-box\"\n >\n <slot />\n <!-- Empty state: only show when the user has typed a query -->\n <AutocompleteEmpty\n v-if=\"ctx.isFilled.value && !ctx.isLoading.value\"\n class=\"py-3 text-center text-sm text-default-400\"\n data-slot=\"empty-content\"\n >\n <slot name=\"empty\">\n No results found\n </slot>\n </AutocompleteEmpty>\n </AutocompleteViewport>\n </div>\n </motion.div>\n </AutocompleteContent>\n </AnimatePresence>\n </AutocompletePortal>\n</template>\n"],"mappings":""}
|
package/dist/components/autocomplete/AutocompleteContent.vue_vue_type_script_setup_true_lang.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutocompleteContent.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/autocomplete/AutocompleteContent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { AutocompletePortal, AutocompleteContent, AutocompleteViewport, AutocompleteEmpty, injectComboboxRootContext } from 'reka-ui'\nimport { motion, AnimatePresence } from 'motion-v'\nimport { useSlots, watchEffect, type VNode } from 'vue'\nimport { useAutocompleteInject } from './Autocomplete.context'\n\nconst props = withDefaults(defineProps<{\n sideOffset?: number\n class?: string\n}>(), {\n sideOffset: 8,\n class: undefined,\n})\n\nconst ctx = useAutocompleteInject()\n// AutocompleteRoot internally provides the ComboboxRoot context\nconst rootContext = injectComboboxRootContext()\n\n// Pre-walk slot VNodes to extract value→label pairs synchronously.\n// This runs before the portal opens so the bridge can resolve labels on initial render.\nconst slots = useSlots()\n\nfunction extractNodeText(nodes: VNode[]): string {\n return nodes.map(n => {\n if (typeof n.children === 'string') return n.children\n if (Array.isArray(n.children)) return extractNodeText(n.children as VNode[])\n return ''\n }).join('')\n}\n\nfunction walkAndRegister(nodes: VNode[]) {\n for (const node of nodes) {\n // AutocompleteItem VNodes have a `value` prop; extract their text children\n if (node.props && typeof node.props.value === 'string') {\n const value = node.props.value as string\n const label = node.props.label as string | undefined\n if (label) {\n ctx.registerItem(value, label)\n } else {\n // Extract text from the default slot children of this VNode\n const children = node.children\n if (children && typeof children === 'object' && 'default' in children) {\n const slotFn = (children as Record<string, () => VNode[]>).default\n if (typeof slotFn === 'function') {\n const text = extractNodeText(slotFn()).trim()\n if (text) ctx.registerItem(value, text)\n }\n } else if (typeof children === 'string') {\n const text = children.trim()\n if (text) ctx.registerItem(value, text)\n } else if (Array.isArray(children)) {\n const text = extractNodeText(children as VNode[]).trim()\n if (text) ctx.registerItem(value, text)\n }\n }\n }\n // Recurse into children\n if (Array.isArray(node.children)) {\n walkAndRegister(node.children as VNode[])\n }\n }\n}\n\n// Run synchronously at setup time and whenever the slot content changes\nwatchEffect(() => {\n const vnodes = slots.default?.()\n if (vnodes) walkAndRegister(vnodes)\n})\n</script>\n\n<template>\n <AutocompletePortal>\n <AnimatePresence>\n <AutocompleteContent\n v-if=\"rootContext.open.value && (ctx.hasItems.value || (ctx.isFilled.value && !ctx.isLoading.value))\"\n position=\"popper\"\n :side-offset=\"props.sideOffset\"\n as-child\n data-slot=\"popover\"\n >\n <motion.div\n :class=\"['autocomplete__popover', 'relative']\"\n :data-loading=\"ctx.isLoading.value ? '' : undefined\"\n :data-truncate-items=\"ctx.truncateItems.value ? undefined : 'false'\"\n :aria-busy=\"ctx.isLoading.value || undefined\"\n :initial=\"{ opacity: 0, scale: 0.95 }\"\n :animate=\"{ opacity: 1, scale: 1 }\"\n :exit=\"{ opacity: 0, scale: 0.95 }\"\n :transition=\"{ duration: 0.15 }\"\n >\n <div\n :class=\"[\n 'transition-opacity duration-150',\n ctx.isLoading.value\n ? 'pointer-events-none opacity-50 grayscale cursor-not-allowed select-none'\n : '',\n ]\"\n :inert=\"ctx.isLoading.value || undefined\"\n :aria-disabled=\"ctx.isLoading.value || undefined\"\n :data-disabled=\"ctx.isLoading.value ? '' : undefined\"\n data-slot=\"list-wrapper\"\n >\n <AutocompleteViewport\n data-slot=\"list-box\"\n >\n <slot />\n <!-- Empty state: only show when the user has typed a query -->\n <AutocompleteEmpty\n v-if=\"ctx.isFilled.value && !ctx.isLoading.value\"\n class=\"py-3 text-center text-sm text-default-400\"\n data-slot=\"empty-content\"\n >\n <slot name=\"empty\">\n No results found\n </slot>\n </AutocompleteEmpty>\n </AutocompleteViewport>\n </div>\n </motion.div>\n </AutocompleteContent>\n </AnimatePresence>\n </AutocompletePortal>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;EAMA,MAAM,QAAQ;EAQd,MAAM,MAAM,uBAAsB;EAElC,MAAM,cAAc,2BAA0B;EAI9C,MAAM,QAAQ,UAAS;EAEvB,SAAS,gBAAgB,OAAwB;AAC/C,UAAO,MAAM,KAAI,MAAK;AACpB,QAAI,OAAO,EAAE,aAAa,SAAU,QAAO,EAAE;AAC7C,QAAI,MAAM,QAAQ,EAAE,SAAS,CAAE,QAAO,gBAAgB,EAAE,SAAmB;AAC3E,WAAO;KACP,CAAC,KAAK,GAAE;;EAGZ,SAAS,gBAAgB,OAAgB;AACvC,QAAK,MAAM,QAAQ,OAAO;AAExB,QAAI,KAAK,SAAS,OAAO,KAAK,MAAM,UAAU,UAAU;KACtD,MAAM,QAAQ,KAAK,MAAM;KACzB,MAAM,QAAQ,KAAK,MAAM;AACzB,SAAI,MACF,KAAI,aAAa,OAAO,MAAK;UACxB;MAEL,MAAM,WAAW,KAAK;AACtB,UAAI,YAAY,OAAO,aAAa,YAAY,aAAa,UAAU;OACrE,MAAM,SAAU,SAA2C;AAC3D,WAAI,OAAO,WAAW,YAAY;QAChC,MAAM,OAAO,gBAAgB,QAAQ,CAAC,CAAC,MAAK;AAC5C,YAAI,KAAM,KAAI,aAAa,OAAO,KAAI;;iBAE/B,OAAO,aAAa,UAAU;OACvC,MAAM,OAAO,SAAS,MAAK;AAC3B,WAAI,KAAM,KAAI,aAAa,OAAO,KAAI;iBAC7B,MAAM,QAAQ,SAAS,EAAE;OAClC,MAAM,OAAO,gBAAgB,SAAoB,CAAC,MAAK;AACvD,WAAI,KAAM,KAAI,aAAa,OAAO,KAAI;;;;AAK5C,QAAI,MAAM,QAAQ,KAAK,SAAS,CAC9B,iBAAgB,KAAK,SAAmB;;;AAM9C,oBAAkB;GAChB,MAAM,
|
|
1
|
+
{"version":3,"file":"AutocompleteContent.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/autocomplete/AutocompleteContent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { AutocompletePortal, AutocompleteContent, AutocompleteViewport, AutocompleteEmpty, injectComboboxRootContext } from 'reka-ui'\nimport { motion, AnimatePresence } from 'motion-v'\nimport { useSlots, watchEffect, type VNode } from 'vue'\nimport { useAutocompleteInject } from './Autocomplete.context'\n\nconst props = withDefaults(defineProps<{\n sideOffset?: number\n class?: string\n}>(), {\n sideOffset: 8,\n class: undefined,\n})\n\nconst ctx = useAutocompleteInject()\n// AutocompleteRoot internally provides the ComboboxRoot context\nconst rootContext = injectComboboxRootContext()\n\n// Pre-walk slot VNodes to extract value→label pairs synchronously.\n// This runs before the portal opens so the bridge can resolve labels on initial render.\nconst slots = useSlots()\n\nfunction extractNodeText(nodes: VNode[]): string {\n return nodes.map(n => {\n if (typeof n.children === 'string') return n.children\n if (Array.isArray(n.children)) return extractNodeText(n.children as VNode[])\n return ''\n }).join('')\n}\n\nfunction walkAndRegister(nodes: VNode[]) {\n for (const node of nodes) {\n // AutocompleteItem VNodes have a `value` prop; extract their text children\n if (node.props && typeof node.props.value === 'string') {\n const value = node.props.value as string\n const label = node.props.label as string | undefined\n if (label) {\n ctx.registerItem(value, label)\n } else {\n // Extract text from the default slot children of this VNode\n const children = node.children\n if (children && typeof children === 'object' && 'default' in children) {\n const slotFn = (children as Record<string, () => VNode[]>).default\n if (typeof slotFn === 'function') {\n const text = extractNodeText(slotFn()).trim()\n if (text) ctx.registerItem(value, text)\n }\n } else if (typeof children === 'string') {\n const text = children.trim()\n if (text) ctx.registerItem(value, text)\n } else if (Array.isArray(children)) {\n const text = extractNodeText(children as VNode[]).trim()\n if (text) ctx.registerItem(value, text)\n }\n }\n }\n // Recurse into children\n if (Array.isArray(node.children)) {\n walkAndRegister(node.children as VNode[])\n }\n }\n}\n\n// Run synchronously at setup time and whenever the slot content changes\nwatchEffect(() => {\n const vnodes = (slots.default as (() => VNode[]) | undefined)?.()\n if (vnodes) walkAndRegister(vnodes)\n})\n</script>\n\n<template>\n <AutocompletePortal>\n <AnimatePresence>\n <AutocompleteContent\n v-if=\"rootContext.open.value && (ctx.hasItems.value || (ctx.isFilled.value && !ctx.isLoading.value))\"\n position=\"popper\"\n :side-offset=\"props.sideOffset\"\n as-child\n data-slot=\"popover\"\n >\n <motion.div\n :class=\"['autocomplete__popover', 'relative']\"\n :data-loading=\"ctx.isLoading.value ? '' : undefined\"\n :data-truncate-items=\"ctx.truncateItems.value ? undefined : 'false'\"\n :aria-busy=\"ctx.isLoading.value || undefined\"\n :initial=\"{ opacity: 0, scale: 0.95 }\"\n :animate=\"{ opacity: 1, scale: 1 }\"\n :exit=\"{ opacity: 0, scale: 0.95 }\"\n :transition=\"{ duration: 0.15 }\"\n >\n <div\n :class=\"[\n 'transition-opacity duration-150',\n ctx.isLoading.value\n ? 'pointer-events-none opacity-50 grayscale cursor-not-allowed select-none'\n : '',\n ]\"\n :inert=\"ctx.isLoading.value || undefined\"\n :aria-disabled=\"ctx.isLoading.value || undefined\"\n :data-disabled=\"ctx.isLoading.value ? '' : undefined\"\n data-slot=\"list-wrapper\"\n >\n <AutocompleteViewport\n data-slot=\"list-box\"\n >\n <slot />\n <!-- Empty state: only show when the user has typed a query -->\n <AutocompleteEmpty\n v-if=\"ctx.isFilled.value && !ctx.isLoading.value\"\n class=\"py-3 text-center text-sm text-default-400\"\n data-slot=\"empty-content\"\n >\n <slot name=\"empty\">\n No results found\n </slot>\n </AutocompleteEmpty>\n </AutocompleteViewport>\n </div>\n </motion.div>\n </AutocompleteContent>\n </AnimatePresence>\n </AutocompletePortal>\n</template>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutocompleteItem.js","names":[],"sources":["../../../src/components/autocomplete/AutocompleteItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, useSlots, type VNode } from 'vue'\nimport { AutocompleteItem, ComboboxItemIndicator } from 'reka-ui'\nimport { useAutocompleteInject } from './Autocomplete.context'\n\nconst props = withDefaults(defineProps<{\n value: string\n isDisabled?: boolean\n class?: string\n}>(), {\n isDisabled: false,\n class: undefined,\n})\n\nconst slots = useSlots()\nconst ctx = useAutocompleteInject()\n\n// Extract plain text from default slot VNodes at render time.\nfunction extractText(nodes: VNode[]): string {\n return nodes.map(n => {\n if (typeof n.children === 'string') return n.children\n if (Array.isArray(n.children)) return extractText(n.children as VNode[])\n return ''\n }).join('')\n}\n\n// The display text Reka writes into the input when this item is selected.\n// Reads slot text content — no extra props needed.\nconst displayText = computed(() => {\n const vnodes = slots.default?.()\n if (!vnodes) return props.value\n return extractText(vnodes).trim() || props.value\n})\n\n// Register this item's value→label mapping with the parent Autocomplete bridge\n// so valueFor() can translate the display label back to the real value.\nonMounted(() => {\n ctx.registerItem(props.value, displayText.value)\n})\n\nonUnmounted(() => {\n ctx.unregisterItem(props.value)\n})\n</script>\n\n<template>\n <AutocompleteItem\n :value=\"displayText\"\n :text-value=\"displayText\"\n :disabled=\"props.isDisabled\"\n :data-item-value=\"props.value\"\n class=\"list-box-item list-box-item--default\"\n data-slot=\"list-box-item\"\n >\n <slot name=\"startContent\" />\n <span\n class=\"autocomplete-item__text\"\n data-slot=\"item-text\"\n ><slot /></span>\n <ComboboxItemIndicator\n class=\"list-box-item__indicator\"\n data-slot=\"list-box-item-indicator\"\n >\n <slot name=\"selectedIcon\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n data-slot=\"list-box-item-indicator--checkmark\"\n aria-hidden=\"true\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </slot>\n </ComboboxItemIndicator>\n <slot name=\"endContent\" />\n </AutocompleteItem>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"AutocompleteItem.js","names":[],"sources":["../../../src/components/autocomplete/AutocompleteItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, useSlots, type Slots, type VNode } from 'vue'\nimport { AutocompleteItem, ComboboxItemIndicator } from 'reka-ui'\nimport { useAutocompleteInject } from './Autocomplete.context'\n\nconst props = withDefaults(defineProps<{\n value: string\n isDisabled?: boolean\n class?: string\n}>(), {\n isDisabled: false,\n class: undefined,\n})\n\nconst slots: Slots = useSlots()\nconst ctx = useAutocompleteInject()\n\n// Extract plain text from default slot VNodes at render time.\nfunction extractText(nodes: VNode[]): string {\n return nodes.map(n => {\n if (typeof n.children === 'string') return n.children\n if (Array.isArray(n.children)) return extractText(n.children as VNode[])\n return ''\n }).join('')\n}\n\n// The display text Reka writes into the input when this item is selected.\n// Reads slot text content — no extra props needed.\nconst displayText = computed((): string => {\n const vnodes: VNode[] | undefined = (slots.default as (() => VNode[]) | undefined)?.()\n if (!vnodes) return props.value\n return extractText(vnodes).trim() || props.value\n})\n\n// Register this item's value→label mapping with the parent Autocomplete bridge\n// so valueFor() can translate the display label back to the real value.\nonMounted(() => {\n ctx.registerItem(props.value, displayText.value)\n})\n\nonUnmounted(() => {\n ctx.unregisterItem(props.value)\n})\n</script>\n\n<template>\n <AutocompleteItem\n :value=\"displayText\"\n :text-value=\"displayText\"\n :disabled=\"props.isDisabled\"\n :data-item-value=\"props.value\"\n class=\"list-box-item list-box-item--default\"\n data-slot=\"list-box-item\"\n >\n <slot name=\"startContent\" />\n <span\n class=\"autocomplete-item__text\"\n data-slot=\"item-text\"\n ><slot /></span>\n <ComboboxItemIndicator\n class=\"list-box-item__indicator\"\n data-slot=\"list-box-item-indicator\"\n >\n <slot name=\"selectedIcon\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n data-slot=\"list-box-item-indicator--checkmark\"\n aria-hidden=\"true\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </slot>\n </ComboboxItemIndicator>\n <slot name=\"endContent\" />\n </AutocompleteItem>\n</template>\n"],"mappings":""}
|
package/dist/components/autocomplete/AutocompleteItem.vue_vue_type_script_setup_true_lang.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutocompleteItem.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/autocomplete/AutocompleteItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, useSlots, type VNode } from 'vue'\nimport { AutocompleteItem, ComboboxItemIndicator } from 'reka-ui'\nimport { useAutocompleteInject } from './Autocomplete.context'\n\nconst props = withDefaults(defineProps<{\n value: string\n isDisabled?: boolean\n class?: string\n}>(), {\n isDisabled: false,\n class: undefined,\n})\n\nconst slots = useSlots()\nconst ctx = useAutocompleteInject()\n\n// Extract plain text from default slot VNodes at render time.\nfunction extractText(nodes: VNode[]): string {\n return nodes.map(n => {\n if (typeof n.children === 'string') return n.children\n if (Array.isArray(n.children)) return extractText(n.children as VNode[])\n return ''\n }).join('')\n}\n\n// The display text Reka writes into the input when this item is selected.\n// Reads slot text content — no extra props needed.\nconst displayText = computed(() => {\n const vnodes = slots.default?.()\n if (!vnodes) return props.value\n return extractText(vnodes).trim() || props.value\n})\n\n// Register this item's value→label mapping with the parent Autocomplete bridge\n// so valueFor() can translate the display label back to the real value.\nonMounted(() => {\n ctx.registerItem(props.value, displayText.value)\n})\n\nonUnmounted(() => {\n ctx.unregisterItem(props.value)\n})\n</script>\n\n<template>\n <AutocompleteItem\n :value=\"displayText\"\n :text-value=\"displayText\"\n :disabled=\"props.isDisabled\"\n :data-item-value=\"props.value\"\n class=\"list-box-item list-box-item--default\"\n data-slot=\"list-box-item\"\n >\n <slot name=\"startContent\" />\n <span\n class=\"autocomplete-item__text\"\n data-slot=\"item-text\"\n ><slot /></span>\n <ComboboxItemIndicator\n class=\"list-box-item__indicator\"\n data-slot=\"list-box-item-indicator\"\n >\n <slot name=\"selectedIcon\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n data-slot=\"list-box-item-indicator--checkmark\"\n aria-hidden=\"true\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </slot>\n </ComboboxItemIndicator>\n <slot name=\"endContent\" />\n </AutocompleteItem>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;EAKA,MAAM,QAAQ;EASd,MAAM,
|
|
1
|
+
{"version":3,"file":"AutocompleteItem.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/autocomplete/AutocompleteItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, useSlots, type Slots, type VNode } from 'vue'\nimport { AutocompleteItem, ComboboxItemIndicator } from 'reka-ui'\nimport { useAutocompleteInject } from './Autocomplete.context'\n\nconst props = withDefaults(defineProps<{\n value: string\n isDisabled?: boolean\n class?: string\n}>(), {\n isDisabled: false,\n class: undefined,\n})\n\nconst slots: Slots = useSlots()\nconst ctx = useAutocompleteInject()\n\n// Extract plain text from default slot VNodes at render time.\nfunction extractText(nodes: VNode[]): string {\n return nodes.map(n => {\n if (typeof n.children === 'string') return n.children\n if (Array.isArray(n.children)) return extractText(n.children as VNode[])\n return ''\n }).join('')\n}\n\n// The display text Reka writes into the input when this item is selected.\n// Reads slot text content — no extra props needed.\nconst displayText = computed((): string => {\n const vnodes: VNode[] | undefined = (slots.default as (() => VNode[]) | undefined)?.()\n if (!vnodes) return props.value\n return extractText(vnodes).trim() || props.value\n})\n\n// Register this item's value→label mapping with the parent Autocomplete bridge\n// so valueFor() can translate the display label back to the real value.\nonMounted(() => {\n ctx.registerItem(props.value, displayText.value)\n})\n\nonUnmounted(() => {\n ctx.unregisterItem(props.value)\n})\n</script>\n\n<template>\n <AutocompleteItem\n :value=\"displayText\"\n :text-value=\"displayText\"\n :disabled=\"props.isDisabled\"\n :data-item-value=\"props.value\"\n class=\"list-box-item list-box-item--default\"\n data-slot=\"list-box-item\"\n >\n <slot name=\"startContent\" />\n <span\n class=\"autocomplete-item__text\"\n data-slot=\"item-text\"\n ><slot /></span>\n <ComboboxItemIndicator\n class=\"list-box-item__indicator\"\n data-slot=\"list-box-item-indicator\"\n >\n <slot name=\"selectedIcon\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n data-slot=\"list-box-item-indicator--checkmark\"\n aria-hidden=\"true\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </slot>\n </ComboboxItemIndicator>\n <slot name=\"endContent\" />\n </AutocompleteItem>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;EAKA,MAAM,QAAQ;EASd,MAAM,QAAe,UAAS;EAC9B,MAAM,MAAM,uBAAsB;EAGlC,SAAS,YAAY,OAAwB;AAC3C,UAAO,MAAM,KAAI,MAAK;AACpB,QAAI,OAAO,EAAE,aAAa,SAAU,QAAO,EAAE;AAC7C,QAAI,MAAM,QAAQ,EAAE,SAAS,CAAE,QAAO,YAAY,EAAE,SAAmB;AACvE,WAAO;KACP,CAAC,KAAK,GAAE;;EAKZ,MAAM,cAAc,eAAuB;GACzC,MAAM,SAA+B,MAAM,WAA0C;AACrF,OAAI,CAAC,OAAQ,QAAO,MAAM;AAC1B,UAAO,YAAY,OAAO,CAAC,MAAM,IAAI,MAAM;IAC5C;AAID,kBAAgB;AACd,OAAI,aAAa,MAAM,OAAO,YAAY,MAAK;IAChD;AAED,oBAAkB;AAChB,OAAI,eAAe,MAAM,MAAK;IAC/B;;uBAIC,YAoCmB,MAAA,iBAAA,EAAA;IAnChB,OAAO,YAAA;IACP,cAAY,YAAA;IACZ,UAAU,MAAM;IAChB,mBAAiB,MAAM;IACxB,OAAM;IACN,aAAU;;2BAEkB;KAA5B,WAA4B,KAAA,QAAA,eAAA;KAC5B,mBAGgB,QAHhB,YAGgB,CAAf,WAAQ,KAAA,QAAA,UAAA,CAAA,CAAA;KACT,YAqBwB,MAAA,sBAAA,EAAA;MApBtB,OAAM;MACN,aAAU;;6BAkBH,CAhBP,WAgBO,KAAA,QAAA,gBAAA,EAAA,QAAA,CAAA,OAAA,OAAA,OAAA,KAfL,mBAcM,OAAA;OAbJ,OAAM;OACN,OAAM;OACN,QAAO;OACP,SAAQ;OACR,MAAK;OACL,QAAO;OACP,gBAAa;OACb,kBAAe;OACf,mBAAgB;OAChB,aAAU;OACV,eAAY;UAEZ,mBAAoC,YAAA,EAA1B,QAAO,kBAAgB,CAAA,CAAA,EAAA,GAAA,EAAA,CAAA,CAAA,CAAA;;;KAIvC,WAA0B,KAAA,QAAA,aAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComboBoxContent.js","names":[],"sources":["../../../src/components/combo-box/ComboBoxContent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ComboboxPortal, ComboboxContent, ComboboxViewport, injectComboboxRootContext } from 'reka-ui'\nimport { motion, AnimatePresence } from 'motion-v'\nimport { useSlots, watchEffect, type VNode } from 'vue'\nimport { useComboBoxInject } from './ComboBox.context'\n\nconst props = withDefaults(defineProps<{\n sideOffset?: number\n class?: string\n}>(), {\n sideOffset: 8,\n class: undefined,\n})\n\nconst ctx = useComboBoxInject()\nconst comboboxRootContext = injectComboboxRootContext()\n\n// Pre-walk slot VNodes to extract value→label pairs synchronously.\n// This runs before the portal opens so the bridge can resolve labels on initial render.\nconst slots = useSlots()\n\nfunction extractNodeText(nodes: VNode[]): string {\n return nodes.map(n => {\n if (typeof n.children === 'string') return n.children\n if (Array.isArray(n.children)) return extractNodeText(n.children as VNode[])\n return ''\n }).join('')\n}\n\nfunction walkAndRegister(nodes: VNode[]) {\n for (const node of nodes) {\n // ComboBoxItem VNodes have a `value` prop; extract their text children\n if (node.props && typeof node.props.value === 'string') {\n const value = node.props.value as string\n const children = node.children\n if (children && typeof children === 'object' && 'default' in children) {\n const slotFn = (children as Record<string, () => VNode[]>).default\n if (typeof slotFn === 'function') {\n const text = extractNodeText(slotFn()).trim()\n if (text) ctx.registerItem(value, text)\n }\n } else if (typeof children === 'string') {\n const text = children.trim()\n if (text) ctx.registerItem(value, text)\n } else if (Array.isArray(children)) {\n const text = extractNodeText(children as VNode[]).trim()\n if (text) ctx.registerItem(value, text)\n }\n }\n // Recurse into children arrays\n if (Array.isArray(node.children)) {\n walkAndRegister(node.children as VNode[])\n }\n }\n}\n\n// Run synchronously at setup time and whenever the slot content changes\nwatchEffect(() => {\n const vnodes = slots.default?.()\n if (vnodes) walkAndRegister(vnodes)\n})\n</script>\n\n<template>\n <ComboboxPortal>\n <AnimatePresence>\n <ComboboxContent\n v-if=\"comboboxRootContext.open.value\"\n position=\"popper\"\n :side-offset=\"props.sideOffset\"\n as-child\n data-slot=\"popover\"\n >\n <motion.div\n :class=\"ctx.slots.value.popover()\"\n :initial=\"{ opacity: 0, scale: 0.95 }\"\n :animate=\"{ opacity: 1, scale: 1 }\"\n :exit=\"{ opacity: 0, scale: 0.95 }\"\n :transition=\"{ duration: 0.15 }\"\n >\n <ComboboxViewport data-slot=\"list-box\">\n <slot />\n <slot name=\"empty\" />\n </ComboboxViewport>\n </motion.div>\n </ComboboxContent>\n </AnimatePresence>\n </ComboboxPortal>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"ComboBoxContent.js","names":[],"sources":["../../../src/components/combo-box/ComboBoxContent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ComboboxPortal, ComboboxContent, ComboboxViewport, injectComboboxRootContext } from 'reka-ui'\nimport { motion, AnimatePresence } from 'motion-v'\nimport { useSlots, watchEffect, type VNode } from 'vue'\nimport { useComboBoxInject } from './ComboBox.context'\n\nconst props = withDefaults(defineProps<{\n sideOffset?: number\n class?: string\n}>(), {\n sideOffset: 8,\n class: undefined,\n})\n\nconst ctx = useComboBoxInject()\nconst comboboxRootContext = injectComboboxRootContext()\n\n// Pre-walk slot VNodes to extract value→label pairs synchronously.\n// This runs before the portal opens so the bridge can resolve labels on initial render.\nconst slots = useSlots()\n\nfunction extractNodeText(nodes: VNode[]): string {\n return nodes.map(n => {\n if (typeof n.children === 'string') return n.children\n if (Array.isArray(n.children)) return extractNodeText(n.children as VNode[])\n return ''\n }).join('')\n}\n\nfunction walkAndRegister(nodes: VNode[]) {\n for (const node of nodes) {\n // ComboBoxItem VNodes have a `value` prop; extract their text children\n if (node.props && typeof node.props.value === 'string') {\n const value = node.props.value as string\n const children = node.children\n if (children && typeof children === 'object' && 'default' in children) {\n const slotFn = (children as Record<string, () => VNode[]>).default\n if (typeof slotFn === 'function') {\n const text = extractNodeText(slotFn()).trim()\n if (text) ctx.registerItem(value, text)\n }\n } else if (typeof children === 'string') {\n const text = children.trim()\n if (text) ctx.registerItem(value, text)\n } else if (Array.isArray(children)) {\n const text = extractNodeText(children as VNode[]).trim()\n if (text) ctx.registerItem(value, text)\n }\n }\n // Recurse into children arrays\n if (Array.isArray(node.children)) {\n walkAndRegister(node.children as VNode[])\n }\n }\n}\n\n// Run synchronously at setup time and whenever the slot content changes\nwatchEffect(() => {\n const vnodes = (slots.default as (() => VNode[]) | undefined)?.()\n if (vnodes) walkAndRegister(vnodes)\n})\n</script>\n\n<template>\n <ComboboxPortal>\n <AnimatePresence>\n <ComboboxContent\n v-if=\"comboboxRootContext.open.value\"\n position=\"popper\"\n :side-offset=\"props.sideOffset\"\n as-child\n data-slot=\"popover\"\n >\n <motion.div\n :class=\"ctx.slots.value.popover()\"\n :initial=\"{ opacity: 0, scale: 0.95 }\"\n :animate=\"{ opacity: 1, scale: 1 }\"\n :exit=\"{ opacity: 0, scale: 0.95 }\"\n :transition=\"{ duration: 0.15 }\"\n >\n <ComboboxViewport data-slot=\"list-box\">\n <slot />\n <slot name=\"empty\" />\n </ComboboxViewport>\n </motion.div>\n </ComboboxContent>\n </AnimatePresence>\n </ComboboxPortal>\n</template>\n"],"mappings":""}
|
package/dist/components/combo-box/ComboBoxContent.vue_vue_type_script_setup_true_lang.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComboBoxContent.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/combo-box/ComboBoxContent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ComboboxPortal, ComboboxContent, ComboboxViewport, injectComboboxRootContext } from 'reka-ui'\nimport { motion, AnimatePresence } from 'motion-v'\nimport { useSlots, watchEffect, type VNode } from 'vue'\nimport { useComboBoxInject } from './ComboBox.context'\n\nconst props = withDefaults(defineProps<{\n sideOffset?: number\n class?: string\n}>(), {\n sideOffset: 8,\n class: undefined,\n})\n\nconst ctx = useComboBoxInject()\nconst comboboxRootContext = injectComboboxRootContext()\n\n// Pre-walk slot VNodes to extract value→label pairs synchronously.\n// This runs before the portal opens so the bridge can resolve labels on initial render.\nconst slots = useSlots()\n\nfunction extractNodeText(nodes: VNode[]): string {\n return nodes.map(n => {\n if (typeof n.children === 'string') return n.children\n if (Array.isArray(n.children)) return extractNodeText(n.children as VNode[])\n return ''\n }).join('')\n}\n\nfunction walkAndRegister(nodes: VNode[]) {\n for (const node of nodes) {\n // ComboBoxItem VNodes have a `value` prop; extract their text children\n if (node.props && typeof node.props.value === 'string') {\n const value = node.props.value as string\n const children = node.children\n if (children && typeof children === 'object' && 'default' in children) {\n const slotFn = (children as Record<string, () => VNode[]>).default\n if (typeof slotFn === 'function') {\n const text = extractNodeText(slotFn()).trim()\n if (text) ctx.registerItem(value, text)\n }\n } else if (typeof children === 'string') {\n const text = children.trim()\n if (text) ctx.registerItem(value, text)\n } else if (Array.isArray(children)) {\n const text = extractNodeText(children as VNode[]).trim()\n if (text) ctx.registerItem(value, text)\n }\n }\n // Recurse into children arrays\n if (Array.isArray(node.children)) {\n walkAndRegister(node.children as VNode[])\n }\n }\n}\n\n// Run synchronously at setup time and whenever the slot content changes\nwatchEffect(() => {\n const vnodes = slots.default?.()\n if (vnodes) walkAndRegister(vnodes)\n})\n</script>\n\n<template>\n <ComboboxPortal>\n <AnimatePresence>\n <ComboboxContent\n v-if=\"comboboxRootContext.open.value\"\n position=\"popper\"\n :side-offset=\"props.sideOffset\"\n as-child\n data-slot=\"popover\"\n >\n <motion.div\n :class=\"ctx.slots.value.popover()\"\n :initial=\"{ opacity: 0, scale: 0.95 }\"\n :animate=\"{ opacity: 1, scale: 1 }\"\n :exit=\"{ opacity: 0, scale: 0.95 }\"\n :transition=\"{ duration: 0.15 }\"\n >\n <ComboboxViewport data-slot=\"list-box\">\n <slot />\n <slot name=\"empty\" />\n </ComboboxViewport>\n </motion.div>\n </ComboboxContent>\n </AnimatePresence>\n </ComboboxPortal>\n</template>\n"],"mappings":";;;;;;;;;;;;;EAMA,MAAM,QAAQ;EAQd,MAAM,MAAM,mBAAkB;EAC9B,MAAM,sBAAsB,2BAA0B;EAItD,MAAM,QAAQ,UAAS;EAEvB,SAAS,gBAAgB,OAAwB;AAC/C,UAAO,MAAM,KAAI,MAAK;AACpB,QAAI,OAAO,EAAE,aAAa,SAAU,QAAO,EAAE;AAC7C,QAAI,MAAM,QAAQ,EAAE,SAAS,CAAE,QAAO,gBAAgB,EAAE,SAAmB;AAC3E,WAAO;KACP,CAAC,KAAK,GAAE;;EAGZ,SAAS,gBAAgB,OAAgB;AACvC,QAAK,MAAM,QAAQ,OAAO;AAExB,QAAI,KAAK,SAAS,OAAO,KAAK,MAAM,UAAU,UAAU;KACtD,MAAM,QAAQ,KAAK,MAAM;KACzB,MAAM,WAAW,KAAK;AACtB,SAAI,YAAY,OAAO,aAAa,YAAY,aAAa,UAAU;MACrE,MAAM,SAAU,SAA2C;AAC3D,UAAI,OAAO,WAAW,YAAY;OAChC,MAAM,OAAO,gBAAgB,QAAQ,CAAC,CAAC,MAAK;AAC5C,WAAI,KAAM,KAAI,aAAa,OAAO,KAAI;;gBAE/B,OAAO,aAAa,UAAU;MACvC,MAAM,OAAO,SAAS,MAAK;AAC3B,UAAI,KAAM,KAAI,aAAa,OAAO,KAAI;gBAC7B,MAAM,QAAQ,SAAS,EAAE;MAClC,MAAM,OAAO,gBAAgB,SAAoB,CAAC,MAAK;AACvD,UAAI,KAAM,KAAI,aAAa,OAAO,KAAI;;;AAI1C,QAAI,MAAM,QAAQ,KAAK,SAAS,CAC9B,iBAAgB,KAAK,SAAmB;;;AAM9C,oBAAkB;GAChB,MAAM,
|
|
1
|
+
{"version":3,"file":"ComboBoxContent.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/combo-box/ComboBoxContent.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ComboboxPortal, ComboboxContent, ComboboxViewport, injectComboboxRootContext } from 'reka-ui'\nimport { motion, AnimatePresence } from 'motion-v'\nimport { useSlots, watchEffect, type VNode } from 'vue'\nimport { useComboBoxInject } from './ComboBox.context'\n\nconst props = withDefaults(defineProps<{\n sideOffset?: number\n class?: string\n}>(), {\n sideOffset: 8,\n class: undefined,\n})\n\nconst ctx = useComboBoxInject()\nconst comboboxRootContext = injectComboboxRootContext()\n\n// Pre-walk slot VNodes to extract value→label pairs synchronously.\n// This runs before the portal opens so the bridge can resolve labels on initial render.\nconst slots = useSlots()\n\nfunction extractNodeText(nodes: VNode[]): string {\n return nodes.map(n => {\n if (typeof n.children === 'string') return n.children\n if (Array.isArray(n.children)) return extractNodeText(n.children as VNode[])\n return ''\n }).join('')\n}\n\nfunction walkAndRegister(nodes: VNode[]) {\n for (const node of nodes) {\n // ComboBoxItem VNodes have a `value` prop; extract their text children\n if (node.props && typeof node.props.value === 'string') {\n const value = node.props.value as string\n const children = node.children\n if (children && typeof children === 'object' && 'default' in children) {\n const slotFn = (children as Record<string, () => VNode[]>).default\n if (typeof slotFn === 'function') {\n const text = extractNodeText(slotFn()).trim()\n if (text) ctx.registerItem(value, text)\n }\n } else if (typeof children === 'string') {\n const text = children.trim()\n if (text) ctx.registerItem(value, text)\n } else if (Array.isArray(children)) {\n const text = extractNodeText(children as VNode[]).trim()\n if (text) ctx.registerItem(value, text)\n }\n }\n // Recurse into children arrays\n if (Array.isArray(node.children)) {\n walkAndRegister(node.children as VNode[])\n }\n }\n}\n\n// Run synchronously at setup time and whenever the slot content changes\nwatchEffect(() => {\n const vnodes = (slots.default as (() => VNode[]) | undefined)?.()\n if (vnodes) walkAndRegister(vnodes)\n})\n</script>\n\n<template>\n <ComboboxPortal>\n <AnimatePresence>\n <ComboboxContent\n v-if=\"comboboxRootContext.open.value\"\n position=\"popper\"\n :side-offset=\"props.sideOffset\"\n as-child\n data-slot=\"popover\"\n >\n <motion.div\n :class=\"ctx.slots.value.popover()\"\n :initial=\"{ opacity: 0, scale: 0.95 }\"\n :animate=\"{ opacity: 1, scale: 1 }\"\n :exit=\"{ opacity: 0, scale: 0.95 }\"\n :transition=\"{ duration: 0.15 }\"\n >\n <ComboboxViewport data-slot=\"list-box\">\n <slot />\n <slot name=\"empty\" />\n </ComboboxViewport>\n </motion.div>\n </ComboboxContent>\n </AnimatePresence>\n </ComboboxPortal>\n</template>\n"],"mappings":";;;;;;;;;;;;;EAMA,MAAM,QAAQ;EAQd,MAAM,MAAM,mBAAkB;EAC9B,MAAM,sBAAsB,2BAA0B;EAItD,MAAM,QAAQ,UAAS;EAEvB,SAAS,gBAAgB,OAAwB;AAC/C,UAAO,MAAM,KAAI,MAAK;AACpB,QAAI,OAAO,EAAE,aAAa,SAAU,QAAO,EAAE;AAC7C,QAAI,MAAM,QAAQ,EAAE,SAAS,CAAE,QAAO,gBAAgB,EAAE,SAAmB;AAC3E,WAAO;KACP,CAAC,KAAK,GAAE;;EAGZ,SAAS,gBAAgB,OAAgB;AACvC,QAAK,MAAM,QAAQ,OAAO;AAExB,QAAI,KAAK,SAAS,OAAO,KAAK,MAAM,UAAU,UAAU;KACtD,MAAM,QAAQ,KAAK,MAAM;KACzB,MAAM,WAAW,KAAK;AACtB,SAAI,YAAY,OAAO,aAAa,YAAY,aAAa,UAAU;MACrE,MAAM,SAAU,SAA2C;AAC3D,UAAI,OAAO,WAAW,YAAY;OAChC,MAAM,OAAO,gBAAgB,QAAQ,CAAC,CAAC,MAAK;AAC5C,WAAI,KAAM,KAAI,aAAa,OAAO,KAAI;;gBAE/B,OAAO,aAAa,UAAU;MACvC,MAAM,OAAO,SAAS,MAAK;AAC3B,UAAI,KAAM,KAAI,aAAa,OAAO,KAAI;gBAC7B,MAAM,QAAQ,SAAS,EAAE;MAClC,MAAM,OAAO,gBAAgB,SAAoB,CAAC,MAAK;AACvD,UAAI,KAAM,KAAI,aAAa,OAAO,KAAI;;;AAI1C,QAAI,MAAM,QAAQ,KAAK,SAAS,CAC9B,iBAAgB,KAAK,SAAmB;;;AAM9C,oBAAkB;GAChB,MAAM,SAAU,MAAM,WAA0C;AAChE,OAAI,OAAQ,iBAAgB,OAAM;IACnC;;uBAIC,YAuBiB,MAAA,eAAA,EAAA,MAAA;2BADG,CArBlB,YAqBkB,MAAA,wBAAA,EAAA,MAAA;4BADE,CAlBV,MAAA,oBAAmB,CAAC,KAAK,SAAA,WAAA,EADjC,YAmBkB,MAAA,gBAAA,EAAA;;MAjBhB,UAAS;MACR,eAAa,MAAM;MACpB,YAAA;MACA,aAAU;;6BAaG,CAXb,YAWa,MAAA,OAAA,CAAA,KAAA;OAVV,OAAK,eAAE,MAAA,IAAG,CAAC,MAAM,MAAM,SAAO,CAAA;OAC9B,SAAS;QAAA,SAAA;QAAA,OAAA;QAA2B;OACpC,SAAS;QAAA,SAAA;QAAA,OAAA;QAAwB;OACjC,MAAM;QAAA,SAAA;QAAA,OAAA;QAA2B;OACjC,YAAY,EAAA,UAAA,KAAkB;;8BAKZ,CAHnB,YAGmB,MAAA,iBAAA,EAAA,EAHD,aAAU,YAAU,EAAA;+BAC5B,CAAR,WAAQ,KAAA,QAAA,UAAA,EACR,WAAqB,KAAA,QAAA,QAAA,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComboBoxItem.js","names":[],"sources":["../../../src/components/combo-box/ComboBoxItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, useSlots, type VNode } from 'vue'\nimport { ComboboxItem, ComboboxItemIndicator } from 'reka-ui'\nimport { useComboBoxInject } from './ComboBox.context'\n\nconst props = withDefaults(defineProps<{\n value: string\n isDisabled?: boolean\n class?: string\n}>(), {\n isDisabled: false,\n class: undefined,\n})\n\nconst slots = useSlots()\nconst ctx = useComboBoxInject()\n\n// Extract plain text from default slot VNodes at render time.\nfunction extractText(nodes: VNode[]): string {\n return nodes.map(n => {\n if (typeof n.children === 'string') return n.children\n if (Array.isArray(n.children)) return extractText(n.children as VNode[])\n return ''\n }).join('')\n}\n\n// The display text Reka writes into the input when this item is selected.\n// Reads slot text content — no extra props needed.\nconst displayText = computed(() => {\n const vnodes = slots.default?.()\n if (!vnodes) return props.value\n return extractText(vnodes).trim() || props.value\n})\n\n// Register this item's value→label mapping with the parent ComboBox bridge\n// so displayValue() and handleModelValueUpdate() can translate correctly.\nonMounted(() => {\n ctx.registerItem(props.value, displayText.value)\n})\n\nonUnmounted(() => {\n ctx.unregisterItem(props.value)\n})\n</script>\n\n<template>\n <ComboboxItem\n :value=\"displayText\"\n :text-value=\"displayText\"\n :disabled=\"props.isDisabled\"\n :data-item-value=\"props.value\"\n class=\"list-box-item list-box-item--default\"\n data-slot=\"list-box-item\"\n >\n <slot name=\"startContent\" />\n <slot />\n <ComboboxItemIndicator\n class=\"list-box-item__indicator\"\n data-slot=\"list-box-item-indicator\"\n >\n <slot name=\"selectedIcon\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n data-slot=\"list-box-item-indicator--checkmark\"\n aria-hidden=\"true\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </slot>\n </ComboboxItemIndicator>\n <slot name=\"endContent\" />\n </ComboboxItem>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"ComboBoxItem.js","names":[],"sources":["../../../src/components/combo-box/ComboBoxItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, useSlots, type Slots, type VNode } from 'vue'\nimport { ComboboxItem, ComboboxItemIndicator } from 'reka-ui'\nimport { useComboBoxInject } from './ComboBox.context'\n\nconst props = withDefaults(defineProps<{\n value: string\n isDisabled?: boolean\n class?: string\n}>(), {\n isDisabled: false,\n class: undefined,\n})\n\nconst slots: Slots = useSlots()\nconst ctx = useComboBoxInject()\n\n// Extract plain text from default slot VNodes at render time.\nfunction extractText(nodes: VNode[]): string {\n return nodes.map(n => {\n if (typeof n.children === 'string') return n.children\n if (Array.isArray(n.children)) return extractText(n.children as VNode[])\n return ''\n }).join('')\n}\n\n// The display text Reka writes into the input when this item is selected.\n// Reads slot text content — no extra props needed.\nconst displayText = computed((): string => {\n const vnodes: VNode[] | undefined = (slots.default as (() => VNode[]) | undefined)?.()\n if (!vnodes) return props.value\n return extractText(vnodes).trim() || props.value\n})\n\n// Register this item's value→label mapping with the parent ComboBox bridge\n// so displayValue() and handleModelValueUpdate() can translate correctly.\nonMounted(() => {\n ctx.registerItem(props.value, displayText.value)\n})\n\nonUnmounted(() => {\n ctx.unregisterItem(props.value)\n})\n</script>\n\n<template>\n <ComboboxItem\n :value=\"displayText\"\n :text-value=\"displayText\"\n :disabled=\"props.isDisabled\"\n :data-item-value=\"props.value\"\n class=\"list-box-item list-box-item--default\"\n data-slot=\"list-box-item\"\n >\n <slot name=\"startContent\" />\n <slot />\n <ComboboxItemIndicator\n class=\"list-box-item__indicator\"\n data-slot=\"list-box-item-indicator\"\n >\n <slot name=\"selectedIcon\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n data-slot=\"list-box-item-indicator--checkmark\"\n aria-hidden=\"true\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </slot>\n </ComboboxItemIndicator>\n <slot name=\"endContent\" />\n </ComboboxItem>\n</template>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComboBoxItem.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/combo-box/ComboBoxItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, useSlots, type VNode } from 'vue'\nimport { ComboboxItem, ComboboxItemIndicator } from 'reka-ui'\nimport { useComboBoxInject } from './ComboBox.context'\n\nconst props = withDefaults(defineProps<{\n value: string\n isDisabled?: boolean\n class?: string\n}>(), {\n isDisabled: false,\n class: undefined,\n})\n\nconst slots = useSlots()\nconst ctx = useComboBoxInject()\n\n// Extract plain text from default slot VNodes at render time.\nfunction extractText(nodes: VNode[]): string {\n return nodes.map(n => {\n if (typeof n.children === 'string') return n.children\n if (Array.isArray(n.children)) return extractText(n.children as VNode[])\n return ''\n }).join('')\n}\n\n// The display text Reka writes into the input when this item is selected.\n// Reads slot text content — no extra props needed.\nconst displayText = computed(() => {\n const vnodes = slots.default?.()\n if (!vnodes) return props.value\n return extractText(vnodes).trim() || props.value\n})\n\n// Register this item's value→label mapping with the parent ComboBox bridge\n// so displayValue() and handleModelValueUpdate() can translate correctly.\nonMounted(() => {\n ctx.registerItem(props.value, displayText.value)\n})\n\nonUnmounted(() => {\n ctx.unregisterItem(props.value)\n})\n</script>\n\n<template>\n <ComboboxItem\n :value=\"displayText\"\n :text-value=\"displayText\"\n :disabled=\"props.isDisabled\"\n :data-item-value=\"props.value\"\n class=\"list-box-item list-box-item--default\"\n data-slot=\"list-box-item\"\n >\n <slot name=\"startContent\" />\n <slot />\n <ComboboxItemIndicator\n class=\"list-box-item__indicator\"\n data-slot=\"list-box-item-indicator\"\n >\n <slot name=\"selectedIcon\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n data-slot=\"list-box-item-indicator--checkmark\"\n aria-hidden=\"true\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </slot>\n </ComboboxItemIndicator>\n <slot name=\"endContent\" />\n </ComboboxItem>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;EAKA,MAAM,QAAQ;EASd,MAAM,
|
|
1
|
+
{"version":3,"file":"ComboBoxItem.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/combo-box/ComboBoxItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, useSlots, type Slots, type VNode } from 'vue'\nimport { ComboboxItem, ComboboxItemIndicator } from 'reka-ui'\nimport { useComboBoxInject } from './ComboBox.context'\n\nconst props = withDefaults(defineProps<{\n value: string\n isDisabled?: boolean\n class?: string\n}>(), {\n isDisabled: false,\n class: undefined,\n})\n\nconst slots: Slots = useSlots()\nconst ctx = useComboBoxInject()\n\n// Extract plain text from default slot VNodes at render time.\nfunction extractText(nodes: VNode[]): string {\n return nodes.map(n => {\n if (typeof n.children === 'string') return n.children\n if (Array.isArray(n.children)) return extractText(n.children as VNode[])\n return ''\n }).join('')\n}\n\n// The display text Reka writes into the input when this item is selected.\n// Reads slot text content — no extra props needed.\nconst displayText = computed((): string => {\n const vnodes: VNode[] | undefined = (slots.default as (() => VNode[]) | undefined)?.()\n if (!vnodes) return props.value\n return extractText(vnodes).trim() || props.value\n})\n\n// Register this item's value→label mapping with the parent ComboBox bridge\n// so displayValue() and handleModelValueUpdate() can translate correctly.\nonMounted(() => {\n ctx.registerItem(props.value, displayText.value)\n})\n\nonUnmounted(() => {\n ctx.unregisterItem(props.value)\n})\n</script>\n\n<template>\n <ComboboxItem\n :value=\"displayText\"\n :text-value=\"displayText\"\n :disabled=\"props.isDisabled\"\n :data-item-value=\"props.value\"\n class=\"list-box-item list-box-item--default\"\n data-slot=\"list-box-item\"\n >\n <slot name=\"startContent\" />\n <slot />\n <ComboboxItemIndicator\n class=\"list-box-item__indicator\"\n data-slot=\"list-box-item-indicator\"\n >\n <slot name=\"selectedIcon\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n data-slot=\"list-box-item-indicator--checkmark\"\n aria-hidden=\"true\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </slot>\n </ComboboxItemIndicator>\n <slot name=\"endContent\" />\n </ComboboxItem>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;EAKA,MAAM,QAAQ;EASd,MAAM,QAAe,UAAS;EAC9B,MAAM,MAAM,mBAAkB;EAG9B,SAAS,YAAY,OAAwB;AAC3C,UAAO,MAAM,KAAI,MAAK;AACpB,QAAI,OAAO,EAAE,aAAa,SAAU,QAAO,EAAE;AAC7C,QAAI,MAAM,QAAQ,EAAE,SAAS,CAAE,QAAO,YAAY,EAAE,SAAmB;AACvE,WAAO;KACP,CAAC,KAAK,GAAE;;EAKZ,MAAM,cAAc,eAAuB;GACzC,MAAM,SAA+B,MAAM,WAA0C;AACrF,OAAI,CAAC,OAAQ,QAAO,MAAM;AAC1B,UAAO,YAAY,OAAO,CAAC,MAAM,IAAI,MAAM;IAC5C;AAID,kBAAgB;AACd,OAAI,aAAa,MAAM,OAAO,YAAY,MAAK;IAChD;AAED,oBAAkB;AAChB,OAAI,eAAe,MAAM,MAAK;IAC/B;;uBAIC,YAiCe,MAAA,aAAA,EAAA;IAhCZ,OAAO,YAAA;IACP,cAAY,YAAA;IACZ,UAAU,MAAM;IAChB,mBAAiB,MAAM;IACxB,OAAM;IACN,aAAU;;2BAEkB;KAA5B,WAA4B,KAAA,QAAA,eAAA;KAC5B,WAAQ,KAAA,QAAA,UAAA;KACR,YAqBwB,MAAA,sBAAA,EAAA;MApBtB,OAAM;MACN,aAAU;;6BAkBH,CAhBP,WAgBO,KAAA,QAAA,gBAAA,EAAA,QAAA,CAAA,OAAA,OAAA,OAAA,KAfL,mBAcM,OAAA;OAbJ,OAAM;OACN,OAAM;OACN,QAAO;OACP,SAAQ;OACR,MAAK;OACL,QAAO;OACP,gBAAa;OACb,kBAAe;OACf,mBAAgB;OAChB,aAAU;OACV,eAAY;UAEZ,mBAAoC,YAAA,EAA1B,QAAO,kBAAgB,CAAA,CAAA,EAAA,GAAA,EAAA,CAAA,CAAA,CAAA;;;KAIvC,WAA0B,KAAA,QAAA,aAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tab.js","names":[],"sources":["../../../src/components/tabs/Tab.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { TabsTrigger } from 'reka-ui'\nimport { composeClassName } from '../../utils/composeClassName'\nimport { useTabsInject } from './tabs.context'\n\nconst props = defineProps<{\n value: string\n disabled?: boolean\n class?: string\n}>()\n\nconst ctx = useTabsInject()\n</script>\n\n<template>\n <TabsTrigger\n :value=\"props.value\"\n :disabled=\"props.disabled\"\n :class=\"composeClassName(ctx.slotFns.value.tab(), props.class)\"\n >\n <slot />\n </TabsTrigger>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"Tab.js","names":[],"sources":["../../../src/components/tabs/Tab.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { TabsTrigger } from 'reka-ui'\nimport { composeClassName } from '../../utils/composeClassName'\nimport { useTabsInject } from './tabs.context'\n\nconst props = defineProps<{\n value: string\n disabled?: boolean\n class?: string\n}>()\n\nconst ctx = useTabsInject()\n</script>\n\n<template>\n <TabsTrigger\n :value=\"props.value\"\n :disabled=\"props.disabled\"\n :data-tab-value=\"props.value\"\n :class=\"composeClassName(ctx.slotFns.value.tab(), props.class)\"\n >\n <slot />\n </TabsTrigger>\n</template>\n"],"mappings":""}
|
|
@@ -17,6 +17,7 @@ var Tab_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComp
|
|
|
17
17
|
return openBlock(), createBlock(unref(TabsTrigger), {
|
|
18
18
|
value: props.value,
|
|
19
19
|
disabled: props.disabled,
|
|
20
|
+
"data-tab-value": props.value,
|
|
20
21
|
class: normalizeClass(unref(composeClassName)(unref(ctx).slotFns.value.tab(), props.class))
|
|
21
22
|
}, {
|
|
22
23
|
default: withCtx(() => [renderSlot(_ctx.$slots, "default")]),
|
|
@@ -24,6 +25,7 @@ var Tab_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComp
|
|
|
24
25
|
}, 8, [
|
|
25
26
|
"value",
|
|
26
27
|
"disabled",
|
|
28
|
+
"data-tab-value",
|
|
27
29
|
"class"
|
|
28
30
|
]);
|
|
29
31
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tab.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/tabs/Tab.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { TabsTrigger } from 'reka-ui'\nimport { composeClassName } from '../../utils/composeClassName'\nimport { useTabsInject } from './tabs.context'\n\nconst props = defineProps<{\n value: string\n disabled?: boolean\n class?: string\n}>()\n\nconst ctx = useTabsInject()\n</script>\n\n<template>\n <TabsTrigger\n :value=\"props.value\"\n :disabled=\"props.disabled\"\n :class=\"composeClassName(ctx.slotFns.value.tab(), props.class)\"\n >\n <slot />\n </TabsTrigger>\n</template>\n"],"mappings":";;;;;;;;;;;;;EAKA,MAAM,QAAQ;EAMd,MAAM,MAAM,eAAc;;uBAIxB,
|
|
1
|
+
{"version":3,"file":"Tab.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/tabs/Tab.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { TabsTrigger } from 'reka-ui'\nimport { composeClassName } from '../../utils/composeClassName'\nimport { useTabsInject } from './tabs.context'\n\nconst props = defineProps<{\n value: string\n disabled?: boolean\n class?: string\n}>()\n\nconst ctx = useTabsInject()\n</script>\n\n<template>\n <TabsTrigger\n :value=\"props.value\"\n :disabled=\"props.disabled\"\n :data-tab-value=\"props.value\"\n :class=\"composeClassName(ctx.slotFns.value.tab(), props.class)\"\n >\n <slot />\n </TabsTrigger>\n</template>\n"],"mappings":";;;;;;;;;;;;;EAKA,MAAM,QAAQ;EAMd,MAAM,MAAM,eAAc;;uBAIxB,YAOc,MAAA,YAAA,EAAA;IANX,OAAO,MAAM;IACb,UAAU,MAAM;IAChB,kBAAgB,MAAM;IACtB,OAAK,eAAE,MAAA,iBAAgB,CAAC,MAAA,IAAG,CAAC,QAAQ,MAAM,KAAG,EAAI,MAAM,MAAK,CAAA;;2BAErD,CAAR,WAAQ,KAAA,QAAA,UAAA,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabList.js","names":[],"sources":["../../../src/components/tabs/TabList.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { TabsList } from 'reka-ui'\nimport { composeClassName } from '../../utils/composeClassName'\nimport { useTabsInject } from './tabs.context'\n\nconst props = defineProps<{\n loop?: boolean\n class?: string\n}>()\n\nconst ctx = useTabsInject()\n</script>\n\n<template>\n <TabsList\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), props.class)\"\n >\n <slot />\n </TabsList>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"TabList.js","names":[],"sources":["../../../src/components/tabs/TabList.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, nextTick, onMounted, watch } from 'vue'\nimport { useTemplateRef } from 'vue'\nimport { TabsList } from 'reka-ui'\nimport { useResizeObserver, onClickOutside } from '@vueuse/core'\nimport { composeClassName } from '../../utils/composeClassName'\nimport { useTabsInject } from './tabs.context'\nimport Button from '../button/Button.vue'\n\nconst props = defineProps<{\n loop?: boolean\n overflow?: 'arrows' | 'dropdown'\n class?: string\n}>()\n\nconst ctx = useTabsInject()\n\n// ── Arrows mode ─────────────────────────────────────────────────────────────\nconst scrollWrapperEl = useTemplateRef<HTMLElement>('scrollWrapperEl')\nconst canScrollLeft = ref(false)\nconst canScrollRight = ref(false)\n\nfunction updateScrollButtons() {\n const el = scrollWrapperEl.value\n if (!el) { canScrollLeft.value = false; canScrollRight.value = false; return }\n canScrollLeft.value = el.scrollLeft > 1\n canScrollRight.value = el.scrollLeft + el.clientWidth < el.scrollWidth - 1\n}\n\nfunction scrollTabs(dir: 'left' | 'right') {\n const el = scrollWrapperEl.value\n if (!el) return\n el.scrollBy({ left: dir === 'left' ? -200 : 200, behavior: 'smooth' })\n // Poll briefly after smooth scroll starts so button states update\n setTimeout(updateScrollButtons, 150)\n setTimeout(updateScrollButtons, 350)\n}\n\nwatch(scrollWrapperEl, (el, oldEl) => {\n if (oldEl) oldEl.removeEventListener('scroll', updateScrollButtons)\n if (el) {\n el.addEventListener('scroll', updateScrollButtons, { passive: true })\n nextTick(updateScrollButtons)\n }\n}, { immediate: true })\n\nuseResizeObserver(scrollWrapperEl, () => nextTick(updateScrollButtons))\n\n// ── Dropdown mode ────────────────────────────────────────────────────────────\ninterface OverflowTab {\n value: string\n label: string\n disabled: boolean\n}\n\nconst containerEl = useTemplateRef<HTMLElement>('containerEl')\n// Button component ref — use .$el to reach the underlying DOM element for offsetWidth\nconst moreBtnEl = useTemplateRef<InstanceType<typeof Button>>('moreBtnEl')\nconst dropdownEl = useTemplateRef<HTMLElement>('dropdownEl')\n\nconst hiddenTabs = ref<OverflowTab[]>([])\nconst dropdownOpen = ref(false)\nconst hasOverflow = computed(() => hiddenTabs.value.length > 0)\n// Pre-measured natural width of the more button (measured once on mount before it's visible)\nlet moreBtnNaturalWidth = 48\n\nonClickOutside(dropdownEl, () => { dropdownOpen.value = false })\n\nfunction computeOverflow() {\n if (!containerEl.value) return\n\n const allTabs = Array.from(\n containerEl.value.querySelectorAll('[data-tab-value]'),\n ) as HTMLElement[]\n\n // Reveal all tabs first\n allTabs.forEach(t => t.removeAttribute('data-overflow-hidden'))\n\n // Tabs use w-full and shrink to share the container width, so offsetWidth after\n // a normal render would be containerWidth/n — useless for overflow detection.\n // Force each tab to its natural content width for measurement only (no paint flash:\n // all DOM reads/writes happen synchronously within this JS task before the next frame).\n const listEl = containerEl.value.querySelector('[role=\"tablist\"]') as HTMLElement | null\n if (listEl) {\n listEl.style.overflow = 'visible'\n allTabs.forEach(t => { t.style.flexShrink = '0'; t.style.width = 'auto' })\n void listEl.offsetWidth // force reflow so offsetWidth reads below are accurate\n }\n\n const containerWidth = containerEl.value.clientWidth\n const tabWidths = allTabs.map(t => t.offsetWidth)\n const totalWidth = tabWidths.reduce((sum, w) => sum + w, 0)\n\n // Restore layout before any early-return so tabs always look correct\n if (listEl) {\n listEl.style.overflow = ''\n allTabs.forEach(t => { t.style.flexShrink = ''; t.style.width = '' })\n }\n\n if (totalWidth <= containerWidth) {\n hiddenTabs.value = []\n return\n }\n\n // More button is in-flow (display:none when no overflow, display:flex when visible).\n // Use the pre-measured natural width so the calculation is accurate on the first run\n // before the button becomes visible.\n const available = containerWidth - moreBtnNaturalWidth\n\n let accumulated = 0\n const newHidden: OverflowTab[] = []\n const visibleEls: HTMLElement[] = []\n\n for (let i = 0; i < allTabs.length; i++) {\n const tab = allTabs[i]\n const w = tabWidths[i]\n if (accumulated + w <= available) {\n accumulated += w\n visibleEls.push(tab)\n } else {\n newHidden.push({\n value: tab.getAttribute('data-tab-value') ?? '',\n label: tab.textContent?.trim() ?? '',\n disabled: tab.hasAttribute('data-disabled') || tab.getAttribute('aria-disabled') === 'true',\n })\n tab.setAttribute('data-overflow-hidden', '')\n }\n }\n\n // If the active tab ended up hidden, swap it with the last visible tab\n const activeValue = ctx.currentValue.value\n if (activeValue) {\n const hiddenActiveIdx = newHidden.findIndex(t => t.value === activeValue)\n if (hiddenActiveIdx !== -1 && visibleEls.length > 0) {\n const displacedEl = visibleEls[visibleEls.length - 1]\n const activeEl = allTabs.find(t => t.getAttribute('data-tab-value') === activeValue)\n\n if (displacedEl && activeEl) {\n // Swap: make displaced tab hidden, active tab visible\n displacedEl.setAttribute('data-overflow-hidden', '')\n activeEl.removeAttribute('data-overflow-hidden')\n\n const displaced: OverflowTab = {\n value: displacedEl.getAttribute('data-tab-value') ?? '',\n label: displacedEl.textContent?.trim() ?? '',\n disabled: displacedEl.hasAttribute('data-disabled') || displacedEl.getAttribute('aria-disabled') === 'true',\n }\n newHidden.splice(hiddenActiveIdx, 1)\n newHidden.unshift(displaced)\n }\n }\n }\n\n hiddenTabs.value = newHidden\n}\n\nuseResizeObserver(containerEl, () => nextTick(computeOverflow))\nonMounted(() => {\n // Pre-measure the more button's natural width before it becomes visible (display:none).\n // Temporarily show it, read offsetWidth, then hide again — happens before first paint.\n const btnEl = (moreBtnEl.value as InstanceType<typeof Button> | null)?.$el as HTMLElement | null\n if (btnEl) {\n btnEl.style.display = 'flex'\n void btnEl.offsetWidth\n moreBtnNaturalWidth = btnEl.offsetWidth\n btnEl.style.display = ''\n }\n nextTick(computeOverflow)\n})\n\n// Recompute when the active tab changes so the active tab is always visible\nwatch(() => ctx.currentValue.value, () => {\n if (props.overflow === 'dropdown') nextTick(computeOverflow)\n})\n\n// When overflow state first transitions false→true the more button enters the flex flow,\n// narrowing the container. Re-run once so the tab count reflects the reduced available space.\nwatch(hasOverflow, () => {\n if (props.overflow === 'dropdown') nextTick(computeOverflow)\n})\n\nfunction selectOverflowTab(value: string) {\n ctx.changeTab(value)\n dropdownOpen.value = false\n}\n</script>\n\n<template>\n <!-- ── Default (no overflow behaviour) ───────────────────────────────────── -->\n <TabsList\n v-if=\"!props.overflow\"\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), props.class)\"\n >\n <slot />\n </TabsList>\n\n <!-- ── Arrows mode ────────────────────────────────────────────────────────── -->\n <div\n v-else-if=\"props.overflow === 'arrows'\"\n class=\"tabs__list-container tabs__list-container--arrows\"\n :class=\"{ 'has-left': canScrollLeft, 'has-right': canScrollRight }\"\n >\n <Button\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n :is-icon-only=\"true\"\n :class=\"composeClassName('tabs__arrow tabs__arrow--left', canScrollLeft && 'is-visible')\"\n aria-label=\"Scroll tabs left\"\n tabindex=\"-1\"\n @click=\"scrollTabs('left')\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M9 11L5 7L9 3\" stroke=\"currentColor\" stroke-width=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n\n <div ref=\"scrollWrapperEl\" class=\"tabs__scroll-wrapper\">\n <TabsList\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--scroll', props.class)\"\n >\n <slot />\n </TabsList>\n </div>\n\n <Button\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n :is-icon-only=\"true\"\n :class=\"composeClassName('tabs__arrow tabs__arrow--right', canScrollRight && 'is-visible')\"\n aria-label=\"Scroll tabs right\"\n tabindex=\"-1\"\n @click=\"scrollTabs('right')\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M5 3L9 7L5 11\" stroke=\"currentColor\" stroke-width=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n </div>\n\n <!-- ── Dropdown mode ──────────────────────────────────────────────────────── -->\n <div\n v-else-if=\"props.overflow === 'dropdown'\"\n ref=\"containerEl\"\n class=\"tabs__list-container tabs__list-container--dropdown\"\n >\n <TabsList\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--clipped', props.class)\"\n >\n <slot />\n </TabsList>\n\n <!-- Always rendered so offsetWidth is measurable; visibility toggled via CSS -->\n <div\n ref=\"dropdownEl\"\n class=\"tabs__more\"\n :class=\"{ 'tabs__more--visible': hasOverflow }\"\n >\n <Button\n ref=\"moreBtnEl\"\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n class=\"tabs__more-btn\"\n :aria-expanded=\"dropdownOpen\"\n aria-haspopup=\"menu\"\n @click=\"dropdownOpen = !dropdownOpen\"\n >\n +{{ hiddenTabs.length }}\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M2 4L6 8L10 4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n\n <div v-if=\"dropdownOpen\" class=\"tabs__overflow-menu\" role=\"menu\">\n <Button\n v-for=\"tab in hiddenTabs\"\n :key=\"tab.value\"\n variant=\"ghost\"\n radius=\"lg\"\n class=\"tabs__overflow-item\"\n role=\"menuitem\"\n :disabled=\"tab.disabled\"\n @click=\"selectOverflowTab(tab.value)\"\n >\n {{ tab.label }}\n </Button>\n </div>\n </div>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -1,25 +1,284 @@
|
|
|
1
1
|
import { composeClassName } from "../../utils/composeClassName.js";
|
|
2
|
+
import Button_default from "../button/Button.js";
|
|
2
3
|
import { useTabsInject } from "./tabs.context.js";
|
|
3
|
-
import { createBlock, defineComponent, normalizeClass, openBlock, renderSlot, unref, withCtx } from "vue";
|
|
4
|
+
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, nextTick, normalizeClass, onMounted, openBlock, ref, renderList, renderSlot, toDisplayString, unref, useTemplateRef, watch, withCtx } from "vue";
|
|
5
|
+
import { onClickOutside, useResizeObserver } from "@vueuse/core";
|
|
4
6
|
import { TabsList } from "reka-ui";
|
|
5
7
|
//#region src/components/tabs/TabList.vue?vue&type=script&setup=true&lang.ts
|
|
8
|
+
var _hoisted_1 = {
|
|
9
|
+
key: 0,
|
|
10
|
+
class: "tabs__overflow-menu",
|
|
11
|
+
role: "menu"
|
|
12
|
+
};
|
|
6
13
|
var TabList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
|
|
7
14
|
__name: "TabList",
|
|
8
15
|
props: {
|
|
9
16
|
loop: { type: Boolean },
|
|
17
|
+
overflow: {},
|
|
10
18
|
class: {}
|
|
11
19
|
},
|
|
12
20
|
setup(__props) {
|
|
13
21
|
const props = __props;
|
|
14
22
|
const ctx = useTabsInject();
|
|
23
|
+
const scrollWrapperEl = useTemplateRef("scrollWrapperEl");
|
|
24
|
+
const canScrollLeft = ref(false);
|
|
25
|
+
const canScrollRight = ref(false);
|
|
26
|
+
function updateScrollButtons() {
|
|
27
|
+
const el = scrollWrapperEl.value;
|
|
28
|
+
if (!el) {
|
|
29
|
+
canScrollLeft.value = false;
|
|
30
|
+
canScrollRight.value = false;
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
canScrollLeft.value = el.scrollLeft > 1;
|
|
34
|
+
canScrollRight.value = el.scrollLeft + el.clientWidth < el.scrollWidth - 1;
|
|
35
|
+
}
|
|
36
|
+
function scrollTabs(dir) {
|
|
37
|
+
const el = scrollWrapperEl.value;
|
|
38
|
+
if (!el) return;
|
|
39
|
+
el.scrollBy({
|
|
40
|
+
left: dir === "left" ? -200 : 200,
|
|
41
|
+
behavior: "smooth"
|
|
42
|
+
});
|
|
43
|
+
setTimeout(updateScrollButtons, 150);
|
|
44
|
+
setTimeout(updateScrollButtons, 350);
|
|
45
|
+
}
|
|
46
|
+
watch(scrollWrapperEl, (el, oldEl) => {
|
|
47
|
+
if (oldEl) oldEl.removeEventListener("scroll", updateScrollButtons);
|
|
48
|
+
if (el) {
|
|
49
|
+
el.addEventListener("scroll", updateScrollButtons, { passive: true });
|
|
50
|
+
nextTick(updateScrollButtons);
|
|
51
|
+
}
|
|
52
|
+
}, { immediate: true });
|
|
53
|
+
useResizeObserver(scrollWrapperEl, () => nextTick(updateScrollButtons));
|
|
54
|
+
const containerEl = useTemplateRef("containerEl");
|
|
55
|
+
const moreBtnEl = useTemplateRef("moreBtnEl");
|
|
56
|
+
const dropdownEl = useTemplateRef("dropdownEl");
|
|
57
|
+
const hiddenTabs = ref([]);
|
|
58
|
+
const dropdownOpen = ref(false);
|
|
59
|
+
const hasOverflow = computed(() => hiddenTabs.value.length > 0);
|
|
60
|
+
let moreBtnNaturalWidth = 48;
|
|
61
|
+
onClickOutside(dropdownEl, () => {
|
|
62
|
+
dropdownOpen.value = false;
|
|
63
|
+
});
|
|
64
|
+
function computeOverflow() {
|
|
65
|
+
if (!containerEl.value) return;
|
|
66
|
+
const allTabs = Array.from(containerEl.value.querySelectorAll("[data-tab-value]"));
|
|
67
|
+
allTabs.forEach((t) => t.removeAttribute("data-overflow-hidden"));
|
|
68
|
+
const listEl = containerEl.value.querySelector("[role=\"tablist\"]");
|
|
69
|
+
if (listEl) {
|
|
70
|
+
listEl.style.overflow = "visible";
|
|
71
|
+
allTabs.forEach((t) => {
|
|
72
|
+
t.style.flexShrink = "0";
|
|
73
|
+
t.style.width = "auto";
|
|
74
|
+
});
|
|
75
|
+
listEl.offsetWidth;
|
|
76
|
+
}
|
|
77
|
+
const containerWidth = containerEl.value.clientWidth;
|
|
78
|
+
const tabWidths = allTabs.map((t) => t.offsetWidth);
|
|
79
|
+
const totalWidth = tabWidths.reduce((sum, w) => sum + w, 0);
|
|
80
|
+
if (listEl) {
|
|
81
|
+
listEl.style.overflow = "";
|
|
82
|
+
allTabs.forEach((t) => {
|
|
83
|
+
t.style.flexShrink = "";
|
|
84
|
+
t.style.width = "";
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
if (totalWidth <= containerWidth) {
|
|
88
|
+
hiddenTabs.value = [];
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const available = containerWidth - moreBtnNaturalWidth;
|
|
92
|
+
let accumulated = 0;
|
|
93
|
+
const newHidden = [];
|
|
94
|
+
const visibleEls = [];
|
|
95
|
+
for (let i = 0; i < allTabs.length; i++) {
|
|
96
|
+
const tab = allTabs[i];
|
|
97
|
+
const w = tabWidths[i];
|
|
98
|
+
if (accumulated + w <= available) {
|
|
99
|
+
accumulated += w;
|
|
100
|
+
visibleEls.push(tab);
|
|
101
|
+
} else {
|
|
102
|
+
newHidden.push({
|
|
103
|
+
value: tab.getAttribute("data-tab-value") ?? "",
|
|
104
|
+
label: tab.textContent?.trim() ?? "",
|
|
105
|
+
disabled: tab.hasAttribute("data-disabled") || tab.getAttribute("aria-disabled") === "true"
|
|
106
|
+
});
|
|
107
|
+
tab.setAttribute("data-overflow-hidden", "");
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const activeValue = ctx.currentValue.value;
|
|
111
|
+
if (activeValue) {
|
|
112
|
+
const hiddenActiveIdx = newHidden.findIndex((t) => t.value === activeValue);
|
|
113
|
+
if (hiddenActiveIdx !== -1 && visibleEls.length > 0) {
|
|
114
|
+
const displacedEl = visibleEls[visibleEls.length - 1];
|
|
115
|
+
const activeEl = allTabs.find((t) => t.getAttribute("data-tab-value") === activeValue);
|
|
116
|
+
if (displacedEl && activeEl) {
|
|
117
|
+
displacedEl.setAttribute("data-overflow-hidden", "");
|
|
118
|
+
activeEl.removeAttribute("data-overflow-hidden");
|
|
119
|
+
const displaced = {
|
|
120
|
+
value: displacedEl.getAttribute("data-tab-value") ?? "",
|
|
121
|
+
label: displacedEl.textContent?.trim() ?? "",
|
|
122
|
+
disabled: displacedEl.hasAttribute("data-disabled") || displacedEl.getAttribute("aria-disabled") === "true"
|
|
123
|
+
};
|
|
124
|
+
newHidden.splice(hiddenActiveIdx, 1);
|
|
125
|
+
newHidden.unshift(displaced);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
hiddenTabs.value = newHidden;
|
|
130
|
+
}
|
|
131
|
+
useResizeObserver(containerEl, () => nextTick(computeOverflow));
|
|
132
|
+
onMounted(() => {
|
|
133
|
+
const btnEl = moreBtnEl.value?.$el;
|
|
134
|
+
if (btnEl) {
|
|
135
|
+
btnEl.style.display = "flex";
|
|
136
|
+
btnEl.offsetWidth;
|
|
137
|
+
moreBtnNaturalWidth = btnEl.offsetWidth;
|
|
138
|
+
btnEl.style.display = "";
|
|
139
|
+
}
|
|
140
|
+
nextTick(computeOverflow);
|
|
141
|
+
});
|
|
142
|
+
watch(() => ctx.currentValue.value, () => {
|
|
143
|
+
if (props.overflow === "dropdown") nextTick(computeOverflow);
|
|
144
|
+
});
|
|
145
|
+
watch(hasOverflow, () => {
|
|
146
|
+
if (props.overflow === "dropdown") nextTick(computeOverflow);
|
|
147
|
+
});
|
|
148
|
+
function selectOverflowTab(value) {
|
|
149
|
+
ctx.changeTab(value);
|
|
150
|
+
dropdownOpen.value = false;
|
|
151
|
+
}
|
|
15
152
|
return (_ctx, _cache) => {
|
|
16
|
-
return openBlock(), createBlock(unref(TabsList), {
|
|
153
|
+
return !props.overflow ? (openBlock(), createBlock(unref(TabsList), {
|
|
154
|
+
key: 0,
|
|
17
155
|
loop: props.loop ?? true,
|
|
18
156
|
class: normalizeClass(unref(composeClassName)(unref(ctx).slotFns.value.tabList(), props.class))
|
|
19
157
|
}, {
|
|
20
158
|
default: withCtx(() => [renderSlot(_ctx.$slots, "default")]),
|
|
21
159
|
_: 3
|
|
22
|
-
}, 8, ["loop", "class"])
|
|
160
|
+
}, 8, ["loop", "class"])) : props.overflow === "arrows" ? (openBlock(), createElementBlock("div", {
|
|
161
|
+
key: 1,
|
|
162
|
+
class: normalizeClass(["tabs__list-container tabs__list-container--arrows", {
|
|
163
|
+
"has-left": canScrollLeft.value,
|
|
164
|
+
"has-right": canScrollRight.value
|
|
165
|
+
}])
|
|
166
|
+
}, [
|
|
167
|
+
createVNode(Button_default, {
|
|
168
|
+
variant: "secondary",
|
|
169
|
+
size: "sm",
|
|
170
|
+
radius: "full",
|
|
171
|
+
"is-icon-only": true,
|
|
172
|
+
class: normalizeClass(unref(composeClassName)("tabs__arrow tabs__arrow--left", canScrollLeft.value && "is-visible")),
|
|
173
|
+
"aria-label": "Scroll tabs left",
|
|
174
|
+
tabindex: "-1",
|
|
175
|
+
onClick: _cache[0] || (_cache[0] = ($event) => scrollTabs("left"))
|
|
176
|
+
}, {
|
|
177
|
+
default: withCtx(() => [..._cache[3] || (_cache[3] = [createElementVNode("svg", {
|
|
178
|
+
width: "14",
|
|
179
|
+
height: "14",
|
|
180
|
+
viewBox: "0 0 14 14",
|
|
181
|
+
fill: "none",
|
|
182
|
+
"aria-hidden": "true"
|
|
183
|
+
}, [createElementVNode("path", {
|
|
184
|
+
d: "M9 11L5 7L9 3",
|
|
185
|
+
stroke: "currentColor",
|
|
186
|
+
"stroke-width": "1.75",
|
|
187
|
+
"stroke-linecap": "round",
|
|
188
|
+
"stroke-linejoin": "round"
|
|
189
|
+
})], -1)])]),
|
|
190
|
+
_: 1
|
|
191
|
+
}, 8, ["class"]),
|
|
192
|
+
createElementVNode("div", {
|
|
193
|
+
ref_key: "scrollWrapperEl",
|
|
194
|
+
ref: scrollWrapperEl,
|
|
195
|
+
class: "tabs__scroll-wrapper"
|
|
196
|
+
}, [createVNode(unref(TabsList), {
|
|
197
|
+
loop: props.loop ?? true,
|
|
198
|
+
class: normalizeClass(unref(composeClassName)(unref(ctx).slotFns.value.tabList(), "tabs__list--scroll", props.class))
|
|
199
|
+
}, {
|
|
200
|
+
default: withCtx(() => [renderSlot(_ctx.$slots, "default")]),
|
|
201
|
+
_: 3
|
|
202
|
+
}, 8, ["loop", "class"])], 512),
|
|
203
|
+
createVNode(Button_default, {
|
|
204
|
+
variant: "secondary",
|
|
205
|
+
size: "sm",
|
|
206
|
+
radius: "full",
|
|
207
|
+
"is-icon-only": true,
|
|
208
|
+
class: normalizeClass(unref(composeClassName)("tabs__arrow tabs__arrow--right", canScrollRight.value && "is-visible")),
|
|
209
|
+
"aria-label": "Scroll tabs right",
|
|
210
|
+
tabindex: "-1",
|
|
211
|
+
onClick: _cache[1] || (_cache[1] = ($event) => scrollTabs("right"))
|
|
212
|
+
}, {
|
|
213
|
+
default: withCtx(() => [..._cache[4] || (_cache[4] = [createElementVNode("svg", {
|
|
214
|
+
width: "14",
|
|
215
|
+
height: "14",
|
|
216
|
+
viewBox: "0 0 14 14",
|
|
217
|
+
fill: "none",
|
|
218
|
+
"aria-hidden": "true"
|
|
219
|
+
}, [createElementVNode("path", {
|
|
220
|
+
d: "M5 3L9 7L5 11",
|
|
221
|
+
stroke: "currentColor",
|
|
222
|
+
"stroke-width": "1.75",
|
|
223
|
+
"stroke-linecap": "round",
|
|
224
|
+
"stroke-linejoin": "round"
|
|
225
|
+
})], -1)])]),
|
|
226
|
+
_: 1
|
|
227
|
+
}, 8, ["class"])
|
|
228
|
+
], 2)) : props.overflow === "dropdown" ? (openBlock(), createElementBlock("div", {
|
|
229
|
+
key: 2,
|
|
230
|
+
ref_key: "containerEl",
|
|
231
|
+
ref: containerEl,
|
|
232
|
+
class: "tabs__list-container tabs__list-container--dropdown"
|
|
233
|
+
}, [createVNode(unref(TabsList), {
|
|
234
|
+
loop: props.loop ?? true,
|
|
235
|
+
class: normalizeClass(unref(composeClassName)(unref(ctx).slotFns.value.tabList(), "tabs__list--clipped", props.class))
|
|
236
|
+
}, {
|
|
237
|
+
default: withCtx(() => [renderSlot(_ctx.$slots, "default")]),
|
|
238
|
+
_: 3
|
|
239
|
+
}, 8, ["loop", "class"]), createElementVNode("div", {
|
|
240
|
+
ref_key: "dropdownEl",
|
|
241
|
+
ref: dropdownEl,
|
|
242
|
+
class: normalizeClass(["tabs__more", { "tabs__more--visible": hasOverflow.value }])
|
|
243
|
+
}, [createVNode(Button_default, {
|
|
244
|
+
ref_key: "moreBtnEl",
|
|
245
|
+
ref: moreBtnEl,
|
|
246
|
+
variant: "secondary",
|
|
247
|
+
size: "sm",
|
|
248
|
+
radius: "full",
|
|
249
|
+
class: "tabs__more-btn",
|
|
250
|
+
"aria-expanded": dropdownOpen.value,
|
|
251
|
+
"aria-haspopup": "menu",
|
|
252
|
+
onClick: _cache[2] || (_cache[2] = ($event) => dropdownOpen.value = !dropdownOpen.value)
|
|
253
|
+
}, {
|
|
254
|
+
default: withCtx(() => [createTextVNode(" +" + toDisplayString(hiddenTabs.value.length) + " ", 1), _cache[5] || (_cache[5] = createElementVNode("svg", {
|
|
255
|
+
width: "12",
|
|
256
|
+
height: "12",
|
|
257
|
+
viewBox: "0 0 12 12",
|
|
258
|
+
fill: "none",
|
|
259
|
+
"aria-hidden": "true"
|
|
260
|
+
}, [createElementVNode("path", {
|
|
261
|
+
d: "M2 4L6 8L10 4",
|
|
262
|
+
stroke: "currentColor",
|
|
263
|
+
"stroke-width": "1.5",
|
|
264
|
+
"stroke-linecap": "round",
|
|
265
|
+
"stroke-linejoin": "round"
|
|
266
|
+
})], -1))]),
|
|
267
|
+
_: 1
|
|
268
|
+
}, 8, ["aria-expanded"]), dropdownOpen.value ? (openBlock(), createElementBlock("div", _hoisted_1, [(openBlock(true), createElementBlock(Fragment, null, renderList(hiddenTabs.value, (tab) => {
|
|
269
|
+
return openBlock(), createBlock(Button_default, {
|
|
270
|
+
key: tab.value,
|
|
271
|
+
variant: "ghost",
|
|
272
|
+
radius: "lg",
|
|
273
|
+
class: "tabs__overflow-item",
|
|
274
|
+
role: "menuitem",
|
|
275
|
+
disabled: tab.disabled,
|
|
276
|
+
onClick: ($event) => selectOverflowTab(tab.value)
|
|
277
|
+
}, {
|
|
278
|
+
default: withCtx(() => [createTextVNode(toDisplayString(tab.label), 1)]),
|
|
279
|
+
_: 2
|
|
280
|
+
}, 1032, ["disabled", "onClick"]);
|
|
281
|
+
}), 128))])) : createCommentVNode("", true)], 2)], 512)) : createCommentVNode("", true);
|
|
23
282
|
};
|
|
24
283
|
}
|
|
25
284
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabList.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/tabs/TabList.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { TabsList } from 'reka-ui'\nimport { composeClassName } from '../../utils/composeClassName'\nimport { useTabsInject } from './tabs.context'\n\nconst props = defineProps<{\n loop?: boolean\n class?: string\n}>()\n\nconst ctx = useTabsInject()\n</script>\n\n<template>\n <TabsList\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), props.class)\"\n >\n <slot />\n </TabsList>\n</template>\n"],"mappings":";;;;;;;;;;;;EAKA,MAAM,QAAQ;EAKd,MAAM,MAAM,eAAc;;uBAIxB,YAKW,MAAA,SAAA,EAAA;IAJR,MAAM,MAAM,QAAI;IAChB,OAAK,eAAE,MAAA,iBAAgB,CAAC,MAAA,IAAG,CAAC,QAAQ,MAAM,SAAO,EAAI,MAAM,MAAK,CAAA;;2BAEzD,CAAR,WAAQ,KAAA,QAAA,UAAA,CAAA,CAAA"}
|
|
1
|
+
{"version":3,"file":"TabList.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/tabs/TabList.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, nextTick, onMounted, watch } from 'vue'\nimport { useTemplateRef } from 'vue'\nimport { TabsList } from 'reka-ui'\nimport { useResizeObserver, onClickOutside } from '@vueuse/core'\nimport { composeClassName } from '../../utils/composeClassName'\nimport { useTabsInject } from './tabs.context'\nimport Button from '../button/Button.vue'\n\nconst props = defineProps<{\n loop?: boolean\n overflow?: 'arrows' | 'dropdown'\n class?: string\n}>()\n\nconst ctx = useTabsInject()\n\n// ── Arrows mode ─────────────────────────────────────────────────────────────\nconst scrollWrapperEl = useTemplateRef<HTMLElement>('scrollWrapperEl')\nconst canScrollLeft = ref(false)\nconst canScrollRight = ref(false)\n\nfunction updateScrollButtons() {\n const el = scrollWrapperEl.value\n if (!el) { canScrollLeft.value = false; canScrollRight.value = false; return }\n canScrollLeft.value = el.scrollLeft > 1\n canScrollRight.value = el.scrollLeft + el.clientWidth < el.scrollWidth - 1\n}\n\nfunction scrollTabs(dir: 'left' | 'right') {\n const el = scrollWrapperEl.value\n if (!el) return\n el.scrollBy({ left: dir === 'left' ? -200 : 200, behavior: 'smooth' })\n // Poll briefly after smooth scroll starts so button states update\n setTimeout(updateScrollButtons, 150)\n setTimeout(updateScrollButtons, 350)\n}\n\nwatch(scrollWrapperEl, (el, oldEl) => {\n if (oldEl) oldEl.removeEventListener('scroll', updateScrollButtons)\n if (el) {\n el.addEventListener('scroll', updateScrollButtons, { passive: true })\n nextTick(updateScrollButtons)\n }\n}, { immediate: true })\n\nuseResizeObserver(scrollWrapperEl, () => nextTick(updateScrollButtons))\n\n// ── Dropdown mode ────────────────────────────────────────────────────────────\ninterface OverflowTab {\n value: string\n label: string\n disabled: boolean\n}\n\nconst containerEl = useTemplateRef<HTMLElement>('containerEl')\n// Button component ref — use .$el to reach the underlying DOM element for offsetWidth\nconst moreBtnEl = useTemplateRef<InstanceType<typeof Button>>('moreBtnEl')\nconst dropdownEl = useTemplateRef<HTMLElement>('dropdownEl')\n\nconst hiddenTabs = ref<OverflowTab[]>([])\nconst dropdownOpen = ref(false)\nconst hasOverflow = computed(() => hiddenTabs.value.length > 0)\n// Pre-measured natural width of the more button (measured once on mount before it's visible)\nlet moreBtnNaturalWidth = 48\n\nonClickOutside(dropdownEl, () => { dropdownOpen.value = false })\n\nfunction computeOverflow() {\n if (!containerEl.value) return\n\n const allTabs = Array.from(\n containerEl.value.querySelectorAll('[data-tab-value]'),\n ) as HTMLElement[]\n\n // Reveal all tabs first\n allTabs.forEach(t => t.removeAttribute('data-overflow-hidden'))\n\n // Tabs use w-full and shrink to share the container width, so offsetWidth after\n // a normal render would be containerWidth/n — useless for overflow detection.\n // Force each tab to its natural content width for measurement only (no paint flash:\n // all DOM reads/writes happen synchronously within this JS task before the next frame).\n const listEl = containerEl.value.querySelector('[role=\"tablist\"]') as HTMLElement | null\n if (listEl) {\n listEl.style.overflow = 'visible'\n allTabs.forEach(t => { t.style.flexShrink = '0'; t.style.width = 'auto' })\n void listEl.offsetWidth // force reflow so offsetWidth reads below are accurate\n }\n\n const containerWidth = containerEl.value.clientWidth\n const tabWidths = allTabs.map(t => t.offsetWidth)\n const totalWidth = tabWidths.reduce((sum, w) => sum + w, 0)\n\n // Restore layout before any early-return so tabs always look correct\n if (listEl) {\n listEl.style.overflow = ''\n allTabs.forEach(t => { t.style.flexShrink = ''; t.style.width = '' })\n }\n\n if (totalWidth <= containerWidth) {\n hiddenTabs.value = []\n return\n }\n\n // More button is in-flow (display:none when no overflow, display:flex when visible).\n // Use the pre-measured natural width so the calculation is accurate on the first run\n // before the button becomes visible.\n const available = containerWidth - moreBtnNaturalWidth\n\n let accumulated = 0\n const newHidden: OverflowTab[] = []\n const visibleEls: HTMLElement[] = []\n\n for (let i = 0; i < allTabs.length; i++) {\n const tab = allTabs[i]\n const w = tabWidths[i]\n if (accumulated + w <= available) {\n accumulated += w\n visibleEls.push(tab)\n } else {\n newHidden.push({\n value: tab.getAttribute('data-tab-value') ?? '',\n label: tab.textContent?.trim() ?? '',\n disabled: tab.hasAttribute('data-disabled') || tab.getAttribute('aria-disabled') === 'true',\n })\n tab.setAttribute('data-overflow-hidden', '')\n }\n }\n\n // If the active tab ended up hidden, swap it with the last visible tab\n const activeValue = ctx.currentValue.value\n if (activeValue) {\n const hiddenActiveIdx = newHidden.findIndex(t => t.value === activeValue)\n if (hiddenActiveIdx !== -1 && visibleEls.length > 0) {\n const displacedEl = visibleEls[visibleEls.length - 1]\n const activeEl = allTabs.find(t => t.getAttribute('data-tab-value') === activeValue)\n\n if (displacedEl && activeEl) {\n // Swap: make displaced tab hidden, active tab visible\n displacedEl.setAttribute('data-overflow-hidden', '')\n activeEl.removeAttribute('data-overflow-hidden')\n\n const displaced: OverflowTab = {\n value: displacedEl.getAttribute('data-tab-value') ?? '',\n label: displacedEl.textContent?.trim() ?? '',\n disabled: displacedEl.hasAttribute('data-disabled') || displacedEl.getAttribute('aria-disabled') === 'true',\n }\n newHidden.splice(hiddenActiveIdx, 1)\n newHidden.unshift(displaced)\n }\n }\n }\n\n hiddenTabs.value = newHidden\n}\n\nuseResizeObserver(containerEl, () => nextTick(computeOverflow))\nonMounted(() => {\n // Pre-measure the more button's natural width before it becomes visible (display:none).\n // Temporarily show it, read offsetWidth, then hide again — happens before first paint.\n const btnEl = (moreBtnEl.value as InstanceType<typeof Button> | null)?.$el as HTMLElement | null\n if (btnEl) {\n btnEl.style.display = 'flex'\n void btnEl.offsetWidth\n moreBtnNaturalWidth = btnEl.offsetWidth\n btnEl.style.display = ''\n }\n nextTick(computeOverflow)\n})\n\n// Recompute when the active tab changes so the active tab is always visible\nwatch(() => ctx.currentValue.value, () => {\n if (props.overflow === 'dropdown') nextTick(computeOverflow)\n})\n\n// When overflow state first transitions false→true the more button enters the flex flow,\n// narrowing the container. Re-run once so the tab count reflects the reduced available space.\nwatch(hasOverflow, () => {\n if (props.overflow === 'dropdown') nextTick(computeOverflow)\n})\n\nfunction selectOverflowTab(value: string) {\n ctx.changeTab(value)\n dropdownOpen.value = false\n}\n</script>\n\n<template>\n <!-- ── Default (no overflow behaviour) ───────────────────────────────────── -->\n <TabsList\n v-if=\"!props.overflow\"\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), props.class)\"\n >\n <slot />\n </TabsList>\n\n <!-- ── Arrows mode ────────────────────────────────────────────────────────── -->\n <div\n v-else-if=\"props.overflow === 'arrows'\"\n class=\"tabs__list-container tabs__list-container--arrows\"\n :class=\"{ 'has-left': canScrollLeft, 'has-right': canScrollRight }\"\n >\n <Button\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n :is-icon-only=\"true\"\n :class=\"composeClassName('tabs__arrow tabs__arrow--left', canScrollLeft && 'is-visible')\"\n aria-label=\"Scroll tabs left\"\n tabindex=\"-1\"\n @click=\"scrollTabs('left')\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M9 11L5 7L9 3\" stroke=\"currentColor\" stroke-width=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n\n <div ref=\"scrollWrapperEl\" class=\"tabs__scroll-wrapper\">\n <TabsList\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--scroll', props.class)\"\n >\n <slot />\n </TabsList>\n </div>\n\n <Button\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n :is-icon-only=\"true\"\n :class=\"composeClassName('tabs__arrow tabs__arrow--right', canScrollRight && 'is-visible')\"\n aria-label=\"Scroll tabs right\"\n tabindex=\"-1\"\n @click=\"scrollTabs('right')\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M5 3L9 7L5 11\" stroke=\"currentColor\" stroke-width=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n </div>\n\n <!-- ── Dropdown mode ──────────────────────────────────────────────────────── -->\n <div\n v-else-if=\"props.overflow === 'dropdown'\"\n ref=\"containerEl\"\n class=\"tabs__list-container tabs__list-container--dropdown\"\n >\n <TabsList\n :loop=\"props.loop ?? true\"\n :class=\"composeClassName(ctx.slotFns.value.tabList(), 'tabs__list--clipped', props.class)\"\n >\n <slot />\n </TabsList>\n\n <!-- Always rendered so offsetWidth is measurable; visibility toggled via CSS -->\n <div\n ref=\"dropdownEl\"\n class=\"tabs__more\"\n :class=\"{ 'tabs__more--visible': hasOverflow }\"\n >\n <Button\n ref=\"moreBtnEl\"\n variant=\"secondary\"\n size=\"sm\"\n radius=\"full\"\n class=\"tabs__more-btn\"\n :aria-expanded=\"dropdownOpen\"\n aria-haspopup=\"menu\"\n @click=\"dropdownOpen = !dropdownOpen\"\n >\n +{{ hiddenTabs.length }}\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M2 4L6 8L10 4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </Button>\n\n <div v-if=\"dropdownOpen\" class=\"tabs__overflow-menu\" role=\"menu\">\n <Button\n v-for=\"tab in hiddenTabs\"\n :key=\"tab.value\"\n variant=\"ghost\"\n radius=\"lg\"\n class=\"tabs__overflow-item\"\n role=\"menuitem\"\n :disabled=\"tab.disabled\"\n @click=\"selectOverflowTab(tab.value)\"\n >\n {{ tab.label }}\n </Button>\n </div>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tabs.js","names":[],"sources":["../../../src/components/tabs/Tabs.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, toRef } from 'vue'\nimport { TabsRoot } from 'reka-ui'\nimport { tabsVariants, type TabsVariants } from '@auronui/styles'\nimport { composeClassName } from '../../utils/composeClassName'\nimport { useTabsProvide } from './tabs.context'\n\nconst props = withDefaults(defineProps<{\n modelValue?: string\n defaultValue?: string\n orientation?: 'horizontal' | 'vertical'\n variant?: TabsVariants['variant']\n activationMode?: 'automatic' | 'manual'\n class?: string\n}>(), {\n orientation: 'horizontal',\n variant: 'primary',\n activationMode: 'automatic',\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string]\n}>()\n\nconst slotFns = computed(() => tabsVariants({ variant: props.variant }))\n\nuseTabsProvide({\n slotFns,\n orientation: toRef(props, 'orientation'),\n})\n</script>\n\n<template>\n <TabsRoot\n :model-value=\"
|
|
1
|
+
{"version":3,"file":"Tabs.js","names":[],"sources":["../../../src/components/tabs/Tabs.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, toRef, watch } from 'vue'\nimport { TabsRoot } from 'reka-ui'\nimport { tabsVariants, type TabsVariants } from '@auronui/styles'\nimport { composeClassName } from '../../utils/composeClassName'\nimport { useTabsProvide } from './tabs.context'\n\nconst props = withDefaults(defineProps<{\n modelValue?: string\n defaultValue?: string\n orientation?: 'horizontal' | 'vertical'\n variant?: TabsVariants['variant']\n activationMode?: 'automatic' | 'manual'\n class?: string\n}>(), {\n orientation: 'horizontal',\n variant: 'primary',\n activationMode: 'automatic',\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string]\n}>()\n\nconst internalValue = ref<string | undefined>(props.modelValue ?? props.defaultValue)\n\nwatch(() => props.modelValue, (v) => {\n if (v !== undefined) internalValue.value = v\n})\n\nfunction changeTab(value: string) {\n internalValue.value = value\n emit('update:modelValue', value)\n}\n\nconst slotFns = computed(() => tabsVariants({ variant: props.variant }))\n\nuseTabsProvide({\n slotFns,\n orientation: toRef(props, 'orientation'),\n currentValue: internalValue,\n changeTab,\n})\n</script>\n\n<template>\n <TabsRoot\n :model-value=\"internalValue\"\n :orientation=\"props.orientation\"\n :activation-mode=\"props.activationMode\"\n :class=\"composeClassName(slotFns.base(), props.class)\"\n :data-orientation=\"props.orientation\"\n @update:model-value=\"changeTab\"\n >\n <slot />\n </TabsRoot>\n</template>\n"],"mappings":""}
|