@7pmlabs/design-system 2.0.9 → 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-system84.js","names":[],"sources":["../src/components/BDropdown/types.ts"],"sourcesContent":["export enum BDropdownTrigger {\n Hover = 'hover',\n Click = 'click',\n ContextMenu = 'contextMenu',\n}\n\nexport enum BDropdownPlacement {\n Bottom = 'bottom',\n BottomLeft = 'bottomLeft',\n BottomRight = 'bottomRight',\n Top = 'top',\n TopLeft = 'topLeft',\n TopRight = 'topRight',\n}\n\nexport interface BDropdownMenuItem {\n /** Unique key for the menu item. */\n key: string | number;\n /** Display label text. */\n label: string;\n /** Icon name to show before the label. */\n icon?: string;\n /** Whether this item is disabled. */\n disabled?: boolean;\n /** Whether this item is a danger/destructive action. */\n danger?: boolean;\n /** Nested children for sub-menus. */\n children?: BDropdownMenuItem[];\n /** If set to 'divider', renders a separator line. */\n type?: 'divider' | 'group';\n /** Group title when type is 'group'. */\n title?: string;\n}\n\nexport interface BDropdownMenuProps {\n /** Array of menu items to render. */\n items: BDropdownMenuItem[];\n /** Currently selected keys. */\n selectedKeys?: (string | number)[];\n /** Whether the menu is selectable. */\n selectable?: boolean;\n /** Allow multiple selection. */\n multiple?: boolean;\n}\n"],"mappings":";AAAA,IAAY,IAAL,yBAAA,GAAA;QACL,EAAA,QAAA,SACA,EAAA,QAAA,SACA,EAAA,cAAA;KACD,EAEW,IAAL,yBAAA,GAAA;QACL,EAAA,SAAA,UACA,EAAA,aAAA,cACA,EAAA,cAAA,eACA,EAAA,MAAA,OACA,EAAA,UAAA,WACA,EAAA,WAAA;KACD"}
|
|
1
|
+
{"version":3,"file":"design-system84.js","names":[],"sources":["../src/components/BDrawer/BDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { BDrawerPlacement, BDrawerSize } from '@/types';\nimport { computed, nextTick, onBeforeUnmount, ref, useId, watch } from 'vue';\n\n// ─────────────────────────────────────────────\n// Props & emits\n// ─────────────────────────────────────────────\nconst {\n placement = 'right',\n size = 'default',\n title = '',\n closable = true,\n mask = true,\n maskClosable = true,\n keyboard = true,\n destroyOnClose = false,\n width,\n height,\n zIndex = 1000,\n getContainer,\n autoFocus = true,\n modelValue = undefined,\n forceRender = false,\n extra = '',\n footer = '',\n loading = false,\n ariaLabel,\n} = defineProps<{\n /** Direction from which the drawer slides in. */\n placement?: BDrawerPlacement;\n /** Preset width/height: 'default' (378px) or 'large' (736px). */\n size?: BDrawerSize;\n /** Drawer title. Also accepts the `title` slot. */\n title?: string;\n /** Whether to show the close button. */\n closable?: boolean;\n /** Whether to show the mask overlay. */\n mask?: boolean;\n /** Clicking the mask closes the drawer. */\n maskClosable?: boolean;\n /** Pressing Escape closes the drawer. */\n keyboard?: boolean;\n /** Destroy child components when closing. */\n destroyOnClose?: boolean;\n /** Custom width (overrides size) for left/right placement. */\n width?: string | number;\n /** Custom height (overrides size) for top/bottom placement. */\n height?: string | number;\n /** z-index of the drawer. */\n zIndex?: number;\n /**\n * CSS selector or element to teleport the drawer into.\n * Defaults to `body`.\n */\n getContainer?: string | HTMLElement;\n /** Whether to auto-focus the first focusable element when opened. */\n autoFocus?: boolean;\n /**\n * Controlled visibility - bind with `v-model`.\n * When not provided the drawer manages its own state.\n */\n modelValue?: boolean;\n /** Force render the drawer content even when hidden. */\n forceRender?: boolean;\n /** Extra content in the header right area (also accepts the `extra` slot). */\n extra?: string;\n /** Footer content (also accepts the `footer` slot). */\n footer?: string;\n /** Show loading spinner in body area. */\n loading?: boolean;\n /**\n * Accessible label for the dialog when no visible title is present.\n * Required when `closable=false` and no `title` prop or `#title` slot is used.\n */\n ariaLabel?: string;\n}>();\n\nconst emit = defineEmits<{\n /** Fired when the user requests to close the drawer. */\n (e: 'close', event: MouseEvent | KeyboardEvent): void;\n /** Fired after the close transition completes. */\n (e: 'afterOpenChange', open: boolean): void;\n /** v-model support */\n (e: 'update:modelValue', value: boolean): void;\n}>();\n\nconst slots = defineSlots<{\n /** Main content of the drawer. */\n default?(): unknown;\n /** Overrides the `title` prop. */\n title?(): unknown;\n /** Overrides the `extra` prop (right side of header). */\n extra?(): unknown;\n /** Overrides the `footer` prop. */\n footer?(): unknown;\n /** Custom close icon. */\n closeIcon?(): unknown;\n}>();\n\n// ─────────────────────────────────────────────\n// Internal state\n// ─────────────────────────────────────────────\nconst titleId = useId();\n\n/** Uncontrolled visibility. */\nconst internalOpen = ref(false);\n\n/** Effective visibility. */\nconst isOpen = computed(() => (modelValue !== undefined ? modelValue : internalOpen.value));\n\n/** Whether the drawer has ever been opened (for lazy rendering). */\nconst hasBeenOpened = ref(false);\n\n/** Whether the content should render. */\nconst shouldRender = computed(() => {\n if (forceRender) return true;\n if (destroyOnClose) return isOpen.value;\n return hasBeenOpened.value || isOpen.value;\n});\n\n// Track when drawer opens at least once\nwatch(isOpen, (val) => {\n if (val) hasBeenOpened.value = true;\n});\n\n// ─────────────────────────────────────────────\n// Derived state\n// ─────────────────────────────────────────────\nconst isHorizontal = computed(() => placement === 'left' || placement === 'right');\n\nconst sizeMap: Record<BDrawerSize, number> = {\n default: 378,\n large: 736,\n};\n\nconst resolvedWidth = computed(() => {\n if (width !== undefined) return typeof width === 'number' ? `${width}px` : width;\n return isHorizontal.value ? `${sizeMap[size]}px` : '100%';\n});\n\nconst resolvedHeight = computed(() => {\n if (height !== undefined) return typeof height === 'number' ? `${height}px` : height;\n return !isHorizontal.value ? `${sizeMap[size]}px` : '100%';\n});\n\nconst hasTitle = computed(() => Boolean(title || slots.title));\nconst hasExtra = computed(() => Boolean(extra || slots.extra));\nconst hasFooter = computed(() => Boolean(footer || slots.footer));\nconst hasHeader = computed(() => hasTitle.value || closable || hasExtra.value);\n\nconst teleportTarget = computed(() => {\n if (getContainer) return getContainer;\n return 'body';\n});\n\nconst panelStyle = computed(() => ({\n width: resolvedWidth.value,\n height: resolvedHeight.value,\n zIndex,\n}));\n\n// ─────────────────────────────────────────────\n// Focus management\n// ─────────────────────────────────────────────\nconst drawerRef = ref<HTMLElement | null>(null);\nlet previouslyFocusedElement: HTMLElement | null = null;\n\nfunction trapFocus(event: KeyboardEvent) {\n if (event.key !== 'Tab' || !drawerRef.value) return;\n\n const focusableSelectors =\n 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n const focusable = Array.from(drawerRef.value.querySelectorAll<HTMLElement>(focusableSelectors));\n\n if (focusable.length === 0) {\n event.preventDefault();\n return;\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n\n if (event.shiftKey) {\n if (document.activeElement === first) {\n event.preventDefault();\n last.focus();\n }\n } else {\n if (document.activeElement === last) {\n event.preventDefault();\n first.focus();\n }\n }\n}\n\nfunction focusFirst() {\n if (!autoFocus || !drawerRef.value) return;\n\n nextTick(() => {\n if (!drawerRef.value) return;\n const focusableSelectors =\n 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n const first = drawerRef.value.querySelector<HTMLElement>(focusableSelectors);\n if (first) {\n first.focus();\n } else {\n // Focus the panel itself as a fallback\n drawerRef.value.focus();\n }\n });\n}\n\nwatch(isOpen, (val) => {\n if (val) {\n previouslyFocusedElement = document.activeElement as HTMLElement | null;\n nextTick(() => focusFirst());\n document.body.style.overflow = 'hidden';\n } else {\n document.body.style.overflow = '';\n }\n});\n\nonBeforeUnmount(() => {\n document.body.style.overflow = '';\n});\n\n// ─────────────────────────────────────────────\n// Behaviour\n// ─────────────────────────────────────────────\nfunction requestClose(event: MouseEvent | KeyboardEvent) {\n emit('close', event);\n if (modelValue !== undefined) {\n emit('update:modelValue', false);\n } else {\n internalOpen.value = false;\n }\n}\n\nfunction onMaskClick(event: MouseEvent) {\n if (maskClosable) {\n requestClose(event);\n }\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n if (event.key === 'Escape' && keyboard) {\n event.stopPropagation();\n requestClose(event);\n }\n trapFocus(event);\n}\n\nfunction onAfterEnter() {\n emit('afterOpenChange', true);\n}\n\nfunction onAfterLeave() {\n emit('afterOpenChange', false);\n // Restore focus to the previously focused element\n if (previouslyFocusedElement && typeof previouslyFocusedElement.focus === 'function') {\n previouslyFocusedElement.focus();\n previouslyFocusedElement = null;\n }\n}\n\n// ─────────────────────────────────────────────\n// Public API\n// ─────────────────────────────────────────────\nfunction open() {\n if (modelValue !== undefined) {\n emit('update:modelValue', true);\n } else {\n internalOpen.value = true;\n }\n}\n\ndefineExpose({ open });\n</script>\n\n<template>\n <Teleport :to=\"teleportTarget\">\n <Transition name=\"b-drawer\" @after-enter=\"onAfterEnter\" @after-leave=\"onAfterLeave\">\n <div\n v-if=\"isOpen\"\n class=\"b-drawer-root\"\n :class=\"`b-drawer-root--${placement}`\"\n :style=\"{ zIndex }\"\n >\n <!-- Mask -->\n <div v-if=\"mask\" class=\"b-drawer__mask\" aria-hidden=\"true\" @click=\"onMaskClick\" />\n\n <!-- Panel -->\n <div\n ref=\"drawerRef\"\n class=\"b-drawer\"\n :class=\"[\n `b-drawer--${placement}`,\n `b-drawer--${size}`,\n {\n 'b-drawer--has-header': hasHeader,\n 'b-drawer--has-footer': hasFooter,\n },\n ]\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-label=\"!hasTitle ? ariaLabel : undefined\"\n :aria-labelledby=\"hasTitle ? titleId : undefined\"\n :style=\"panelStyle\"\n tabindex=\"-1\"\n @keydown=\"onKeydown\"\n >\n <!-- Header -->\n <div v-if=\"hasHeader\" class=\"b-drawer__header\">\n <div class=\"b-drawer__header-title-wrapper\">\n <!-- Close button -->\n <button\n v-if=\"closable\"\n type=\"button\"\n class=\"b-drawer__close\"\n aria-label=\"Close drawer\"\n @click=\"requestClose\"\n >\n <slot name=\"closeIcon\">\n <svg\n class=\"b-drawer__close-icon\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <path\n d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"\n />\n </svg>\n </slot>\n </button>\n\n <!-- Title -->\n <div v-if=\"hasTitle\" :id=\"titleId\" class=\"b-drawer__title\">\n <slot name=\"title\">{{ title }}</slot>\n </div>\n </div>\n\n <!-- Extra -->\n <div v-if=\"hasExtra\" class=\"b-drawer__extra\">\n <slot name=\"extra\">{{ extra }}</slot>\n </div>\n </div>\n\n <!-- Body -->\n <div v-if=\"shouldRender\" class=\"b-drawer__body\">\n <div v-if=\"loading\" class=\"b-drawer__loading\" aria-live=\"polite\">\n <svg\n class=\"b-drawer__spinner\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-dasharray=\"31.4 31.4\"\n stroke-linecap=\"round\"\n />\n </svg>\n <span class=\"b-drawer__loading-text\">Loading…</span>\n </div>\n <slot v-else />\n </div>\n\n <!-- Footer -->\n <div v-if=\"hasFooter\" class=\"b-drawer__footer\">\n <slot name=\"footer\">{{ footer }}</slot>\n </div>\n </div>\n </div>\n </Transition>\n </Teleport>\n</template>\n\n<style>\n/* ────────────────────────────────────────────\n CSS Custom Properties (tokens)\n ──────────────────────────────────────────── */\n.b-drawer-root {\n --b-drawer-bg: #fff;\n --b-drawer-color: oklch(25% 0 0);\n --b-drawer-mask-bg: rgba(0, 0, 0, 0.45);\n --b-drawer-border-color: oklch(90% 0 0);\n --b-drawer-header-padding: 1rem 1.5rem;\n --b-drawer-body-padding: 1.5rem;\n --b-drawer-footer-padding: 0.5rem 1rem;\n --b-drawer-close-color: oklch(40% 0 0);\n --b-drawer-close-hover-color: oklch(20% 0 0);\n --b-drawer-title-font-size: 1rem;\n --b-drawer-title-font-weight: 600;\n --b-drawer-title-line-height: 1.5;\n --b-drawer-transition-duration: 300ms;\n --b-drawer-shadow:\n -6px 0 16px 0 rgba(0, 0, 0, 0.08), -3px 0 6px -4px rgba(0, 0, 0, 0.12),\n -9px 0 28px 8px rgba(0, 0, 0, 0.05);\n}\n\n/* ── Dark mode ── */\n[data-prefers-color='dark'] .b-drawer-root {\n --b-drawer-bg: oklch(20% 0 0);\n --b-drawer-color: oklch(90% 0 0);\n --b-drawer-mask-bg: rgba(0, 0, 0, 0.65);\n --b-drawer-border-color: oklch(30% 0 0);\n --b-drawer-close-color: oklch(65% 0 0);\n --b-drawer-close-hover-color: oklch(90% 0 0);\n --b-drawer-shadow:\n -6px 0 16px 0 rgba(0, 0, 0, 0.24), -3px 0 6px -4px rgba(0, 0, 0, 0.36),\n -9px 0 28px 8px rgba(0, 0, 0, 0.2);\n}\n\n@media (prefers-color-scheme: dark) {\n [data-prefers-color='system'] .b-drawer-root {\n --b-drawer-bg: oklch(20% 0 0);\n --b-drawer-color: oklch(90% 0 0);\n --b-drawer-mask-bg: rgba(0, 0, 0, 0.65);\n --b-drawer-border-color: oklch(30% 0 0);\n --b-drawer-close-color: oklch(65% 0 0);\n --b-drawer-close-hover-color: oklch(90% 0 0);\n --b-drawer-shadow:\n -6px 0 16px 0 rgba(0, 0, 0, 0.24), -3px 0 6px -4px rgba(0, 0, 0, 0.36),\n -9px 0 28px 8px rgba(0, 0, 0, 0.2);\n }\n}\n\n/* ─────────────────────────────────────────────\n Root wrapper (mask + panel)\n ───────────────────────────────────────────── */\n.b-drawer-root {\n position: fixed;\n inset: 0;\n}\n\n/* ── Mask ── */\n.b-drawer__mask {\n position: absolute;\n inset: 0;\n background: var(--b-drawer-mask-bg);\n}\n\n/* ── Panel base ── */\n.b-drawer {\n position: absolute;\n display: flex;\n flex-direction: column;\n background: var(--b-drawer-bg);\n color: var(--b-drawer-color);\n box-shadow: var(--b-drawer-shadow);\n outline: none;\n box-sizing: border-box;\n overflow: hidden;\n}\n\n/* Placement positioning */\n.b-drawer--right {\n top: 0;\n right: 0;\n bottom: 0;\n}\n\n.b-drawer--left {\n top: 0;\n left: 0;\n bottom: 0;\n}\n\n.b-drawer--top {\n top: 0;\n left: 0;\n right: 0;\n}\n\n.b-drawer--bottom {\n bottom: 0;\n left: 0;\n right: 0;\n}\n\n/* ── Header ── */\n.b-drawer__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--b-drawer-header-padding);\n border-bottom: 1px solid var(--b-drawer-border-color);\n flex-shrink: 0;\n}\n\n.b-drawer__header-title-wrapper {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n min-width: 0;\n flex: 1;\n}\n\n.b-drawer__title {\n font-size: var(--b-drawer-title-font-size);\n font-weight: var(--b-drawer-title-font-weight);\n line-height: var(--b-drawer-title-line-height);\n color: var(--b-drawer-color);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.b-drawer__extra {\n flex-shrink: 0;\n}\n\n/* ── Close button ── */\n.b-drawer__close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: none;\n border-radius: 0.25rem;\n background: transparent;\n color: var(--b-drawer-close-color);\n cursor: pointer;\n width: 1.375rem;\n height: 1.375rem;\n font-size: 1rem;\n line-height: 1;\n transition: color var(--b-drawer-transition-duration) ease;\n}\n\n.b-drawer__close:hover {\n color: var(--b-drawer-close-hover-color);\n}\n\n.b-drawer__close:focus-visible {\n outline: 2px solid oklch(62.3% 0.214 259.815);\n outline-offset: 2px;\n}\n\n.b-drawer__close-icon {\n width: 1em;\n height: 1em;\n fill: currentColor;\n display: block;\n}\n\n/* ── Body ── */\n.b-drawer__body {\n flex: 1;\n padding: var(--b-drawer-body-padding);\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n/* ── Footer ── */\n.b-drawer__footer {\n flex-shrink: 0;\n padding: var(--b-drawer-footer-padding);\n border-top: 1px solid var(--b-drawer-border-color);\n}\n\n/* ── Loading spinner ── */\n.b-drawer__loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 0.75rem;\n padding: 2rem;\n color: var(--b-drawer-close-color);\n}\n\n.b-drawer__spinner {\n width: 2rem;\n height: 2rem;\n animation: b-drawer-spin 1s linear infinite;\n}\n\n.b-drawer__loading-text {\n font-size: 0.875rem;\n}\n\n@keyframes b-drawer-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n/* ─────────────────────────────────────────────\n Slide transitions\n ─────────────────────────────────────────────\n Vue's <Transition> adds .b-drawer-{enter|leave}-* classes\n to the root element (.b-drawer-root). We target the\n children (.b-drawer and .b-drawer__mask) from there.\n ───────────────────────────────────────────── */\n\n/*\n * Vue's <Transition> listens for `transitionend` on the root element\n * (.b-drawer-root) to know when the leave animation finishes.\n * We must put a real transition on the root itself so that event fires.\n * We use `visibility` which is invisible to the user but gives Vue\n * the transitionend signal it needs.\n */\n.b-drawer-enter-active,\n.b-drawer-leave-active {\n transition: visibility var(--b-drawer-transition-duration) linear;\n}\n\n.b-drawer-leave-to {\n visibility: hidden;\n}\n\n/* - Active phase: set transition on children - */\n.b-drawer-enter-active > .b-drawer,\n.b-drawer-leave-active > .b-drawer {\n transition: transform var(--b-drawer-transition-duration) cubic-bezier(0.7, 0.3, 0.1, 1);\n}\n\n.b-drawer-enter-active > .b-drawer__mask,\n.b-drawer-leave-active > .b-drawer__mask {\n transition: opacity var(--b-drawer-transition-duration) ease;\n}\n\n/* - From / To: mask fades - */\n.b-drawer-enter-from > .b-drawer__mask,\n.b-drawer-leave-to > .b-drawer__mask {\n opacity: 0;\n}\n\n/* - From / To: panel slides (right) - */\n.b-drawer-enter-from > .b-drawer--right,\n.b-drawer-leave-to > .b-drawer--right {\n transform: translateX(100%);\n}\n\n/* - From / To: panel slides (left) - */\n.b-drawer-enter-from > .b-drawer--left,\n.b-drawer-leave-to > .b-drawer--left {\n transform: translateX(-100%);\n}\n\n/* - From / To: panel slides (top) - */\n.b-drawer-enter-from > .b-drawer--top,\n.b-drawer-leave-to > .b-drawer--top {\n transform: translateY(-100%);\n}\n\n/* - From / To: panel slides (bottom) - */\n.b-drawer-enter-from > .b-drawer--bottom,\n.b-drawer-leave-to > .b-drawer--bottom {\n transform: translateY(100%);\n}\n\n/* ── Reduced motion ── */\n@media (prefers-reduced-motion: reduce) {\n .b-drawer-enter-active,\n .b-drawer-leave-active,\n .b-drawer-enter-active > .b-drawer,\n .b-drawer-leave-active > .b-drawer,\n .b-drawer-enter-active > .b-drawer__mask,\n .b-drawer-leave-active > .b-drawer__mask {\n transition-duration: 0ms;\n }\n\n .b-drawer__spinner {\n animation: none;\n }\n}\n</style>\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design-system86.js","names":[],"sources":["../src/components/BDrawer/BDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { BDrawerPlacement, BDrawerSize } from '@/types';\nimport { computed, nextTick, onBeforeUnmount, ref, useId, watch } from 'vue';\n\n// ─────────────────────────────────────────────\n// Props & emits\n// ─────────────────────────────────────────────\nconst {\n placement = 'right',\n size = 'default',\n title = '',\n closable = true,\n mask = true,\n maskClosable = true,\n keyboard = true,\n destroyOnClose = false,\n width,\n height,\n zIndex = 1000,\n getContainer,\n autoFocus = true,\n modelValue = undefined,\n forceRender = false,\n extra = '',\n footer = '',\n loading = false,\n ariaLabel,\n} = defineProps<{\n /** Direction from which the drawer slides in. */\n placement?: BDrawerPlacement;\n /** Preset width/height: 'default' (378px) or 'large' (736px). */\n size?: BDrawerSize;\n /** Drawer title. Also accepts the `title` slot. */\n title?: string;\n /** Whether to show the close button. */\n closable?: boolean;\n /** Whether to show the mask overlay. */\n mask?: boolean;\n /** Clicking the mask closes the drawer. */\n maskClosable?: boolean;\n /** Pressing Escape closes the drawer. */\n keyboard?: boolean;\n /** Destroy child components when closing. */\n destroyOnClose?: boolean;\n /** Custom width (overrides size) for left/right placement. */\n width?: string | number;\n /** Custom height (overrides size) for top/bottom placement. */\n height?: string | number;\n /** z-index of the drawer. */\n zIndex?: number;\n /**\n * CSS selector or element to teleport the drawer into.\n * Defaults to `body`.\n */\n getContainer?: string | HTMLElement;\n /** Whether to auto-focus the first focusable element when opened. */\n autoFocus?: boolean;\n /**\n * Controlled visibility - bind with `v-model`.\n * When not provided the drawer manages its own state.\n */\n modelValue?: boolean;\n /** Force render the drawer content even when hidden. */\n forceRender?: boolean;\n /** Extra content in the header right area (also accepts the `extra` slot). */\n extra?: string;\n /** Footer content (also accepts the `footer` slot). */\n footer?: string;\n /** Show loading spinner in body area. */\n loading?: boolean;\n /**\n * Accessible label for the dialog when no visible title is present.\n * Required when `closable=false` and no `title` prop or `#title` slot is used.\n */\n ariaLabel?: string;\n}>();\n\nconst emit = defineEmits<{\n /** Fired when the user requests to close the drawer. */\n (e: 'close', event: MouseEvent | KeyboardEvent): void;\n /** Fired after the close transition completes. */\n (e: 'afterOpenChange', open: boolean): void;\n /** v-model support */\n (e: 'update:modelValue', value: boolean): void;\n}>();\n\nconst slots = defineSlots<{\n /** Main content of the drawer. */\n default?(): unknown;\n /** Overrides the `title` prop. */\n title?(): unknown;\n /** Overrides the `extra` prop (right side of header). */\n extra?(): unknown;\n /** Overrides the `footer` prop. */\n footer?(): unknown;\n /** Custom close icon. */\n closeIcon?(): unknown;\n}>();\n\n// ─────────────────────────────────────────────\n// Internal state\n// ─────────────────────────────────────────────\nconst titleId = useId();\n\n/** Uncontrolled visibility. */\nconst internalOpen = ref(false);\n\n/** Effective visibility. */\nconst isOpen = computed(() => (modelValue !== undefined ? modelValue : internalOpen.value));\n\n/** Whether the drawer has ever been opened (for lazy rendering). */\nconst hasBeenOpened = ref(false);\n\n/** Whether the content should render. */\nconst shouldRender = computed(() => {\n if (forceRender) return true;\n if (destroyOnClose) return isOpen.value;\n return hasBeenOpened.value || isOpen.value;\n});\n\n// Track when drawer opens at least once\nwatch(isOpen, (val) => {\n if (val) hasBeenOpened.value = true;\n});\n\n// ─────────────────────────────────────────────\n// Derived state\n// ─────────────────────────────────────────────\nconst isHorizontal = computed(() => placement === 'left' || placement === 'right');\n\nconst sizeMap: Record<BDrawerSize, number> = {\n default: 378,\n large: 736,\n};\n\nconst resolvedWidth = computed(() => {\n if (width !== undefined) return typeof width === 'number' ? `${width}px` : width;\n return isHorizontal.value ? `${sizeMap[size]}px` : '100%';\n});\n\nconst resolvedHeight = computed(() => {\n if (height !== undefined) return typeof height === 'number' ? `${height}px` : height;\n return !isHorizontal.value ? `${sizeMap[size]}px` : '100%';\n});\n\nconst hasTitle = computed(() => Boolean(title || slots.title));\nconst hasExtra = computed(() => Boolean(extra || slots.extra));\nconst hasFooter = computed(() => Boolean(footer || slots.footer));\nconst hasHeader = computed(() => hasTitle.value || closable || hasExtra.value);\n\nconst teleportTarget = computed(() => {\n if (getContainer) return getContainer;\n return 'body';\n});\n\nconst panelStyle = computed(() => ({\n width: resolvedWidth.value,\n height: resolvedHeight.value,\n zIndex,\n}));\n\n// ─────────────────────────────────────────────\n// Focus management\n// ─────────────────────────────────────────────\nconst drawerRef = ref<HTMLElement | null>(null);\nlet previouslyFocusedElement: HTMLElement | null = null;\n\nfunction trapFocus(event: KeyboardEvent) {\n if (event.key !== 'Tab' || !drawerRef.value) return;\n\n const focusableSelectors =\n 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n const focusable = Array.from(drawerRef.value.querySelectorAll<HTMLElement>(focusableSelectors));\n\n if (focusable.length === 0) {\n event.preventDefault();\n return;\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n\n if (event.shiftKey) {\n if (document.activeElement === first) {\n event.preventDefault();\n last.focus();\n }\n } else {\n if (document.activeElement === last) {\n event.preventDefault();\n first.focus();\n }\n }\n}\n\nfunction focusFirst() {\n if (!autoFocus || !drawerRef.value) return;\n\n nextTick(() => {\n if (!drawerRef.value) return;\n const focusableSelectors =\n 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n const first = drawerRef.value.querySelector<HTMLElement>(focusableSelectors);\n if (first) {\n first.focus();\n } else {\n // Focus the panel itself as a fallback\n drawerRef.value.focus();\n }\n });\n}\n\nwatch(isOpen, (val) => {\n if (val) {\n previouslyFocusedElement = document.activeElement as HTMLElement | null;\n nextTick(() => focusFirst());\n document.body.style.overflow = 'hidden';\n } else {\n document.body.style.overflow = '';\n }\n});\n\nonBeforeUnmount(() => {\n document.body.style.overflow = '';\n});\n\n// ─────────────────────────────────────────────\n// Behaviour\n// ─────────────────────────────────────────────\nfunction requestClose(event: MouseEvent | KeyboardEvent) {\n emit('close', event);\n if (modelValue !== undefined) {\n emit('update:modelValue', false);\n } else {\n internalOpen.value = false;\n }\n}\n\nfunction onMaskClick(event: MouseEvent) {\n if (maskClosable) {\n requestClose(event);\n }\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n if (event.key === 'Escape' && keyboard) {\n event.stopPropagation();\n requestClose(event);\n }\n trapFocus(event);\n}\n\nfunction onAfterEnter() {\n emit('afterOpenChange', true);\n}\n\nfunction onAfterLeave() {\n emit('afterOpenChange', false);\n // Restore focus to the previously focused element\n if (previouslyFocusedElement && typeof previouslyFocusedElement.focus === 'function') {\n previouslyFocusedElement.focus();\n previouslyFocusedElement = null;\n }\n}\n\n// ─────────────────────────────────────────────\n// Public API\n// ─────────────────────────────────────────────\nfunction open() {\n if (modelValue !== undefined) {\n emit('update:modelValue', true);\n } else {\n internalOpen.value = true;\n }\n}\n\ndefineExpose({ open });\n</script>\n\n<template>\n <Teleport :to=\"teleportTarget\">\n <Transition name=\"b-drawer\" @after-enter=\"onAfterEnter\" @after-leave=\"onAfterLeave\">\n <div\n v-if=\"isOpen\"\n class=\"b-drawer-root\"\n :class=\"`b-drawer-root--${placement}`\"\n :style=\"{ zIndex }\"\n >\n <!-- Mask -->\n <div v-if=\"mask\" class=\"b-drawer__mask\" aria-hidden=\"true\" @click=\"onMaskClick\" />\n\n <!-- Panel -->\n <div\n ref=\"drawerRef\"\n class=\"b-drawer\"\n :class=\"[\n `b-drawer--${placement}`,\n `b-drawer--${size}`,\n {\n 'b-drawer--has-header': hasHeader,\n 'b-drawer--has-footer': hasFooter,\n },\n ]\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-label=\"!hasTitle ? ariaLabel : undefined\"\n :aria-labelledby=\"hasTitle ? titleId : undefined\"\n :style=\"panelStyle\"\n tabindex=\"-1\"\n @keydown=\"onKeydown\"\n >\n <!-- Header -->\n <div v-if=\"hasHeader\" class=\"b-drawer__header\">\n <div class=\"b-drawer__header-title-wrapper\">\n <!-- Close button -->\n <button\n v-if=\"closable\"\n type=\"button\"\n class=\"b-drawer__close\"\n aria-label=\"Close drawer\"\n @click=\"requestClose\"\n >\n <slot name=\"closeIcon\">\n <svg\n class=\"b-drawer__close-icon\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <path\n d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"\n />\n </svg>\n </slot>\n </button>\n\n <!-- Title -->\n <div v-if=\"hasTitle\" :id=\"titleId\" class=\"b-drawer__title\">\n <slot name=\"title\">{{ title }}</slot>\n </div>\n </div>\n\n <!-- Extra -->\n <div v-if=\"hasExtra\" class=\"b-drawer__extra\">\n <slot name=\"extra\">{{ extra }}</slot>\n </div>\n </div>\n\n <!-- Body -->\n <div v-if=\"shouldRender\" class=\"b-drawer__body\">\n <div v-if=\"loading\" class=\"b-drawer__loading\" aria-live=\"polite\">\n <svg\n class=\"b-drawer__spinner\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-dasharray=\"31.4 31.4\"\n stroke-linecap=\"round\"\n />\n </svg>\n <span class=\"b-drawer__loading-text\">Loading…</span>\n </div>\n <slot v-else />\n </div>\n\n <!-- Footer -->\n <div v-if=\"hasFooter\" class=\"b-drawer__footer\">\n <slot name=\"footer\">{{ footer }}</slot>\n </div>\n </div>\n </div>\n </Transition>\n </Teleport>\n</template>\n\n<style>\n/* ────────────────────────────────────────────\n CSS Custom Properties (tokens)\n ──────────────────────────────────────────── */\n.b-drawer-root {\n --b-drawer-bg: #fff;\n --b-drawer-color: oklch(25% 0 0);\n --b-drawer-mask-bg: rgba(0, 0, 0, 0.45);\n --b-drawer-border-color: oklch(90% 0 0);\n --b-drawer-header-padding: 1rem 1.5rem;\n --b-drawer-body-padding: 1.5rem;\n --b-drawer-footer-padding: 0.5rem 1rem;\n --b-drawer-close-color: oklch(40% 0 0);\n --b-drawer-close-hover-color: oklch(20% 0 0);\n --b-drawer-title-font-size: 1rem;\n --b-drawer-title-font-weight: 600;\n --b-drawer-title-line-height: 1.5;\n --b-drawer-transition-duration: 300ms;\n --b-drawer-shadow:\n -6px 0 16px 0 rgba(0, 0, 0, 0.08), -3px 0 6px -4px rgba(0, 0, 0, 0.12),\n -9px 0 28px 8px rgba(0, 0, 0, 0.05);\n}\n\n/* ── Dark mode ── */\n[data-prefers-color='dark'] .b-drawer-root {\n --b-drawer-bg: oklch(20% 0 0);\n --b-drawer-color: oklch(90% 0 0);\n --b-drawer-mask-bg: rgba(0, 0, 0, 0.65);\n --b-drawer-border-color: oklch(30% 0 0);\n --b-drawer-close-color: oklch(65% 0 0);\n --b-drawer-close-hover-color: oklch(90% 0 0);\n --b-drawer-shadow:\n -6px 0 16px 0 rgba(0, 0, 0, 0.24), -3px 0 6px -4px rgba(0, 0, 0, 0.36),\n -9px 0 28px 8px rgba(0, 0, 0, 0.2);\n}\n\n@media (prefers-color-scheme: dark) {\n [data-prefers-color='system'] .b-drawer-root {\n --b-drawer-bg: oklch(20% 0 0);\n --b-drawer-color: oklch(90% 0 0);\n --b-drawer-mask-bg: rgba(0, 0, 0, 0.65);\n --b-drawer-border-color: oklch(30% 0 0);\n --b-drawer-close-color: oklch(65% 0 0);\n --b-drawer-close-hover-color: oklch(90% 0 0);\n --b-drawer-shadow:\n -6px 0 16px 0 rgba(0, 0, 0, 0.24), -3px 0 6px -4px rgba(0, 0, 0, 0.36),\n -9px 0 28px 8px rgba(0, 0, 0, 0.2);\n }\n}\n\n/* ─────────────────────────────────────────────\n Root wrapper (mask + panel)\n ───────────────────────────────────────────── */\n.b-drawer-root {\n position: fixed;\n inset: 0;\n}\n\n/* ── Mask ── */\n.b-drawer__mask {\n position: absolute;\n inset: 0;\n background: var(--b-drawer-mask-bg);\n}\n\n/* ── Panel base ── */\n.b-drawer {\n position: absolute;\n display: flex;\n flex-direction: column;\n background: var(--b-drawer-bg);\n color: var(--b-drawer-color);\n box-shadow: var(--b-drawer-shadow);\n outline: none;\n box-sizing: border-box;\n overflow: hidden;\n}\n\n/* Placement positioning */\n.b-drawer--right {\n top: 0;\n right: 0;\n bottom: 0;\n}\n\n.b-drawer--left {\n top: 0;\n left: 0;\n bottom: 0;\n}\n\n.b-drawer--top {\n top: 0;\n left: 0;\n right: 0;\n}\n\n.b-drawer--bottom {\n bottom: 0;\n left: 0;\n right: 0;\n}\n\n/* ── Header ── */\n.b-drawer__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--b-drawer-header-padding);\n border-bottom: 1px solid var(--b-drawer-border-color);\n flex-shrink: 0;\n}\n\n.b-drawer__header-title-wrapper {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n min-width: 0;\n flex: 1;\n}\n\n.b-drawer__title {\n font-size: var(--b-drawer-title-font-size);\n font-weight: var(--b-drawer-title-font-weight);\n line-height: var(--b-drawer-title-line-height);\n color: var(--b-drawer-color);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.b-drawer__extra {\n flex-shrink: 0;\n}\n\n/* ── Close button ── */\n.b-drawer__close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: none;\n border-radius: 0.25rem;\n background: transparent;\n color: var(--b-drawer-close-color);\n cursor: pointer;\n width: 1.375rem;\n height: 1.375rem;\n font-size: 1rem;\n line-height: 1;\n transition: color var(--b-drawer-transition-duration) ease;\n}\n\n.b-drawer__close:hover {\n color: var(--b-drawer-close-hover-color);\n}\n\n.b-drawer__close:focus-visible {\n outline: 2px solid oklch(62.3% 0.214 259.815);\n outline-offset: 2px;\n}\n\n.b-drawer__close-icon {\n width: 1em;\n height: 1em;\n fill: currentColor;\n display: block;\n}\n\n/* ── Body ── */\n.b-drawer__body {\n flex: 1;\n padding: var(--b-drawer-body-padding);\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n/* ── Footer ── */\n.b-drawer__footer {\n flex-shrink: 0;\n padding: var(--b-drawer-footer-padding);\n border-top: 1px solid var(--b-drawer-border-color);\n}\n\n/* ── Loading spinner ── */\n.b-drawer__loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 0.75rem;\n padding: 2rem;\n color: var(--b-drawer-close-color);\n}\n\n.b-drawer__spinner {\n width: 2rem;\n height: 2rem;\n animation: b-drawer-spin 1s linear infinite;\n}\n\n.b-drawer__loading-text {\n font-size: 0.875rem;\n}\n\n@keyframes b-drawer-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n/* ─────────────────────────────────────────────\n Slide transitions\n ─────────────────────────────────────────────\n Vue's <Transition> adds .b-drawer-{enter|leave}-* classes\n to the root element (.b-drawer-root). We target the\n children (.b-drawer and .b-drawer__mask) from there.\n ───────────────────────────────────────────── */\n\n/*\n * Vue's <Transition> listens for `transitionend` on the root element\n * (.b-drawer-root) to know when the leave animation finishes.\n * We must put a real transition on the root itself so that event fires.\n * We use `visibility` which is invisible to the user but gives Vue\n * the transitionend signal it needs.\n */\n.b-drawer-enter-active,\n.b-drawer-leave-active {\n transition: visibility var(--b-drawer-transition-duration) linear;\n}\n\n.b-drawer-leave-to {\n visibility: hidden;\n}\n\n/* - Active phase: set transition on children - */\n.b-drawer-enter-active > .b-drawer,\n.b-drawer-leave-active > .b-drawer {\n transition: transform var(--b-drawer-transition-duration) cubic-bezier(0.7, 0.3, 0.1, 1);\n}\n\n.b-drawer-enter-active > .b-drawer__mask,\n.b-drawer-leave-active > .b-drawer__mask {\n transition: opacity var(--b-drawer-transition-duration) ease;\n}\n\n/* - From / To: mask fades - */\n.b-drawer-enter-from > .b-drawer__mask,\n.b-drawer-leave-to > .b-drawer__mask {\n opacity: 0;\n}\n\n/* - From / To: panel slides (right) - */\n.b-drawer-enter-from > .b-drawer--right,\n.b-drawer-leave-to > .b-drawer--right {\n transform: translateX(100%);\n}\n\n/* - From / To: panel slides (left) - */\n.b-drawer-enter-from > .b-drawer--left,\n.b-drawer-leave-to > .b-drawer--left {\n transform: translateX(-100%);\n}\n\n/* - From / To: panel slides (top) - */\n.b-drawer-enter-from > .b-drawer--top,\n.b-drawer-leave-to > .b-drawer--top {\n transform: translateY(-100%);\n}\n\n/* - From / To: panel slides (bottom) - */\n.b-drawer-enter-from > .b-drawer--bottom,\n.b-drawer-leave-to > .b-drawer--bottom {\n transform: translateY(100%);\n}\n\n/* ── Reduced motion ── */\n@media (prefers-reduced-motion: reduce) {\n .b-drawer-enter-active,\n .b-drawer-leave-active,\n .b-drawer-enter-active > .b-drawer,\n .b-drawer-leave-active > .b-drawer,\n .b-drawer-enter-active > .b-drawer__mask,\n .b-drawer-leave-active > .b-drawer__mask {\n transition-duration: 0ms;\n }\n\n .b-drawer__spinner {\n animation: none;\n }\n}\n</style>\n"],"mappings":""}
|
package/dist/design-system87.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
/*
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
//#region src/components/BDropdown/types.ts
|
|
2
|
+
var e = /* @__PURE__ */ function(e) {
|
|
3
|
+
return e.Hover = "hover", e.Click = "click", e.ContextMenu = "contextMenu", e;
|
|
4
|
+
}({}), t = /* @__PURE__ */ function(e) {
|
|
5
|
+
return e.Bottom = "bottom", e.BottomLeft = "bottomLeft", e.BottomRight = "bottomRight", e.Top = "top", e.TopLeft = "topLeft", e.TopRight = "topRight", e;
|
|
6
|
+
}({});
|
|
5
7
|
//#endregion
|
|
6
|
-
export { t as
|
|
8
|
+
export { t as BDropdownPlacement, e as BDropdownTrigger };
|
|
7
9
|
|
|
8
10
|
//# sourceMappingURL=design-system87.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"design-system87.js","names":[],"sources":["../src/components/BDropdown/BDropdown.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useComponentId } from '@/composables/useComponentId.ts';\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, useId, watch } from 'vue';\n\nimport type { BDropdownMenuItem, BDropdownMenuProps } from './types.ts';\nimport { BDropdownPlacement, BDropdownTrigger } from './types.ts';\n\nconst {\n trigger = BDropdownTrigger.Hover,\n placement = BDropdownPlacement.BottomLeft,\n arrow = false,\n disabled = false,\n destroyOnHidden = false,\n mouseEnterDelay = 100,\n mouseLeaveDelay = 100,\n menu,\n modelValue = undefined,\n} = defineProps<{\n /** The trigger mode which executes the dropdown action. */\n trigger?: `${BDropdownTrigger}`;\n /** Placement of popup menu. */\n placement?: `${BDropdownPlacement}`;\n /** Whether to show the dropdown chevron indicator next to the trigger. */\n arrow?: boolean;\n /** Whether the dropdown menu is disabled. */\n disabled?: boolean;\n /** Whether to destroy popup on hide. */\n destroyOnHidden?: boolean;\n /** Delay in ms before showing on mouseenter (hover trigger only). */\n mouseEnterDelay?: number;\n /** Delay in ms before hiding on mouseleave (hover trigger only). */\n mouseLeaveDelay?: number;\n /** Menu configuration: items, selectable, multiple, selectedKeys. */\n menu?: BDropdownMenuProps;\n /** Controlled open state - bind with `v-model:open`. */\n modelValue?: boolean;\n}>();\n\nconst emit = defineEmits<{\n /** Emitted when the dropdown visibility changes. */\n (e: 'openChange', open: boolean): void;\n /** v-model:open support. */\n (e: 'update:modelValue', value: boolean): void;\n /** Emitted when a menu item is clicked. */\n (e: 'menuClick', info: { key: string | number; item: BDropdownMenuItem }): void;\n}>();\n\ndefineSlots<{\n /** The trigger element. Receives `triggerProps` to bind ARIA attributes. */\n default?(props: { triggerProps: Record<string, unknown> }): unknown;\n /** Custom overlay content (replaces default menu rendering). */\n overlay?(): unknown;\n}>();\n\n// ─────────────────────────────────────────────\n// Internal state\n// ─────────────────────────────────────────────\nconst { componentUID } = useComponentId();\nconst dropdownId = useId();\nconst menuId = `${dropdownId}-menu`;\n\nconst internalOpen = ref(false);\nconst isOpen = computed(() => (modelValue !== undefined ? modelValue : internalOpen.value));\n\nconst shouldRender = computed(() => {\n if (destroyOnHidden) return isOpen.value;\n return 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 if (disabled) return;\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 popoverRef.value?.showPopover();\n}\n\nfunction doClose() {\n popoverRef.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 popoverRef = ref<HTMLDivElement | null>(null);\nconst toggleRef = ref<HTMLDivElement | null>(null);\n\n// ─────────────────────────────────────────────\n// Focus management\n// ─────────────────────────────────────────────\nlet previouslyFocusedElement: HTMLElement | null = null;\nconst focusedIndex = ref(-1);\n\nconst focusableSelector = '[role=\"menuitem\"]:not([aria-disabled=\"true\"])';\n\nfunction getFocusableItems(): HTMLElement[] {\n if (!popoverRef.value) return [];\n return Array.from(popoverRef.value.querySelectorAll<HTMLElement>(focusableSelector));\n}\n\nfunction focusItem(index: number) {\n const items = getFocusableItems();\n if (items.length === 0) return;\n const clamped = Math.max(0, Math.min(index, items.length - 1));\n focusedIndex.value = clamped;\n items[clamped]?.focus();\n}\n\nfunction focusFirst() {\n nextTick(() => focusItem(0));\n}\n\nfunction focusLast() {\n nextTick(() => {\n const items = getFocusableItems();\n focusItem(items.length - 1);\n });\n}\n\nwatch(isOpen, (val) => {\n if (val) {\n previouslyFocusedElement = document.activeElement as HTMLElement | null;\n focusFirst();\n } else {\n focusedIndex.value = -1;\n if (previouslyFocusedElement) {\n nextTick(() => previouslyFocusedElement?.focus());\n }\n }\n});\n\n// ─────────────────────────────────────────────\n// Menu item click\n// ─────────────────────────────────────────────\nfunction onItemClick(item: BDropdownMenuItem) {\n if (item.disabled) return;\n emit('menuClick', { key: item.key, item });\n requestClose();\n}\n\n// ─────────────────────────────────────────────\n// Event handlers\n// ─────────────────────────────────────────────\nfunction onClick() {\n if (disabled) return;\n if (isOpen.value) {\n requestClose();\n } else {\n requestOpen();\n }\n}\n\nfunction onContextMenu(event: MouseEvent) {\n if (disabled) return;\n event.preventDefault();\n if (isOpen.value) {\n requestClose();\n } else {\n requestOpen();\n }\n}\n\nfunction onMouseEnter() {\n if (disabled) return;\n requestOpen(mouseEnterDelay);\n}\n\nfunction onMouseLeave() {\n requestClose(mouseLeaveDelay);\n}\n\nfunction onTriggerKeydown(event: KeyboardEvent) {\n if (disabled) return;\n\n switch (event.key) {\n case 'Enter':\n case ' ':\n case 'ArrowDown':\n event.preventDefault();\n if (!isOpen.value) {\n requestOpen();\n nextTick(() => focusFirst());\n } else {\n focusFirst();\n }\n break;\n case 'ArrowUp':\n event.preventDefault();\n if (!isOpen.value) {\n requestOpen();\n nextTick(() => focusLast());\n } else {\n focusLast();\n }\n break;\n case 'Escape':\n if (isOpen.value) {\n event.preventDefault();\n requestClose();\n }\n break;\n }\n}\n\nfunction onMenuKeydown(event: KeyboardEvent) {\n const items = getFocusableItems();\n const currentIndex = items.indexOf(document.activeElement as HTMLElement);\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n focusItem(currentIndex < items.length - 1 ? currentIndex + 1 : 0);\n break;\n case 'ArrowUp':\n event.preventDefault();\n focusItem(currentIndex > 0 ? currentIndex - 1 : items.length - 1);\n break;\n case 'Home':\n event.preventDefault();\n focusItem(0);\n break;\n case 'End':\n event.preventDefault();\n focusItem(items.length - 1);\n break;\n case 'Enter':\n case ' ':\n event.preventDefault();\n if (document.activeElement) {\n (document.activeElement as HTMLElement).click();\n }\n break;\n case 'Escape':\n event.preventDefault();\n requestClose();\n break;\n case 'Tab':\n requestClose();\n break;\n }\n}\n\n// ─────────────────────────────────────────────\n// Popover hover (keep open when hovering content)\n// ─────────────────────────────────────────────\nfunction onPopoverMouseEnter() {\n if (trigger === BDropdownTrigger.Hover) {\n clearTimers();\n }\n}\n\nfunction onPopoverMouseLeave() {\n if (trigger === BDropdownTrigger.Hover) {\n requestClose(mouseLeaveDelay);\n }\n}\n\n// ─────────────────────────────────────────────\n// Click outside handler\n// ─────────────────────────────────────────────\nfunction onDocumentClick(event: MouseEvent) {\n if (!isOpen.value) return;\n const target = event.target as Node;\n if (toggleRef.value?.contains(target)) return;\n if (popoverRef.value?.contains(target)) return;\n requestClose();\n}\n\n// ─────────────────────────────────────────────\n// Event listener management\n// ─────────────────────────────────────────────\nfunction attachListeners() {\n const el = toggleRef.value;\n if (!el) return;\n\n el.addEventListener('keydown', onTriggerKeydown);\n\n switch (trigger) {\n case BDropdownTrigger.Click:\n el.addEventListener('click', onClick);\n break;\n case BDropdownTrigger.ContextMenu:\n el.addEventListener('contextmenu', onContextMenu);\n break;\n case BDropdownTrigger.Hover:\n default:\n el.addEventListener('mouseenter', onMouseEnter);\n el.addEventListener('mouseleave', onMouseLeave);\n break;\n }\n}\n\nfunction detachListeners() {\n const el = toggleRef.value;\n if (!el) return;\n\n el.removeEventListener('keydown', onTriggerKeydown);\n el.removeEventListener('click', onClick);\n el.removeEventListener('contextmenu', onContextMenu);\n el.removeEventListener('mouseenter', onMouseEnter);\n el.removeEventListener('mouseleave', onMouseLeave);\n}\n\nonMounted(() => {\n attachListeners();\n});\n\nonBeforeUnmount(() => {\n detachListeners();\n document.removeEventListener('click', onDocumentClick, true);\n clearTimers();\n});\n\nwatch(isOpen, (val) => {\n if (val) {\n document.addEventListener('click', onDocumentClick, true);\n } else {\n document.removeEventListener('click', onDocumentClick, true);\n }\n});\n\nwatch(\n () => trigger,\n () => {\n detachListeners();\n attachListeners();\n },\n);\n\nwatch(\n () => modelValue,\n (val) => {\n if (val === undefined) return;\n if (val) {\n popoverRef.value?.showPopover();\n } else {\n popoverRef.value?.hidePopover();\n }\n },\n);\n\n// ─────────────────────────────────────────────\n// Computed styles\n// ─────────────────────────────────────────────\nconst anchorName = computed(() => `--b-dropdown-anchor-${componentUID.value}`);\n\nconst placementClass = computed(() => {\n const map: Record<string, string> = {\n [BDropdownPlacement.Bottom]: 'bottom-center',\n [BDropdownPlacement.BottomLeft]: 'bottom-left',\n [BDropdownPlacement.BottomRight]: 'bottom-right',\n [BDropdownPlacement.Top]: 'top-center',\n [BDropdownPlacement.TopLeft]: 'top-left',\n [BDropdownPlacement.TopRight]: 'top-right',\n };\n return map[placement] ?? 'bottom-left';\n});\n\nconst menuItems = computed(() => menu?.items ?? []);\n\nconst triggerProps = computed(() => ({\n id: dropdownId,\n 'aria-haspopup': 'menu' as const,\n 'aria-expanded': isOpen.value,\n 'aria-disabled': disabled || undefined,\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-dropdown__toggle', { 'b-dropdown__toggle--open': isOpen }]\"\n :style=\"{ anchorName: anchorName }\"\n >\n <slot :trigger-props=\"triggerProps\" />\n <span v-if=\"arrow\" class=\"b-dropdown__indicator\" aria-hidden=\"true\" />\n </div>\n\n <div\n ref=\"popoverRef\"\n popover=\"manual\"\n :class=\"['b-dropdown', placementClass]\"\n :style=\"{ positionAnchor: anchorName }\"\n :id=\"menuId\"\n role=\"menu\"\n :aria-labelledby=\"dropdownId\"\n tabindex=\"-1\"\n @toggle=\"onPopoverToggle\"\n @keydown=\"onMenuKeydown\"\n @mouseenter=\"onPopoverMouseEnter\"\n @mouseleave=\"onPopoverMouseLeave\"\n >\n <template v-if=\"shouldRender\">\n <div class=\"b-dropdown__content\">\n <slot name=\"overlay\">\n <template v-for=\"item in menuItems\" :key=\"item.key\">\n <div v-if=\"item.type === 'divider'\" class=\"b-dropdown__divider\" role=\"separator\" />\n <div\n v-else-if=\"item.type === 'group'\"\n class=\"b-dropdown__group\"\n role=\"group\"\n :aria-label=\"item.title\"\n >\n <div class=\"b-dropdown__group-title\">{{ item.title }}</div>\n <div\n v-for=\"child in item.children\"\n :key=\"child.key\"\n :class=\"[\n 'b-dropdown__item',\n { 'b-dropdown__item--disabled': child.disabled },\n { 'b-dropdown__item--danger': child.danger },\n { 'b-dropdown__item--selected': menu?.selectedKeys?.includes(child.key) },\n ]\"\n role=\"menuitem\"\n :tabindex=\"child.disabled ? -1 : 0\"\n :aria-disabled=\"child.disabled || undefined\"\n @click=\"onItemClick(child)\"\n >\n <span v-if=\"child.icon\" class=\"b-dropdown__item-icon\" aria-hidden=\"true\">{{\n child.icon\n }}</span>\n <span class=\"b-dropdown__item-label\">{{ child.label }}</span>\n </div>\n </div>\n <div\n v-else\n :class=\"[\n 'b-dropdown__item',\n { 'b-dropdown__item--disabled': item.disabled },\n { 'b-dropdown__item--danger': item.danger },\n { 'b-dropdown__item--selected': menu?.selectedKeys?.includes(item.key) },\n ]\"\n role=\"menuitem\"\n :tabindex=\"item.disabled ? -1 : 0\"\n :aria-disabled=\"item.disabled || undefined\"\n @click=\"onItemClick(item)\"\n >\n <span v-if=\"item.icon\" class=\"b-dropdown__item-icon\" aria-hidden=\"true\">{{\n item.icon\n }}</span>\n <span class=\"b-dropdown__item-label\">{{ item.label }}</span>\n </div>\n </template>\n </slot>\n </div>\n </template>\n </div>\n</template>\n\n<style>\n/* ────────────────────────────────────────────\n CSS Custom Properties (tokens)\n ──────────────────────────────────────────── */\n.b-dropdown {\n --b-dropdown-z-index: 1050;\n --b-dropdown-bg: #fff;\n --b-dropdown-color: rgba(0, 0, 0, 0.88);\n --b-dropdown-border-radius: 8px;\n --b-dropdown-padding-block: 4px;\n --b-dropdown-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 --b-dropdown-font-size: 14px;\n --b-dropdown-line-height: 1.5714;\n --b-dropdown-min-width: 120px;\n --b-dropdown-max-width: 320px;\n --b-dropdown-gap: 4px;\n --b-dropdown-transition-duration: 200ms;\n\n --b-dropdown-item-padding-x: 12px;\n --b-dropdown-item-padding-y: 5px;\n --b-dropdown-item-border-radius: 4px;\n --b-dropdown-item-color: rgba(0, 0, 0, 0.88);\n --b-dropdown-item-hover-bg: rgba(0, 0, 0, 0.04);\n --b-dropdown-item-active-bg: rgba(0, 0, 0, 0.06);\n --b-dropdown-item-disabled-color: rgba(0, 0, 0, 0.25);\n --b-dropdown-item-danger-color: #ff4d4f;\n --b-dropdown-item-danger-hover-bg: #fff2f0;\n --b-dropdown-item-selected-bg: #e6f4ff;\n --b-dropdown-item-selected-color: #1677ff;\n --b-dropdown-item-icon-margin-right: 8px;\n --b-dropdown-item-icon-size: 14px;\n\n --b-dropdown-divider-color: rgba(5, 5, 5, 0.06);\n --b-dropdown-divider-margin: 4px 0;\n\n --b-dropdown-group-title-color: rgba(0, 0, 0, 0.45);\n --b-dropdown-group-title-font-size: 12px;\n --b-dropdown-group-title-padding: 5px 12px;\n}\n\n/* ── Dark mode ── */\n[data-prefers-color='dark'] .b-dropdown {\n --b-dropdown-bg: #1f1f1f;\n --b-dropdown-color: rgba(255, 255, 255, 0.85);\n --b-dropdown-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 --b-dropdown-item-color: rgba(255, 255, 255, 0.85);\n --b-dropdown-item-hover-bg: rgba(255, 255, 255, 0.08);\n --b-dropdown-item-active-bg: rgba(255, 255, 255, 0.12);\n --b-dropdown-item-disabled-color: rgba(255, 255, 255, 0.25);\n --b-dropdown-item-danger-color: #ff7875;\n --b-dropdown-item-danger-hover-bg: rgba(255, 77, 79, 0.12);\n --b-dropdown-item-selected-bg: rgba(22, 119, 255, 0.15);\n --b-dropdown-item-selected-color: #4096ff;\n --b-dropdown-divider-color: rgba(253, 253, 253, 0.12);\n --b-dropdown-group-title-color: rgba(255, 255, 255, 0.45);\n}\n\n@media (prefers-color-scheme: dark) {\n [data-prefers-color='system'] .b-dropdown {\n --b-dropdown-bg: #1f1f1f;\n --b-dropdown-color: rgba(255, 255, 255, 0.85);\n --b-dropdown-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 --b-dropdown-item-color: rgba(255, 255, 255, 0.85);\n --b-dropdown-item-hover-bg: rgba(255, 255, 255, 0.08);\n --b-dropdown-item-active-bg: rgba(255, 255, 255, 0.12);\n --b-dropdown-item-disabled-color: rgba(255, 255, 255, 0.25);\n --b-dropdown-item-danger-color: #ff7875;\n --b-dropdown-item-danger-hover-bg: rgba(255, 77, 79, 0.12);\n --b-dropdown-item-selected-bg: rgba(22, 119, 255, 0.15);\n --b-dropdown-item-selected-color: #4096ff;\n --b-dropdown-divider-color: rgba(253, 253, 253, 0.12);\n --b-dropdown-group-title-color: rgba(255, 255, 255, 0.45);\n }\n}\n\n/* ─────────────────────────────────────────────\n Toggle wrapper\n ───────────────────────────────────────────── */\n.b-dropdown__toggle {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n cursor: pointer;\n\n &[aria-disabled='true'] {\n cursor: not-allowed;\n opacity: 0.5;\n }\n}\n\n/* ─────────────────────────────────────────────\n Chevron indicator (CSS-only)\n ───────────────────────────────────────────── */\n.b-dropdown__indicator {\n display: inline-block;\n width: 0.625em;\n height: 0.625em;\n border-right: 1.5px solid currentColor;\n border-bottom: 1.5px solid currentColor;\n transform: rotate(45deg) translateY(-2px);\n transition: transform 200ms;\n opacity: 0.65;\n flex-shrink: 0;\n}\n\n.b-dropdown__toggle--open .b-dropdown__indicator {\n transform: rotate(-135deg) translateY(-1px);\n}\n\n/* ─────────────────────────────────────────────\n Dropdown popover\n ───────────────────────────────────────────── */\n.b-dropdown {\n position: absolute;\n border: none;\n padding: 0;\n margin: 0;\n background: transparent;\n overflow: visible;\n z-index: var(--b-dropdown-z-index);\n min-width: var(--b-dropdown-min-width);\n max-width: var(--b-dropdown-max-width);\n box-sizing: border-box;\n pointer-events: auto;\n\n transition:\n display var(--b-dropdown-transition-duration),\n opacity var(--b-dropdown-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: Bottom ── */\n &.bottom-left {\n inset: auto;\n top: anchor(bottom);\n left: anchor(left);\n margin-top: var(--b-dropdown-gap);\n }\n &.bottom-center {\n inset: auto;\n top: anchor(bottom);\n justify-self: anchor-center;\n margin-top: var(--b-dropdown-gap);\n }\n &.bottom-right {\n inset: auto;\n top: anchor(bottom);\n right: anchor(right);\n margin-top: var(--b-dropdown-gap);\n }\n\n /* ── Placement: Top ── */\n &.top-left {\n inset: auto;\n bottom: anchor(top);\n left: anchor(left);\n margin-bottom: var(--b-dropdown-gap);\n }\n &.top-center {\n inset: auto;\n bottom: anchor(top);\n justify-self: anchor-center;\n margin-bottom: var(--b-dropdown-gap);\n }\n &.top-right {\n inset: auto;\n bottom: anchor(top);\n right: anchor(right);\n margin-bottom: var(--b-dropdown-gap);\n }\n}\n\n/* ─────────────────────────────────────────────\n Content wrapper\n ───────────────────────────────────────────── */\n.b-dropdown__content {\n background: var(--b-dropdown-bg);\n color: var(--b-dropdown-color);\n font-size: var(--b-dropdown-font-size);\n line-height: var(--b-dropdown-line-height);\n padding: var(--b-dropdown-padding-block) 0;\n border-radius: var(--b-dropdown-border-radius);\n box-shadow: var(--b-dropdown-shadow);\n overflow: hidden auto;\n max-height: 60vh;\n}\n\n/* ─────────────────────────────────────────────\n Menu items\n ───────────────────────────────────────────── */\n.b-dropdown__item {\n display: flex;\n align-items: center;\n padding: var(--b-dropdown-item-padding-y) var(--b-dropdown-item-padding-x);\n margin: 0 4px;\n border-radius: var(--b-dropdown-item-border-radius);\n color: var(--b-dropdown-item-color);\n cursor: pointer;\n user-select: none;\n outline: none;\n transition: background-color 150ms;\n\n &:hover,\n &:focus-visible {\n background: var(--b-dropdown-item-hover-bg);\n }\n\n &:active {\n background: var(--b-dropdown-item-active-bg);\n }\n\n &--disabled {\n color: var(--b-dropdown-item-disabled-color);\n cursor: not-allowed;\n pointer-events: none;\n }\n\n &--danger {\n color: var(--b-dropdown-item-danger-color);\n\n &:hover,\n &:focus-visible {\n background: var(--b-dropdown-item-danger-hover-bg);\n }\n }\n\n &--selected {\n background: var(--b-dropdown-item-selected-bg);\n color: var(--b-dropdown-item-selected-color);\n }\n}\n\n.b-dropdown__item-icon {\n margin-right: var(--b-dropdown-item-icon-margin-right);\n font-size: var(--b-dropdown-item-icon-size);\n display: inline-flex;\n align-items: center;\n}\n\n.b-dropdown__item-label {\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* ─────────────────────────────────────────────\n Divider\n ───────────────────────────────────────────── */\n.b-dropdown__divider {\n height: 1px;\n margin: var(--b-dropdown-divider-margin);\n background: var(--b-dropdown-divider-color);\n}\n\n/* ─────────────────────────────────────────────\n Group\n ───────────────────────────────────────────── */\n.b-dropdown__group-title {\n padding: var(--b-dropdown-group-title-padding);\n color: var(--b-dropdown-group-title-color);\n font-size: var(--b-dropdown-group-title-font-size);\n font-weight: 500;\n}\n\n/* ─────────────────────────────────────────────\n Position fallbacks\n ───────────────────────────────────────────── */\n@position-try --b-dropdown-bottom {\n inset: auto;\n top: anchor(bottom);\n left: anchor(left);\n margin-top: var(--b-dropdown-gap);\n}\n\n@position-try --b-dropdown-top {\n inset: auto;\n bottom: anchor(top);\n left: anchor(left);\n margin-bottom: var(--b-dropdown-gap);\n}\n\n/* ── Reduced motion ── */\n@media (prefers-reduced-motion: reduce) {\n .b-dropdown {\n transition-duration: 0ms;\n }\n\n .b-dropdown__item {\n transition-duration: 0ms;\n }\n}\n</style>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"design-system87.js","names":[],"sources":["../src/components/BDropdown/types.ts"],"sourcesContent":["export enum BDropdownTrigger {\n Hover = 'hover',\n Click = 'click',\n ContextMenu = 'contextMenu',\n}\n\nexport enum BDropdownPlacement {\n Bottom = 'bottom',\n BottomLeft = 'bottomLeft',\n BottomRight = 'bottomRight',\n Top = 'top',\n TopLeft = 'topLeft',\n TopRight = 'topRight',\n}\n\nexport interface BDropdownMenuItem {\n /** Unique key for the menu item. */\n key: string | number;\n /** Display label text. */\n label: string;\n /** Icon name to show before the label. */\n icon?: string;\n /** Whether this item is disabled. */\n disabled?: boolean;\n /** Whether this item is a danger/destructive action. */\n danger?: boolean;\n /** Nested children for sub-menus. */\n children?: BDropdownMenuItem[];\n /** If set to 'divider', renders a separator line. */\n type?: 'divider' | 'group';\n /** Group title when type is 'group'. */\n title?: string;\n}\n\nexport interface BDropdownMenuProps {\n /** Array of menu items to render. */\n items: BDropdownMenuItem[];\n /** Currently selected keys. */\n selectedKeys?: (string | number)[];\n /** Whether the menu is selectable. */\n selectable?: boolean;\n /** Allow multiple selection. */\n multiple?: boolean;\n}\n"],"mappings":";AAAA,IAAY,IAAL,yBAAA,GAAA;QACL,EAAA,QAAA,SACA,EAAA,QAAA,SACA,EAAA,cAAA;KACD,EAEW,IAAL,yBAAA,GAAA;QACL,EAAA,SAAA,UACA,EAAA,aAAA,cACA,EAAA,cAAA,eACA,EAAA,MAAA,OACA,EAAA,UAAA,WACA,EAAA,WAAA;KACD"}
|
package/dist/design-system88.js
CHANGED
|
@@ -1,60 +1,276 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { useComponentId as e } from "./design-system10.js";
|
|
2
|
+
import { BDropdownPlacement as t, BDropdownTrigger as n } from "./design-system87.js";
|
|
3
|
+
import { Fragment as r, computed as i, createCommentVNode as a, createElementBlock as o, createElementVNode as s, defineComponent as c, nextTick as l, normalizeClass as u, normalizeStyle as d, onBeforeUnmount as ee, onMounted as te, openBlock as f, ref as p, renderList as m, renderSlot as h, toDisplayString as g, unref as ne, useId as re, watch as _ } from "vue";
|
|
4
|
+
//#region src/components/BDropdown/BDropdown.vue?vue&type=script&setup=true&lang.ts
|
|
5
|
+
var ie = {
|
|
5
6
|
key: 0,
|
|
6
|
-
class: "b-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"aria-hidden": "true",
|
|
10
|
-
focusable: "false"
|
|
11
|
-
}, _ = {
|
|
12
|
-
key: 1,
|
|
13
|
-
class: "b-empty__svg b-empty__svg--simple",
|
|
14
|
-
viewBox: "0 0 64 41",
|
|
15
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
16
|
-
"aria-hidden": "true",
|
|
17
|
-
focusable: "false"
|
|
18
|
-
}, v = ["src"], y = {
|
|
7
|
+
class: "b-dropdown__indicator",
|
|
8
|
+
"aria-hidden": "true"
|
|
9
|
+
}, ae = ["aria-labelledby"], v = {
|
|
19
10
|
key: 0,
|
|
20
|
-
class: "b-
|
|
21
|
-
},
|
|
22
|
-
key:
|
|
23
|
-
class: "b-
|
|
24
|
-
|
|
25
|
-
|
|
11
|
+
class: "b-dropdown__content"
|
|
12
|
+
}, y = {
|
|
13
|
+
key: 0,
|
|
14
|
+
class: "b-dropdown__divider",
|
|
15
|
+
role: "separator"
|
|
16
|
+
}, oe = ["aria-label"], se = { class: "b-dropdown__group-title" }, ce = [
|
|
17
|
+
"tabindex",
|
|
18
|
+
"aria-disabled",
|
|
19
|
+
"onClick"
|
|
20
|
+
], le = {
|
|
21
|
+
key: 0,
|
|
22
|
+
class: "b-dropdown__item-icon",
|
|
23
|
+
"aria-hidden": "true"
|
|
24
|
+
}, ue = { class: "b-dropdown__item-label" }, de = [
|
|
25
|
+
"tabindex",
|
|
26
|
+
"aria-disabled",
|
|
27
|
+
"onClick"
|
|
28
|
+
], fe = {
|
|
29
|
+
key: 0,
|
|
30
|
+
class: "b-dropdown__item-icon",
|
|
31
|
+
"aria-hidden": "true"
|
|
32
|
+
}, b = { class: "b-dropdown__item-label" }, x = "[role=\"menuitem\"]:not([aria-disabled=\"true\"])", S = /* @__PURE__ */ c({
|
|
33
|
+
__name: "BDropdown",
|
|
26
34
|
props: {
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
trigger: { default: () => n.Hover },
|
|
36
|
+
placement: { default: () => t.BottomLeft },
|
|
37
|
+
arrow: {
|
|
38
|
+
type: Boolean,
|
|
39
|
+
default: !1
|
|
40
|
+
},
|
|
41
|
+
disabled: {
|
|
29
42
|
type: Boolean,
|
|
30
43
|
default: !1
|
|
31
44
|
},
|
|
32
|
-
|
|
33
|
-
|
|
45
|
+
destroyOnHidden: {
|
|
46
|
+
type: Boolean,
|
|
47
|
+
default: !1
|
|
48
|
+
},
|
|
49
|
+
mouseEnterDelay: { default: 100 },
|
|
50
|
+
mouseLeaveDelay: { default: 100 },
|
|
51
|
+
menu: {},
|
|
52
|
+
modelValue: {
|
|
53
|
+
type: Boolean,
|
|
54
|
+
default: () => void 0
|
|
55
|
+
}
|
|
34
56
|
},
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
emits: [
|
|
58
|
+
"openChange",
|
|
59
|
+
"update:modelValue",
|
|
60
|
+
"menuClick"
|
|
61
|
+
],
|
|
62
|
+
setup(c, { expose: S, emit: pe }) {
|
|
63
|
+
let C = pe, { componentUID: me } = e(), w = re(), he = `${w}-menu`, T = p(!1), E = i(() => c.modelValue === void 0 ? T.value : c.modelValue), ge = i(() => c.destroyOnHidden ? E.value : !0), D = null, O = null;
|
|
64
|
+
function k() {
|
|
65
|
+
D &&= (clearTimeout(D), null), O &&= (clearTimeout(O), null);
|
|
66
|
+
}
|
|
67
|
+
function A(e = 0) {
|
|
68
|
+
c.disabled || (k(), !E.value && (e > 0 ? D = setTimeout(() => M(), e) : M()));
|
|
69
|
+
}
|
|
70
|
+
function j(e = 0) {
|
|
71
|
+
k(), E.value && (e > 0 ? O = setTimeout(() => N(), e) : N());
|
|
72
|
+
}
|
|
73
|
+
function M() {
|
|
74
|
+
I.value?.showPopover();
|
|
75
|
+
}
|
|
76
|
+
function N() {
|
|
77
|
+
I.value?.hidePopover();
|
|
78
|
+
}
|
|
79
|
+
function P(e) {
|
|
80
|
+
c.modelValue === void 0 ? T.value = e : C("update:modelValue", e), C("openChange", e);
|
|
81
|
+
}
|
|
82
|
+
let F = ({ newState: e }) => {
|
|
83
|
+
P(e === "open");
|
|
84
|
+
}, I = p(null), L = p(null), R = null, z = p(-1);
|
|
85
|
+
function B() {
|
|
86
|
+
return I.value ? Array.from(I.value.querySelectorAll(x)) : [];
|
|
87
|
+
}
|
|
88
|
+
function V(e) {
|
|
89
|
+
let t = B();
|
|
90
|
+
if (t.length === 0) return;
|
|
91
|
+
let n = Math.max(0, Math.min(e, t.length - 1));
|
|
92
|
+
z.value = n, t[n]?.focus();
|
|
93
|
+
}
|
|
94
|
+
function H() {
|
|
95
|
+
l(() => V(0));
|
|
96
|
+
}
|
|
97
|
+
function U() {
|
|
98
|
+
l(() => {
|
|
99
|
+
V(B().length - 1);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
_(E, (e) => {
|
|
103
|
+
e ? (R = document.activeElement, H()) : (z.value = -1, R && l(() => R?.focus()));
|
|
104
|
+
});
|
|
105
|
+
function W(e) {
|
|
106
|
+
e.disabled || (C("menuClick", {
|
|
107
|
+
key: e.key,
|
|
108
|
+
item: e
|
|
109
|
+
}), j());
|
|
110
|
+
}
|
|
111
|
+
function G() {
|
|
112
|
+
c.disabled || (E.value ? j() : A());
|
|
113
|
+
}
|
|
114
|
+
function K(e) {
|
|
115
|
+
c.disabled || (e.preventDefault(), E.value ? j() : A());
|
|
116
|
+
}
|
|
117
|
+
function q() {
|
|
118
|
+
c.disabled || A(c.mouseEnterDelay);
|
|
119
|
+
}
|
|
120
|
+
function J() {
|
|
121
|
+
j(c.mouseLeaveDelay);
|
|
122
|
+
}
|
|
123
|
+
function Y(e) {
|
|
124
|
+
if (!c.disabled) switch (e.key) {
|
|
125
|
+
case "Enter":
|
|
126
|
+
case " ":
|
|
127
|
+
case "ArrowDown":
|
|
128
|
+
e.preventDefault(), E.value ? H() : (A(), l(() => H()));
|
|
129
|
+
break;
|
|
130
|
+
case "ArrowUp":
|
|
131
|
+
e.preventDefault(), E.value ? U() : (A(), l(() => U()));
|
|
132
|
+
break;
|
|
133
|
+
case "Escape":
|
|
134
|
+
E.value && (e.preventDefault(), j());
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function _e(e) {
|
|
139
|
+
let t = B(), n = t.indexOf(document.activeElement);
|
|
140
|
+
switch (e.key) {
|
|
141
|
+
case "ArrowDown":
|
|
142
|
+
e.preventDefault(), V(n < t.length - 1 ? n + 1 : 0);
|
|
143
|
+
break;
|
|
144
|
+
case "ArrowUp":
|
|
145
|
+
e.preventDefault(), V(n > 0 ? n - 1 : t.length - 1);
|
|
146
|
+
break;
|
|
147
|
+
case "Home":
|
|
148
|
+
e.preventDefault(), V(0);
|
|
149
|
+
break;
|
|
150
|
+
case "End":
|
|
151
|
+
e.preventDefault(), V(t.length - 1);
|
|
152
|
+
break;
|
|
153
|
+
case "Enter":
|
|
154
|
+
case " ":
|
|
155
|
+
e.preventDefault(), document.activeElement && document.activeElement.click();
|
|
156
|
+
break;
|
|
157
|
+
case "Escape":
|
|
158
|
+
e.preventDefault(), j();
|
|
159
|
+
break;
|
|
160
|
+
case "Tab":
|
|
161
|
+
j();
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function ve() {
|
|
166
|
+
c.trigger === n.Hover && k();
|
|
167
|
+
}
|
|
168
|
+
function ye() {
|
|
169
|
+
c.trigger === n.Hover && j(c.mouseLeaveDelay);
|
|
170
|
+
}
|
|
171
|
+
function X(e) {
|
|
172
|
+
if (!E.value) return;
|
|
173
|
+
let t = e.target;
|
|
174
|
+
L.value?.contains(t) || I.value?.contains(t) || j();
|
|
175
|
+
}
|
|
176
|
+
function Z() {
|
|
177
|
+
let e = L.value;
|
|
178
|
+
if (e) switch (e.addEventListener("keydown", Y), c.trigger) {
|
|
179
|
+
case n.Click:
|
|
180
|
+
e.addEventListener("click", G);
|
|
181
|
+
break;
|
|
182
|
+
case n.ContextMenu:
|
|
183
|
+
e.addEventListener("contextmenu", K);
|
|
184
|
+
break;
|
|
185
|
+
case n.Hover:
|
|
186
|
+
default:
|
|
187
|
+
e.addEventListener("mouseenter", q), e.addEventListener("mouseleave", J);
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function Q() {
|
|
192
|
+
let e = L.value;
|
|
193
|
+
e && (e.removeEventListener("keydown", Y), e.removeEventListener("click", G), e.removeEventListener("contextmenu", K), e.removeEventListener("mouseenter", q), e.removeEventListener("mouseleave", J));
|
|
194
|
+
}
|
|
195
|
+
te(() => {
|
|
196
|
+
Z();
|
|
197
|
+
}), ee(() => {
|
|
198
|
+
Q(), document.removeEventListener("click", X, !0), k();
|
|
199
|
+
}), _(E, (e) => {
|
|
200
|
+
e ? document.addEventListener("click", X, !0) : document.removeEventListener("click", X, !0);
|
|
201
|
+
}), _(() => c.trigger, () => {
|
|
202
|
+
Q(), Z();
|
|
203
|
+
}), _(() => c.modelValue, (e) => {
|
|
204
|
+
e !== void 0 && (e ? I.value?.showPopover() : I.value?.hidePopover());
|
|
205
|
+
});
|
|
206
|
+
let $ = i(() => `--b-dropdown-anchor-${me.value}`), be = i(() => ({
|
|
207
|
+
[t.Bottom]: "bottom-center",
|
|
208
|
+
[t.BottomLeft]: "bottom-left",
|
|
209
|
+
[t.BottomRight]: "bottom-right",
|
|
210
|
+
[t.Top]: "top-center",
|
|
211
|
+
[t.TopLeft]: "top-left",
|
|
212
|
+
[t.TopRight]: "top-right"
|
|
213
|
+
})[c.placement] ?? "bottom-left"), xe = i(() => c.menu?.items ?? []), Se = i(() => ({
|
|
214
|
+
id: w,
|
|
215
|
+
"aria-haspopup": "menu",
|
|
216
|
+
"aria-expanded": E.value,
|
|
217
|
+
"aria-disabled": c.disabled || void 0
|
|
218
|
+
}));
|
|
219
|
+
return S({
|
|
220
|
+
open: M,
|
|
221
|
+
close: N
|
|
222
|
+
}), (e, t) => (f(), o(r, null, [s("div", {
|
|
223
|
+
ref_key: "toggleRef",
|
|
224
|
+
ref: L,
|
|
225
|
+
class: u(["b-dropdown__toggle", { "b-dropdown__toggle--open": E.value }]),
|
|
226
|
+
style: d({ anchorName: $.value })
|
|
227
|
+
}, [h(e.$slots, "default", { triggerProps: Se.value }), c.arrow ? (f(), o("span", ie)) : a("", !0)], 6), s("div", {
|
|
228
|
+
ref_key: "popoverRef",
|
|
229
|
+
ref: I,
|
|
230
|
+
popover: "manual",
|
|
231
|
+
class: u(["b-dropdown", be.value]),
|
|
232
|
+
style: d({ positionAnchor: $.value }),
|
|
233
|
+
id: he,
|
|
234
|
+
role: "menu",
|
|
235
|
+
"aria-labelledby": ne(w),
|
|
236
|
+
tabindex: "-1",
|
|
237
|
+
onToggle: F,
|
|
238
|
+
onKeydown: _e,
|
|
239
|
+
onMouseenter: ve,
|
|
240
|
+
onMouseleave: ye
|
|
241
|
+
}, [ge.value ? (f(), o("div", v, [h(e.$slots, "overlay", {}, () => [(f(!0), o(r, null, m(xe.value, (e) => (f(), o(r, { key: e.key }, [e.type === "divider" ? (f(), o("div", y)) : e.type === "group" ? (f(), o("div", {
|
|
242
|
+
key: 1,
|
|
243
|
+
class: "b-dropdown__group",
|
|
244
|
+
role: "group",
|
|
245
|
+
"aria-label": e.title
|
|
246
|
+
}, [s("div", se, g(e.title), 1), (f(!0), o(r, null, m(e.children, (e) => (f(), o("div", {
|
|
247
|
+
key: e.key,
|
|
248
|
+
class: u([
|
|
249
|
+
"b-dropdown__item",
|
|
250
|
+
{ "b-dropdown__item--disabled": e.disabled },
|
|
251
|
+
{ "b-dropdown__item--danger": e.danger },
|
|
252
|
+
{ "b-dropdown__item--selected": c.menu?.selectedKeys?.includes(e.key) }
|
|
253
|
+
]),
|
|
254
|
+
role: "menuitem",
|
|
255
|
+
tabindex: e.disabled ? -1 : 0,
|
|
256
|
+
"aria-disabled": e.disabled || void 0,
|
|
257
|
+
onClick: (t) => W(e)
|
|
258
|
+
}, [e.icon ? (f(), o("span", le, g(e.icon), 1)) : a("", !0), s("span", ue, g(e.label), 1)], 10, ce))), 128))], 8, oe)) : (f(), o("div", {
|
|
259
|
+
key: 2,
|
|
260
|
+
class: u([
|
|
261
|
+
"b-dropdown__item",
|
|
262
|
+
{ "b-dropdown__item--disabled": e.disabled },
|
|
263
|
+
{ "b-dropdown__item--danger": e.danger },
|
|
264
|
+
{ "b-dropdown__item--selected": c.menu?.selectedKeys?.includes(e.key) }
|
|
265
|
+
]),
|
|
266
|
+
role: "menuitem",
|
|
267
|
+
tabindex: e.disabled ? -1 : 0,
|
|
268
|
+
"aria-disabled": e.disabled || void 0,
|
|
269
|
+
onClick: (t) => W(e)
|
|
270
|
+
}, [e.icon ? (f(), o("span", fe, g(e.icon), 1)) : a("", !0), s("span", b, g(e.label), 1)], 10, de))], 64))), 128))])])) : a("", !0)], 46, ae)], 64));
|
|
55
271
|
}
|
|
56
272
|
});
|
|
57
273
|
//#endregion
|
|
58
|
-
export {
|
|
274
|
+
export { S as default };
|
|
59
275
|
|
|
60
276
|
//# sourceMappingURL=design-system88.js.map
|