@bagelink/vue 1.12.44 → 1.12.49

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/vue",
3
3
  "type": "module",
4
- "version": "1.12.44",
4
+ "version": "1.12.49",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Bagel Studio",
@@ -11,7 +11,10 @@ export type Alignment = 'start' | 'end'
11
11
  export type AlignedPlacement = 'auto' | Side | `${Side}-${Alignment}`
12
12
  export type TriggerEvent = 'click' | 'hover'
13
13
 
14
- defineOptions({ inheritAttrs: false })
14
+ defineOptions({ inheritAttrs: false, name: 'DropDown' })
15
+
16
+ // Module-level counter so each Dropdown instance gets a unique id
17
+ let _bglIdCounter = 0
15
18
 
16
19
  const props = withDefaults(defineProps<{
17
20
  value?: string
@@ -38,6 +41,8 @@ const props = withDefaults(defineProps<{
38
41
  showGroup?: string
39
42
  card?: boolean
40
43
  delay?: number | { show: number; hide: number }
44
+ /** Override the anchor element used for positioning. When provided, the #trigger slot is not rendered. */
45
+ referenceEl?: Element | null
41
46
  }>(), {
42
47
  thin: true,
43
48
  flat: true,
@@ -57,6 +62,9 @@ const shown = defineModel('shown', { type: Boolean, default: false })
57
62
 
58
63
  const triggerWrapRef = ref<HTMLElement | null>(null)
59
64
  const popoverRef = ref<HTMLElement | null>(null)
65
+
66
+ // Unique id for this popover instance, used to track parent–child relationships across teleported popovers
67
+ const bglId = `bgl-dd-${++_bglIdCounter}`
60
68
  const teleportTarget = ref<string | Element>('body')
61
69
 
62
70
  const { isMobile, innerWidth } = useDevice()
@@ -97,7 +105,7 @@ const resolvedDelay = computed((): { show: number; hide: number } => {
97
105
  const groupRegistry = new Map<string, Set<() => void>>()
98
106
 
99
107
  async function updatePosition() {
100
- const triggerEl = triggerWrapRef.value?.firstElementChild as HTMLElement | null
108
+ const triggerEl = (props.referenceEl ?? triggerWrapRef.value?.firstElementChild) as HTMLElement | null
101
109
  if (!popoverRef.value || !triggerEl || shouldDisablePositioning.value) return
102
110
 
103
111
  const isAuto = props.placement === 'auto'
@@ -133,6 +141,14 @@ async function internalShow() {
133
141
  // Wait for Teleport to move the element to the new target before promoting to top layer
134
142
  await nextTick()
135
143
  if (!popoverRef.value) return
144
+
145
+ // Tag with our own id and, if the trigger lives inside another open popover, tag with that owner's id.
146
+ // This lets ancestor Dropdowns skip closing when a click lands inside our (teleported) popover.
147
+ popoverRef.value.dataset.bglId = bglId
148
+ const ownerPopover = triggerWrapRef.value?.closest<HTMLElement>('[data-bgl-id]')
149
+ if (ownerPopover?.dataset.bglId) popoverRef.value.dataset.bglOwner = ownerPopover.dataset.bglId
150
+ else delete popoverRef.value.dataset.bglOwner
151
+
136
152
  // Show hidden first so floating-ui can measure it, then position, then reveal
137
153
  popoverRef.value.style.opacity = '0'
138
154
  popoverRef.value.showPopover()
@@ -178,6 +194,15 @@ function onDocumentPointerDown(e: PointerEvent) {
178
194
  if (!props.autoHide || !isOpen()) return
179
195
  const target = e.target as Node
180
196
  if (popoverRef.value?.contains(target) || triggerWrapRef.value?.contains(target)) return
197
+ // Don't close if the click landed inside a descendant popover (e.g. a SelectInput inside this
198
+ // dropdown that teleports its popup to <body>). We detect this via a data-bgl-owner attribute
199
+ // that each Dropdown sets on its popover element to point to the nearest ancestor popover's id.
200
+ const openPopovers = document.querySelectorAll<HTMLElement>('[popover]:popover-open')
201
+ const myId = popoverRef.value?.dataset.bglId
202
+ for (const p of openPopovers) {
203
+ if (p === popoverRef.value) continue
204
+ if (p.contains(target) && myId && p.dataset.bglOwner === myId) return
205
+ }
181
206
  internalHide()
182
207
  }
183
208
 
@@ -245,8 +270,9 @@ defineExpose({ show, hide, shown })
245
270
 
246
271
  <template>
247
272
  <div style="display: contents">
248
- <!-- Trigger wrapper — click/hover only apply to the default Btn trigger -->
273
+ <!-- Trigger wrapper — omitted when referenceEl is provided externally -->
249
274
  <div
275
+ v-if="!referenceEl"
250
276
  ref="triggerWrapRef" v-bind="$attrs"
251
277
  @mouseenter="onTriggerMouseenter" @mouseleave="onTriggerMouseleave" @focus="onTriggerMouseenter"
252
278
  @blur="onTriggerMouseleave"
@@ -290,7 +290,6 @@ function onConnectorChange(id: string, connector: LogicalOperator) {
290
290
  <Dropdown
291
291
  flat placement="bottom-end" icon="filter_alt"
292
292
  :value="activeFiltersCount > 0 ? `${currentTexts.filter} (${activeFiltersCount})` : currentTexts.filter" thin
293
- :auto-hide="false"
294
293
  >
295
294
  <div class="p-1 m_p-05">
296
295
  <div class="p-025 bg-bg radius-1 mb-05 m_max-h-300px m_overflow m_border">