|
23 | 23 | <div class="modal-dialog" :class="modalDialogClasses">
|
24 | 24 | <div v-if="lazyShowing" class="modal-content" :class="contentClass">
|
25 | 25 | <div v-if="!hideHeaderBoolean" class="modal-header" :class="headerClasses">
|
26 |
| - <slot |
27 |
| - name="header" |
28 |
| - :cancel="() => hide('cancel')" |
29 |
| - :close="() => hide('close')" |
30 |
| - :hide="hide" |
31 |
| - :ok="() => hide('ok')" |
32 |
| - :visible="modelValueBoolean" |
33 |
| - > |
| 26 | + <slot name="header" v-bind="sharedSlots"> |
34 | 27 | <component
|
35 | 28 | :is="titleTag"
|
36 | 29 | :id="`${computedId}-label`"
|
37 | 30 | class="modal-title"
|
38 | 31 | :class="titleClasses"
|
39 | 32 | >
|
40 |
| - <slot |
41 |
| - name="title" |
42 |
| - :cancel="() => hide('cancel')" |
43 |
| - :close="() => hide('close')" |
44 |
| - :hide="hide" |
45 |
| - :ok="() => hide('ok')" |
46 |
| - :visible="modelValueBoolean" |
47 |
| - > |
| 33 | + <slot name="title" v-bind="sharedSlots"> |
48 | 34 | {{ title }}
|
49 | 35 | </slot>
|
50 | 36 | </component>
|
|
66 | 52 | </slot>
|
67 | 53 | </div>
|
68 | 54 | <div :id="`${computedId}-body`" class="modal-body" :class="bodyClasses">
|
69 |
| - <slot |
70 |
| - :cancel="() => hide('cancel')" |
71 |
| - :close="() => hide('close')" |
72 |
| - :hide="hide" |
73 |
| - :ok="() => hide('ok')" |
74 |
| - :visible="modelValueBoolean" |
75 |
| - /> |
| 55 | + <slot v-bind="sharedSlots" /> |
76 | 56 | </div>
|
77 | 57 | <div v-if="!hideFooterBoolean" class="modal-footer" :class="footerClasses">
|
78 |
| - <slot |
79 |
| - name="footer" |
80 |
| - :cancel="() => hide('cancel')" |
81 |
| - :close="() => hide('close')" |
82 |
| - :hide="hide" |
83 |
| - :ok="() => hide('ok')" |
84 |
| - :visible="modelValueBoolean" |
85 |
| - > |
86 |
| - <slot |
87 |
| - name="cancel" |
88 |
| - :cancel="() => hide('cancel')" |
89 |
| - :close="() => hide('close')" |
90 |
| - :hide="hide" |
91 |
| - :ok="() => hide('ok')" |
92 |
| - :visible="modelValueBoolean" |
93 |
| - > |
| 58 | + <slot name="footer" v-bind="sharedSlots"> |
| 59 | + <slot name="cancel" v-bind="sharedSlots"> |
94 | 60 | <BButton
|
95 | 61 | v-if="!okOnlyBoolean"
|
96 | 62 | ref="cancelButton"
|
|
102 | 68 | {{ cancelTitle }}
|
103 | 69 | </BButton>
|
104 | 70 | </slot>
|
105 |
| - <slot |
106 |
| - name="ok" |
107 |
| - :cancel="() => hide('cancel')" |
108 |
| - :close="() => hide('close')" |
109 |
| - :hide="hide" |
110 |
| - :ok="() => hide('ok')" |
111 |
| - :visible="modelValueBoolean" |
112 |
| - > |
| 71 | + <slot name="ok" v-bind="sharedSlots"> |
113 | 72 | <BButton
|
114 | 73 | ref="okButton"
|
115 | 74 | :disabled="disableOk"
|
|
141 | 100 | </template>
|
142 | 101 |
|
143 | 102 | <script setup lang="ts">
|
144 |
| -import {computed, ref, type RendererElement, useSlots} from 'vue' |
| 103 | +import {computed, reactive, ref, type RendererElement, useSlots} from 'vue' |
145 | 104 | import {useBooleanish, useId, useModalManager, useSafeScrollLock} from '../composables'
|
146 | 105 | import {onKeyStroke, useEventListener, useFocus, useVModel} from '@vueuse/core'
|
147 | 106 | import type {Booleanish, ButtonVariant, ClassValue, ColorVariant, Size} from '../types'
|
@@ -284,57 +243,29 @@ const emit = defineEmits<{
|
284 | 243 | 'close': [value: BvTriggerableEvent]
|
285 | 244 | }>()
|
286 | 245 |
|
| 246 | +type SharedSlotsData = { |
| 247 | + cancel: () => void |
| 248 | + close: () => void |
| 249 | + hide: (trigger?: string) => void |
| 250 | + ok: () => void |
| 251 | + visible: boolean |
| 252 | +} |
| 253 | +
|
287 | 254 | defineSlots<{
|
288 |
| - 'header'?: (props: { |
289 |
| - cancel: () => void |
290 |
| - close: () => void |
291 |
| - hide: (trigger?: string) => void |
292 |
| - ok: () => void |
293 |
| - visible: boolean |
294 |
| - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
295 |
| - }) => any |
296 |
| - 'title'?: (props: { |
297 |
| - cancel: () => void |
298 |
| - close: () => void |
299 |
| - hide: (trigger?: string) => void |
300 |
| - ok: () => void |
301 |
| - visible: boolean |
302 |
| - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
303 |
| - }) => any |
| 255 | + // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 256 | + 'header'?: (props: SharedSlotsData) => any |
| 257 | + // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 258 | + 'title'?: (props: SharedSlotsData) => any |
304 | 259 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
305 | 260 | 'header-close'?: (props: Record<string, never>) => any
|
306 |
| - 'default'?: (props: { |
307 |
| - cancel: () => void |
308 |
| - close: () => void |
309 |
| - hide: (trigger?: string) => void |
310 |
| - ok: () => void |
311 |
| - visible: boolean |
312 |
| - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
313 |
| - }) => any |
314 |
| - 'footer'?: (props: { |
315 |
| - cancel: () => void |
316 |
| - close: () => void |
317 |
| - hide: (trigger?: string) => void |
318 |
| - ok: () => void |
319 |
| - visible: boolean |
320 |
| - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
321 |
| - }) => any |
322 |
| - 'cancel'?: (props: { |
323 |
| - cancel: () => void |
324 |
| - close: () => void |
325 |
| - hide: (trigger?: string) => void |
326 |
| - ok: () => void |
327 |
| - visible: boolean |
328 |
| - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
329 |
| - }) => any |
330 |
| - 'ok'?: (props: { |
331 |
| - cancel: () => void |
332 |
| - close: () => void |
333 |
| - hide: (trigger?: string) => void |
334 |
| - ok: () => void |
335 |
| - visible: boolean |
336 |
| - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
337 |
| - }) => any |
| 261 | + // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 262 | + 'default'?: (props: SharedSlotsData) => any |
| 263 | + // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 264 | + 'footer'?: (props: SharedSlotsData) => any |
| 265 | + // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 266 | + 'cancel'?: (props: SharedSlotsData) => any |
| 267 | + // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 268 | + 'ok'?: (props: SharedSlotsData) => any |
338 | 269 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
339 | 270 | 'backdrop'?: (props: Record<string, never>) => any
|
340 | 271 | }>()
|
@@ -554,6 +485,14 @@ useEventListener(element, 'bv-toggle', () => {
|
554 | 485 | modelValueBoolean.value ? hide() : showFn()
|
555 | 486 | })
|
556 | 487 |
|
| 488 | +const sharedSlots: SharedSlotsData = reactive({ |
| 489 | + cancel: () => hide('cancel'), |
| 490 | + close: () => hide('close'), |
| 491 | + hide, |
| 492 | + ok: () => hide('ok'), |
| 493 | + visible: modelValueBoolean, |
| 494 | +}) |
| 495 | +
|
557 | 496 | defineExpose({
|
558 | 497 | hide,
|
559 | 498 | show: showFn,
|
|
0 commit comments