@7pmlabs/design-system 2.0.8 → 2.1.0
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/README.md +4 -4
- package/dist/design-system.css +1 -1
- package/dist/design-system.js +65 -59
- package/dist/design-system100.js +1 -1
- package/dist/design-system100.js.map +1 -1
- package/dist/design-system101.js +87 -53
- package/dist/design-system101.js.map +1 -1
- package/dist/design-system103.js +5 -13
- package/dist/design-system103.js.map +1 -1
- package/dist/design-system104.js +53 -108
- package/dist/design-system104.js.map +1 -1
- package/dist/{design-system102.js → design-system105.js} +1 -1
- package/dist/{design-system102.js.map → design-system105.js.map} +1 -1
- package/dist/design-system106.js +13 -6
- package/dist/design-system106.js.map +1 -1
- package/dist/design-system107.js +93 -190
- package/dist/design-system107.js.map +1 -1
- package/dist/design-system109.js +2 -2
- package/dist/design-system109.js.map +1 -1
- package/dist/design-system110.js +183 -484
- package/dist/design-system110.js.map +1 -1
- package/dist/design-system112.js +5 -4
- package/dist/design-system112.js.map +1 -1
- package/dist/design-system113.js +507 -7
- package/dist/design-system113.js.map +1 -1
- package/dist/design-system115.js +8 -0
- package/dist/design-system115.js.map +1 -0
- package/dist/design-system116.js +7 -6
- package/dist/design-system116.js.map +1 -1
- package/dist/design-system117.js +154 -169
- package/dist/design-system117.js.map +1 -1
- package/dist/design-system119.js +2 -2
- package/dist/design-system119.js.map +1 -1
- package/dist/design-system120.js +210 -149
- package/dist/design-system120.js.map +1 -1
- package/dist/design-system122.js +5 -4
- package/dist/design-system122.js.map +1 -1
- package/dist/design-system123.js +160 -9
- package/dist/design-system123.js.map +1 -1
- package/dist/design-system125.js +8 -0
- package/dist/design-system125.js.map +1 -0
- package/dist/design-system126.js +176 -6
- package/dist/design-system126.js.map +1 -1
- package/dist/design-system128.js +8 -0
- package/dist/design-system128.js.map +1 -0
- package/dist/design-system129.js +213 -5
- package/dist/design-system129.js.map +1 -1
- package/dist/design-system131.js +5 -90
- package/dist/design-system131.js.map +1 -1
- package/dist/design-system132.js +166 -0
- package/dist/design-system132.js.map +1 -0
- package/dist/design-system134.js +5 -42
- package/dist/design-system134.js.map +1 -1
- package/dist/design-system135.js +12 -0
- package/dist/design-system135.js.map +1 -0
- package/dist/design-system136.js +274 -5
- package/dist/design-system136.js.map +1 -1
- package/dist/design-system138.js +9 -0
- package/dist/{design-system124.js.map → design-system138.js.map} +1 -1
- package/dist/design-system139.js +16 -5
- package/dist/design-system139.js.map +1 -1
- package/dist/design-system141.js +8 -0
- package/dist/{design-system127.js.map → design-system141.js.map} +1 -1
- package/dist/design-system142.js +12 -5
- package/dist/design-system142.js.map +1 -1
- package/dist/design-system143.js +78 -83
- package/dist/design-system143.js.map +1 -1
- package/dist/design-system145.js +1 -1
- package/dist/design-system145.js.map +1 -1
- package/dist/design-system146.js +42 -9
- package/dist/design-system146.js.map +1 -1
- package/dist/design-system148.js +3 -2
- package/dist/design-system148.js.map +1 -1
- package/dist/design-system149.js +230 -18
- package/dist/design-system149.js.map +1 -1
- package/dist/design-system151.js +5 -158
- package/dist/design-system151.js.map +1 -1
- package/dist/{design-system140.js → design-system152.js} +6 -6
- package/dist/{design-system140.js.map → design-system152.js.map} +1 -1
- package/dist/design-system154.js +5 -307
- package/dist/design-system154.js.map +1 -1
- package/dist/design-system155.js +98 -0
- package/dist/design-system155.js.map +1 -0
- package/dist/design-system157.js +5 -240
- package/dist/design-system157.js.map +1 -1
- package/dist/design-system158.js +12 -0
- package/dist/design-system158.js.map +1 -0
- package/dist/design-system159.js +37 -5
- package/dist/design-system159.js.map +1 -1
- package/dist/design-system160.js +4 -189
- package/dist/design-system160.js.map +1 -1
- package/dist/design-system161.js +24 -0
- package/dist/{design-system150.js.map → design-system161.js.map} +1 -1
- package/dist/design-system162.js +2 -3
- package/dist/design-system162.js.map +1 -1
- package/dist/design-system163.js +158 -3
- package/dist/design-system163.js.map +1 -1
- package/dist/{design-system153.js → design-system165.js} +2 -2
- package/dist/{design-system153.js.map → design-system165.js.map} +1 -1
- package/dist/design-system166.js +307 -6
- package/dist/design-system166.js.map +1 -1
- package/dist/{design-system156.js → design-system168.js} +2 -2
- package/dist/{design-system156.js.map → design-system168.js.map} +1 -1
- package/dist/design-system169.js +167 -6
- package/dist/design-system169.js.map +1 -1
- package/dist/design-system171.js +8 -0
- package/dist/design-system171.js.map +1 -0
- package/dist/design-system172.js +240 -6
- package/dist/design-system172.js.map +1 -1
- package/dist/design-system174.js +8 -0
- package/dist/design-system174.js.map +1 -0
- package/dist/design-system175.js +189 -6
- package/dist/design-system175.js.map +1 -1
- package/dist/design-system177.js +8 -0
- package/dist/design-system177.js.map +1 -0
- package/dist/design-system178.js +3 -5
- package/dist/design-system178.js.map +1 -1
- package/dist/design-system179.js +58 -11
- package/dist/design-system179.js.map +1 -1
- package/dist/design-system181.js +9 -0
- package/dist/design-system181.js.map +1 -0
- package/dist/design-system182.js +56 -6
- package/dist/design-system182.js.map +1 -1
- package/dist/design-system184.js +9 -0
- package/dist/{design-system167.js.map → design-system184.js.map} +1 -1
- package/dist/design-system185.js +69 -5
- package/dist/design-system185.js.map +1 -1
- package/dist/design-system187.js +9 -0
- package/dist/{design-system170.js.map → design-system187.js.map} +1 -1
- package/dist/design-system188.js +182 -5
- package/dist/design-system188.js.map +1 -1
- package/dist/design-system190.js +9 -0
- package/dist/design-system190.js.map +1 -0
- package/dist/design-system191.js +115 -5
- package/dist/design-system191.js.map +1 -1
- package/dist/design-system193.js +8 -0
- package/dist/{design-system176.js.map → design-system193.js.map} +1 -1
- package/dist/design-system194.js +11 -5
- package/dist/design-system194.js.map +1 -1
- package/dist/design-system195.js +453 -24
- package/dist/design-system195.js.map +1 -1
- package/dist/design-system197.js +5 -4
- package/dist/design-system197.js.map +1 -1
- package/dist/design-system198.js +20 -16
- package/dist/design-system198.js.map +1 -1
- package/dist/design-system200.js +1 -1
- package/dist/design-system200.js.map +1 -1
- package/dist/design-system201.js +70 -314
- package/dist/design-system201.js.map +1 -1
- package/dist/design-system203.js +1 -1
- package/dist/design-system203.js.map +1 -1
- package/dist/design-system204.js +24 -89
- package/dist/design-system204.js.map +1 -1
- package/dist/design-system206.js +1 -1
- package/dist/design-system206.js.map +1 -1
- package/dist/design-system207.js +26 -17
- package/dist/design-system207.js.map +1 -1
- package/dist/design-system209.js +5 -3
- package/dist/design-system209.js.map +1 -1
- package/dist/design-system210.js +22 -408
- package/dist/design-system210.js.map +1 -1
- package/dist/design-system212.js +1 -1
- package/dist/design-system212.js.map +1 -1
- package/dist/design-system213.js +24 -52
- package/dist/design-system213.js.map +1 -1
- package/dist/design-system215.js +1 -1
- package/dist/design-system215.js.map +1 -1
- package/dist/design-system216.js +329 -85
- package/dist/design-system216.js.map +1 -1
- package/dist/design-system218.js +5 -108
- package/dist/design-system218.js.map +1 -1
- package/dist/design-system219.js +103 -0
- package/dist/design-system219.js.map +1 -0
- package/dist/design-system221.js +5 -106
- package/dist/design-system221.js.map +1 -1
- package/dist/design-system222.js +22 -0
- package/dist/{design-system208.js.map → design-system222.js.map} +1 -1
- package/dist/design-system223.js +4 -6
- package/dist/design-system223.js.map +1 -1
- package/dist/design-system224.js +3 -737
- package/dist/design-system224.js.map +1 -1
- package/dist/design-system225.js +422 -0
- package/dist/design-system225.js.map +1 -0
- package/dist/design-system227.js +5 -11
- package/dist/design-system227.js.map +1 -1
- package/dist/design-system228.js +51 -517
- package/dist/design-system228.js.map +1 -1
- package/dist/design-system230.js +1 -1
- package/dist/design-system230.js.map +1 -1
- package/dist/design-system231.js +88 -3
- package/dist/design-system231.js.map +1 -1
- package/dist/design-system232.js +4 -46
- package/dist/design-system232.js.map +1 -1
- package/dist/design-system233.js +108 -4
- package/dist/design-system233.js.map +1 -1
- package/dist/{design-system220.js → design-system235.js} +2 -2
- package/dist/{design-system220.js.map → design-system235.js.map} +1 -1
- package/dist/design-system236.js +106 -5
- package/dist/design-system236.js.map +1 -1
- package/dist/design-system238.js +9 -0
- package/dist/design-system238.js.map +1 -0
- package/dist/design-system239.js +737 -5
- package/dist/design-system239.js.map +1 -1
- package/dist/{design-system226.js → design-system241.js} +2 -2
- package/dist/{design-system226.js.map → design-system241.js.map} +1 -1
- package/dist/design-system242.js +3 -5
- package/dist/design-system242.js.map +1 -1
- package/dist/design-system243.js +42 -50
- package/dist/design-system243.js.map +1 -1
- package/dist/design-system244.js +1 -1
- package/dist/design-system244.js.map +1 -1
- package/dist/design-system245.js +254 -141
- package/dist/design-system245.js.map +1 -1
- package/dist/design-system247.js +1 -1
- package/dist/design-system247.js.map +1 -1
- package/dist/design-system248.js +119 -7
- package/dist/design-system248.js.map +1 -1
- package/dist/design-system250.js +8 -0
- package/dist/design-system250.js.map +1 -0
- package/dist/design-system251.js +172 -5
- package/dist/design-system251.js.map +1 -1
- package/dist/design-system253.js +8 -0
- package/dist/design-system253.js.map +1 -0
- package/dist/design-system254.js +11 -6
- package/dist/design-system254.js.map +1 -1
- package/dist/design-system255.js +525 -9
- package/dist/design-system255.js.map +1 -1
- package/dist/design-system257.js +8 -0
- package/dist/design-system257.js.map +1 -0
- package/dist/design-system258.js +112 -6
- package/dist/design-system258.js.map +1 -1
- package/dist/design-system260.js +5 -374
- package/dist/design-system260.js.map +1 -1
- package/dist/design-system261.js +57 -0
- package/dist/design-system261.js.map +1 -0
- package/dist/design-system262.js +4 -6
- package/dist/design-system262.js.map +1 -1
- package/dist/design-system263.js +173 -0
- package/dist/design-system263.js.map +1 -0
- package/dist/design-system265.js +8 -0
- package/dist/design-system265.js.map +1 -0
- package/dist/design-system266.js +10 -0
- package/dist/design-system266.js.map +1 -0
- package/dist/{design-system249.js → design-system267.js} +2 -2
- package/dist/{design-system249.js.map → design-system267.js.map} +1 -1
- package/dist/design-system269.js +8 -0
- package/dist/design-system269.js.map +1 -0
- package/dist/{design-system252.js → design-system270.js} +1 -1
- package/dist/{design-system252.js.map → design-system270.js.map} +1 -1
- package/dist/design-system272.js +9 -0
- package/dist/design-system272.js.map +1 -0
- package/dist/design-system273.js +12 -0
- package/dist/design-system273.js.map +1 -0
- package/dist/{design-system256.js → design-system274.js} +2 -2
- package/dist/{design-system256.js.map → design-system274.js.map} +1 -1
- package/dist/design-system276.js +9 -0
- package/dist/design-system276.js.map +1 -0
- package/dist/{design-system259.js → design-system277.js} +1 -1
- package/dist/{design-system259.js.map → design-system277.js.map} +1 -1
- package/dist/design-system278.js +377 -0
- package/dist/design-system278.js.map +1 -0
- package/dist/design-system280.js +9 -0
- package/dist/design-system280.js.map +1 -0
- package/dist/design-system69.js +182 -13
- package/dist/design-system69.js.map +1 -1
- package/dist/design-system71.js +8 -0
- package/dist/design-system71.js.map +1 -0
- package/dist/design-system72.js +13 -5
- package/dist/design-system72.js.map +1 -1
- package/dist/design-system73.js +677 -139
- package/dist/design-system73.js.map +1 -1
- package/dist/design-system75.js +1 -1
- package/dist/design-system75.js.map +1 -1
- package/dist/design-system76.js +152 -23
- package/dist/design-system76.js.map +1 -1
- package/dist/design-system78.js +5 -49
- package/dist/design-system78.js.map +1 -1
- package/dist/design-system79.js +32 -0
- package/dist/design-system79.js.map +1 -0
- package/dist/design-system80.js +2 -3
- package/dist/design-system80.js.map +1 -1
- package/dist/design-system81.js +38 -188
- package/dist/design-system81.js.map +1 -1
- package/dist/design-system83.js +1 -1
- package/dist/design-system83.js.map +1 -1
- package/dist/design-system84.js +199 -7
- package/dist/design-system84.js.map +1 -1
- package/dist/design-system86.js +8 -0
- package/dist/design-system86.js.map +1 -0
- package/dist/design-system87.js +7 -5
- package/dist/design-system87.js.map +1 -1
- package/dist/design-system88.js +264 -48
- package/dist/design-system88.js.map +1 -1
- package/dist/design-system90.js +1 -1
- package/dist/design-system90.js.map +1 -1
- package/dist/design-system91.js +57 -11
- package/dist/design-system91.js.map +1 -1
- package/dist/design-system93.js +8 -0
- package/dist/design-system93.js.map +1 -0
- package/dist/design-system94.js +11 -5
- package/dist/design-system94.js.map +1 -1
- package/dist/design-system95.js +92 -59
- package/dist/design-system95.js.map +1 -1
- package/dist/design-system97.js +1 -1
- package/dist/design-system97.js.map +1 -1
- package/dist/design-system98.js +56 -78
- package/dist/design-system98.js.map +1 -1
- package/dist/types/components/BContextMenu/BContextMenu.spec.d.ts +1 -0
- package/dist/types/components/BContextMenu/BContextMenu.vue.d.ts +42 -0
- package/dist/types/components/BContextMenu/index.d.ts +2 -0
- package/dist/types/components/BContextMenu/types.d.ts +23 -0
- package/dist/types/components/BInputTags/BInputTags.spec.d.ts +1 -0
- package/dist/types/components/BInputTags/BInputTags.vue.d.ts +54 -0
- package/dist/types/components/BInputTags/index.d.ts +1 -0
- package/dist/types/components/BLink/BLink.spec.d.ts +1 -0
- package/dist/types/components/BLink/BLink.vue.d.ts +100 -0
- package/dist/types/components/BLink/index.d.ts +1 -0
- package/dist/types/components/BListbox/BListbox.spec.d.ts +1 -0
- package/dist/types/components/BListbox/BListbox.vue.d.ts +52 -0
- package/dist/types/components/BListbox/index.d.ts +1 -0
- package/dist/types/components/BModal/BModal.spec.d.ts +1 -0
- package/dist/types/components/BPinInput/BPinInput.spec.d.ts +1 -0
- package/dist/types/components/BPinInput/BPinInput.vue.d.ts +43 -0
- package/dist/types/components/BPinInput/index.d.ts +1 -0
- package/dist/types/components/BProgress/BProgress.vue.d.ts +47 -2
- package/dist/types/components/BTextarea/BTextarea.spec.d.ts +1 -0
- package/dist/types/components/BTextarea/BTextarea.vue.d.ts +77 -0
- package/dist/types/components/BTextarea/index.d.ts +1 -0
- package/dist/types/components/index.d.ts +7 -1
- package/package.json +1 -1
- package/dist/design-system114.js +0 -212
- package/dist/design-system114.js.map +0 -1
- package/dist/design-system124.js +0 -277
- package/dist/design-system127.js +0 -19
- package/dist/design-system130.js +0 -15
- package/dist/design-system130.js.map +0 -1
- package/dist/design-system133.js +0 -8
- package/dist/design-system133.js.map +0 -1
- package/dist/design-system137.js +0 -236
- package/dist/design-system137.js.map +0 -1
- package/dist/design-system147.js +0 -40
- package/dist/design-system147.js.map +0 -1
- package/dist/design-system150.js +0 -7
- package/dist/design-system164.js +0 -61
- package/dist/design-system164.js.map +0 -1
- package/dist/design-system167.js +0 -59
- package/dist/design-system170.js +0 -72
- package/dist/design-system173.js +0 -185
- package/dist/design-system173.js.map +0 -1
- package/dist/design-system176.js +0 -118
- package/dist/design-system180.js +0 -465
- package/dist/design-system180.js.map +0 -1
- package/dist/design-system183.js +0 -38
- package/dist/design-system183.js.map +0 -1
- package/dist/design-system186.js +0 -91
- package/dist/design-system186.js.map +0 -1
- package/dist/design-system189.js +0 -38
- package/dist/design-system189.js.map +0 -1
- package/dist/design-system192.js +0 -31
- package/dist/design-system192.js.map +0 -1
- package/dist/design-system208.js +0 -7
- package/dist/design-system217.js +0 -7
- package/dist/design-system217.js.map +0 -1
- package/dist/design-system234.js +0 -286
- package/dist/design-system234.js.map +0 -1
- package/dist/design-system237.js +0 -122
- package/dist/design-system237.js.map +0 -1
- package/dist/design-system240.js +0 -115
- package/dist/design-system240.js.map +0 -1
- package/dist/design-system70.js +0 -699
- package/dist/design-system70.js.map +0 -1
- package/dist/design-system77.js +0 -7
- package/dist/design-system77.js.map +0 -1
- package/dist/design-system85.js +0 -276
- package/dist/design-system85.js.map +0 -1
- package/dist/design-system92.js +0 -102
- package/dist/design-system92.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"design-system245.js","names":[],"sources":["../src/components/BTooltip/BTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useComponentId } from '@/composables/useComponentId.ts';\nimport { BTooltipPlacement, BTooltipTrigger } from '@/types.ts';\nimport { computed, onBeforeUnmount, onMounted, ref, useId, watch } from 'vue';\n\n// ─────────────────────────────────────────────\n// Props & emits\n// ─────────────────────────────────────────────\nconst {\n title,\n trigger = BTooltipTrigger.Hover,\n placement = BTooltipPlacement.TopCenter,\n arrow = true,\n color,\n mouseEnterDelay = 100,\n mouseLeaveDelay = 100,\n destroyTooltipOnHide = false,\n zIndex = 1070,\n fresh = false,\n modelValue = undefined,\n} = defineProps<{\n /** The text shown inside the tooltip. Also accepts the `title` slot. */\n title?: string;\n /** The event that triggers the tooltip to open. */\n trigger?: `${BTooltipTrigger}`;\n /** Placement of the tooltip relative to the target element. */\n placement?: `${BTooltipPlacement}`;\n /** Whether the tooltip has an arrow pointing to the target. */\n arrow?: boolean;\n /** Custom background color of the tooltip. */\n color?: string;\n /** Delay in ms before showing on mouseenter. */\n mouseEnterDelay?: number;\n /** Delay in ms before hiding on mouseleave. */\n mouseLeaveDelay?: number;\n /** Whether to destroy the tooltip DOM when hidden. */\n destroyTooltipOnHide?: boolean;\n /** z-index of the tooltip. */\n zIndex?: number;\n /** Force re-render when tooltip is shown. */\n fresh?: boolean;\n /** Whether to auto-adjust placement when tooltip overflows viewport. */\n autoAdjustOverflow?: boolean;\n /** Controlled visibility - bind with `v-model`. */\n modelValue?: boolean;\n /** Additional classes to apply to the toggle wrapper. */\n toggleClass?: string;\n /** Additional classes to apply to the tooltip content container. */\n tooltipClass?: string;\n /** Additional classes to apply to the tooltip inner element. */\n tooltipInnerClass?: string;\n}>();\n\nconst emit = defineEmits<{\n /** Emitted when the tooltip visibility changes. */\n (e: 'openChange', open: boolean): void;\n /** v-model support. */\n (e: 'update:modelValue', value: boolean): void;\n}>();\n\ndefineSlots<{\n /** The target element that triggers the tooltip. */\n default?(): unknown;\n /** Overrides the `title` prop. */\n title?(): unknown;\n}>();\n\n// ─────────────────────────────────────────────\n// Internal state\n// ─────────────────────────────────────────────\nconst { componentUID } = useComponentId();\nconst tooltipId = useId();\n\nconst internalOpen = ref(false);\nconst isOpen = computed(() => (modelValue !== undefined ? modelValue : internalOpen.value));\n\nconst hasBeenOpened = ref(false);\nconst shouldRender = computed(() => {\n if (fresh) return isOpen.value;\n if (destroyTooltipOnHide) return isOpen.value;\n return hasBeenOpened.value || isOpen.value;\n});\n\nwatch(isOpen, (val) => {\n if (val) hasBeenOpened.value = true;\n});\n\n// ─────────────────────────────────────────────\n// Visibility control\n// ─────────────────────────────────────────────\nlet showTimer: ReturnType<typeof setTimeout> | null = null;\nlet hideTimer: ReturnType<typeof setTimeout> | null = null;\n\nfunction clearTimers() {\n if (showTimer) {\n clearTimeout(showTimer);\n showTimer = null;\n }\n if (hideTimer) {\n clearTimeout(hideTimer);\n hideTimer = null;\n }\n}\n\nfunction requestOpen(delay = 0) {\n clearTimers();\n if (isOpen.value) return;\n if (delay > 0) {\n showTimer = setTimeout(() => doOpen(), delay);\n } else {\n doOpen();\n }\n}\n\nfunction requestClose(delay = 0) {\n clearTimers();\n if (!isOpen.value) return;\n if (delay > 0) {\n hideTimer = setTimeout(() => doClose(), delay);\n } else {\n doClose();\n }\n}\n\nfunction doOpen() {\n tooltipRef.value?.showPopover();\n}\n\nfunction doClose() {\n tooltipRef.value?.hidePopover();\n}\n\nfunction setOpen(val: boolean) {\n if (modelValue !== undefined) {\n emit('update:modelValue', val);\n } else {\n internalOpen.value = val;\n }\n emit('openChange', val);\n}\n\n// ─────────────────────────────────────────────\n// Popover toggle event\n// ─────────────────────────────────────────────\nconst onPopoverToggle = ({ newState }: ToggleEvent) => {\n setOpen(newState === 'open');\n};\n\n// ─────────────────────────────────────────────\n// Refs\n// ─────────────────────────────────────────────\nconst tooltipRef = ref<HTMLDivElement | null>(null);\nconst toggleRef = ref<HTMLDivElement | null>(null);\n\n// ─────────────────────────────────────────────\n// Event handlers\n// ─────────────────────────────────────────────\nfunction onClick() {\n if (isOpen.value) {\n requestClose();\n } else {\n requestOpen();\n }\n}\n\nfunction onMouseEnter() {\n requestOpen(mouseEnterDelay);\n}\n\nfunction onMouseLeave() {\n requestClose(mouseLeaveDelay);\n}\n\nfunction onFocusIn() {\n requestOpen();\n}\n\nfunction onFocusOut() {\n requestClose();\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n if (event.key === 'Escape' && isOpen.value) {\n event.preventDefault();\n requestClose();\n toggleRef.value?.focus();\n }\n}\n\n// ─────────────────────────────────────────────\n// Tooltip hover (keep tooltip open when hovering it)\n// ─────────────────────────────────────────────\nfunction onTooltipMouseEnter() {\n if (trigger === BTooltipTrigger.Hover) {\n clearTimers();\n }\n}\n\nfunction onTooltipMouseLeave() {\n if (trigger === BTooltipTrigger.Hover) {\n requestClose(mouseLeaveDelay);\n }\n}\n\n// ─────────────────────────────────────────────\n// Event listener management\n// ─────────────────────────────────────────────\nfunction attachListeners() {\n const el = toggleRef.value;\n if (!el) return;\n\n // Keyboard always attached\n el.addEventListener('keydown', onKeydown);\n\n switch (trigger) {\n case BTooltipTrigger.Click:\n el.addEventListener('click', onClick);\n break;\n case BTooltipTrigger.Focus:\n el.addEventListener('focusin', onFocusIn);\n el.addEventListener('focusout', onFocusOut);\n break;\n case BTooltipTrigger.Hover:\n default:\n el.addEventListener('mouseenter', onMouseEnter);\n el.addEventListener('mouseleave', onMouseLeave);\n el.addEventListener('focusin', onFocusIn);\n el.addEventListener('focusout', onFocusOut);\n break;\n }\n}\n\nfunction detachListeners() {\n const el = toggleRef.value;\n if (!el) return;\n\n el.removeEventListener('keydown', onKeydown);\n el.removeEventListener('click', onClick);\n el.removeEventListener('focusin', onFocusIn);\n el.removeEventListener('focusout', onFocusOut);\n el.removeEventListener('mouseenter', onMouseEnter);\n el.removeEventListener('mouseleave', onMouseLeave);\n}\n\nonMounted(() => {\n attachListeners();\n});\n\nonBeforeUnmount(() => {\n detachListeners();\n clearTimers();\n});\n\nwatch(\n () => trigger,\n () => {\n detachListeners();\n attachListeners();\n },\n);\n\n// Sync controlled v-model → popover state\nwatch(\n () => modelValue,\n (val) => {\n if (val === undefined) return;\n if (val) {\n tooltipRef.value?.showPopover();\n } else {\n tooltipRef.value?.hidePopover();\n }\n },\n);\n\n// ─────────────────────────────────────────────\n// Computed styles\n// ─────────────────────────────────────────────\nconst anchorName = computed(() => `--b-tooltip-anchor-${componentUID.value}`);\n\nconst placementClass = computed(() => {\n const map: Record<string, string> = {\n [BTooltipPlacement.TopLeft]: 'top-left',\n [BTooltipPlacement.TopCenter]: 'top-center',\n [BTooltipPlacement.TopRight]: 'top-right',\n [BTooltipPlacement.RightTop]: 'right-top',\n [BTooltipPlacement.RightCenter]: 'right-center',\n [BTooltipPlacement.RightBottom]: 'right-bottom',\n [BTooltipPlacement.BottomRight]: 'bottom-right',\n [BTooltipPlacement.BottomCenter]: 'bottom-center',\n [BTooltipPlacement.BottomLeft]: 'bottom-left',\n [BTooltipPlacement.LeftBottom]: 'left-bottom',\n [BTooltipPlacement.LeftCenter]: 'left-center',\n [BTooltipPlacement.LeftTop]: 'left-top',\n };\n return map[placement] ?? 'top-center';\n});\n\nconst customColorStyle = computed(() => {\n if (!color) return undefined;\n return {\n '--b-tooltip-bg': color,\n '--b-tooltip-arrow-color': color,\n } as Record<string, string>;\n});\n\n// ─────────────────────────────────────────────\n// Public API\n// ─────────────────────────────────────────────\ndefineExpose({ open: doOpen, close: doClose });\n</script>\n\n<template>\n <div\n ref=\"toggleRef\"\n :class=\"['b-tooltip__toggle', toggleClass]\"\n :style=\"{ anchorName: anchorName }\"\n :aria-describedby=\"isOpen ? tooltipId : undefined\"\n >\n <slot />\n </div>\n\n <div\n ref=\"tooltipRef\"\n popover=\"manual\"\n :class=\"[\n 'b-tooltip__content',\n placementClass,\n { 'b-tooltip__content--no-arrow': !arrow },\n tooltipClass,\n ]\"\n :style=\"[{ zIndex, positionAnchor: anchorName }, customColorStyle]\"\n role=\"tooltip\"\n :id=\"tooltipId\"\n @toggle=\"onPopoverToggle\"\n @mouseenter=\"onTooltipMouseEnter\"\n @mouseleave=\"onTooltipMouseLeave\"\n >\n <template v-if=\"shouldRender || !destroyTooltipOnHide\">\n <div v-if=\"arrow\" class=\"b-tooltip__arrow\" aria-hidden=\"true\" />\n <div :class=\"['b-tooltip__inner', tooltipInnerClass]\">\n <slot name=\"title\">\n {{ title }}\n </slot>\n </div>\n </template>\n </div>\n</template>\n\n<style>\n/* ────────────────────────────────────────────\n CSS Custom Properties (tokens)\n ──────────────────────────────────────────── */\n:root {\n --b-tooltip-bg: oklch(20% 0 0);\n --b-tooltip-color: #fff;\n --b-tooltip-font-size: 0.875rem;\n --b-tooltip-line-height: 1.5;\n --b-tooltip-padding-x: 0.5rem;\n --b-tooltip-padding-y: 0.375rem;\n --b-tooltip-border-radius: 0.375rem;\n --b-tooltip-max-width: 250px;\n --b-tooltip-arrow-size: 8px;\n --b-tooltip-arrow-color: oklch(20% 0 0);\n --b-tooltip-gap: 8px;\n --b-tooltip-transition-duration: 200ms;\n --b-tooltip-shadow:\n 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12),\n 0 9px 28px 8px rgba(0, 0, 0, 0.05);\n}\n\n/* ── Dark mode ── */\n[data-prefers-color='dark'] {\n --b-tooltip-bg: oklch(35% 0 0);\n --b-tooltip-arrow-color: oklch(35% 0 0);\n --b-tooltip-shadow:\n 0 6px 16px 0 rgba(0, 0, 0, 0.24), 0 3px 6px -4px rgba(0, 0, 0, 0.36),\n 0 9px 28px 8px rgba(0, 0, 0, 0.2);\n}\n\n@media (prefers-color-scheme: dark) {\n [data-prefers-color='system'] {\n --b-tooltip-bg: oklch(35% 0 0);\n --b-tooltip-arrow-color: oklch(35% 0 0);\n --b-tooltip-shadow:\n 0 6px 16px 0 rgba(0, 0, 0, 0.24), 0 3px 6px -4px rgba(0, 0, 0, 0.36),\n 0 9px 28px 8px rgba(0, 0, 0, 0.2);\n }\n}\n\n/* ─────────────────────────────────────────────\n Toggle wrapper\n ───────────────────────────────────────────── */\n.b-tooltip__toggle {\n display: inline-block;\n}\n\n/* ─────────────────────────────────────────────\n Tooltip content (popover)\n ───────────────────────────────────────────── */\n.b-tooltip__content {\n /* Reset popover defaults */\n position: absolute;\n border: none;\n padding: 0;\n margin: 0;\n background: transparent;\n overflow: visible;\n max-width: var(--b-tooltip-max-width);\n box-sizing: border-box;\n pointer-events: auto;\n\n /* Animation and visibility */\n transition:\n display var(--b-tooltip-transition-duration),\n opacity var(--b-tooltip-transition-duration);\n transition-behavior: allow-discrete;\n opacity: 0;\n\n &:popover-open {\n opacity: 1;\n\n @starting-style {\n opacity: 0;\n }\n }\n\n /* ── Placement: Top ── */\n &.top-left {\n inset: auto;\n bottom: anchor(top);\n left: anchor(left);\n margin-bottom: var(--b-tooltip-gap);\n }\n &.top-center {\n inset: auto;\n bottom: anchor(top);\n justify-self: anchor-center;\n margin-bottom: var(--b-tooltip-gap);\n }\n &.top-right {\n inset: auto;\n bottom: anchor(top);\n right: anchor(right);\n margin-bottom: var(--b-tooltip-gap);\n }\n\n /* ── Placement: Right ── */\n &.right-top {\n inset: auto;\n top: anchor(top);\n left: anchor(right);\n margin-left: var(--b-tooltip-gap);\n }\n &.right-center {\n inset: auto;\n align-self: anchor-center;\n left: anchor(right);\n margin-left: var(--b-tooltip-gap);\n }\n &.right-bottom {\n inset: auto;\n bottom: anchor(bottom);\n left: anchor(right);\n margin-left: var(--b-tooltip-gap);\n }\n\n /* ── Placement: Bottom ── */\n &.bottom-right {\n inset: auto;\n top: anchor(bottom);\n right: anchor(right);\n margin-top: var(--b-tooltip-gap);\n }\n &.bottom-center {\n inset: auto;\n top: anchor(bottom);\n justify-self: anchor-center;\n margin-top: var(--b-tooltip-gap);\n }\n &.bottom-left {\n inset: auto;\n top: anchor(bottom);\n left: anchor(left);\n margin-top: var(--b-tooltip-gap);\n }\n\n /* ── Placement: Left ── */\n &.left-bottom {\n inset: auto;\n bottom: anchor(bottom);\n right: anchor(left);\n margin-right: var(--b-tooltip-gap);\n }\n &.left-center {\n inset: auto;\n align-self: anchor-center;\n right: anchor(left);\n margin-right: var(--b-tooltip-gap);\n }\n &.left-top {\n inset: auto;\n top: anchor(top);\n right: anchor(left);\n margin-right: var(--b-tooltip-gap);\n }\n}\n\n/* ─────────────────────────────────────────────\n Inner content\n ───────────────────────────────────────────── */\n.b-tooltip__inner {\n background: var(--b-tooltip-bg);\n color: var(--b-tooltip-color);\n font-size: var(--b-tooltip-font-size);\n line-height: var(--b-tooltip-line-height);\n padding: var(--b-tooltip-padding-y) var(--b-tooltip-padding-x);\n border-radius: var(--b-tooltip-border-radius);\n box-shadow: var(--b-tooltip-shadow);\n word-wrap: break-word;\n}\n\n/* ─────────────────────────────────────────────\n Arrow\n ───────────────────────────────────────────── */\n.b-tooltip__arrow {\n position: absolute;\n width: var(--b-tooltip-arrow-size);\n height: var(--b-tooltip-arrow-size);\n background: var(--b-tooltip-arrow-color);\n transform: rotate(45deg);\n pointer-events: none;\n}\n\n/* Arrow positioning for top placements */\n.b-tooltip__content.top-left .b-tooltip__arrow,\n.b-tooltip__content.top-center .b-tooltip__arrow,\n.b-tooltip__content.top-right .b-tooltip__arrow {\n bottom: calc(var(--b-tooltip-arrow-size) / -2);\n left: 50%;\n margin-left: calc(var(--b-tooltip-arrow-size) / -2);\n}\n\n/* Arrow positioning for bottom placements */\n.b-tooltip__content.bottom-left .b-tooltip__arrow,\n.b-tooltip__content.bottom-center .b-tooltip__arrow,\n.b-tooltip__content.bottom-right .b-tooltip__arrow {\n top: calc(var(--b-tooltip-arrow-size) / -2);\n left: 50%;\n margin-left: calc(var(--b-tooltip-arrow-size) / -2);\n}\n\n/* Arrow positioning for right placements */\n.b-tooltip__content.right-top .b-tooltip__arrow,\n.b-tooltip__content.right-center .b-tooltip__arrow,\n.b-tooltip__content.right-bottom .b-tooltip__arrow {\n left: calc(var(--b-tooltip-arrow-size) / -2);\n top: 50%;\n margin-top: calc(var(--b-tooltip-arrow-size) / -2);\n}\n\n/* Arrow positioning for left placements */\n.b-tooltip__content.left-top .b-tooltip__arrow,\n.b-tooltip__content.left-center .b-tooltip__arrow,\n.b-tooltip__content.left-bottom .b-tooltip__arrow {\n right: calc(var(--b-tooltip-arrow-size) / -2);\n top: 50%;\n margin-top: calc(var(--b-tooltip-arrow-size) / -2);\n}\n\n/* ─────────────────────────────────────────────\n Position fallbacks (auto-adjust overflow)\n ───────────────────────────────────────────── */\n@position-try --b-tooltip-top-center {\n inset: auto;\n bottom: anchor(top);\n justify-self: anchor-center;\n margin-bottom: var(--b-tooltip-gap);\n}\n\n@position-try --b-tooltip-bottom-center {\n inset: auto;\n top: anchor(bottom);\n justify-self: anchor-center;\n margin-top: var(--b-tooltip-gap);\n}\n\n@position-try --b-tooltip-right-center {\n inset: auto;\n align-self: anchor-center;\n left: anchor(right);\n margin-left: var(--b-tooltip-gap);\n}\n\n@position-try --b-tooltip-left-center {\n inset: auto;\n align-self: anchor-center;\n right: anchor(left);\n margin-right: var(--b-tooltip-gap);\n}\n\n/* ── Reduced motion ── */\n@media (prefers-reduced-motion: reduce) {\n .b-tooltip__content {\n transition-duration: 0ms;\n }\n}\n</style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"design-system245.js","names":["$slots"],"sources":["../src/components/BTabs/BTabs.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { Component, VNode } from 'vue';\nimport { computed, defineComponent, h, nextTick, onMounted, provide, ref, useId, watch } from 'vue';\n\nimport type {\n BTabItem,\n BTabPaneRegistration,\n BTabsContext,\n BTabsPlacement,\n BTabsSize,\n BTabsType,\n} from './types';\nimport { BTabsContextKey } from './types';\n\n// ─────────────────────────────────────────────\n// Props\n// ─────────────────────────────────────────────\nconst {\n activeKey,\n defaultActiveKey,\n items = [],\n type = 'line',\n placement = 'top',\n size = 'middle',\n centered = false,\n animated = true,\n hideAdd = false,\n destroyOnHidden = false,\n keepAlive = false,\n tabBarGutter,\n} = defineProps<{\n /** Current active tab key (controlled via v-model:activeKey). */\n activeKey?: string;\n /** Initial active tab key for uncontrolled mode. @default first non-disabled tab */\n defaultActiveKey?: string;\n /** Tab items configuration. When provided and non-empty, BTabPane children are ignored. */\n items?: BTabItem[];\n /** Visual style of the tabs. @default 'line' */\n type?: BTabsType;\n /** Position of the tab bar. @default 'top' */\n placement?: BTabsPlacement;\n /** Size preset for the tab bar. @default 'middle' */\n size?: BTabsSize;\n /** Whether to center the tab items. @default false */\n centered?: boolean;\n /** Whether content switching is animated. @default true */\n animated?: boolean;\n /** Whether to hide the add button in editable-card mode. @default false */\n hideAdd?: boolean;\n /** Whether to destroy inactive tab content globally. @default false */\n destroyOnHidden?: boolean;\n /** Whether to keep component state alive when switching tabs globally. @default false */\n keepAlive?: boolean;\n /** Gap between tabs in pixels. */\n tabBarGutter?: number;\n}>();\n\n// ─────────────────────────────────────────────\n// Emits\n// ─────────────────────────────────────────────\nconst emit = defineEmits<{\n /** Fires when the active tab changes. */\n (e: 'update:activeKey', key: string): void;\n /** Fires when the active tab changes (alias for update:activeKey). */\n (e: 'change', key: string): void;\n /** Fires when a tab is clicked. */\n (e: 'tabClick', key: string, event: MouseEvent): void;\n /** Fires when a tab is added or removed (editable-card only). */\n (e: 'edit', key: string | null, action: 'add' | 'remove'): void;\n}>();\n\n// ─────────────────────────────────────────────\n// Slots\n// ─────────────────────────────────────────────\ndefineSlots<{\n /** Items mode: receives { item } scoped prop. Pane mode: contains BTabPane children (no props). */\n default?: (props: { item?: BTabItem }) => unknown;\n /** Custom label renderer for each tab (items mode). */\n label?: (props: { item: BTabItem; active: boolean }) => unknown;\n /** Extra content on the left side of the tab bar. */\n leftExtra?: () => unknown;\n /** Extra content on the right side of the tab bar. */\n rightExtra?: () => unknown;\n /** Custom add button (editable-card type). */\n addIcon?: () => unknown;\n /** Custom remove/close icon (editable-card type). */\n removeIcon?: (props: { item: BTabItem }) => unknown;\n}>();\n\n// ─────────────────────────────────────────────\n// Instance-scoped ID prefix (prevents duplicate IDs when multiple BTabs on page)\n// ─────────────────────────────────────────────\nconst uid = useId();\nconst tabId = (key: string) => `${uid}-tab-${key}`;\nconst panelId = (key: string) => `${uid}-tabpanel-${key}`;\n\n// ─────────────────────────────────────────────\n// Pane registry (for BTabPane child component API)\n// ─────────────────────────────────────────────\nconst paneRegistry = ref(new Map<string, BTabPaneRegistration>());\nconst paneOrder = ref<string[]>([]);\n\nfunction registerPane(pane: BTabPaneRegistration) {\n paneRegistry.value.set(pane.key, pane);\n if (!paneOrder.value.includes(pane.key)) {\n paneOrder.value = [...paneOrder.value, pane.key];\n }\n}\n\nfunction unregisterPane(key: string) {\n paneRegistry.value.delete(key);\n paneOrder.value = paneOrder.value.filter((k) => k !== key);\n}\n\nfunction updatePane(key: string, pane: BTabPaneRegistration) {\n paneRegistry.value.set(key, pane);\n}\n\n// ─────────────────────────────────────────────\n// Mode detection + effective items\n// ─────────────────────────────────────────────\nconst isItemsMode = computed(() => items && items.length > 0);\n\nconst effectiveItems = computed<BTabItem[]>(() => {\n if (isItemsMode.value) return items;\n return paneOrder.value\n .map((key) => paneRegistry.value.get(key))\n .filter((p): p is BTabPaneRegistration => p !== undefined)\n .map((pane) => ({\n key: pane.key,\n label: pane.label,\n disabled: pane.disabled,\n closable: pane.closable,\n destroyOnHidden: pane.destroyOnHidden,\n forceRender: pane.forceRender,\n keepAlive: pane.keepAlive,\n }));\n});\n\n// ─────────────────────────────────────────────\n// Internal state\n// ─────────────────────────────────────────────\nconst isControlled = computed(() => activeKey !== undefined);\n\nconst firstEnabledKey = computed(\n () => effectiveItems.value.find((i) => !i.disabled)?.key ?? effectiveItems.value[0]?.key ?? '',\n);\n\nconst internalKey = ref<string>(activeKey ?? defaultActiveKey ?? firstEnabledKey.value);\n\nwatch(\n () => activeKey,\n (val) => {\n if (val !== undefined) internalKey.value = val;\n },\n);\n\nwatch(effectiveItems, () => {\n if (\n internalKey.value === undefined ||\n !effectiveItems.value.find((i) => i.key === internalKey.value)\n ) {\n internalKey.value = firstEnabledKey.value;\n }\n});\n\nconst currentKey = computed(() => (isControlled.value ? activeKey! : internalKey.value));\n\n// ─────────────────────────────────────────────\n// Provide context to BTabPane children\n// ─────────────────────────────────────────────\nconst context: BTabsContext = {\n activeKey: currentKey,\n type: computed(() => type),\n size: computed(() => size),\n placement: computed(() => placement),\n keepAlive: computed(() => keepAlive),\n destroyOnHidden: computed(() => destroyOnHidden),\n register: registerPane,\n unregister: unregisterPane,\n update: updatePane,\n};\n\nprovide(BTabsContextKey, context);\n\n// ─────────────────────────────────────────────\n// Tab activation\n// ─────────────────────────────────────────────\nfunction activateTab(key: string, event?: MouseEvent) {\n const item = effectiveItems.value.find((i) => i.key === key);\n if (!item || item.disabled) return;\n\n if (event) {\n emit('tabClick', key, event);\n }\n\n if (key === currentKey.value) return;\n\n if (!isControlled.value) {\n internalKey.value = key;\n }\n emit('update:activeKey', key);\n emit('change', key);\n}\n\n// ─────────────────────────────────────────────\n// Editable-card actions\n// ─────────────────────────────────────────────\nfunction onAdd() {\n emit('edit', null, 'add');\n}\n\nfunction onRemove(key: string, event: MouseEvent) {\n event.stopPropagation();\n emit('edit', key, 'remove');\n}\n\n// ─────────────────────────────────────────────\n// Ink bar positioning\n// ─────────────────────────────────────────────\nconst tabListRef = ref<HTMLElement | null>(null);\nconst inkBarStyle = ref<Record<string, string>>({});\n\nfunction updateInkBar() {\n if (!tabListRef.value || type !== 'line') return;\n const activeEl = tabListRef.value.querySelector<HTMLElement>('.b-tabs__tab--active');\n if (!activeEl) return;\n\n const isVertical = placement === 'left' || placement === 'right';\n\n if (isVertical) {\n inkBarStyle.value = {\n top: `${activeEl.offsetTop}px`,\n height: `${activeEl.offsetHeight}px`,\n };\n } else {\n inkBarStyle.value = {\n left: `${activeEl.offsetLeft}px`,\n width: `${activeEl.offsetWidth}px`,\n };\n }\n}\n\nwatch(currentKey, async () => {\n await nextTick();\n updateInkBar();\n});\n\nonMounted(() => {\n updateInkBar();\n});\n\n// ─────────────────────────────────────────────\n// Keyboard navigation (roving tabindex)\n// ─────────────────────────────────────────────\nfunction onKeydown(event: KeyboardEvent) {\n const isVertical = placement === 'left' || placement === 'right';\n const nextKeys = isVertical ? ['ArrowDown'] : ['ArrowRight'];\n const prevKeys = isVertical ? ['ArrowUp'] : ['ArrowLeft'];\n\n // Delete key closes the active tab in editable-card mode\n if (event.key === 'Delete' && type === 'editable-card') {\n const item = effectiveItems.value.find((i) => i.key === currentKey.value);\n if (item && item.closable !== false) {\n event.preventDefault();\n emit('edit', currentKey.value, 'remove');\n }\n return;\n }\n\n if ([...nextKeys, ...prevKeys, 'Home', 'End'].includes(event.key)) {\n event.preventDefault();\n const enabledItems = effectiveItems.value.filter((i) => !i.disabled);\n if (enabledItems.length === 0) return;\n\n const currentIdx = enabledItems.findIndex((i) => i.key === currentKey.value);\n\n let targetIdx: number;\n if (nextKeys.includes(event.key)) {\n targetIdx = (currentIdx + 1) % enabledItems.length;\n } else if (prevKeys.includes(event.key)) {\n targetIdx = (currentIdx - 1 + enabledItems.length) % enabledItems.length;\n } else if (event.key === 'Home') {\n targetIdx = 0;\n } else {\n targetIdx = enabledItems.length - 1;\n }\n\n const targetKey = enabledItems[targetIdx].key;\n activateTab(targetKey);\n\n nextTick(() => {\n if (!tabListRef.value) return;\n const targetEl = tabListRef.value.querySelector<HTMLElement>(`[data-tab-key=\"${targetKey}\"]`);\n targetEl?.focus();\n });\n }\n}\n\n// ─────────────────────────────────────────────\n// KeepAlive + content visibility\n// ─────────────────────────────────────────────\nconst renderedKeys = ref<Set<string>>(new Set([currentKey.value]));\n\nwatch(currentKey, (key) => {\n renderedKeys.value.add(key);\n});\n\nfunction shouldUseKeepAlive(item: BTabItem): boolean {\n if (item.destroyOnHidden) return false;\n if (item.keepAlive !== undefined) return item.keepAlive;\n if (destroyOnHidden) return false;\n return keepAlive;\n}\n\nfunction shouldRender(item: BTabItem): boolean {\n if (item.forceRender) return true;\n if (shouldUseKeepAlive(item)) return true;\n const itemDestroy = item.destroyOnHidden ?? destroyOnHidden;\n if (itemDestroy) return item.key === currentKey.value;\n return renderedKeys.value.has(item.key);\n}\n\n// ─────────────────────────────────────────────\n// KeepAlive panel wrapper components\n// ─────────────────────────────────────────────\nconst panelWrappers = computed<Record<string, Component>>(() => {\n const wrappers: Record<string, Component> = {};\n for (const item of effectiveItems.value) {\n if (!shouldUseKeepAlive(item)) continue;\n wrappers[item.key] = defineComponent({\n name: `BTabPanel_${item.key}`,\n setup() {\n return () => {\n const pane = paneRegistry.value.get(item.key);\n if (pane) {\n return pane.renderContent();\n }\n return null;\n };\n },\n });\n }\n return wrappers;\n});\n\nfunction getPaneContent(key: string): VNode[] {\n const pane = paneRegistry.value.get(key);\n return pane?.renderContent() ?? [];\n}\n\nfunction getPaneLabel(key: string): VNode[] | undefined {\n const pane = paneRegistry.value.get(key);\n return pane?.renderLabel?.();\n}\n\n// ─────────────────────────────────────────────\n// Computed classes\n// ─────────────────────────────────────────────\nconst rootClasses = computed(() => [\n 'b-tabs',\n `b-tabs--${type}`,\n `b-tabs--${placement}`,\n `b-tabs--${size}`,\n { 'b-tabs--centered': centered },\n]);\n\nconst tabBarGutterStyle = computed(() =>\n tabBarGutter !== undefined ? { gap: `${tabBarGutter}px` } : undefined,\n);\n</script>\n\n<template>\n <div :class=\"rootClasses\">\n <!-- Tab bar -->\n <div class=\"b-tabs__header\">\n <div v-if=\"$slots.leftExtra\" class=\"b-tabs__extra b-tabs__extra--left\">\n <slot name=\"leftExtra\" />\n </div>\n\n <div\n ref=\"tabListRef\"\n class=\"b-tabs__list\"\n role=\"tablist\"\n :aria-orientation=\"\n placement === 'left' || placement === 'right' ? 'vertical' : 'horizontal'\n \"\n :style=\"tabBarGutterStyle\"\n >\n <div\n v-for=\"item in effectiveItems\"\n :key=\"item.key\"\n :data-tab-key=\"item.key\"\n class=\"b-tabs__tab\"\n :class=\"{\n 'b-tabs__tab--active': item.key === currentKey,\n 'b-tabs__tab--disabled': item.disabled,\n }\"\n role=\"tab\"\n :aria-selected=\"item.key === currentKey\"\n :aria-disabled=\"item.disabled || undefined\"\n :aria-controls=\"panelId(item.key)\"\n :id=\"tabId(item.key)\"\n :tabindex=\"item.key === currentKey ? 0 : -1\"\n @click=\"!item.disabled && activateTab(item.key, $event)\"\n @keydown=\"onKeydown\"\n >\n <span class=\"b-tabs__tab-label\">\n <!-- Items mode: use label slot or item.label -->\n <template v-if=\"isItemsMode\">\n <slot name=\"label\" :item=\"item\" :active=\"item.key === currentKey\">\n {{ item.label }}\n </slot>\n </template>\n <!-- Pane mode: use pane's renderLabel or label string -->\n <template v-else>\n <component\n v-if=\"getPaneLabel(item.key)\"\n :is=\"() => h('span', getPaneLabel(item.key)!)\"\n />\n <template v-else>{{ item.label }}</template>\n </template>\n </span>\n <span\n v-if=\"type === 'editable-card' && item.closable !== false\"\n class=\"b-tabs__tab-remove\"\n aria-hidden=\"true\"\n @click.stop=\"onRemove(item.key, $event)\"\n >\n <slot name=\"removeIcon\" :item=\"item\">\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"b-tabs__close-icon\">\n <path\n d=\"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z\"\n />\n </svg>\n </slot>\n </span>\n </div>\n\n <!-- Ink bar (line type only) -->\n <div\n v-if=\"type === 'line'\"\n class=\"b-tabs__ink-bar\"\n aria-hidden=\"true\"\n :style=\"inkBarStyle\"\n />\n </div>\n\n <!-- Add button (outside tablist to avoid aria-required-children violation) -->\n <button\n v-if=\"type === 'editable-card' && !hideAdd\"\n class=\"b-tabs__add\"\n aria-label=\"Add tab\"\n @click=\"onAdd\"\n >\n <slot name=\"addIcon\">\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\" class=\"b-tabs__add-icon\">\n <path\n d=\"M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z\"\n />\n </svg>\n </slot>\n </button>\n\n <div v-if=\"$slots.rightExtra\" class=\"b-tabs__extra b-tabs__extra--right\">\n <slot name=\"rightExtra\" />\n </div>\n </div>\n\n <!-- Hidden slot area for BTabPane registration (pane mode only) -->\n <div v-if=\"!isItemsMode\" v-show=\"false\" aria-hidden=\"true\" style=\"display: none\">\n <slot />\n </div>\n\n <!-- Tab panels -->\n <div class=\"b-tabs__content\">\n <template v-for=\"item in effectiveItems\" :key=\"item.key\">\n <!-- KeepAlive panels -->\n <div\n v-if=\"shouldUseKeepAlive(item)\"\n :id=\"panelId(item.key)\"\n class=\"b-tabs__panel\"\n :class=\"{\n 'b-tabs__panel--active': item.key === currentKey,\n 'b-tabs__panel--animated': animated,\n }\"\n role=\"tabpanel\"\n :aria-labelledby=\"tabId(item.key)\"\n :tabindex=\"item.key === currentKey ? 0 : -1\"\n :aria-hidden=\"item.key !== currentKey\"\n v-show=\"item.key === currentKey\"\n >\n <!-- Pane mode: KeepAlive caches wrapper component instances -->\n <KeepAlive v-if=\"!isItemsMode\">\n <component\n v-if=\"item.key === currentKey\"\n :is=\"panelWrappers[item.key] ?? (() => null)\"\n :key=\"item.key\"\n />\n </KeepAlive>\n <!-- Items mode: always render slot content; v-show on parent preserves state -->\n <template v-if=\"isItemsMode\">\n <slot :item=\"item\" />\n </template>\n </div>\n\n <!-- Standard panels (no KeepAlive) -->\n <div\n v-else-if=\"shouldRender(item)\"\n v-show=\"item.key === currentKey\"\n :id=\"panelId(item.key)\"\n class=\"b-tabs__panel\"\n :class=\"{\n 'b-tabs__panel--active': item.key === currentKey,\n 'b-tabs__panel--animated': animated,\n }\"\n role=\"tabpanel\"\n :aria-labelledby=\"tabId(item.key)\"\n :tabindex=\"item.key === currentKey ? 0 : -1\"\n :aria-hidden=\"item.key !== currentKey\"\n >\n <!-- Items mode: scoped slot -->\n <template v-if=\"isItemsMode\">\n <slot :item=\"item\" />\n </template>\n <!-- Pane mode: render registered content -->\n <component v-else :is=\"() => getPaneContent(item.key)\" />\n </div>\n </template>\n </div>\n </div>\n</template>\n\n<style>\n/* ─────────────────────────────────────────────\n BTabs - Design tokens (scoped to .b-tabs)\n ───────────────────────────────────────────── */\n.b-tabs {\n --b-tabs-ink-bar-color: oklch(54.6% 0.245 262.881);\n --b-tabs-item-active-color: oklch(35% 0.2 260);\n --b-tabs-item-color: oklch(30% 0.02 260 / 88%);\n --b-tabs-item-hover-color: oklch(54.6% 0.245 262.881);\n --b-tabs-item-selected-color: oklch(54.6% 0.245 262.881);\n --b-tabs-item-disabled-color: oklch(30% 0.02 260 / 25%);\n --b-tabs-title-font-size: 14px;\n --b-tabs-title-font-size-lg: 16px;\n --b-tabs-title-font-size-sm: 14px;\n --b-tabs-card-bg: oklch(97% 0.003 260 / 50%);\n --b-tabs-card-height: 40px;\n --b-tabs-card-height-lg: 48px;\n --b-tabs-card-height-sm: 32px;\n --b-tabs-card-padding: 8px 16px;\n --b-tabs-card-padding-lg: 11px 16px;\n --b-tabs-card-padding-sm: 4px 8px;\n --b-tabs-card-gutter: 2px;\n --b-tabs-card-border-radius: 8px 8px 0 0;\n --b-tabs-horizontal-item-gutter: 32px;\n --b-tabs-horizontal-item-padding: 12px 0;\n --b-tabs-horizontal-item-padding-lg: 16px 0;\n --b-tabs-horizontal-item-padding-sm: 8px 0;\n --b-tabs-horizontal-margin: 0 0 16px 0;\n --b-tabs-vertical-item-margin: 16px 0 0 0;\n --b-tabs-vertical-item-padding: 8px 24px;\n --b-tabs-border-color: oklch(80% 0.005 260);\n --b-tabs-content-min-height: 0;\n --b-tabs-focus-ring: 0 0 0 2px oklch(54.6% 0.245 262.881 / 20%);\n --b-tabs-transition-duration: 200ms;\n\n display: flex;\n flex-direction: column;\n font-size: var(--b-tabs-title-font-size);\n line-height: 1.5;\n}\n\n/* ── Placement layouts ── */\n.b-tabs--left {\n flex-direction: row;\n}\n\n.b-tabs--right {\n flex-direction: row-reverse;\n}\n\n.b-tabs--bottom {\n flex-direction: column-reverse;\n}\n\n/* ── Size variants ── */\n.b-tabs--large {\n --b-tabs-title-font-size: var(--b-tabs-title-font-size-lg);\n}\n\n.b-tabs--small {\n --b-tabs-title-font-size: var(--b-tabs-title-font-size-sm);\n}\n\n/* ─────────────────────────────────────────────\n Header\n ───────────────────────────────────────────── */\n.b-tabs__header {\n display: flex;\n align-items: center;\n position: relative;\n flex-shrink: 0;\n}\n\n.b-tabs--top .b-tabs__header,\n.b-tabs--bottom .b-tabs__header {\n border-bottom: 1px solid var(--b-tabs-border-color);\n margin: var(--b-tabs-horizontal-margin);\n}\n\n.b-tabs--bottom .b-tabs__header {\n border-bottom: none;\n border-top: 1px solid var(--b-tabs-border-color);\n margin: 0;\n}\n\n.b-tabs--left .b-tabs__header,\n.b-tabs--right .b-tabs__header {\n flex-direction: column;\n align-items: stretch;\n border-right: 1px solid var(--b-tabs-border-color);\n margin: 0;\n}\n\n.b-tabs--right .b-tabs__header {\n border-right: none;\n border-left: 1px solid var(--b-tabs-border-color);\n}\n\n/* Card type removes border from header */\n.b-tabs--card .b-tabs__header,\n.b-tabs--editable-card .b-tabs__header {\n border-bottom: 1px solid var(--b-tabs-border-color);\n}\n\n/* ─────────────────────────────────────────────\n Tab list (roving tabindex container)\n ───────────────────────────────────────────── */\n.b-tabs__list {\n display: flex;\n position: relative;\n flex: 1;\n gap: var(--b-tabs-horizontal-item-gutter);\n}\n\n.b-tabs--centered .b-tabs__list {\n justify-content: center;\n}\n\n.b-tabs--left .b-tabs__list,\n.b-tabs--right .b-tabs__list {\n flex-direction: column;\n gap: 0;\n}\n\n/* ─────────────────────────────────────────────\n Individual tab\n ───────────────────────────────────────────── */\n.b-tabs__tab {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n position: relative;\n padding: var(--b-tabs-horizontal-item-padding);\n border: none;\n background: none;\n color: var(--b-tabs-item-color);\n font-size: inherit;\n font-family: inherit;\n cursor: pointer;\n white-space: nowrap;\n outline: none;\n transition: color var(--b-tabs-transition-duration);\n line-height: 1.5;\n}\n\n.b-tabs__tab:hover:not(.b-tabs__tab--disabled) {\n color: var(--b-tabs-item-hover-color);\n}\n\n.b-tabs__tab--active {\n color: var(--b-tabs-item-selected-color);\n font-weight: 500;\n}\n\n.b-tabs__tab--active:hover {\n color: var(--b-tabs-item-active-color);\n}\n\n.b-tabs__tab--disabled {\n color: var(--b-tabs-item-disabled-color);\n cursor: not-allowed;\n}\n\n.b-tabs__tab:focus-visible {\n box-shadow: var(--b-tabs-focus-ring);\n border-radius: 4px;\n}\n\n/* Large size - tab padding */\n.b-tabs--large .b-tabs__tab {\n padding: var(--b-tabs-horizontal-item-padding-lg);\n}\n\n/* Small size - tab padding */\n.b-tabs--small .b-tabs__tab {\n padding: var(--b-tabs-horizontal-item-padding-sm);\n}\n\n/* Vertical tabs */\n.b-tabs--left .b-tabs__tab,\n.b-tabs--right .b-tabs__tab {\n padding: var(--b-tabs-vertical-item-padding);\n justify-content: flex-start;\n}\n\n.b-tabs--left .b-tabs__tab:not(:first-child),\n.b-tabs--right .b-tabs__tab:not(:first-child) {\n margin: var(--b-tabs-vertical-item-margin);\n}\n\n/* ─────────────────────────────────────────────\n Card-type tab\n ───────────────────────────────────────────── */\n.b-tabs--card .b-tabs__list,\n.b-tabs--editable-card .b-tabs__list {\n gap: var(--b-tabs-card-gutter);\n}\n\n.b-tabs--card .b-tabs__tab,\n.b-tabs--editable-card .b-tabs__tab {\n padding: var(--b-tabs-card-padding);\n background: var(--b-tabs-card-bg);\n border: 1px solid var(--b-tabs-border-color);\n border-bottom: none;\n border-radius: var(--b-tabs-card-border-radius);\n height: var(--b-tabs-card-height);\n margin-bottom: -1px;\n}\n\n.b-tabs--card .b-tabs__tab--active,\n.b-tabs--editable-card .b-tabs__tab--active {\n background: white;\n border-bottom-color: white;\n}\n\n.b-tabs--large.b-tabs--card .b-tabs__tab,\n.b-tabs--large.b-tabs--editable-card .b-tabs__tab {\n padding: var(--b-tabs-card-padding-lg);\n height: var(--b-tabs-card-height-lg);\n}\n\n.b-tabs--small.b-tabs--card .b-tabs__tab,\n.b-tabs--small.b-tabs--editable-card .b-tabs__tab {\n padding: var(--b-tabs-card-padding-sm);\n height: var(--b-tabs-card-height-sm);\n}\n\n/* ─────────────────────────────────────────────\n Ink bar (line type indicator)\n ───────────────────────────────────────────── */\n.b-tabs__ink-bar {\n position: absolute;\n background: var(--b-tabs-ink-bar-color);\n transition:\n left var(--b-tabs-transition-duration) cubic-bezier(0.645, 0.045, 0.355, 1),\n width var(--b-tabs-transition-duration) cubic-bezier(0.645, 0.045, 0.355, 1),\n top var(--b-tabs-transition-duration) cubic-bezier(0.645, 0.045, 0.355, 1),\n height var(--b-tabs-transition-duration) cubic-bezier(0.645, 0.045, 0.355, 1);\n pointer-events: none;\n}\n\n.b-tabs--top .b-tabs__ink-bar,\n.b-tabs--bottom .b-tabs__ink-bar {\n bottom: 0;\n height: 2px;\n}\n\n.b-tabs--bottom .b-tabs__ink-bar {\n bottom: auto;\n top: 0;\n}\n\n.b-tabs--left .b-tabs__ink-bar {\n right: 0;\n width: 2px;\n}\n\n.b-tabs--right .b-tabs__ink-bar {\n left: 0;\n width: 2px;\n}\n\n/* ─────────────────────────────────────────────\n Close / Remove button\n ───────────────────────────────────────────── */\n.b-tabs__tab-remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n cursor: pointer;\n opacity: 0.6;\n transition:\n opacity var(--b-tabs-transition-duration),\n background var(--b-tabs-transition-duration);\n}\n\n.b-tabs__tab-remove:hover {\n opacity: 1;\n background: oklch(0% 0 0 / 8%);\n}\n\n.b-tabs__close-icon {\n width: 12px;\n height: 12px;\n}\n\n/* ─────────────────────────────────────────────\n Add button\n ───────────────────────────────────────────── */\n.b-tabs__add {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: var(--b-tabs-card-padding);\n background: var(--b-tabs-card-bg);\n border: 1px solid var(--b-tabs-border-color);\n border-bottom: none;\n border-radius: var(--b-tabs-card-border-radius);\n height: var(--b-tabs-card-height);\n margin-bottom: -1px;\n cursor: pointer;\n color: var(--b-tabs-item-color);\n transition: color var(--b-tabs-transition-duration);\n}\n\n.b-tabs__add:hover {\n color: var(--b-tabs-item-hover-color);\n}\n\n.b-tabs__add:focus-visible {\n box-shadow: var(--b-tabs-focus-ring);\n}\n\n.b-tabs__add-icon {\n width: 16px;\n height: 16px;\n}\n\n/* ─────────────────────────────────────────────\n Extra content slots\n ───────────────────────────────────────────── */\n.b-tabs__extra {\n display: flex;\n align-items: center;\n padding: 0 8px;\n flex-shrink: 0;\n}\n\n/* ─────────────────────────────────────────────\n Content area\n ───────────────────────────────────────────── */\n.b-tabs__content {\n flex: 1;\n min-height: var(--b-tabs-content-min-height);\n}\n\n.b-tabs__panel {\n outline: none;\n}\n\n.b-tabs__panel--animated {\n animation: b-tabs-fade-in var(--b-tabs-transition-duration) ease-in-out;\n}\n\n@keyframes b-tabs-fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n/* ─────────────────────────────────────────────\n Dark mode\n ───────────────────────────────────────────── */\n[data-prefers-color='dark'] .b-tabs {\n --b-tabs-ink-bar-color: oklch(70% 0.18 262.881);\n --b-tabs-item-active-color: oklch(80% 0.14 262.881);\n --b-tabs-item-color: oklch(85% 0.01 260 / 88%);\n --b-tabs-item-hover-color: oklch(70% 0.18 262.881);\n --b-tabs-item-selected-color: oklch(70% 0.18 262.881);\n --b-tabs-item-disabled-color: oklch(85% 0.01 260 / 25%);\n --b-tabs-card-bg: oklch(25% 0.015 260 / 50%);\n --b-tabs-border-color: oklch(35% 0.01 260);\n}\n\n[data-prefers-color='dark'] .b-tabs--card .b-tabs__tab--active,\n[data-prefers-color='dark'] .b-tabs--editable-card .b-tabs__tab--active {\n background: oklch(20% 0.015 260);\n border-bottom-color: oklch(20% 0.015 260);\n}\n\n@media (prefers-color-scheme: dark) {\n [data-prefers-color='system'] .b-tabs {\n --b-tabs-ink-bar-color: oklch(70% 0.18 262.881);\n --b-tabs-item-active-color: oklch(80% 0.14 262.881);\n --b-tabs-item-color: oklch(85% 0.01 260 / 88%);\n --b-tabs-item-hover-color: oklch(70% 0.18 262.881);\n --b-tabs-item-selected-color: oklch(70% 0.18 262.881);\n --b-tabs-item-disabled-color: oklch(85% 0.01 260 / 25%);\n --b-tabs-card-bg: oklch(25% 0.015 260 / 50%);\n --b-tabs-border-color: oklch(35% 0.01 260);\n }\n [data-prefers-color='system'] .b-tabs--editable-card .b-tabs__tab--active {\n background: oklch(20% 0.015 260);\n border-bottom-color: oklch(20% 0.015 260);\n }\n}\n\n/* ─────────────────────────────────────────────\n Reduced motion\n ───────────────────────────────────────────── */\n@media (prefers-reduced-motion: reduce) {\n .b-tabs {\n --b-tabs-transition-duration: 0ms;\n }\n\n .b-tabs__panel--animated {\n animation: none;\n }\n}\n</style>\n"],"mappings":"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"}
|
package/dist/design-system247.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"design-system247.js","names":[],"sources":["../src/components/BTooltip/BTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useComponentId } from '@/composables/useComponentId.ts';\nimport { BTooltipPlacement, BTooltipTrigger } from '@/types.ts';\nimport { computed, onBeforeUnmount, onMounted, ref, useId, watch } from 'vue';\n\n// ─────────────────────────────────────────────\n// Props & emits\n// ─────────────────────────────────────────────\nconst {\n title,\n trigger = BTooltipTrigger.Hover,\n placement = BTooltipPlacement.TopCenter,\n arrow = true,\n color,\n mouseEnterDelay = 100,\n mouseLeaveDelay = 100,\n destroyTooltipOnHide = false,\n zIndex = 1070,\n fresh = false,\n modelValue = undefined,\n} = defineProps<{\n /** The text shown inside the tooltip. Also accepts the `title` slot. */\n title?: string;\n /** The event that triggers the tooltip to open. */\n trigger?: `${BTooltipTrigger}`;\n /** Placement of the tooltip relative to the target element. */\n placement?: `${BTooltipPlacement}`;\n /** Whether the tooltip has an arrow pointing to the target. */\n arrow?: boolean;\n /** Custom background color of the tooltip. */\n color?: string;\n /** Delay in ms before showing on mouseenter. */\n mouseEnterDelay?: number;\n /** Delay in ms before hiding on mouseleave. */\n mouseLeaveDelay?: number;\n /** Whether to destroy the tooltip DOM when hidden. */\n destroyTooltipOnHide?: boolean;\n /** z-index of the tooltip. */\n zIndex?: number;\n /** Force re-render when tooltip is shown. */\n fresh?: boolean;\n /** Whether to auto-adjust placement when tooltip overflows viewport. */\n autoAdjustOverflow?: boolean;\n /** Controlled visibility - bind with `v-model`. */\n modelValue?: boolean;\n /** Additional classes to apply to the toggle wrapper. */\n toggleClass?: string;\n /** Additional classes to apply to the tooltip content container. */\n tooltipClass?: string;\n /** Additional classes to apply to the tooltip inner element. */\n tooltipInnerClass?: string;\n}>();\n\nconst emit = defineEmits<{\n /** Emitted when the tooltip visibility changes. */\n (e: 'openChange', open: boolean): void;\n /** v-model support. */\n (e: 'update:modelValue', value: boolean): void;\n}>();\n\ndefineSlots<{\n /** The target element that triggers the tooltip. */\n default?(): unknown;\n /** Overrides the `title` prop. */\n title?(): unknown;\n}>();\n\n// ─────────────────────────────────────────────\n// Internal state\n// ─────────────────────────────────────────────\nconst { componentUID } = useComponentId();\nconst tooltipId = useId();\n\nconst internalOpen = ref(false);\nconst isOpen = computed(() => (modelValue !== undefined ? modelValue : internalOpen.value));\n\nconst hasBeenOpened = ref(false);\nconst shouldRender = computed(() => {\n if (fresh) return isOpen.value;\n if (destroyTooltipOnHide) return isOpen.value;\n return hasBeenOpened.value || isOpen.value;\n});\n\nwatch(isOpen, (val) => {\n if (val) hasBeenOpened.value = true;\n});\n\n// ─────────────────────────────────────────────\n// Visibility control\n// ─────────────────────────────────────────────\nlet showTimer: ReturnType<typeof setTimeout> | null = null;\nlet hideTimer: ReturnType<typeof setTimeout> | null = null;\n\nfunction clearTimers() {\n if (showTimer) {\n clearTimeout(showTimer);\n showTimer = null;\n }\n if (hideTimer) {\n clearTimeout(hideTimer);\n hideTimer = null;\n }\n}\n\nfunction requestOpen(delay = 0) {\n clearTimers();\n if (isOpen.value) return;\n if (delay > 0) {\n showTimer = setTimeout(() => doOpen(), delay);\n } else {\n doOpen();\n }\n}\n\nfunction requestClose(delay = 0) {\n clearTimers();\n if (!isOpen.value) return;\n if (delay > 0) {\n hideTimer = setTimeout(() => doClose(), delay);\n } else {\n doClose();\n }\n}\n\nfunction doOpen() {\n tooltipRef.value?.showPopover();\n}\n\nfunction doClose() {\n tooltipRef.value?.hidePopover();\n}\n\nfunction setOpen(val: boolean) {\n if (modelValue !== undefined) {\n emit('update:modelValue', val);\n } else {\n internalOpen.value = val;\n }\n emit('openChange', val);\n}\n\n// ─────────────────────────────────────────────\n// Popover toggle event\n// ─────────────────────────────────────────────\nconst onPopoverToggle = ({ newState }: ToggleEvent) => {\n setOpen(newState === 'open');\n};\n\n// ─────────────────────────────────────────────\n// Refs\n// ─────────────────────────────────────────────\nconst tooltipRef = ref<HTMLDivElement | null>(null);\nconst toggleRef = ref<HTMLDivElement | null>(null);\n\n// ─────────────────────────────────────────────\n// Event handlers\n// ─────────────────────────────────────────────\nfunction onClick() {\n if (isOpen.value) {\n requestClose();\n } else {\n requestOpen();\n }\n}\n\nfunction onMouseEnter() {\n requestOpen(mouseEnterDelay);\n}\n\nfunction onMouseLeave() {\n requestClose(mouseLeaveDelay);\n}\n\nfunction onFocusIn() {\n requestOpen();\n}\n\nfunction onFocusOut() {\n requestClose();\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n if (event.key === 'Escape' && isOpen.value) {\n event.preventDefault();\n requestClose();\n toggleRef.value?.focus();\n }\n}\n\n// ─────────────────────────────────────────────\n// Tooltip hover (keep tooltip open when hovering it)\n// ─────────────────────────────────────────────\nfunction onTooltipMouseEnter() {\n if (trigger === BTooltipTrigger.Hover) {\n clearTimers();\n }\n}\n\nfunction onTooltipMouseLeave() {\n if (trigger === BTooltipTrigger.Hover) {\n requestClose(mouseLeaveDelay);\n }\n}\n\n// ─────────────────────────────────────────────\n// Event listener management\n// ─────────────────────────────────────────────\nfunction attachListeners() {\n const el = toggleRef.value;\n if (!el) return;\n\n // Keyboard always attached\n el.addEventListener('keydown', onKeydown);\n\n switch (trigger) {\n case BTooltipTrigger.Click:\n el.addEventListener('click', onClick);\n break;\n case BTooltipTrigger.Focus:\n el.addEventListener('focusin', onFocusIn);\n el.addEventListener('focusout', onFocusOut);\n break;\n case BTooltipTrigger.Hover:\n default:\n el.addEventListener('mouseenter', onMouseEnter);\n el.addEventListener('mouseleave', onMouseLeave);\n el.addEventListener('focusin', onFocusIn);\n el.addEventListener('focusout', onFocusOut);\n break;\n }\n}\n\nfunction detachListeners() {\n const el = toggleRef.value;\n if (!el) return;\n\n el.removeEventListener('keydown', onKeydown);\n el.removeEventListener('click', onClick);\n el.removeEventListener('focusin', onFocusIn);\n el.removeEventListener('focusout', onFocusOut);\n el.removeEventListener('mouseenter', onMouseEnter);\n el.removeEventListener('mouseleave', onMouseLeave);\n}\n\nonMounted(() => {\n attachListeners();\n});\n\nonBeforeUnmount(() => {\n detachListeners();\n clearTimers();\n});\n\nwatch(\n () => trigger,\n () => {\n detachListeners();\n attachListeners();\n },\n);\n\n// Sync controlled v-model → popover state\nwatch(\n () => modelValue,\n (val) => {\n if (val === undefined) return;\n if (val) {\n tooltipRef.value?.showPopover();\n } else {\n tooltipRef.value?.hidePopover();\n }\n },\n);\n\n// ─────────────────────────────────────────────\n// Computed styles\n// ─────────────────────────────────────────────\nconst anchorName = computed(() => `--b-tooltip-anchor-${componentUID.value}`);\n\nconst placementClass = computed(() => {\n const map: Record<string, string> = {\n [BTooltipPlacement.TopLeft]: 'top-left',\n [BTooltipPlacement.TopCenter]: 'top-center',\n [BTooltipPlacement.TopRight]: 'top-right',\n [BTooltipPlacement.RightTop]: 'right-top',\n [BTooltipPlacement.RightCenter]: 'right-center',\n [BTooltipPlacement.RightBottom]: 'right-bottom',\n [BTooltipPlacement.BottomRight]: 'bottom-right',\n [BTooltipPlacement.BottomCenter]: 'bottom-center',\n [BTooltipPlacement.BottomLeft]: 'bottom-left',\n [BTooltipPlacement.LeftBottom]: 'left-bottom',\n [BTooltipPlacement.LeftCenter]: 'left-center',\n [BTooltipPlacement.LeftTop]: 'left-top',\n };\n return map[placement] ?? 'top-center';\n});\n\nconst customColorStyle = computed(() => {\n if (!color) return undefined;\n return {\n '--b-tooltip-bg': color,\n '--b-tooltip-arrow-color': color,\n } as Record<string, string>;\n});\n\n// ─────────────────────────────────────────────\n// Public API\n// ─────────────────────────────────────────────\ndefineExpose({ open: doOpen, close: doClose });\n</script>\n\n<template>\n <div\n ref=\"toggleRef\"\n :class=\"['b-tooltip__toggle', toggleClass]\"\n :style=\"{ anchorName: anchorName }\"\n :aria-describedby=\"isOpen ? tooltipId : undefined\"\n >\n <slot />\n </div>\n\n <div\n ref=\"tooltipRef\"\n popover=\"manual\"\n :class=\"[\n 'b-tooltip__content',\n placementClass,\n { 'b-tooltip__content--no-arrow': !arrow },\n tooltipClass,\n ]\"\n :style=\"[{ zIndex, positionAnchor: anchorName }, customColorStyle]\"\n role=\"tooltip\"\n :id=\"tooltipId\"\n @toggle=\"onPopoverToggle\"\n @mouseenter=\"onTooltipMouseEnter\"\n @mouseleave=\"onTooltipMouseLeave\"\n >\n <template v-if=\"shouldRender || !destroyTooltipOnHide\">\n <div v-if=\"arrow\" class=\"b-tooltip__arrow\" aria-hidden=\"true\" />\n <div :class=\"['b-tooltip__inner', tooltipInnerClass]\">\n <slot name=\"title\">\n {{ title }}\n </slot>\n </div>\n </template>\n </div>\n</template>\n\n<style>\n/* ────────────────────────────────────────────\n CSS Custom Properties (tokens)\n ──────────────────────────────────────────── */\n:root {\n --b-tooltip-bg: oklch(20% 0 0);\n --b-tooltip-color: #fff;\n --b-tooltip-font-size: 0.875rem;\n --b-tooltip-line-height: 1.5;\n --b-tooltip-padding-x: 0.5rem;\n --b-tooltip-padding-y: 0.375rem;\n --b-tooltip-border-radius: 0.375rem;\n --b-tooltip-max-width: 250px;\n --b-tooltip-arrow-size: 8px;\n --b-tooltip-arrow-color: oklch(20% 0 0);\n --b-tooltip-gap: 8px;\n --b-tooltip-transition-duration: 200ms;\n --b-tooltip-shadow:\n 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12),\n 0 9px 28px 8px rgba(0, 0, 0, 0.05);\n}\n\n/* ── Dark mode ── */\n[data-prefers-color='dark'] {\n --b-tooltip-bg: oklch(35% 0 0);\n --b-tooltip-arrow-color: oklch(35% 0 0);\n --b-tooltip-shadow:\n 0 6px 16px 0 rgba(0, 0, 0, 0.24), 0 3px 6px -4px rgba(0, 0, 0, 0.36),\n 0 9px 28px 8px rgba(0, 0, 0, 0.2);\n}\n\n@media (prefers-color-scheme: dark) {\n [data-prefers-color='system'] {\n --b-tooltip-bg: oklch(35% 0 0);\n --b-tooltip-arrow-color: oklch(35% 0 0);\n --b-tooltip-shadow:\n 0 6px 16px 0 rgba(0, 0, 0, 0.24), 0 3px 6px -4px rgba(0, 0, 0, 0.36),\n 0 9px 28px 8px rgba(0, 0, 0, 0.2);\n }\n}\n\n/* ─────────────────────────────────────────────\n Toggle wrapper\n ───────────────────────────────────────────── */\n.b-tooltip__toggle {\n display: inline-block;\n}\n\n/* ─────────────────────────────────────────────\n Tooltip content (popover)\n ───────────────────────────────────────────── */\n.b-tooltip__content {\n /* Reset popover defaults */\n position: absolute;\n border: none;\n padding: 0;\n margin: 0;\n background: transparent;\n overflow: visible;\n max-width: var(--b-tooltip-max-width);\n box-sizing: border-box;\n pointer-events: auto;\n\n /* Animation and visibility */\n transition:\n display var(--b-tooltip-transition-duration),\n opacity var(--b-tooltip-transition-duration);\n transition-behavior: allow-discrete;\n opacity: 0;\n\n &:popover-open {\n opacity: 1;\n\n @starting-style {\n opacity: 0;\n }\n }\n\n /* ── Placement: Top ── */\n &.top-left {\n inset: auto;\n bottom: anchor(top);\n left: anchor(left);\n margin-bottom: var(--b-tooltip-gap);\n }\n &.top-center {\n inset: auto;\n bottom: anchor(top);\n justify-self: anchor-center;\n margin-bottom: var(--b-tooltip-gap);\n }\n &.top-right {\n inset: auto;\n bottom: anchor(top);\n right: anchor(right);\n margin-bottom: var(--b-tooltip-gap);\n }\n\n /* ── Placement: Right ── */\n &.right-top {\n inset: auto;\n top: anchor(top);\n left: anchor(right);\n margin-left: var(--b-tooltip-gap);\n }\n &.right-center {\n inset: auto;\n align-self: anchor-center;\n left: anchor(right);\n margin-left: var(--b-tooltip-gap);\n }\n &.right-bottom {\n inset: auto;\n bottom: anchor(bottom);\n left: anchor(right);\n margin-left: var(--b-tooltip-gap);\n }\n\n /* ── Placement: Bottom ── */\n &.bottom-right {\n inset: auto;\n top: anchor(bottom);\n right: anchor(right);\n margin-top: var(--b-tooltip-gap);\n }\n &.bottom-center {\n inset: auto;\n top: anchor(bottom);\n justify-self: anchor-center;\n margin-top: var(--b-tooltip-gap);\n }\n &.bottom-left {\n inset: auto;\n top: anchor(bottom);\n left: anchor(left);\n margin-top: var(--b-tooltip-gap);\n }\n\n /* ── Placement: Left ── */\n &.left-bottom {\n inset: auto;\n bottom: anchor(bottom);\n right: anchor(left);\n margin-right: var(--b-tooltip-gap);\n }\n &.left-center {\n inset: auto;\n align-self: anchor-center;\n right: anchor(left);\n margin-right: var(--b-tooltip-gap);\n }\n &.left-top {\n inset: auto;\n top: anchor(top);\n right: anchor(left);\n margin-right: var(--b-tooltip-gap);\n }\n}\n\n/* ─────────────────────────────────────────────\n Inner content\n ───────────────────────────────────────────── */\n.b-tooltip__inner {\n background: var(--b-tooltip-bg);\n color: var(--b-tooltip-color);\n font-size: var(--b-tooltip-font-size);\n line-height: var(--b-tooltip-line-height);\n padding: var(--b-tooltip-padding-y) var(--b-tooltip-padding-x);\n border-radius: var(--b-tooltip-border-radius);\n box-shadow: var(--b-tooltip-shadow);\n word-wrap: break-word;\n}\n\n/* ─────────────────────────────────────────────\n Arrow\n ───────────────────────────────────────────── */\n.b-tooltip__arrow {\n position: absolute;\n width: var(--b-tooltip-arrow-size);\n height: var(--b-tooltip-arrow-size);\n background: var(--b-tooltip-arrow-color);\n transform: rotate(45deg);\n pointer-events: none;\n}\n\n/* Arrow positioning for top placements */\n.b-tooltip__content.top-left .b-tooltip__arrow,\n.b-tooltip__content.top-center .b-tooltip__arrow,\n.b-tooltip__content.top-right .b-tooltip__arrow {\n bottom: calc(var(--b-tooltip-arrow-size) / -2);\n left: 50%;\n margin-left: calc(var(--b-tooltip-arrow-size) / -2);\n}\n\n/* Arrow positioning for bottom placements */\n.b-tooltip__content.bottom-left .b-tooltip__arrow,\n.b-tooltip__content.bottom-center .b-tooltip__arrow,\n.b-tooltip__content.bottom-right .b-tooltip__arrow {\n top: calc(var(--b-tooltip-arrow-size) / -2);\n left: 50%;\n margin-left: calc(var(--b-tooltip-arrow-size) / -2);\n}\n\n/* Arrow positioning for right placements */\n.b-tooltip__content.right-top .b-tooltip__arrow,\n.b-tooltip__content.right-center .b-tooltip__arrow,\n.b-tooltip__content.right-bottom .b-tooltip__arrow {\n left: calc(var(--b-tooltip-arrow-size) / -2);\n top: 50%;\n margin-top: calc(var(--b-tooltip-arrow-size) / -2);\n}\n\n/* Arrow positioning for left placements */\n.b-tooltip__content.left-top .b-tooltip__arrow,\n.b-tooltip__content.left-center .b-tooltip__arrow,\n.b-tooltip__content.left-bottom .b-tooltip__arrow {\n right: calc(var(--b-tooltip-arrow-size) / -2);\n top: 50%;\n margin-top: calc(var(--b-tooltip-arrow-size) / -2);\n}\n\n/* ─────────────────────────────────────────────\n Position fallbacks (auto-adjust overflow)\n ───────────────────────────────────────────── */\n@position-try --b-tooltip-top-center {\n inset: auto;\n bottom: anchor(top);\n justify-self: anchor-center;\n margin-bottom: var(--b-tooltip-gap);\n}\n\n@position-try --b-tooltip-bottom-center {\n inset: auto;\n top: anchor(bottom);\n justify-self: anchor-center;\n margin-top: var(--b-tooltip-gap);\n}\n\n@position-try --b-tooltip-right-center {\n inset: auto;\n align-self: anchor-center;\n left: anchor(right);\n margin-left: var(--b-tooltip-gap);\n}\n\n@position-try --b-tooltip-left-center {\n inset: auto;\n align-self: anchor-center;\n right: anchor(left);\n margin-right: var(--b-tooltip-gap);\n}\n\n/* ── Reduced motion ── */\n@media (prefers-reduced-motion: reduce) {\n .b-tooltip__content {\n transition-duration: 0ms;\n }\n}\n</style>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"design-system247.js","names":[],"sources":["../src/components/BTabs/BTabs.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { Component, VNode } from 'vue';\nimport { computed, defineComponent, h, nextTick, onMounted, provide, ref, useId, watch } from 'vue';\n\nimport type {\n BTabItem,\n BTabPaneRegistration,\n BTabsContext,\n BTabsPlacement,\n BTabsSize,\n BTabsType,\n} from './types';\nimport { BTabsContextKey } from './types';\n\n// ─────────────────────────────────────────────\n// Props\n// ─────────────────────────────────────────────\nconst {\n activeKey,\n defaultActiveKey,\n items = [],\n type = 'line',\n placement = 'top',\n size = 'middle',\n centered = false,\n animated = true,\n hideAdd = false,\n destroyOnHidden = false,\n keepAlive = false,\n tabBarGutter,\n} = defineProps<{\n /** Current active tab key (controlled via v-model:activeKey). */\n activeKey?: string;\n /** Initial active tab key for uncontrolled mode. @default first non-disabled tab */\n defaultActiveKey?: string;\n /** Tab items configuration. When provided and non-empty, BTabPane children are ignored. */\n items?: BTabItem[];\n /** Visual style of the tabs. @default 'line' */\n type?: BTabsType;\n /** Position of the tab bar. @default 'top' */\n placement?: BTabsPlacement;\n /** Size preset for the tab bar. @default 'middle' */\n size?: BTabsSize;\n /** Whether to center the tab items. @default false */\n centered?: boolean;\n /** Whether content switching is animated. @default true */\n animated?: boolean;\n /** Whether to hide the add button in editable-card mode. @default false */\n hideAdd?: boolean;\n /** Whether to destroy inactive tab content globally. @default false */\n destroyOnHidden?: boolean;\n /** Whether to keep component state alive when switching tabs globally. @default false */\n keepAlive?: boolean;\n /** Gap between tabs in pixels. */\n tabBarGutter?: number;\n}>();\n\n// ─────────────────────────────────────────────\n// Emits\n// ─────────────────────────────────────────────\nconst emit = defineEmits<{\n /** Fires when the active tab changes. */\n (e: 'update:activeKey', key: string): void;\n /** Fires when the active tab changes (alias for update:activeKey). */\n (e: 'change', key: string): void;\n /** Fires when a tab is clicked. */\n (e: 'tabClick', key: string, event: MouseEvent): void;\n /** Fires when a tab is added or removed (editable-card only). */\n (e: 'edit', key: string | null, action: 'add' | 'remove'): void;\n}>();\n\n// ─────────────────────────────────────────────\n// Slots\n// ─────────────────────────────────────────────\ndefineSlots<{\n /** Items mode: receives { item } scoped prop. Pane mode: contains BTabPane children (no props). */\n default?: (props: { item?: BTabItem }) => unknown;\n /** Custom label renderer for each tab (items mode). */\n label?: (props: { item: BTabItem; active: boolean }) => unknown;\n /** Extra content on the left side of the tab bar. */\n leftExtra?: () => unknown;\n /** Extra content on the right side of the tab bar. */\n rightExtra?: () => unknown;\n /** Custom add button (editable-card type). */\n addIcon?: () => unknown;\n /** Custom remove/close icon (editable-card type). */\n removeIcon?: (props: { item: BTabItem }) => unknown;\n}>();\n\n// ─────────────────────────────────────────────\n// Instance-scoped ID prefix (prevents duplicate IDs when multiple BTabs on page)\n// ─────────────────────────────────────────────\nconst uid = useId();\nconst tabId = (key: string) => `${uid}-tab-${key}`;\nconst panelId = (key: string) => `${uid}-tabpanel-${key}`;\n\n// ─────────────────────────────────────────────\n// Pane registry (for BTabPane child component API)\n// ─────────────────────────────────────────────\nconst paneRegistry = ref(new Map<string, BTabPaneRegistration>());\nconst paneOrder = ref<string[]>([]);\n\nfunction registerPane(pane: BTabPaneRegistration) {\n paneRegistry.value.set(pane.key, pane);\n if (!paneOrder.value.includes(pane.key)) {\n paneOrder.value = [...paneOrder.value, pane.key];\n }\n}\n\nfunction unregisterPane(key: string) {\n paneRegistry.value.delete(key);\n paneOrder.value = paneOrder.value.filter((k) => k !== key);\n}\n\nfunction updatePane(key: string, pane: BTabPaneRegistration) {\n paneRegistry.value.set(key, pane);\n}\n\n// ─────────────────────────────────────────────\n// Mode detection + effective items\n// ─────────────────────────────────────────────\nconst isItemsMode = computed(() => items && items.length > 0);\n\nconst effectiveItems = computed<BTabItem[]>(() => {\n if (isItemsMode.value) return items;\n return paneOrder.value\n .map((key) => paneRegistry.value.get(key))\n .filter((p): p is BTabPaneRegistration => p !== undefined)\n .map((pane) => ({\n key: pane.key,\n label: pane.label,\n disabled: pane.disabled,\n closable: pane.closable,\n destroyOnHidden: pane.destroyOnHidden,\n forceRender: pane.forceRender,\n keepAlive: pane.keepAlive,\n }));\n});\n\n// ─────────────────────────────────────────────\n// Internal state\n// ─────────────────────────────────────────────\nconst isControlled = computed(() => activeKey !== undefined);\n\nconst firstEnabledKey = computed(\n () => effectiveItems.value.find((i) => !i.disabled)?.key ?? effectiveItems.value[0]?.key ?? '',\n);\n\nconst internalKey = ref<string>(activeKey ?? defaultActiveKey ?? firstEnabledKey.value);\n\nwatch(\n () => activeKey,\n (val) => {\n if (val !== undefined) internalKey.value = val;\n },\n);\n\nwatch(effectiveItems, () => {\n if (\n internalKey.value === undefined ||\n !effectiveItems.value.find((i) => i.key === internalKey.value)\n ) {\n internalKey.value = firstEnabledKey.value;\n }\n});\n\nconst currentKey = computed(() => (isControlled.value ? activeKey! : internalKey.value));\n\n// ─────────────────────────────────────────────\n// Provide context to BTabPane children\n// ─────────────────────────────────────────────\nconst context: BTabsContext = {\n activeKey: currentKey,\n type: computed(() => type),\n size: computed(() => size),\n placement: computed(() => placement),\n keepAlive: computed(() => keepAlive),\n destroyOnHidden: computed(() => destroyOnHidden),\n register: registerPane,\n unregister: unregisterPane,\n update: updatePane,\n};\n\nprovide(BTabsContextKey, context);\n\n// ─────────────────────────────────────────────\n// Tab activation\n// ─────────────────────────────────────────────\nfunction activateTab(key: string, event?: MouseEvent) {\n const item = effectiveItems.value.find((i) => i.key === key);\n if (!item || item.disabled) return;\n\n if (event) {\n emit('tabClick', key, event);\n }\n\n if (key === currentKey.value) return;\n\n if (!isControlled.value) {\n internalKey.value = key;\n }\n emit('update:activeKey', key);\n emit('change', key);\n}\n\n// ─────────────────────────────────────────────\n// Editable-card actions\n// ─────────────────────────────────────────────\nfunction onAdd() {\n emit('edit', null, 'add');\n}\n\nfunction onRemove(key: string, event: MouseEvent) {\n event.stopPropagation();\n emit('edit', key, 'remove');\n}\n\n// ─────────────────────────────────────────────\n// Ink bar positioning\n// ─────────────────────────────────────────────\nconst tabListRef = ref<HTMLElement | null>(null);\nconst inkBarStyle = ref<Record<string, string>>({});\n\nfunction updateInkBar() {\n if (!tabListRef.value || type !== 'line') return;\n const activeEl = tabListRef.value.querySelector<HTMLElement>('.b-tabs__tab--active');\n if (!activeEl) return;\n\n const isVertical = placement === 'left' || placement === 'right';\n\n if (isVertical) {\n inkBarStyle.value = {\n top: `${activeEl.offsetTop}px`,\n height: `${activeEl.offsetHeight}px`,\n };\n } else {\n inkBarStyle.value = {\n left: `${activeEl.offsetLeft}px`,\n width: `${activeEl.offsetWidth}px`,\n };\n }\n}\n\nwatch(currentKey, async () => {\n await nextTick();\n updateInkBar();\n});\n\nonMounted(() => {\n updateInkBar();\n});\n\n// ─────────────────────────────────────────────\n// Keyboard navigation (roving tabindex)\n// ─────────────────────────────────────────────\nfunction onKeydown(event: KeyboardEvent) {\n const isVertical = placement === 'left' || placement === 'right';\n const nextKeys = isVertical ? ['ArrowDown'] : ['ArrowRight'];\n const prevKeys = isVertical ? ['ArrowUp'] : ['ArrowLeft'];\n\n // Delete key closes the active tab in editable-card mode\n if (event.key === 'Delete' && type === 'editable-card') {\n const item = effectiveItems.value.find((i) => i.key === currentKey.value);\n if (item && item.closable !== false) {\n event.preventDefault();\n emit('edit', currentKey.value, 'remove');\n }\n return;\n }\n\n if ([...nextKeys, ...prevKeys, 'Home', 'End'].includes(event.key)) {\n event.preventDefault();\n const enabledItems = effectiveItems.value.filter((i) => !i.disabled);\n if (enabledItems.length === 0) return;\n\n const currentIdx = enabledItems.findIndex((i) => i.key === currentKey.value);\n\n let targetIdx: number;\n if (nextKeys.includes(event.key)) {\n targetIdx = (currentIdx + 1) % enabledItems.length;\n } else if (prevKeys.includes(event.key)) {\n targetIdx = (currentIdx - 1 + enabledItems.length) % enabledItems.length;\n } else if (event.key === 'Home') {\n targetIdx = 0;\n } else {\n targetIdx = enabledItems.length - 1;\n }\n\n const targetKey = enabledItems[targetIdx].key;\n activateTab(targetKey);\n\n nextTick(() => {\n if (!tabListRef.value) return;\n const targetEl = tabListRef.value.querySelector<HTMLElement>(`[data-tab-key=\"${targetKey}\"]`);\n targetEl?.focus();\n });\n }\n}\n\n// ─────────────────────────────────────────────\n// KeepAlive + content visibility\n// ─────────────────────────────────────────────\nconst renderedKeys = ref<Set<string>>(new Set([currentKey.value]));\n\nwatch(currentKey, (key) => {\n renderedKeys.value.add(key);\n});\n\nfunction shouldUseKeepAlive(item: BTabItem): boolean {\n if (item.destroyOnHidden) return false;\n if (item.keepAlive !== undefined) return item.keepAlive;\n if (destroyOnHidden) return false;\n return keepAlive;\n}\n\nfunction shouldRender(item: BTabItem): boolean {\n if (item.forceRender) return true;\n if (shouldUseKeepAlive(item)) return true;\n const itemDestroy = item.destroyOnHidden ?? destroyOnHidden;\n if (itemDestroy) return item.key === currentKey.value;\n return renderedKeys.value.has(item.key);\n}\n\n// ─────────────────────────────────────────────\n// KeepAlive panel wrapper components\n// ─────────────────────────────────────────────\nconst panelWrappers = computed<Record<string, Component>>(() => {\n const wrappers: Record<string, Component> = {};\n for (const item of effectiveItems.value) {\n if (!shouldUseKeepAlive(item)) continue;\n wrappers[item.key] = defineComponent({\n name: `BTabPanel_${item.key}`,\n setup() {\n return () => {\n const pane = paneRegistry.value.get(item.key);\n if (pane) {\n return pane.renderContent();\n }\n return null;\n };\n },\n });\n }\n return wrappers;\n});\n\nfunction getPaneContent(key: string): VNode[] {\n const pane = paneRegistry.value.get(key);\n return pane?.renderContent() ?? [];\n}\n\nfunction getPaneLabel(key: string): VNode[] | undefined {\n const pane = paneRegistry.value.get(key);\n return pane?.renderLabel?.();\n}\n\n// ─────────────────────────────────────────────\n// Computed classes\n// ─────────────────────────────────────────────\nconst rootClasses = computed(() => [\n 'b-tabs',\n `b-tabs--${type}`,\n `b-tabs--${placement}`,\n `b-tabs--${size}`,\n { 'b-tabs--centered': centered },\n]);\n\nconst tabBarGutterStyle = computed(() =>\n tabBarGutter !== undefined ? { gap: `${tabBarGutter}px` } : undefined,\n);\n</script>\n\n<template>\n <div :class=\"rootClasses\">\n <!-- Tab bar -->\n <div class=\"b-tabs__header\">\n <div v-if=\"$slots.leftExtra\" class=\"b-tabs__extra b-tabs__extra--left\">\n <slot name=\"leftExtra\" />\n </div>\n\n <div\n ref=\"tabListRef\"\n class=\"b-tabs__list\"\n role=\"tablist\"\n :aria-orientation=\"\n placement === 'left' || placement === 'right' ? 'vertical' : 'horizontal'\n \"\n :style=\"tabBarGutterStyle\"\n >\n <div\n v-for=\"item in effectiveItems\"\n :key=\"item.key\"\n :data-tab-key=\"item.key\"\n class=\"b-tabs__tab\"\n :class=\"{\n 'b-tabs__tab--active': item.key === currentKey,\n 'b-tabs__tab--disabled': item.disabled,\n }\"\n role=\"tab\"\n :aria-selected=\"item.key === currentKey\"\n :aria-disabled=\"item.disabled || undefined\"\n :aria-controls=\"panelId(item.key)\"\n :id=\"tabId(item.key)\"\n :tabindex=\"item.key === currentKey ? 0 : -1\"\n @click=\"!item.disabled && activateTab(item.key, $event)\"\n @keydown=\"onKeydown\"\n >\n <span class=\"b-tabs__tab-label\">\n <!-- Items mode: use label slot or item.label -->\n <template v-if=\"isItemsMode\">\n <slot name=\"label\" :item=\"item\" :active=\"item.key === currentKey\">\n {{ item.label }}\n </slot>\n </template>\n <!-- Pane mode: use pane's renderLabel or label string -->\n <template v-else>\n <component\n v-if=\"getPaneLabel(item.key)\"\n :is=\"() => h('span', getPaneLabel(item.key)!)\"\n />\n <template v-else>{{ item.label }}</template>\n </template>\n </span>\n <span\n v-if=\"type === 'editable-card' && item.closable !== false\"\n class=\"b-tabs__tab-remove\"\n aria-hidden=\"true\"\n @click.stop=\"onRemove(item.key, $event)\"\n >\n <slot name=\"removeIcon\" :item=\"item\">\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"b-tabs__close-icon\">\n <path\n d=\"M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z\"\n />\n </svg>\n </slot>\n </span>\n </div>\n\n <!-- Ink bar (line type only) -->\n <div\n v-if=\"type === 'line'\"\n class=\"b-tabs__ink-bar\"\n aria-hidden=\"true\"\n :style=\"inkBarStyle\"\n />\n </div>\n\n <!-- Add button (outside tablist to avoid aria-required-children violation) -->\n <button\n v-if=\"type === 'editable-card' && !hideAdd\"\n class=\"b-tabs__add\"\n aria-label=\"Add tab\"\n @click=\"onAdd\"\n >\n <slot name=\"addIcon\">\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\" class=\"b-tabs__add-icon\">\n <path\n d=\"M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z\"\n />\n </svg>\n </slot>\n </button>\n\n <div v-if=\"$slots.rightExtra\" class=\"b-tabs__extra b-tabs__extra--right\">\n <slot name=\"rightExtra\" />\n </div>\n </div>\n\n <!-- Hidden slot area for BTabPane registration (pane mode only) -->\n <div v-if=\"!isItemsMode\" v-show=\"false\" aria-hidden=\"true\" style=\"display: none\">\n <slot />\n </div>\n\n <!-- Tab panels -->\n <div class=\"b-tabs__content\">\n <template v-for=\"item in effectiveItems\" :key=\"item.key\">\n <!-- KeepAlive panels -->\n <div\n v-if=\"shouldUseKeepAlive(item)\"\n :id=\"panelId(item.key)\"\n class=\"b-tabs__panel\"\n :class=\"{\n 'b-tabs__panel--active': item.key === currentKey,\n 'b-tabs__panel--animated': animated,\n }\"\n role=\"tabpanel\"\n :aria-labelledby=\"tabId(item.key)\"\n :tabindex=\"item.key === currentKey ? 0 : -1\"\n :aria-hidden=\"item.key !== currentKey\"\n v-show=\"item.key === currentKey\"\n >\n <!-- Pane mode: KeepAlive caches wrapper component instances -->\n <KeepAlive v-if=\"!isItemsMode\">\n <component\n v-if=\"item.key === currentKey\"\n :is=\"panelWrappers[item.key] ?? (() => null)\"\n :key=\"item.key\"\n />\n </KeepAlive>\n <!-- Items mode: always render slot content; v-show on parent preserves state -->\n <template v-if=\"isItemsMode\">\n <slot :item=\"item\" />\n </template>\n </div>\n\n <!-- Standard panels (no KeepAlive) -->\n <div\n v-else-if=\"shouldRender(item)\"\n v-show=\"item.key === currentKey\"\n :id=\"panelId(item.key)\"\n class=\"b-tabs__panel\"\n :class=\"{\n 'b-tabs__panel--active': item.key === currentKey,\n 'b-tabs__panel--animated': animated,\n }\"\n role=\"tabpanel\"\n :aria-labelledby=\"tabId(item.key)\"\n :tabindex=\"item.key === currentKey ? 0 : -1\"\n :aria-hidden=\"item.key !== currentKey\"\n >\n <!-- Items mode: scoped slot -->\n <template v-if=\"isItemsMode\">\n <slot :item=\"item\" />\n </template>\n <!-- Pane mode: render registered content -->\n <component v-else :is=\"() => getPaneContent(item.key)\" />\n </div>\n </template>\n </div>\n </div>\n</template>\n\n<style>\n/* ─────────────────────────────────────────────\n BTabs - Design tokens (scoped to .b-tabs)\n ───────────────────────────────────────────── */\n.b-tabs {\n --b-tabs-ink-bar-color: oklch(54.6% 0.245 262.881);\n --b-tabs-item-active-color: oklch(35% 0.2 260);\n --b-tabs-item-color: oklch(30% 0.02 260 / 88%);\n --b-tabs-item-hover-color: oklch(54.6% 0.245 262.881);\n --b-tabs-item-selected-color: oklch(54.6% 0.245 262.881);\n --b-tabs-item-disabled-color: oklch(30% 0.02 260 / 25%);\n --b-tabs-title-font-size: 14px;\n --b-tabs-title-font-size-lg: 16px;\n --b-tabs-title-font-size-sm: 14px;\n --b-tabs-card-bg: oklch(97% 0.003 260 / 50%);\n --b-tabs-card-height: 40px;\n --b-tabs-card-height-lg: 48px;\n --b-tabs-card-height-sm: 32px;\n --b-tabs-card-padding: 8px 16px;\n --b-tabs-card-padding-lg: 11px 16px;\n --b-tabs-card-padding-sm: 4px 8px;\n --b-tabs-card-gutter: 2px;\n --b-tabs-card-border-radius: 8px 8px 0 0;\n --b-tabs-horizontal-item-gutter: 32px;\n --b-tabs-horizontal-item-padding: 12px 0;\n --b-tabs-horizontal-item-padding-lg: 16px 0;\n --b-tabs-horizontal-item-padding-sm: 8px 0;\n --b-tabs-horizontal-margin: 0 0 16px 0;\n --b-tabs-vertical-item-margin: 16px 0 0 0;\n --b-tabs-vertical-item-padding: 8px 24px;\n --b-tabs-border-color: oklch(80% 0.005 260);\n --b-tabs-content-min-height: 0;\n --b-tabs-focus-ring: 0 0 0 2px oklch(54.6% 0.245 262.881 / 20%);\n --b-tabs-transition-duration: 200ms;\n\n display: flex;\n flex-direction: column;\n font-size: var(--b-tabs-title-font-size);\n line-height: 1.5;\n}\n\n/* ── Placement layouts ── */\n.b-tabs--left {\n flex-direction: row;\n}\n\n.b-tabs--right {\n flex-direction: row-reverse;\n}\n\n.b-tabs--bottom {\n flex-direction: column-reverse;\n}\n\n/* ── Size variants ── */\n.b-tabs--large {\n --b-tabs-title-font-size: var(--b-tabs-title-font-size-lg);\n}\n\n.b-tabs--small {\n --b-tabs-title-font-size: var(--b-tabs-title-font-size-sm);\n}\n\n/* ─────────────────────────────────────────────\n Header\n ───────────────────────────────────────────── */\n.b-tabs__header {\n display: flex;\n align-items: center;\n position: relative;\n flex-shrink: 0;\n}\n\n.b-tabs--top .b-tabs__header,\n.b-tabs--bottom .b-tabs__header {\n border-bottom: 1px solid var(--b-tabs-border-color);\n margin: var(--b-tabs-horizontal-margin);\n}\n\n.b-tabs--bottom .b-tabs__header {\n border-bottom: none;\n border-top: 1px solid var(--b-tabs-border-color);\n margin: 0;\n}\n\n.b-tabs--left .b-tabs__header,\n.b-tabs--right .b-tabs__header {\n flex-direction: column;\n align-items: stretch;\n border-right: 1px solid var(--b-tabs-border-color);\n margin: 0;\n}\n\n.b-tabs--right .b-tabs__header {\n border-right: none;\n border-left: 1px solid var(--b-tabs-border-color);\n}\n\n/* Card type removes border from header */\n.b-tabs--card .b-tabs__header,\n.b-tabs--editable-card .b-tabs__header {\n border-bottom: 1px solid var(--b-tabs-border-color);\n}\n\n/* ─────────────────────────────────────────────\n Tab list (roving tabindex container)\n ───────────────────────────────────────────── */\n.b-tabs__list {\n display: flex;\n position: relative;\n flex: 1;\n gap: var(--b-tabs-horizontal-item-gutter);\n}\n\n.b-tabs--centered .b-tabs__list {\n justify-content: center;\n}\n\n.b-tabs--left .b-tabs__list,\n.b-tabs--right .b-tabs__list {\n flex-direction: column;\n gap: 0;\n}\n\n/* ─────────────────────────────────────────────\n Individual tab\n ───────────────────────────────────────────── */\n.b-tabs__tab {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n position: relative;\n padding: var(--b-tabs-horizontal-item-padding);\n border: none;\n background: none;\n color: var(--b-tabs-item-color);\n font-size: inherit;\n font-family: inherit;\n cursor: pointer;\n white-space: nowrap;\n outline: none;\n transition: color var(--b-tabs-transition-duration);\n line-height: 1.5;\n}\n\n.b-tabs__tab:hover:not(.b-tabs__tab--disabled) {\n color: var(--b-tabs-item-hover-color);\n}\n\n.b-tabs__tab--active {\n color: var(--b-tabs-item-selected-color);\n font-weight: 500;\n}\n\n.b-tabs__tab--active:hover {\n color: var(--b-tabs-item-active-color);\n}\n\n.b-tabs__tab--disabled {\n color: var(--b-tabs-item-disabled-color);\n cursor: not-allowed;\n}\n\n.b-tabs__tab:focus-visible {\n box-shadow: var(--b-tabs-focus-ring);\n border-radius: 4px;\n}\n\n/* Large size - tab padding */\n.b-tabs--large .b-tabs__tab {\n padding: var(--b-tabs-horizontal-item-padding-lg);\n}\n\n/* Small size - tab padding */\n.b-tabs--small .b-tabs__tab {\n padding: var(--b-tabs-horizontal-item-padding-sm);\n}\n\n/* Vertical tabs */\n.b-tabs--left .b-tabs__tab,\n.b-tabs--right .b-tabs__tab {\n padding: var(--b-tabs-vertical-item-padding);\n justify-content: flex-start;\n}\n\n.b-tabs--left .b-tabs__tab:not(:first-child),\n.b-tabs--right .b-tabs__tab:not(:first-child) {\n margin: var(--b-tabs-vertical-item-margin);\n}\n\n/* ─────────────────────────────────────────────\n Card-type tab\n ───────────────────────────────────────────── */\n.b-tabs--card .b-tabs__list,\n.b-tabs--editable-card .b-tabs__list {\n gap: var(--b-tabs-card-gutter);\n}\n\n.b-tabs--card .b-tabs__tab,\n.b-tabs--editable-card .b-tabs__tab {\n padding: var(--b-tabs-card-padding);\n background: var(--b-tabs-card-bg);\n border: 1px solid var(--b-tabs-border-color);\n border-bottom: none;\n border-radius: var(--b-tabs-card-border-radius);\n height: var(--b-tabs-card-height);\n margin-bottom: -1px;\n}\n\n.b-tabs--card .b-tabs__tab--active,\n.b-tabs--editable-card .b-tabs__tab--active {\n background: white;\n border-bottom-color: white;\n}\n\n.b-tabs--large.b-tabs--card .b-tabs__tab,\n.b-tabs--large.b-tabs--editable-card .b-tabs__tab {\n padding: var(--b-tabs-card-padding-lg);\n height: var(--b-tabs-card-height-lg);\n}\n\n.b-tabs--small.b-tabs--card .b-tabs__tab,\n.b-tabs--small.b-tabs--editable-card .b-tabs__tab {\n padding: var(--b-tabs-card-padding-sm);\n height: var(--b-tabs-card-height-sm);\n}\n\n/* ─────────────────────────────────────────────\n Ink bar (line type indicator)\n ───────────────────────────────────────────── */\n.b-tabs__ink-bar {\n position: absolute;\n background: var(--b-tabs-ink-bar-color);\n transition:\n left var(--b-tabs-transition-duration) cubic-bezier(0.645, 0.045, 0.355, 1),\n width var(--b-tabs-transition-duration) cubic-bezier(0.645, 0.045, 0.355, 1),\n top var(--b-tabs-transition-duration) cubic-bezier(0.645, 0.045, 0.355, 1),\n height var(--b-tabs-transition-duration) cubic-bezier(0.645, 0.045, 0.355, 1);\n pointer-events: none;\n}\n\n.b-tabs--top .b-tabs__ink-bar,\n.b-tabs--bottom .b-tabs__ink-bar {\n bottom: 0;\n height: 2px;\n}\n\n.b-tabs--bottom .b-tabs__ink-bar {\n bottom: auto;\n top: 0;\n}\n\n.b-tabs--left .b-tabs__ink-bar {\n right: 0;\n width: 2px;\n}\n\n.b-tabs--right .b-tabs__ink-bar {\n left: 0;\n width: 2px;\n}\n\n/* ─────────────────────────────────────────────\n Close / Remove button\n ───────────────────────────────────────────── */\n.b-tabs__tab-remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n cursor: pointer;\n opacity: 0.6;\n transition:\n opacity var(--b-tabs-transition-duration),\n background var(--b-tabs-transition-duration);\n}\n\n.b-tabs__tab-remove:hover {\n opacity: 1;\n background: oklch(0% 0 0 / 8%);\n}\n\n.b-tabs__close-icon {\n width: 12px;\n height: 12px;\n}\n\n/* ─────────────────────────────────────────────\n Add button\n ───────────────────────────────────────────── */\n.b-tabs__add {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: var(--b-tabs-card-padding);\n background: var(--b-tabs-card-bg);\n border: 1px solid var(--b-tabs-border-color);\n border-bottom: none;\n border-radius: var(--b-tabs-card-border-radius);\n height: var(--b-tabs-card-height);\n margin-bottom: -1px;\n cursor: pointer;\n color: var(--b-tabs-item-color);\n transition: color var(--b-tabs-transition-duration);\n}\n\n.b-tabs__add:hover {\n color: var(--b-tabs-item-hover-color);\n}\n\n.b-tabs__add:focus-visible {\n box-shadow: var(--b-tabs-focus-ring);\n}\n\n.b-tabs__add-icon {\n width: 16px;\n height: 16px;\n}\n\n/* ─────────────────────────────────────────────\n Extra content slots\n ───────────────────────────────────────────── */\n.b-tabs__extra {\n display: flex;\n align-items: center;\n padding: 0 8px;\n flex-shrink: 0;\n}\n\n/* ─────────────────────────────────────────────\n Content area\n ───────────────────────────────────────────── */\n.b-tabs__content {\n flex: 1;\n min-height: var(--b-tabs-content-min-height);\n}\n\n.b-tabs__panel {\n outline: none;\n}\n\n.b-tabs__panel--animated {\n animation: b-tabs-fade-in var(--b-tabs-transition-duration) ease-in-out;\n}\n\n@keyframes b-tabs-fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n/* ─────────────────────────────────────────────\n Dark mode\n ───────────────────────────────────────────── */\n[data-prefers-color='dark'] .b-tabs {\n --b-tabs-ink-bar-color: oklch(70% 0.18 262.881);\n --b-tabs-item-active-color: oklch(80% 0.14 262.881);\n --b-tabs-item-color: oklch(85% 0.01 260 / 88%);\n --b-tabs-item-hover-color: oklch(70% 0.18 262.881);\n --b-tabs-item-selected-color: oklch(70% 0.18 262.881);\n --b-tabs-item-disabled-color: oklch(85% 0.01 260 / 25%);\n --b-tabs-card-bg: oklch(25% 0.015 260 / 50%);\n --b-tabs-border-color: oklch(35% 0.01 260);\n}\n\n[data-prefers-color='dark'] .b-tabs--card .b-tabs__tab--active,\n[data-prefers-color='dark'] .b-tabs--editable-card .b-tabs__tab--active {\n background: oklch(20% 0.015 260);\n border-bottom-color: oklch(20% 0.015 260);\n}\n\n@media (prefers-color-scheme: dark) {\n [data-prefers-color='system'] .b-tabs {\n --b-tabs-ink-bar-color: oklch(70% 0.18 262.881);\n --b-tabs-item-active-color: oklch(80% 0.14 262.881);\n --b-tabs-item-color: oklch(85% 0.01 260 / 88%);\n --b-tabs-item-hover-color: oklch(70% 0.18 262.881);\n --b-tabs-item-selected-color: oklch(70% 0.18 262.881);\n --b-tabs-item-disabled-color: oklch(85% 0.01 260 / 25%);\n --b-tabs-card-bg: oklch(25% 0.015 260 / 50%);\n --b-tabs-border-color: oklch(35% 0.01 260);\n }\n [data-prefers-color='system'] .b-tabs--editable-card .b-tabs__tab--active {\n background: oklch(20% 0.015 260);\n border-bottom-color: oklch(20% 0.015 260);\n }\n}\n\n/* ─────────────────────────────────────────────\n Reduced motion\n ───────────────────────────────────────────── */\n@media (prefers-reduced-motion: reduce) {\n .b-tabs {\n --b-tabs-transition-duration: 0ms;\n }\n\n .b-tabs__panel--animated {\n animation: none;\n }\n}\n</style>\n"],"mappings":""}
|
package/dist/design-system248.js
CHANGED
|
@@ -1,10 +1,122 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { Transition as e, computed as t, createBlock as n, createCommentVNode as r, createElementBlock as i, createElementVNode as a, createTextVNode as o, defineComponent as s, normalizeClass as c, normalizeStyle as l, openBlock as u, ref as d, renderSlot as f, toDisplayString as p, watch as m, withCtx as h, withModifiers as g } from "vue";
|
|
2
|
+
//#region src/components/BTag/BTag.vue?vue&type=script&setup=true&lang.ts
|
|
3
|
+
var _ = ["aria-hidden"], v = { class: "b-tag__content" }, y = ["data-icon"], b = {
|
|
4
|
+
key: 1,
|
|
5
|
+
class: "b-tag__close-icon",
|
|
6
|
+
viewBox: "0 0 12 12",
|
|
7
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
8
|
+
"aria-hidden": "true",
|
|
9
|
+
focusable: "false"
|
|
10
|
+
}, x = /* @__PURE__ */ s({
|
|
11
|
+
__name: "BTag",
|
|
12
|
+
props: {
|
|
13
|
+
color: {},
|
|
14
|
+
variant: { default: "filled" },
|
|
15
|
+
size: { default: "default" },
|
|
16
|
+
closable: {
|
|
17
|
+
type: Boolean,
|
|
18
|
+
default: !1
|
|
19
|
+
},
|
|
20
|
+
closeIcon: {},
|
|
21
|
+
visible: {
|
|
22
|
+
type: Boolean,
|
|
23
|
+
default: () => void 0
|
|
24
|
+
},
|
|
25
|
+
bordered: {
|
|
26
|
+
type: Boolean,
|
|
27
|
+
default: !0
|
|
28
|
+
},
|
|
29
|
+
icon: {}
|
|
30
|
+
},
|
|
31
|
+
emits: [
|
|
32
|
+
"close",
|
|
33
|
+
"afterClose",
|
|
34
|
+
"update:visible"
|
|
35
|
+
],
|
|
36
|
+
setup(s, { emit: x }) {
|
|
37
|
+
let S = x, C = [
|
|
38
|
+
"default",
|
|
39
|
+
"success",
|
|
40
|
+
"processing",
|
|
41
|
+
"error",
|
|
42
|
+
"warning",
|
|
43
|
+
"magenta",
|
|
44
|
+
"red",
|
|
45
|
+
"volcano",
|
|
46
|
+
"orange",
|
|
47
|
+
"gold",
|
|
48
|
+
"lime",
|
|
49
|
+
"green",
|
|
50
|
+
"cyan",
|
|
51
|
+
"blue",
|
|
52
|
+
"geekblue",
|
|
53
|
+
"purple"
|
|
54
|
+
], w = t(() => s.color === void 0 || C.includes(s.color)), T = t(() => w.value ? s.color ?? "default" : "default"), E = t(() => s.visible !== void 0), D = d(!0);
|
|
55
|
+
m(() => s.visible, (e) => {
|
|
56
|
+
e !== void 0 && (D.value = e);
|
|
57
|
+
});
|
|
58
|
+
let O = t(() => E.value ? s.visible : D.value);
|
|
59
|
+
function k(e) {
|
|
60
|
+
S("close", e), E.value ? S("update:visible", !1) : D.value = !1;
|
|
61
|
+
}
|
|
62
|
+
function A(e) {
|
|
63
|
+
k(e);
|
|
64
|
+
}
|
|
65
|
+
function j(e) {
|
|
66
|
+
(e.key === "Enter" || e.key === " " || e.key === "Escape") && (e.preventDefault(), k(e));
|
|
67
|
+
}
|
|
68
|
+
function M() {
|
|
69
|
+
S("afterClose");
|
|
70
|
+
}
|
|
71
|
+
let N = t(() => [
|
|
72
|
+
"b-tag",
|
|
73
|
+
`b-tag--${T.value}`,
|
|
74
|
+
`b-tag--${s.variant}`,
|
|
75
|
+
{
|
|
76
|
+
"b-tag--borderless": !s.bordered,
|
|
77
|
+
"b-tag--closable": s.closable,
|
|
78
|
+
"b-tag--small": s.size === "small",
|
|
79
|
+
"b-tag--large": s.size === "large",
|
|
80
|
+
"b-tag--custom-color": !w.value
|
|
81
|
+
}
|
|
82
|
+
]), P = t(() => {
|
|
83
|
+
if (!w.value) return { "--b-tag-custom-color": s.color };
|
|
84
|
+
});
|
|
85
|
+
return (t, d) => (u(), n(e, {
|
|
86
|
+
name: "b-tag-fade",
|
|
87
|
+
onAfterLeave: M
|
|
88
|
+
}, {
|
|
89
|
+
default: h(() => [O.value ? (u(), i("span", {
|
|
90
|
+
key: 0,
|
|
91
|
+
class: c(N.value),
|
|
92
|
+
style: l(P.value)
|
|
93
|
+
}, [
|
|
94
|
+
t.$slots.icon || s.icon ? (u(), i("span", {
|
|
95
|
+
key: 0,
|
|
96
|
+
class: "b-tag__icon",
|
|
97
|
+
"aria-hidden": t.$slots.icon ? void 0 : "true"
|
|
98
|
+
}, [f(t.$slots, "icon", {}, () => [o(p(s.icon), 1)])], 8, _)) : r("", !0),
|
|
99
|
+
a("span", v, [f(t.$slots, "default")]),
|
|
100
|
+
s.closable ? (u(), i("button", {
|
|
101
|
+
key: 1,
|
|
102
|
+
type: "button",
|
|
103
|
+
class: "b-tag__close",
|
|
104
|
+
"aria-label": "Remove tag",
|
|
105
|
+
tabindex: "0",
|
|
106
|
+
onClick: g(A, ["stop"]),
|
|
107
|
+
onKeydown: j
|
|
108
|
+
}, [f(t.$slots, "closeIcon", {}, () => [s.closeIcon ? (u(), i("span", {
|
|
109
|
+
key: 0,
|
|
110
|
+
class: "b-tag__close-label",
|
|
111
|
+
"aria-hidden": "true",
|
|
112
|
+
"data-icon": s.closeIcon
|
|
113
|
+
}, null, 8, y)) : (u(), i("svg", b, [...d[0] ||= [a("path", { d: "M9.5 3.205 8.795 2.5 6 5.295 3.205 2.5 2.5 3.205 5.295 6 2.5 8.795 3.205 9.5 6 6.705 8.795 9.5 9.5 8.795 6.705 6z" }, null, -1)]]))])], 32)) : r("", !0)
|
|
114
|
+
], 6)) : r("", !0)]),
|
|
115
|
+
_: 3
|
|
116
|
+
}));
|
|
117
|
+
}
|
|
118
|
+
});
|
|
7
119
|
//#endregion
|
|
8
|
-
export {
|
|
120
|
+
export { x as default };
|
|
9
121
|
|
|
10
122
|
//# sourceMappingURL=design-system248.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"design-system248.js","names":[],"sources":["../src/components/BTour/types.ts"],"sourcesContent":["import type { InjectionKey } from 'vue';\n\n// ─────────────────────────────────────────────\n// Enums\n// ─────────────────────────────────────────────\n\nexport enum BTourPlacement {\n Center = 'center',\n Top = 'top',\n TopLeft = 'topLeft',\n TopRight = 'topRight',\n Bottom = 'bottom',\n BottomLeft = 'bottomLeft',\n BottomRight = 'bottomRight',\n Left = 'left',\n LeftTop = 'leftTop',\n LeftBottom = 'leftBottom',\n Right = 'right',\n RightTop = 'rightTop',\n RightBottom = 'rightBottom',\n}\n\nexport enum BTourType {\n Default = 'default',\n Primary = 'primary',\n}\n\n// ─────────────────────────────────────────────\n// Interfaces\n// ─────────────────────────────────────────────\n\nexport interface BTourArrowOptions {\n /** Point the arrow at the center of the target element. */\n pointAtCenter?: boolean;\n}\n\nexport interface BTourGapOptions {\n /** Pixel offset between the highlight box and the target element. */\n offset?: number | [number, number];\n /** Border-radius of the highlight box (px). */\n radius?: number;\n}\n\nexport interface BTourButtonProps {\n children?: string;\n onClick?: () => void;\n className?: string;\n style?: Record<string, string>;\n}\n\nexport interface BTourScrollIntoViewOptions {\n behavior?: ScrollBehavior;\n block?: ScrollLogicalPosition;\n inline?: ScrollLogicalPosition;\n}\n\nexport interface BTourStep {\n /** Title of the step. */\n title: string;\n /** Description text for the step. */\n description?: string;\n /** Cover image or video URL shown above title, or arbitrary HTML. */\n cover?: string;\n /**\n * CSS selector string, HTMLElement reference, or getter function\n * returning an element. Passing `null` centers the tour popup.\n */\n target?: string | HTMLElement | (() => HTMLElement | null) | null;\n /** Arrow configuration for this step (overrides Tour-level). */\n arrow?: boolean | BTourArrowOptions;\n /** Placement for this step (overrides Tour-level). */\n placement?: `${BTourPlacement}`;\n /** Mask configuration for this step (overrides Tour-level). */\n mask?: boolean | { style?: Record<string, string>; color?: string };\n /** Type variant for this step (overrides Tour-level). */\n type?: `${BTourType}`;\n /** Custom next-button props. */\n nextButtonProps?: BTourButtonProps;\n /** Custom prev-button props. */\n prevButtonProps?: BTourButtonProps;\n /** Custom close icon for this step. */\n closeIcon?: boolean | string;\n /** Scroll-into-view options for this step. */\n scrollIntoViewOptions?: boolean | BTourScrollIntoViewOptions;\n /** Fired when this step's close button is clicked. */\n onClose?: () => void;\n}\n\n// ─────────────────────────────────────────────\n// Internal computed step (resolved)\n// ─────────────────────────────────────────────\n\nexport interface BTourResolvedStep extends BTourStep {\n resolvedTarget: HTMLElement | null;\n index: number;\n}\n\n// ─────────────────────────────────────────────\n// Injection key (unused currently - kept for extensibility)\n// ─────────────────────────────────────────────\n\nexport const BTourContextKey: InjectionKey<null> = Symbol('BTourContext');\n"],"mappings":";AAMA,IAAY,IAAL,yBAAA,GAAA;QACL,EAAA,SAAA,UACA,EAAA,MAAA,OACA,EAAA,UAAA,WACA,EAAA,WAAA,YACA,EAAA,SAAA,UACA,EAAA,aAAA,cACA,EAAA,cAAA,eACA,EAAA,OAAA,QACA,EAAA,UAAA,WACA,EAAA,aAAA,cACA,EAAA,QAAA,SACA,EAAA,WAAA,YACA,EAAA,cAAA;KACD,EAEW,IAAL,yBAAA,GAAA;QACL,EAAA,UAAA,WACA,EAAA,UAAA;KACD"}
|
|
1
|
+
{"version":3,"file":"design-system248.js","names":["$slots"],"sources":["../src/components/BTag/BTag.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue';\n\nimport type { BTagColor, BTagPresetColor, BTagSize, BTagVariant } from './types';\n\n// ─────────────────────────────────────────────\n// Props\n// ─────────────────────────────────────────────\nconst {\n color,\n variant = 'filled',\n size = 'default',\n closable = false,\n closeIcon,\n visible = undefined,\n bordered = true,\n icon,\n} = defineProps<{\n /**\n * Preset semantic color name or any CSS color value.\n * Preset names map to a full color scale (bg, border, text).\n * Any other string is treated as a raw CSS color and applied to the border.\n * @example 'success' | 'processing' | 'error' | '#ff0000' | 'rgb(0,0,255)'\n */\n color?: BTagColor;\n /**\n * Visual style variant.\n * @default 'filled'\n */\n variant?: BTagVariant;\n /**\n * Size of the tag.\n * @default 'default'\n */\n size?: BTagSize;\n /**\n * Whether the tag can be closed/removed.\n * @default false\n */\n closable?: boolean;\n /**\n * Custom icon shown as the close trigger (string emoji / unicode or slot).\n * If omitted the default × SVG is used.\n */\n closeIcon?: string;\n /**\n * Controlled visibility - operate the tag in controlled mode via v-model.\n * When undefined the component manages its own visibility.\n */\n visible?: boolean;\n /**\n * Whether the tag has a border.\n * @default true\n */\n bordered?: boolean;\n /**\n * Leading icon string (emoji / unicode). For accessible icon rendering\n * prefer the `#icon` slot which lets callers set `role=\"img\"` + `aria-label`.\n */\n icon?: string;\n}>();\n\n// ─────────────────────────────────────────────\n// Emits\n// ─────────────────────────────────────────────\nconst emit = defineEmits<{\n /** Fires synchronously when the close button is clicked/activated. */\n (e: 'close', event: MouseEvent | KeyboardEvent): void;\n /** Fires after the fade-out transition fully completes. */\n (e: 'afterClose'): void;\n /** v-model support - emitted with `false` when the tag is closed. */\n (e: 'update:visible', value: boolean): void;\n}>();\n\n// ─────────────────────────────────────────────\n// Slots\n// ─────────────────────────────────────────────\ndefineSlots<{\n /** Default tag content. */\n default?(): unknown;\n /** Leading icon area - receives no scoped props. */\n icon?(): unknown;\n /** Overrides the built-in close icon. */\n closeIcon?(): unknown;\n}>();\n\n// ─────────────────────────────────────────────\n// Preset colors\n// ─────────────────────────────────────────────\nconst PRESET_COLORS: BTagPresetColor[] = [\n 'default',\n 'success',\n 'processing',\n 'error',\n 'warning',\n 'magenta',\n 'red',\n 'volcano',\n 'orange',\n 'gold',\n 'lime',\n 'green',\n 'cyan',\n 'blue',\n 'geekblue',\n 'purple',\n];\n\nconst isPreset = computed(() => color === undefined || (PRESET_COLORS as string[]).includes(color));\n\nconst effectiveColor = computed<BTagPresetColor>(() =>\n isPreset.value ? ((color ?? 'default') as BTagPresetColor) : 'default',\n);\n\n// ─────────────────────────────────────────────\n// Visibility state\n// ─────────────────────────────────────────────\nconst isControlled = computed(() => visible !== undefined);\nconst internalVisible = ref(true);\n\n// Sync external → internal when switching to controlled\nwatch(\n () => visible,\n (val) => {\n if (val !== undefined) internalVisible.value = val;\n },\n);\n\nconst isVisible = computed(() => (isControlled.value ? visible! : internalVisible.value));\n\n// ─────────────────────────────────────────────\n// Close logic\n// ─────────────────────────────────────────────\nfunction handleClose(event: MouseEvent | KeyboardEvent) {\n emit('close', event);\n if (isControlled.value) {\n emit('update:visible', false);\n } else {\n internalVisible.value = false;\n }\n}\n\nfunction onCloseClick(event: MouseEvent) {\n handleClose(event);\n}\n\nfunction onCloseKeydown(event: KeyboardEvent) {\n if (event.key === 'Enter' || event.key === ' ' || event.key === 'Escape') {\n event.preventDefault();\n handleClose(event);\n }\n}\n\nfunction onAfterLeave() {\n emit('afterClose');\n}\n\n// ─────────────────────────────────────────────\n// Root class\n// ─────────────────────────────────────────────\nconst rootClasses = computed(() => [\n 'b-tag',\n `b-tag--${effectiveColor.value}`,\n `b-tag--${variant}`,\n {\n 'b-tag--borderless': !bordered,\n 'b-tag--closable': closable,\n 'b-tag--small': size === 'small',\n 'b-tag--large': size === 'large',\n 'b-tag--custom-color': !isPreset.value,\n },\n]);\n\n// ─────────────────────────────────────────────\n// Custom color inline style\n// ─────────────────────────────────────────────\nconst customColorStyle = computed(() => {\n if (isPreset.value) return undefined;\n // For custom colors: use the color as border + text; tint bg at 10% opacity\n return {\n '--b-tag-custom-color': color,\n } as Record<string, string>;\n});\n</script>\n\n<template>\n <Transition name=\"b-tag-fade\" @after-leave=\"onAfterLeave\">\n <span v-if=\"isVisible\" :class=\"rootClasses\" :style=\"customColorStyle\">\n <!-- Leading icon -->\n <span\n v-if=\"$slots.icon || icon\"\n class=\"b-tag__icon\"\n :aria-hidden=\"$slots.icon ? undefined : 'true'\"\n >\n <slot name=\"icon\">{{ icon }}</slot>\n </span>\n\n <!-- Content -->\n <span class=\"b-tag__content\">\n <slot />\n </span>\n\n <!-- Close button -->\n <button\n v-if=\"closable\"\n type=\"button\"\n class=\"b-tag__close\"\n aria-label=\"Remove tag\"\n tabindex=\"0\"\n @click.stop=\"onCloseClick\"\n @keydown=\"onCloseKeydown\"\n >\n <slot name=\"closeIcon\">\n <span\n v-if=\"closeIcon\"\n class=\"b-tag__close-label\"\n aria-hidden=\"true\"\n :data-icon=\"closeIcon\"\n />\n <svg\n v-else\n class=\"b-tag__close-icon\"\n viewBox=\"0 0 12 12\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <path\n d=\"M9.5 3.205 8.795 2.5 6 5.295 3.205 2.5 2.5 3.205 5.295 6 2.5 8.795 3.205 9.5 6 6.705 8.795 9.5 9.5 8.795 6.705 6z\"\n />\n </svg>\n </slot>\n </button>\n </span>\n </Transition>\n</template>\n\n<style>\n/* ─────────────────────────────────────────────\n BTag - CSS custom properties (scoped to root)\n ───────────────────────────────────────────── */\n.b-tag {\n /* Layout */\n --b-tag-height: 22px;\n --b-tag-padding: 0 7px;\n --b-tag-border-radius: 4px;\n --b-tag-font-size: 12px;\n --b-tag-line-height: 20px;\n --b-tag-gap: 4px;\n\n /* Close button */\n --b-tag-close-size: 12px;\n --b-tag-close-offset: 3px;\n --b-tag-close-opacity: 0.45;\n --b-tag-close-hover-opacity: 1;\n\n /* Animation */\n --b-tag-transition-duration: 200ms;\n\n /* Custom color (set via inline style for non-preset colors) */\n --b-tag-custom-color: initial;\n\n /* ── Default color scheme ── */\n --b-tag-bg: oklch(96% 0.003 260);\n --b-tag-border-color: oklch(87% 0.007 260);\n --b-tag-color: oklch(32% 0.02 260);\n\n /* ── Layout ── */\n display: inline-flex;\n align-items: center;\n gap: var(--b-tag-gap);\n height: var(--b-tag-height);\n padding: var(--b-tag-padding);\n border-radius: var(--b-tag-border-radius);\n border: 1px solid var(--b-tag-border-color);\n background: var(--b-tag-bg);\n color: var(--b-tag-color);\n font-size: var(--b-tag-font-size);\n line-height: var(--b-tag-line-height);\n white-space: nowrap;\n box-sizing: border-box;\n vertical-align: middle;\n cursor: default;\n user-select: none;\n}\n\n/* ── Size variants ── */\n.b-tag--small {\n --b-tag-height: 18px;\n --b-tag-padding: 0 5px;\n --b-tag-font-size: 11px;\n --b-tag-line-height: 16px;\n --b-tag-close-size: 10px;\n}\n\n.b-tag--large {\n --b-tag-height: 28px;\n --b-tag-padding: 0 10px;\n --b-tag-font-size: 14px;\n --b-tag-line-height: 26px;\n --b-tag-close-size: 14px;\n}\n\n/* ── Borderless ── */\n.b-tag--borderless {\n border-color: transparent;\n}\n\n/* ── Outlined variant ── */\n.b-tag--outlined {\n background: transparent;\n}\n\n/* ── Icon ── */\n.b-tag__icon {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n font-size: var(--b-tag-font-size);\n}\n\n/* ── Content ── */\n.b-tag__content {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n line-height: var(--b-tag-line-height);\n}\n\n/* ── Close button ── */\n.b-tag__close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n padding: 0;\n margin-left: var(--b-tag-close-offset);\n border: none;\n border-radius: 2px;\n background: transparent;\n color: inherit;\n cursor: pointer;\n opacity: var(--b-tag-close-opacity);\n line-height: 1;\n font-size: var(--b-tag-close-size);\n width: var(--b-tag-close-size);\n height: var(--b-tag-close-size);\n transition: opacity var(--b-tag-transition-duration) ease;\n}\n\n.b-tag__close:hover {\n opacity: var(--b-tag-close-hover-opacity);\n}\n\n.b-tag__close:focus-visible {\n outline: 2px solid currentColor;\n outline-offset: 2px;\n opacity: var(--b-tag-close-hover-opacity);\n}\n\n.b-tag__close-icon {\n width: 1em;\n height: 1em;\n fill: currentColor;\n display: block;\n}\n\n.b-tag__close-label::before {\n content: attr(data-icon);\n}\n\n/* ─────────────────────────────────────────────\n Preset color schemes\n ───────────────────────────────────────────── */\n\n/* ── success ── */\n.b-tag--success {\n --b-tag-bg: oklch(95% 0.05 145);\n --b-tag-border-color: oklch(78% 0.14 148);\n --b-tag-color: oklch(40% 0.14 148);\n}\n\n/* ── processing (blue pulse-ready) ── */\n.b-tag--processing {\n --b-tag-bg: oklch(94% 0.05 260);\n --b-tag-border-color: oklch(72% 0.17 262);\n --b-tag-color: oklch(45% 0.18 262);\n}\n\n/* ── error ── */\n.b-tag--error {\n --b-tag-bg: oklch(96% 0.04 20);\n --b-tag-border-color: oklch(78% 0.15 22);\n --b-tag-color: oklch(40% 0.17 22);\n}\n\n/* ── warning ── */\n.b-tag--warning {\n --b-tag-bg: oklch(97% 0.06 75);\n --b-tag-border-color: oklch(82% 0.17 58);\n --b-tag-color: oklch(42% 0.14 55);\n}\n\n/* ── magenta ── */\n.b-tag--magenta {\n --b-tag-bg: oklch(95% 0.04 345);\n --b-tag-border-color: oklch(76% 0.18 350);\n --b-tag-color: oklch(42% 0.2 348);\n}\n\n/* ── red ── */\n.b-tag--red {\n --b-tag-bg: oklch(96% 0.035 15);\n --b-tag-border-color: oklch(74% 0.19 18);\n --b-tag-color: oklch(40% 0.2 18);\n}\n\n/* ── volcano ── */\n.b-tag--volcano {\n --b-tag-bg: oklch(96% 0.04 38);\n --b-tag-border-color: oklch(76% 0.17 38);\n --b-tag-color: oklch(42% 0.18 38);\n}\n\n/* ── orange ── */\n.b-tag--orange {\n --b-tag-bg: oklch(97% 0.055 65);\n --b-tag-border-color: oklch(80% 0.18 62);\n --b-tag-color: oklch(44% 0.16 60);\n}\n\n/* ── gold ── */\n.b-tag--gold {\n --b-tag-bg: oklch(97% 0.06 80);\n --b-tag-border-color: oklch(82% 0.18 78);\n --b-tag-color: oklch(45% 0.14 78);\n}\n\n/* ── lime ── */\n.b-tag--lime {\n --b-tag-bg: oklch(96% 0.07 128);\n --b-tag-border-color: oklch(80% 0.18 128);\n --b-tag-color: oklch(42% 0.15 128);\n}\n\n/* ── green ── */\n.b-tag--green {\n --b-tag-bg: oklch(95% 0.05 145);\n --b-tag-border-color: oklch(76% 0.16 147);\n --b-tag-color: oklch(38% 0.14 147);\n}\n\n/* ── cyan ── */\n.b-tag--cyan {\n --b-tag-bg: oklch(95% 0.05 200);\n --b-tag-border-color: oklch(76% 0.14 200);\n --b-tag-color: oklch(40% 0.12 200);\n}\n\n/* ── blue ── */\n.b-tag--blue {\n --b-tag-bg: oklch(94% 0.05 255);\n --b-tag-border-color: oklch(72% 0.17 258);\n --b-tag-color: oklch(42% 0.18 258);\n}\n\n/* ── geekblue ── */\n.b-tag--geekblue {\n --b-tag-bg: oklch(94% 0.04 270);\n --b-tag-border-color: oklch(68% 0.2 272);\n --b-tag-color: oklch(38% 0.22 272);\n}\n\n/* ── purple ── */\n.b-tag--purple {\n --b-tag-bg: oklch(95% 0.04 300);\n --b-tag-border-color: oklch(72% 0.18 300);\n --b-tag-color: oklch(40% 0.2 300);\n}\n\n/* ─────────────────────────────────────────────\n Custom (non-preset) color\n ───────────────────────────────────────────── */\n.b-tag--custom-color {\n /* 8% tint keeps the background very light; 55% blend with black produces\n text dark enough to clear WCAG AA 4.5:1 against that near-white bg. */\n --b-tag-bg: color-mix(in oklch, var(--b-tag-custom-color) 8%, white);\n --b-tag-border-color: color-mix(in oklch, var(--b-tag-custom-color) 50%, white);\n --b-tag-color: color-mix(in oklch, var(--b-tag-custom-color) 55%, black);\n}\n\n/* ─────────────────────────────────────────────\n Dark mode\n ───────────────────────────────────────────── */\n[data-prefers-color='dark'] .b-tag {\n --b-tag-bg: oklch(26% 0.008 260);\n --b-tag-border-color: oklch(36% 0.012 260);\n --b-tag-color: oklch(82% 0.01 260);\n}\n\n[data-prefers-color='dark'] .b-tag--success {\n --b-tag-bg: oklch(20% 0.06 148);\n --b-tag-border-color: oklch(38% 0.12 148);\n --b-tag-color: oklch(78% 0.12 148);\n}\n\n[data-prefers-color='dark'] .b-tag--processing {\n --b-tag-bg: oklch(20% 0.06 260);\n --b-tag-border-color: oklch(40% 0.14 262);\n --b-tag-color: oklch(76% 0.15 262);\n}\n\n[data-prefers-color='dark'] .b-tag--error {\n --b-tag-bg: oklch(20% 0.05 20);\n --b-tag-border-color: oklch(38% 0.14 22);\n --b-tag-color: oklch(78% 0.14 22);\n}\n\n[data-prefers-color='dark'] .b-tag--warning {\n --b-tag-bg: oklch(20% 0.06 58);\n --b-tag-border-color: oklch(40% 0.15 58);\n --b-tag-color: oklch(80% 0.14 58);\n}\n\n[data-prefers-color='dark'] .b-tag--magenta {\n --b-tag-bg: oklch(20% 0.05 348);\n --b-tag-border-color: oklch(38% 0.16 350);\n --b-tag-color: oklch(76% 0.16 348);\n}\n\n[data-prefers-color='dark'] .b-tag--red {\n --b-tag-bg: oklch(20% 0.05 18);\n --b-tag-border-color: oklch(38% 0.17 18);\n --b-tag-color: oklch(76% 0.17 18);\n}\n\n[data-prefers-color='dark'] .b-tag--volcano {\n --b-tag-bg: oklch(20% 0.05 38);\n --b-tag-border-color: oklch(38% 0.15 38);\n --b-tag-color: oklch(76% 0.15 38);\n}\n\n[data-prefers-color='dark'] .b-tag--orange {\n --b-tag-bg: oklch(20% 0.06 62);\n --b-tag-border-color: oklch(40% 0.16 62);\n --b-tag-color: oklch(80% 0.16 62);\n}\n\n[data-prefers-color='dark'] .b-tag--gold {\n --b-tag-bg: oklch(20% 0.06 78);\n --b-tag-border-color: oklch(40% 0.16 78);\n --b-tag-color: oklch(80% 0.14 78);\n}\n\n[data-prefers-color='dark'] .b-tag--lime {\n --b-tag-bg: oklch(20% 0.07 128);\n --b-tag-border-color: oklch(40% 0.16 128);\n --b-tag-color: oklch(80% 0.14 128);\n}\n\n[data-prefers-color='dark'] .b-tag--green {\n --b-tag-bg: oklch(20% 0.06 147);\n --b-tag-border-color: oklch(38% 0.14 147);\n --b-tag-color: oklch(76% 0.13 147);\n}\n\n[data-prefers-color='dark'] .b-tag--cyan {\n --b-tag-bg: oklch(20% 0.05 200);\n --b-tag-border-color: oklch(38% 0.12 200);\n --b-tag-color: oklch(76% 0.11 200);\n}\n\n[data-prefers-color='dark'] .b-tag--blue {\n --b-tag-bg: oklch(20% 0.06 258);\n --b-tag-border-color: oklch(38% 0.15 258);\n --b-tag-color: oklch(74% 0.15 258);\n}\n\n[data-prefers-color='dark'] .b-tag--geekblue {\n --b-tag-bg: oklch(20% 0.05 272);\n --b-tag-border-color: oklch(36% 0.18 272);\n --b-tag-color: oklch(72% 0.18 272);\n}\n\n[data-prefers-color='dark'] .b-tag--purple {\n --b-tag-bg: oklch(20% 0.05 300);\n --b-tag-border-color: oklch(36% 0.16 300);\n --b-tag-color: oklch(74% 0.16 300);\n}\n\n[data-prefers-color='dark'] .b-tag--custom-color {\n --b-tag-bg: color-mix(in oklch, var(--b-tag-custom-color) 15%, oklch(15% 0 0));\n --b-tag-border-color: color-mix(in oklch, var(--b-tag-custom-color) 50%, oklch(15% 0 0));\n --b-tag-color: color-mix(in oklch, var(--b-tag-custom-color) 85%, white);\n}\n\n@media (prefers-color-scheme: dark) {\n [data-prefers-color='system'] .b-tag {\n --b-tag-bg: oklch(26% 0.008 260);\n --b-tag-border-color: oklch(36% 0.012 260);\n --b-tag-color: oklch(82% 0.01 260);\n }\n [data-prefers-color='system'] .b-tag--success {\n --b-tag-bg: oklch(20% 0.06 148);\n --b-tag-border-color: oklch(38% 0.12 148);\n --b-tag-color: oklch(78% 0.12 148);\n }\n [data-prefers-color='system'] .b-tag--processing {\n --b-tag-bg: oklch(20% 0.06 260);\n --b-tag-border-color: oklch(40% 0.14 262);\n --b-tag-color: oklch(76% 0.15 262);\n }\n [data-prefers-color='system'] .b-tag--error {\n --b-tag-bg: oklch(20% 0.05 20);\n --b-tag-border-color: oklch(38% 0.14 22);\n --b-tag-color: oklch(78% 0.14 22);\n }\n [data-prefers-color='system'] .b-tag--warning {\n --b-tag-bg: oklch(20% 0.06 58);\n --b-tag-border-color: oklch(40% 0.15 58);\n --b-tag-color: oklch(80% 0.14 58);\n }\n [data-prefers-color='system'] .b-tag--magenta {\n --b-tag-bg: oklch(20% 0.05 348);\n --b-tag-border-color: oklch(38% 0.16 350);\n --b-tag-color: oklch(76% 0.16 348);\n }\n [data-prefers-color='system'] .b-tag--red {\n --b-tag-bg: oklch(20% 0.05 18);\n --b-tag-border-color: oklch(38% 0.17 18);\n --b-tag-color: oklch(76% 0.17 18);\n }\n [data-prefers-color='system'] .b-tag--volcano {\n --b-tag-bg: oklch(20% 0.05 38);\n --b-tag-border-color: oklch(38% 0.15 38);\n --b-tag-color: oklch(76% 0.15 38);\n }\n [data-prefers-color='system'] .b-tag--orange {\n --b-tag-bg: oklch(20% 0.06 62);\n --b-tag-border-color: oklch(40% 0.16 62);\n --b-tag-color: oklch(80% 0.16 62);\n }\n [data-prefers-color='system'] .b-tag--gold {\n --b-tag-bg: oklch(20% 0.06 78);\n --b-tag-border-color: oklch(40% 0.16 78);\n --b-tag-color: oklch(80% 0.14 78);\n }\n [data-prefers-color='system'] .b-tag--lime {\n --b-tag-bg: oklch(20% 0.07 128);\n --b-tag-border-color: oklch(40% 0.16 128);\n --b-tag-color: oklch(80% 0.14 128);\n }\n [data-prefers-color='system'] .b-tag--green {\n --b-tag-bg: oklch(20% 0.06 147);\n --b-tag-border-color: oklch(38% 0.14 147);\n --b-tag-color: oklch(76% 0.13 147);\n }\n [data-prefers-color='system'] .b-tag--cyan {\n --b-tag-bg: oklch(20% 0.05 200);\n --b-tag-border-color: oklch(38% 0.12 200);\n --b-tag-color: oklch(76% 0.11 200);\n }\n [data-prefers-color='system'] .b-tag--blue {\n --b-tag-bg: oklch(20% 0.06 258);\n --b-tag-border-color: oklch(38% 0.15 258);\n --b-tag-color: oklch(74% 0.15 258);\n }\n [data-prefers-color='system'] .b-tag--geekblue {\n --b-tag-bg: oklch(20% 0.05 272);\n --b-tag-border-color: oklch(36% 0.18 272);\n --b-tag-color: oklch(72% 0.18 272);\n }\n [data-prefers-color='system'] .b-tag--purple {\n --b-tag-bg: oklch(20% 0.05 300);\n --b-tag-border-color: oklch(36% 0.16 300);\n --b-tag-color: oklch(74% 0.16 300);\n }\n [data-prefers-color='system'] .b-tag--custom-color {\n --b-tag-bg: color-mix(in oklch, var(--b-tag-custom-color) 15%, oklch(15% 0 0));\n --b-tag-border-color: color-mix(in oklch, var(--b-tag-custom-color) 50%, oklch(15% 0 0));\n --b-tag-color: color-mix(in oklch, var(--b-tag-custom-color) 85%, white);\n }\n}\n\n/* ─────────────────────────────────────────────\n Transition (fade)\n ───────────────────────────────────────────── */\n.b-tag-fade-enter-active,\n.b-tag-fade-leave-active {\n transition:\n opacity var(--b-tag-transition-duration) ease,\n transform var(--b-tag-transition-duration) ease;\n}\n\n.b-tag-fade-enter-from,\n.b-tag-fade-leave-to {\n opacity: 0;\n transform: scale(0.85);\n}\n\n/* ── Reduced motion ── */\n@media (prefers-reduced-motion: reduce) {\n .b-tag {\n --b-tag-transition-duration: 0ms;\n }\n\n .b-tag-fade-enter-active,\n .b-tag-fade-leave-active {\n transition: opacity var(--b-tag-transition-duration) ease;\n transform: none !important;\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiEA,IAAM,IAAO,GAwBP,IAAmC;GACvC;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD,EAEK,IAAW,QAAe,EAAA,UAAU,KAAA,KAAc,EAA2B,SAAS,EAAA,MAAM,CAAC,EAE7F,IAAiB,QACrB,EAAS,QAAU,EAAA,SAAS,YAAiC,UAC9D,EAKK,IAAe,QAAe,EAAA,YAAY,KAAA,EAAU,EACpD,IAAkB,EAAI,GAAK;AAGjC,UACQ,EAAA,UACL,MAAQ;AACP,GAAI,MAAQ,KAAA,MAAW,EAAgB,QAAQ;IAElD;EAED,IAAM,IAAY,QAAgB,EAAa,QAAQ,EAAA,UAAW,EAAgB,MAAO;EAKzF,SAAS,EAAY,GAAmC;AAEtD,GADA,EAAK,SAAS,EAAM,EAChB,EAAa,QACf,EAAK,kBAAkB,GAAM,GAE7B,EAAgB,QAAQ;;EAI5B,SAAS,EAAa,GAAmB;AACvC,KAAY,EAAM;;EAGpB,SAAS,EAAe,GAAsB;AAC5C,IAAI,EAAM,QAAQ,WAAW,EAAM,QAAQ,OAAO,EAAM,QAAQ,cAC9D,EAAM,gBAAgB,EACtB,EAAY,EAAM;;EAItB,SAAS,IAAe;AACtB,KAAK,aAAa;;EAMpB,IAAM,IAAc,QAAe;GACjC;GACA,UAAU,EAAe;GACzB,UAAU,EAAA;GACV;IACE,qBAAqB,CAAC,EAAA;IACtB,mBAAmB,EAAA;IACnB,gBAAgB,EAAA,SAAS;IACzB,gBAAgB,EAAA,SAAS;IACzB,uBAAuB,CAAC,EAAS;IAClC;GACF,CAAC,EAKI,IAAmB,QAAe;AAClC,UAAS,MAEb,QAAO,EACL,wBAAwB,EAAA,OACzB;IACD;yBAIA,EAgDa,GAAA;GAhDD,MAAK;GAA2B;;oBA+CnC,CA9CK,EAAA,SAAA,GAAA,EAAZ,EA8CO,QAAA;;IA9CiB,OAAK,EAAE,EAAA,MAAW;IAAG,OAAK,EAAE,EAAA,MAAgB;;IAG1DA,EAAAA,OAAO,QAAQ,EAAA,QAAA,GAAA,EADvB,EAMO,QAAA;;KAJL,OAAM;KACL,eAAaA,EAAAA,OAAO,OAAO,KAAA,IAAS;QAErC,EAAmC,EAAA,QAAA,QAAA,EAAA,QAAA,CAAA,EAAA,EAAd,EAAA,KAAI,EAAA,EAAA,CAAA,CAAA,CAAA,EAAA,GAAA,EAAA,IAAA,EAAA,IAAA,GAAA;IAI3B,EAEO,QAFP,GAEO,CADL,EAAQ,EAAA,QAAA,UAAA,CAAA,CAAA;IAKF,EAAA,YAAA,GAAA,EADR,EA6BS,UAAA;;KA3BP,MAAK;KACL,OAAM;KACN,cAAW;KACX,UAAS;KACR,SAAK,EAAO,GAAY,CAAA,OAAA,CAAA;KACxB,WAAS;QAEV,EAmBO,EAAA,QAAA,aAAA,EAAA,QAAA,CAjBG,EAAA,aAAA,GAAA,EADR,EAKE,QAAA;;KAHA,OAAM;KACN,eAAY;KACX,aAAW,EAAA;4BAEd,EAWM,OAXN,GAWM,CAAA,GAAA,AAAA,EAAA,OAAA,CAHJ,EAEE,QAAA,EADA,GAAE,qHAAmH,EAAA,MAAA,GAAA,CAAA,CAAA,CAAA,EAAA,CAAA,CAAA,EAAA,GAAA,IAAA,EAAA,IAAA,GAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design-system250.js","names":[],"sources":["../src/components/BTag/BTag.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue';\n\nimport type { BTagColor, BTagPresetColor, BTagSize, BTagVariant } from './types';\n\n// ─────────────────────────────────────────────\n// Props\n// ─────────────────────────────────────────────\nconst {\n color,\n variant = 'filled',\n size = 'default',\n closable = false,\n closeIcon,\n visible = undefined,\n bordered = true,\n icon,\n} = defineProps<{\n /**\n * Preset semantic color name or any CSS color value.\n * Preset names map to a full color scale (bg, border, text).\n * Any other string is treated as a raw CSS color and applied to the border.\n * @example 'success' | 'processing' | 'error' | '#ff0000' | 'rgb(0,0,255)'\n */\n color?: BTagColor;\n /**\n * Visual style variant.\n * @default 'filled'\n */\n variant?: BTagVariant;\n /**\n * Size of the tag.\n * @default 'default'\n */\n size?: BTagSize;\n /**\n * Whether the tag can be closed/removed.\n * @default false\n */\n closable?: boolean;\n /**\n * Custom icon shown as the close trigger (string emoji / unicode or slot).\n * If omitted the default × SVG is used.\n */\n closeIcon?: string;\n /**\n * Controlled visibility - operate the tag in controlled mode via v-model.\n * When undefined the component manages its own visibility.\n */\n visible?: boolean;\n /**\n * Whether the tag has a border.\n * @default true\n */\n bordered?: boolean;\n /**\n * Leading icon string (emoji / unicode). For accessible icon rendering\n * prefer the `#icon` slot which lets callers set `role=\"img\"` + `aria-label`.\n */\n icon?: string;\n}>();\n\n// ─────────────────────────────────────────────\n// Emits\n// ─────────────────────────────────────────────\nconst emit = defineEmits<{\n /** Fires synchronously when the close button is clicked/activated. */\n (e: 'close', event: MouseEvent | KeyboardEvent): void;\n /** Fires after the fade-out transition fully completes. */\n (e: 'afterClose'): void;\n /** v-model support - emitted with `false` when the tag is closed. */\n (e: 'update:visible', value: boolean): void;\n}>();\n\n// ─────────────────────────────────────────────\n// Slots\n// ─────────────────────────────────────────────\ndefineSlots<{\n /** Default tag content. */\n default?(): unknown;\n /** Leading icon area - receives no scoped props. */\n icon?(): unknown;\n /** Overrides the built-in close icon. */\n closeIcon?(): unknown;\n}>();\n\n// ─────────────────────────────────────────────\n// Preset colors\n// ─────────────────────────────────────────────\nconst PRESET_COLORS: BTagPresetColor[] = [\n 'default',\n 'success',\n 'processing',\n 'error',\n 'warning',\n 'magenta',\n 'red',\n 'volcano',\n 'orange',\n 'gold',\n 'lime',\n 'green',\n 'cyan',\n 'blue',\n 'geekblue',\n 'purple',\n];\n\nconst isPreset = computed(() => color === undefined || (PRESET_COLORS as string[]).includes(color));\n\nconst effectiveColor = computed<BTagPresetColor>(() =>\n isPreset.value ? ((color ?? 'default') as BTagPresetColor) : 'default',\n);\n\n// ─────────────────────────────────────────────\n// Visibility state\n// ─────────────────────────────────────────────\nconst isControlled = computed(() => visible !== undefined);\nconst internalVisible = ref(true);\n\n// Sync external → internal when switching to controlled\nwatch(\n () => visible,\n (val) => {\n if (val !== undefined) internalVisible.value = val;\n },\n);\n\nconst isVisible = computed(() => (isControlled.value ? visible! : internalVisible.value));\n\n// ─────────────────────────────────────────────\n// Close logic\n// ─────────────────────────────────────────────\nfunction handleClose(event: MouseEvent | KeyboardEvent) {\n emit('close', event);\n if (isControlled.value) {\n emit('update:visible', false);\n } else {\n internalVisible.value = false;\n }\n}\n\nfunction onCloseClick(event: MouseEvent) {\n handleClose(event);\n}\n\nfunction onCloseKeydown(event: KeyboardEvent) {\n if (event.key === 'Enter' || event.key === ' ' || event.key === 'Escape') {\n event.preventDefault();\n handleClose(event);\n }\n}\n\nfunction onAfterLeave() {\n emit('afterClose');\n}\n\n// ─────────────────────────────────────────────\n// Root class\n// ─────────────────────────────────────────────\nconst rootClasses = computed(() => [\n 'b-tag',\n `b-tag--${effectiveColor.value}`,\n `b-tag--${variant}`,\n {\n 'b-tag--borderless': !bordered,\n 'b-tag--closable': closable,\n 'b-tag--small': size === 'small',\n 'b-tag--large': size === 'large',\n 'b-tag--custom-color': !isPreset.value,\n },\n]);\n\n// ─────────────────────────────────────────────\n// Custom color inline style\n// ─────────────────────────────────────────────\nconst customColorStyle = computed(() => {\n if (isPreset.value) return undefined;\n // For custom colors: use the color as border + text; tint bg at 10% opacity\n return {\n '--b-tag-custom-color': color,\n } as Record<string, string>;\n});\n</script>\n\n<template>\n <Transition name=\"b-tag-fade\" @after-leave=\"onAfterLeave\">\n <span v-if=\"isVisible\" :class=\"rootClasses\" :style=\"customColorStyle\">\n <!-- Leading icon -->\n <span\n v-if=\"$slots.icon || icon\"\n class=\"b-tag__icon\"\n :aria-hidden=\"$slots.icon ? undefined : 'true'\"\n >\n <slot name=\"icon\">{{ icon }}</slot>\n </span>\n\n <!-- Content -->\n <span class=\"b-tag__content\">\n <slot />\n </span>\n\n <!-- Close button -->\n <button\n v-if=\"closable\"\n type=\"button\"\n class=\"b-tag__close\"\n aria-label=\"Remove tag\"\n tabindex=\"0\"\n @click.stop=\"onCloseClick\"\n @keydown=\"onCloseKeydown\"\n >\n <slot name=\"closeIcon\">\n <span\n v-if=\"closeIcon\"\n class=\"b-tag__close-label\"\n aria-hidden=\"true\"\n :data-icon=\"closeIcon\"\n />\n <svg\n v-else\n class=\"b-tag__close-icon\"\n viewBox=\"0 0 12 12\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <path\n d=\"M9.5 3.205 8.795 2.5 6 5.295 3.205 2.5 2.5 3.205 5.295 6 2.5 8.795 3.205 9.5 6 6.705 8.795 9.5 9.5 8.795 6.705 6z\"\n />\n </svg>\n </slot>\n </button>\n </span>\n </Transition>\n</template>\n\n<style>\n/* ─────────────────────────────────────────────\n BTag - CSS custom properties (scoped to root)\n ───────────────────────────────────────────── */\n.b-tag {\n /* Layout */\n --b-tag-height: 22px;\n --b-tag-padding: 0 7px;\n --b-tag-border-radius: 4px;\n --b-tag-font-size: 12px;\n --b-tag-line-height: 20px;\n --b-tag-gap: 4px;\n\n /* Close button */\n --b-tag-close-size: 12px;\n --b-tag-close-offset: 3px;\n --b-tag-close-opacity: 0.45;\n --b-tag-close-hover-opacity: 1;\n\n /* Animation */\n --b-tag-transition-duration: 200ms;\n\n /* Custom color (set via inline style for non-preset colors) */\n --b-tag-custom-color: initial;\n\n /* ── Default color scheme ── */\n --b-tag-bg: oklch(96% 0.003 260);\n --b-tag-border-color: oklch(87% 0.007 260);\n --b-tag-color: oklch(32% 0.02 260);\n\n /* ── Layout ── */\n display: inline-flex;\n align-items: center;\n gap: var(--b-tag-gap);\n height: var(--b-tag-height);\n padding: var(--b-tag-padding);\n border-radius: var(--b-tag-border-radius);\n border: 1px solid var(--b-tag-border-color);\n background: var(--b-tag-bg);\n color: var(--b-tag-color);\n font-size: var(--b-tag-font-size);\n line-height: var(--b-tag-line-height);\n white-space: nowrap;\n box-sizing: border-box;\n vertical-align: middle;\n cursor: default;\n user-select: none;\n}\n\n/* ── Size variants ── */\n.b-tag--small {\n --b-tag-height: 18px;\n --b-tag-padding: 0 5px;\n --b-tag-font-size: 11px;\n --b-tag-line-height: 16px;\n --b-tag-close-size: 10px;\n}\n\n.b-tag--large {\n --b-tag-height: 28px;\n --b-tag-padding: 0 10px;\n --b-tag-font-size: 14px;\n --b-tag-line-height: 26px;\n --b-tag-close-size: 14px;\n}\n\n/* ── Borderless ── */\n.b-tag--borderless {\n border-color: transparent;\n}\n\n/* ── Outlined variant ── */\n.b-tag--outlined {\n background: transparent;\n}\n\n/* ── Icon ── */\n.b-tag__icon {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n font-size: var(--b-tag-font-size);\n}\n\n/* ── Content ── */\n.b-tag__content {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n line-height: var(--b-tag-line-height);\n}\n\n/* ── Close button ── */\n.b-tag__close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n padding: 0;\n margin-left: var(--b-tag-close-offset);\n border: none;\n border-radius: 2px;\n background: transparent;\n color: inherit;\n cursor: pointer;\n opacity: var(--b-tag-close-opacity);\n line-height: 1;\n font-size: var(--b-tag-close-size);\n width: var(--b-tag-close-size);\n height: var(--b-tag-close-size);\n transition: opacity var(--b-tag-transition-duration) ease;\n}\n\n.b-tag__close:hover {\n opacity: var(--b-tag-close-hover-opacity);\n}\n\n.b-tag__close:focus-visible {\n outline: 2px solid currentColor;\n outline-offset: 2px;\n opacity: var(--b-tag-close-hover-opacity);\n}\n\n.b-tag__close-icon {\n width: 1em;\n height: 1em;\n fill: currentColor;\n display: block;\n}\n\n.b-tag__close-label::before {\n content: attr(data-icon);\n}\n\n/* ─────────────────────────────────────────────\n Preset color schemes\n ───────────────────────────────────────────── */\n\n/* ── success ── */\n.b-tag--success {\n --b-tag-bg: oklch(95% 0.05 145);\n --b-tag-border-color: oklch(78% 0.14 148);\n --b-tag-color: oklch(40% 0.14 148);\n}\n\n/* ── processing (blue pulse-ready) ── */\n.b-tag--processing {\n --b-tag-bg: oklch(94% 0.05 260);\n --b-tag-border-color: oklch(72% 0.17 262);\n --b-tag-color: oklch(45% 0.18 262);\n}\n\n/* ── error ── */\n.b-tag--error {\n --b-tag-bg: oklch(96% 0.04 20);\n --b-tag-border-color: oklch(78% 0.15 22);\n --b-tag-color: oklch(40% 0.17 22);\n}\n\n/* ── warning ── */\n.b-tag--warning {\n --b-tag-bg: oklch(97% 0.06 75);\n --b-tag-border-color: oklch(82% 0.17 58);\n --b-tag-color: oklch(42% 0.14 55);\n}\n\n/* ── magenta ── */\n.b-tag--magenta {\n --b-tag-bg: oklch(95% 0.04 345);\n --b-tag-border-color: oklch(76% 0.18 350);\n --b-tag-color: oklch(42% 0.2 348);\n}\n\n/* ── red ── */\n.b-tag--red {\n --b-tag-bg: oklch(96% 0.035 15);\n --b-tag-border-color: oklch(74% 0.19 18);\n --b-tag-color: oklch(40% 0.2 18);\n}\n\n/* ── volcano ── */\n.b-tag--volcano {\n --b-tag-bg: oklch(96% 0.04 38);\n --b-tag-border-color: oklch(76% 0.17 38);\n --b-tag-color: oklch(42% 0.18 38);\n}\n\n/* ── orange ── */\n.b-tag--orange {\n --b-tag-bg: oklch(97% 0.055 65);\n --b-tag-border-color: oklch(80% 0.18 62);\n --b-tag-color: oklch(44% 0.16 60);\n}\n\n/* ── gold ── */\n.b-tag--gold {\n --b-tag-bg: oklch(97% 0.06 80);\n --b-tag-border-color: oklch(82% 0.18 78);\n --b-tag-color: oklch(45% 0.14 78);\n}\n\n/* ── lime ── */\n.b-tag--lime {\n --b-tag-bg: oklch(96% 0.07 128);\n --b-tag-border-color: oklch(80% 0.18 128);\n --b-tag-color: oklch(42% 0.15 128);\n}\n\n/* ── green ── */\n.b-tag--green {\n --b-tag-bg: oklch(95% 0.05 145);\n --b-tag-border-color: oklch(76% 0.16 147);\n --b-tag-color: oklch(38% 0.14 147);\n}\n\n/* ── cyan ── */\n.b-tag--cyan {\n --b-tag-bg: oklch(95% 0.05 200);\n --b-tag-border-color: oklch(76% 0.14 200);\n --b-tag-color: oklch(40% 0.12 200);\n}\n\n/* ── blue ── */\n.b-tag--blue {\n --b-tag-bg: oklch(94% 0.05 255);\n --b-tag-border-color: oklch(72% 0.17 258);\n --b-tag-color: oklch(42% 0.18 258);\n}\n\n/* ── geekblue ── */\n.b-tag--geekblue {\n --b-tag-bg: oklch(94% 0.04 270);\n --b-tag-border-color: oklch(68% 0.2 272);\n --b-tag-color: oklch(38% 0.22 272);\n}\n\n/* ── purple ── */\n.b-tag--purple {\n --b-tag-bg: oklch(95% 0.04 300);\n --b-tag-border-color: oklch(72% 0.18 300);\n --b-tag-color: oklch(40% 0.2 300);\n}\n\n/* ─────────────────────────────────────────────\n Custom (non-preset) color\n ───────────────────────────────────────────── */\n.b-tag--custom-color {\n /* 8% tint keeps the background very light; 55% blend with black produces\n text dark enough to clear WCAG AA 4.5:1 against that near-white bg. */\n --b-tag-bg: color-mix(in oklch, var(--b-tag-custom-color) 8%, white);\n --b-tag-border-color: color-mix(in oklch, var(--b-tag-custom-color) 50%, white);\n --b-tag-color: color-mix(in oklch, var(--b-tag-custom-color) 55%, black);\n}\n\n/* ─────────────────────────────────────────────\n Dark mode\n ───────────────────────────────────────────── */\n[data-prefers-color='dark'] .b-tag {\n --b-tag-bg: oklch(26% 0.008 260);\n --b-tag-border-color: oklch(36% 0.012 260);\n --b-tag-color: oklch(82% 0.01 260);\n}\n\n[data-prefers-color='dark'] .b-tag--success {\n --b-tag-bg: oklch(20% 0.06 148);\n --b-tag-border-color: oklch(38% 0.12 148);\n --b-tag-color: oklch(78% 0.12 148);\n}\n\n[data-prefers-color='dark'] .b-tag--processing {\n --b-tag-bg: oklch(20% 0.06 260);\n --b-tag-border-color: oklch(40% 0.14 262);\n --b-tag-color: oklch(76% 0.15 262);\n}\n\n[data-prefers-color='dark'] .b-tag--error {\n --b-tag-bg: oklch(20% 0.05 20);\n --b-tag-border-color: oklch(38% 0.14 22);\n --b-tag-color: oklch(78% 0.14 22);\n}\n\n[data-prefers-color='dark'] .b-tag--warning {\n --b-tag-bg: oklch(20% 0.06 58);\n --b-tag-border-color: oklch(40% 0.15 58);\n --b-tag-color: oklch(80% 0.14 58);\n}\n\n[data-prefers-color='dark'] .b-tag--magenta {\n --b-tag-bg: oklch(20% 0.05 348);\n --b-tag-border-color: oklch(38% 0.16 350);\n --b-tag-color: oklch(76% 0.16 348);\n}\n\n[data-prefers-color='dark'] .b-tag--red {\n --b-tag-bg: oklch(20% 0.05 18);\n --b-tag-border-color: oklch(38% 0.17 18);\n --b-tag-color: oklch(76% 0.17 18);\n}\n\n[data-prefers-color='dark'] .b-tag--volcano {\n --b-tag-bg: oklch(20% 0.05 38);\n --b-tag-border-color: oklch(38% 0.15 38);\n --b-tag-color: oklch(76% 0.15 38);\n}\n\n[data-prefers-color='dark'] .b-tag--orange {\n --b-tag-bg: oklch(20% 0.06 62);\n --b-tag-border-color: oklch(40% 0.16 62);\n --b-tag-color: oklch(80% 0.16 62);\n}\n\n[data-prefers-color='dark'] .b-tag--gold {\n --b-tag-bg: oklch(20% 0.06 78);\n --b-tag-border-color: oklch(40% 0.16 78);\n --b-tag-color: oklch(80% 0.14 78);\n}\n\n[data-prefers-color='dark'] .b-tag--lime {\n --b-tag-bg: oklch(20% 0.07 128);\n --b-tag-border-color: oklch(40% 0.16 128);\n --b-tag-color: oklch(80% 0.14 128);\n}\n\n[data-prefers-color='dark'] .b-tag--green {\n --b-tag-bg: oklch(20% 0.06 147);\n --b-tag-border-color: oklch(38% 0.14 147);\n --b-tag-color: oklch(76% 0.13 147);\n}\n\n[data-prefers-color='dark'] .b-tag--cyan {\n --b-tag-bg: oklch(20% 0.05 200);\n --b-tag-border-color: oklch(38% 0.12 200);\n --b-tag-color: oklch(76% 0.11 200);\n}\n\n[data-prefers-color='dark'] .b-tag--blue {\n --b-tag-bg: oklch(20% 0.06 258);\n --b-tag-border-color: oklch(38% 0.15 258);\n --b-tag-color: oklch(74% 0.15 258);\n}\n\n[data-prefers-color='dark'] .b-tag--geekblue {\n --b-tag-bg: oklch(20% 0.05 272);\n --b-tag-border-color: oklch(36% 0.18 272);\n --b-tag-color: oklch(72% 0.18 272);\n}\n\n[data-prefers-color='dark'] .b-tag--purple {\n --b-tag-bg: oklch(20% 0.05 300);\n --b-tag-border-color: oklch(36% 0.16 300);\n --b-tag-color: oklch(74% 0.16 300);\n}\n\n[data-prefers-color='dark'] .b-tag--custom-color {\n --b-tag-bg: color-mix(in oklch, var(--b-tag-custom-color) 15%, oklch(15% 0 0));\n --b-tag-border-color: color-mix(in oklch, var(--b-tag-custom-color) 50%, oklch(15% 0 0));\n --b-tag-color: color-mix(in oklch, var(--b-tag-custom-color) 85%, white);\n}\n\n@media (prefers-color-scheme: dark) {\n [data-prefers-color='system'] .b-tag {\n --b-tag-bg: oklch(26% 0.008 260);\n --b-tag-border-color: oklch(36% 0.012 260);\n --b-tag-color: oklch(82% 0.01 260);\n }\n [data-prefers-color='system'] .b-tag--success {\n --b-tag-bg: oklch(20% 0.06 148);\n --b-tag-border-color: oklch(38% 0.12 148);\n --b-tag-color: oklch(78% 0.12 148);\n }\n [data-prefers-color='system'] .b-tag--processing {\n --b-tag-bg: oklch(20% 0.06 260);\n --b-tag-border-color: oklch(40% 0.14 262);\n --b-tag-color: oklch(76% 0.15 262);\n }\n [data-prefers-color='system'] .b-tag--error {\n --b-tag-bg: oklch(20% 0.05 20);\n --b-tag-border-color: oklch(38% 0.14 22);\n --b-tag-color: oklch(78% 0.14 22);\n }\n [data-prefers-color='system'] .b-tag--warning {\n --b-tag-bg: oklch(20% 0.06 58);\n --b-tag-border-color: oklch(40% 0.15 58);\n --b-tag-color: oklch(80% 0.14 58);\n }\n [data-prefers-color='system'] .b-tag--magenta {\n --b-tag-bg: oklch(20% 0.05 348);\n --b-tag-border-color: oklch(38% 0.16 350);\n --b-tag-color: oklch(76% 0.16 348);\n }\n [data-prefers-color='system'] .b-tag--red {\n --b-tag-bg: oklch(20% 0.05 18);\n --b-tag-border-color: oklch(38% 0.17 18);\n --b-tag-color: oklch(76% 0.17 18);\n }\n [data-prefers-color='system'] .b-tag--volcano {\n --b-tag-bg: oklch(20% 0.05 38);\n --b-tag-border-color: oklch(38% 0.15 38);\n --b-tag-color: oklch(76% 0.15 38);\n }\n [data-prefers-color='system'] .b-tag--orange {\n --b-tag-bg: oklch(20% 0.06 62);\n --b-tag-border-color: oklch(40% 0.16 62);\n --b-tag-color: oklch(80% 0.16 62);\n }\n [data-prefers-color='system'] .b-tag--gold {\n --b-tag-bg: oklch(20% 0.06 78);\n --b-tag-border-color: oklch(40% 0.16 78);\n --b-tag-color: oklch(80% 0.14 78);\n }\n [data-prefers-color='system'] .b-tag--lime {\n --b-tag-bg: oklch(20% 0.07 128);\n --b-tag-border-color: oklch(40% 0.16 128);\n --b-tag-color: oklch(80% 0.14 128);\n }\n [data-prefers-color='system'] .b-tag--green {\n --b-tag-bg: oklch(20% 0.06 147);\n --b-tag-border-color: oklch(38% 0.14 147);\n --b-tag-color: oklch(76% 0.13 147);\n }\n [data-prefers-color='system'] .b-tag--cyan {\n --b-tag-bg: oklch(20% 0.05 200);\n --b-tag-border-color: oklch(38% 0.12 200);\n --b-tag-color: oklch(76% 0.11 200);\n }\n [data-prefers-color='system'] .b-tag--blue {\n --b-tag-bg: oklch(20% 0.06 258);\n --b-tag-border-color: oklch(38% 0.15 258);\n --b-tag-color: oklch(74% 0.15 258);\n }\n [data-prefers-color='system'] .b-tag--geekblue {\n --b-tag-bg: oklch(20% 0.05 272);\n --b-tag-border-color: oklch(36% 0.18 272);\n --b-tag-color: oklch(72% 0.18 272);\n }\n [data-prefers-color='system'] .b-tag--purple {\n --b-tag-bg: oklch(20% 0.05 300);\n --b-tag-border-color: oklch(36% 0.16 300);\n --b-tag-color: oklch(74% 0.16 300);\n }\n [data-prefers-color='system'] .b-tag--custom-color {\n --b-tag-bg: color-mix(in oklch, var(--b-tag-custom-color) 15%, oklch(15% 0 0));\n --b-tag-border-color: color-mix(in oklch, var(--b-tag-custom-color) 50%, oklch(15% 0 0));\n --b-tag-color: color-mix(in oklch, var(--b-tag-custom-color) 85%, white);\n }\n}\n\n/* ─────────────────────────────────────────────\n Transition (fade)\n ───────────────────────────────────────────── */\n.b-tag-fade-enter-active,\n.b-tag-fade-leave-active {\n transition:\n opacity var(--b-tag-transition-duration) ease,\n transform var(--b-tag-transition-duration) ease;\n}\n\n.b-tag-fade-enter-from,\n.b-tag-fade-leave-to {\n opacity: 0;\n transform: scale(0.85);\n}\n\n/* ── Reduced motion ── */\n@media (prefers-reduced-motion: reduce) {\n .b-tag {\n --b-tag-transition-duration: 0ms;\n }\n\n .b-tag-fade-enter-active,\n .b-tag-fade-leave-active {\n transition: opacity var(--b-tag-transition-duration) ease;\n transform: none !important;\n }\n}\n</style>\n"],"mappings":""}
|