@bitrix24/b24ui-nuxt 0.6.3 → 0.6.4

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.
Files changed (34) hide show
  1. package/dist/meta.d.mts +253 -134
  2. package/dist/meta.mjs +253 -134
  3. package/dist/module.json +1 -1
  4. package/dist/module.mjs +1 -1
  5. package/dist/runtime/components/Alert.vue +3 -3
  6. package/dist/runtime/components/App.vue +4 -0
  7. package/dist/runtime/components/App.vue.d.ts +1 -0
  8. package/dist/runtime/components/DropdownMenu.vue +1 -1
  9. package/dist/runtime/components/DropdownMenu.vue.d.ts +1 -1
  10. package/dist/runtime/components/DropdownMenuContent.vue +5 -3
  11. package/dist/runtime/components/DropdownMenuContent.vue.d.ts +1 -1
  12. package/dist/runtime/components/Form.vue +2 -1
  13. package/dist/runtime/components/Form.vue.d.ts +17 -12
  14. package/dist/runtime/components/InputMenu.vue +4 -2
  15. package/dist/runtime/components/InputMenu.vue.d.ts +1 -1
  16. package/dist/runtime/components/Modal.vue +4 -2
  17. package/dist/runtime/components/Modal.vue.d.ts +2 -2
  18. package/dist/runtime/components/Popover.vue +4 -2
  19. package/dist/runtime/components/Popover.vue.d.ts +2 -2
  20. package/dist/runtime/components/Select.vue +4 -2
  21. package/dist/runtime/components/Select.vue.d.ts +1 -1
  22. package/dist/runtime/components/SelectMenu.vue +4 -2
  23. package/dist/runtime/components/SelectMenu.vue.d.ts +1 -1
  24. package/dist/runtime/components/Slideover.vue +4 -2
  25. package/dist/runtime/components/Slideover.vue.d.ts +2 -2
  26. package/dist/runtime/components/Toast.vue +3 -3
  27. package/dist/runtime/components/Toaster.vue +5 -3
  28. package/dist/runtime/components/Toaster.vue.d.ts +2 -2
  29. package/dist/runtime/components/Tooltip.vue +4 -2
  30. package/dist/runtime/components/Tooltip.vue.d.ts +2 -2
  31. package/dist/runtime/composables/usePortal.d.ts +6 -0
  32. package/dist/runtime/composables/usePortal.js +17 -0
  33. package/dist/runtime/types/form.d.ts +3 -1
  34. package/package.json +7 -8
package/dist/module.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bitrix24/b24ui-nuxt",
3
- "version": "0.6.3",
3
+ "version": "0.6.4",
4
4
  "docs": "https://bitrix24.github.io/b24ui/guide/installation-nuxt-app.html",
5
5
  "configKey": "b24ui",
6
6
  "compatibility": {
package/dist/module.mjs CHANGED
@@ -5,7 +5,7 @@ import 'node:url';
5
5
  import 'scule';
6
6
 
7
7
  const name = "@bitrix24/b24ui-nuxt";
8
- const version = "0.6.3";
8
+ const version = "0.6.4";
9
9
 
10
10
  const module = defineNuxtModule({
11
11
  meta: {
@@ -61,15 +61,15 @@ const b24ui = computed(() => tv({ extend: tv(theme), ...appConfig.b24ui?.alert |
61
61
  </slot>
62
62
  </div>
63
63
 
64
- <div v-if="orientation === 'vertical' && actions?.length" :class="b24ui.actions({ class: props.b24ui?.actions })">
64
+ <div v-if="orientation === 'vertical' && (actions?.length || !!slots.actions)" :class="b24ui.actions({ class: props.b24ui?.actions })">
65
65
  <slot name="actions">
66
66
  <B24Button v-for="(action, index) in actions" :key="index" size="xs" v-bind="action" />
67
67
  </slot>
68
68
  </div>
69
69
  </div>
70
70
 
71
- <div v-if="orientation === 'horizontal' && actions?.length || close" :class="b24ui.actions({ class: props.b24ui?.actions, orientation: 'horizontal' })">
72
- <template v-if="orientation === 'horizontal' && actions?.length">
71
+ <div v-if="orientation === 'horizontal' && (actions?.length || !!slots.actions) || close" :class="b24ui.actions({ class: props.b24ui?.actions, orientation: 'horizontal' })">
72
+ <template v-if="orientation === 'horizontal' && (actions?.length || !!slots.actions)">
73
73
  <slot name="actions">
74
74
  <B24Button v-for="(action, index) in actions" :key="index" size="xs" v-bind="action" />
75
75
  </slot>
@@ -9,12 +9,14 @@ import { toRef, useId, provide } from "vue";
9
9
  import { ConfigProvider, TooltipProvider, useForwardProps } from "reka-ui";
10
10
  import { reactivePick } from "@vueuse/core";
11
11
  import { localeContextInjectionKey } from "../composables/useLocale";
12
+ import { portalTargetInjectionKey } from "../composables/usePortal";
12
13
  import B24Toaster from "./Toaster.vue";
13
14
  import B24OverlayProvider from "./OverlayProvider.vue";
14
15
  const props = defineProps({
15
16
  tooltip: { type: Object, required: false },
16
17
  toaster: { type: [Object, null], required: false },
17
18
  locale: { type: null, required: false },
19
+ portal: { type: null, required: false, default: "body" },
18
20
  scrollBody: { type: [Boolean, Object], required: false },
19
21
  nonce: { type: String, required: false }
20
22
  });
@@ -24,6 +26,8 @@ const tooltipProps = toRef(() => props.tooltip);
24
26
  const toasterProps = toRef(() => props.toaster);
25
27
  const locale = toRef(() => props.locale);
26
28
  provide(localeContextInjectionKey, locale);
29
+ const portal = toRef(() => props.portal);
30
+ provide(portalTargetInjectionKey, portal);
27
31
  </script>
28
32
 
29
33
  <template>
@@ -4,6 +4,7 @@ export interface AppProps<T extends Messages = Messages> extends Omit<ConfigProv
4
4
  tooltip?: TooltipProviderProps;
5
5
  toaster?: ToasterProps | null;
6
6
  locale?: Locale<T>;
7
+ portal?: string | HTMLElement;
7
8
  }
8
9
  export interface AppSlots {
9
10
  default(props?: {}): any;
@@ -18,7 +18,7 @@ const props = defineProps({
18
18
  externalIcon: { type: [Boolean, Function, Object], required: false, default: true },
19
19
  content: { type: Object, required: false },
20
20
  arrow: { type: [Boolean, Object], required: false },
21
- portal: { type: Boolean, required: false, default: true },
21
+ portal: { type: [Boolean, String], required: false, skipCheck: true, default: true },
22
22
  labelKey: { type: null, required: false, default: "label" },
23
23
  disabled: { type: Boolean, required: false },
24
24
  class: { type: null, required: false },
@@ -64,7 +64,7 @@ export interface DropdownMenuProps<T extends ArrayOrNested<DropdownMenuItem> = A
64
64
  * Render the menu in a portal.
65
65
  * @defaultValue true
66
66
  */
67
- portal?: boolean;
67
+ portal?: boolean | string | HTMLElement;
68
68
  /**
69
69
  * The key used to get the label from the item.
70
70
  * @defaultValue 'label'
@@ -3,11 +3,12 @@
3
3
  </script>
4
4
 
5
5
  <script setup>
6
- import { computed } from "vue";
6
+ import { computed, toRef } from "vue";
7
7
  import { DropdownMenu } from "reka-ui/namespaced";
8
8
  import { useForwardPropsEmits } from "reka-ui";
9
9
  import { reactiveOmit, createReusableTemplate } from "@vueuse/core";
10
10
  import { useLocale } from "../composables/useLocale";
11
+ import { usePortal } from "../composables/usePortal";
11
12
  import { omit, get, isArrayOfArray } from "../utils";
12
13
  import { pickLinkProps } from "../utils/link";
13
14
  import icons from "../dictionary/icons";
@@ -18,7 +19,7 @@ import B24Kbd from "./Kbd.vue";
18
19
  import B24DropdownMenuContent from "./DropdownMenuContent.vue";
19
20
  const props = defineProps({
20
21
  items: { type: null, required: false },
21
- portal: { type: Boolean, required: false },
22
+ portal: { type: [Boolean, String], required: false, skipCheck: true },
22
23
  sub: { type: Boolean, required: false },
23
24
  labelKey: { type: null, required: true },
24
25
  checkedIcon: { type: [Function, Object], required: false },
@@ -46,6 +47,7 @@ const props = defineProps({
46
47
  const emits = defineEmits(["escapeKeyDown", "pointerDownOutside", "focusOutside", "interactOutside", "closeAutoFocus"]);
47
48
  const slots = defineSlots();
48
49
  const { dir } = useLocale();
50
+ const portalProps = usePortal(toRef(() => props.portal));
49
51
  const contentProps = useForwardPropsEmits(reactiveOmit(props, "sub", "items", "portal", "labelKey", "checkedIcon", "externalIcon", "class", "b24ui", "b24uiOverride"), emits);
50
52
  const proxySlots = omit(slots, ["default"]);
51
53
  const getLabel = (item) => {
@@ -113,7 +115,7 @@ const groups = computed(
113
115
  </slot>
114
116
  </DefineItemTemplate>
115
117
 
116
- <DropdownMenu.Portal :disabled="!portal">
118
+ <DropdownMenu.Portal v-bind="portalProps">
117
119
  <component :is="sub ? DropdownMenu.SubContent : DropdownMenu.Content" :class="props.class" v-bind="contentProps">
118
120
  <DropdownMenu.Group v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="b24ui.group({ class: b24uiOverride?.group })">
119
121
  <template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
@@ -7,7 +7,7 @@ import type { ArrayOrNested, NestedItem, ComponentConfig } from '../types/utils'
7
7
  type DropdownMenu = ComponentConfig<typeof theme, AppConfig, 'dropdownMenu'>;
8
8
  interface DropdownMenuContentProps<T extends ArrayOrNested<DropdownMenuItem>> extends Omit<RekaDropdownMenuContentProps, 'as' | 'asChild' | 'forceMount'> {
9
9
  items?: T;
10
- portal?: boolean;
10
+ portal?: boolean | string | HTMLElement;
11
11
  sub?: boolean;
12
12
  labelKey: keyof NestedItem<T>;
13
13
  /**
@@ -21,6 +21,7 @@ const props = defineProps({
21
21
  disabled: { type: Boolean, required: false },
22
22
  validateOnInputDelay: { type: Number, required: false, default: 300 },
23
23
  transform: { type: Boolean, required: false, default: true },
24
+ attach: { type: Boolean, required: false, default: true },
24
25
  loadingAuto: { type: Boolean, required: false, default: true },
25
26
  class: { type: null, required: false },
26
27
  onSubmit: { type: Function, required: false }
@@ -31,7 +32,7 @@ const appConfig = useAppConfig();
31
32
  const b24ui = computed(() => tv({ extend: tv(theme), ...appConfig.b24ui?.form || {} }));
32
33
  const formId = props.id ?? useId();
33
34
  const bus = useEventBus(`form-${formId}`);
34
- const parentBus = inject(
35
+ const parentBus = props.attach && inject(
35
36
  formBusInjectionKey,
36
37
  void 0
37
38
  );
@@ -1,16 +1,16 @@
1
- import type { FormSchema, FormError, FormInputEvents, FormErrorEvent, FormSubmitEvent, Form } from '../types/form';
2
- export interface FormProps<T extends object> {
1
+ import type { FormSchema, FormError, FormInputEvents, FormErrorEvent, FormSubmitEvent, Form, InferInput, InferOutput } from '../types/form';
2
+ export interface FormProps<S extends FormSchema> {
3
3
  id?: string | number;
4
4
  /** Schema to validate the form state. Supports Standard Schema objects, Yup, Joi, and Superstructs. */
5
- schema?: FormSchema<T>;
5
+ schema?: S;
6
6
  /** An object representing the current state of the form. */
7
- state: Partial<T>;
7
+ state: Partial<InferInput<S>>;
8
8
  /**
9
9
  * Custom validation function to validate the form state.
10
10
  * @param state - The current state of the form.
11
11
  * @returns A promise that resolves to an array of FormError objects, or an array of FormError objects directly.
12
12
  */
13
- validate?: (state: Partial<T>) => Promise<FormError[]> | FormError[];
13
+ validate?: (state: Partial<InferInput<S>>) => Promise<FormError[]> | FormError[];
14
14
  /**
15
15
  * The list of input events that trigger the form validation.
16
16
  * @defaultValue `['blur', 'change', 'input']`
@@ -28,6 +28,11 @@ export interface FormProps<T extends object> {
28
28
  * @defaultValue `true`
29
29
  */
30
30
  transform?: boolean;
31
+ /**
32
+ * If true, this form will attach to its parent Form (if any) and validate at the same time.
33
+ * @defaultValue `true`
34
+ */
35
+ attach?: boolean;
31
36
  /**
32
37
  * When `true`, all form elements will be disabled on `@submit` event.
33
38
  * This will cause any focused input elements to lose their focus state.
@@ -35,10 +40,10 @@ export interface FormProps<T extends object> {
35
40
  */
36
41
  loadingAuto?: boolean;
37
42
  class?: any;
38
- onSubmit?: ((event: FormSubmitEvent<T>) => void | Promise<void>) | (() => void | Promise<void>);
43
+ onSubmit?: ((event: FormSubmitEvent<InferOutput<S>>) => void | Promise<void>) | (() => void | Promise<void>);
39
44
  }
40
- export interface FormEmits<T extends object> {
41
- (e: 'submit', payload: FormSubmitEvent<T>): void;
45
+ export interface FormEmits<S extends FormSchema> {
46
+ (e: 'submit', payload: FormSubmitEvent<InferOutput<S>>): void;
42
47
  (e: 'error', payload: FormErrorEvent): void;
43
48
  }
44
49
  export interface FormSlots {
@@ -46,12 +51,12 @@ export interface FormSlots {
46
51
  errors: FormError[];
47
52
  }): any;
48
53
  }
49
- declare const _default: <T extends object>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
50
- props: __VLS_PrettifyLocal<any & FormProps<T> & Partial<{}>> & (import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps);
51
- expose(exposed: import("vue").ShallowUnwrapRef<Form<T>>): void;
54
+ declare const _default: <S extends FormSchema>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
55
+ props: __VLS_PrettifyLocal<any & FormProps<S> & Partial<{}>> & (import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps);
56
+ expose(exposed: import("vue").ShallowUnwrapRef<Form<InferInput<S>>>): void;
52
57
  attrs: any;
53
58
  slots: Readonly<FormSlots> & FormSlots;
54
- emit: FormEmits<T>;
59
+ emit: FormEmits<S>;
55
60
  }>) => import("vue").VNode & {
56
61
  __ctx?: Awaited<typeof __VLS_setup>;
57
62
  };
@@ -13,6 +13,7 @@ import { useButtonGroup } from "../composables/useButtonGroup";
13
13
  import { useComponentIcons } from "../composables/useComponentIcons";
14
14
  import { useFormField } from "../composables/useFormField";
15
15
  import { useLocale } from "../composables/useLocale";
16
+ import { usePortal } from "../composables/usePortal";
16
17
  import { compare, get, isArrayOfArray } from "../utils";
17
18
  import { tv } from "../utils/tv";
18
19
  import icons from "../dictionary/icons";
@@ -38,7 +39,7 @@ const props = defineProps({
38
39
  deleteIcon: { type: [Function, Object], required: false },
39
40
  content: { type: Object, required: false },
40
41
  arrow: { type: [Boolean, Object], required: false },
41
- portal: { type: Boolean, required: false, default: true },
42
+ portal: { type: [Boolean, String], required: false, skipCheck: true, default: true },
42
43
  valueKey: { type: null, required: false },
43
44
  labelKey: { type: null, required: false, default: "label" },
44
45
  items: { type: null, required: false },
@@ -72,6 +73,7 @@ const { t } = useLocale();
72
73
  const appConfig = useAppConfig();
73
74
  const { contains } = useFilter({ sensitivity: "base" });
74
75
  const rootProps = useForwardPropsEmits(reactivePick(props, "as", "modelValue", "defaultValue", "open", "defaultOpen", "required", "multiple", "resetSearchTermOnBlur", "resetSearchTermOnSelect", "highlightOnHover", "ignoreFilter"), emits);
76
+ const portalProps = usePortal(toRef(() => props.portal));
75
77
  const contentProps = toRef(() => defu(props.content, { side: "bottom", sideOffset: 8, collisionPadding: 8, position: "popper" }));
76
78
  const arrowProps = toRef(() => props.arrow);
77
79
  const { emitFormBlur, emitFormFocus, emitFormChange, emitFormInput, size: formGroupSize, color, id, name, highlight, disabled, ariaAttrs } = useFormField(props);
@@ -326,7 +328,7 @@ defineExpose({
326
328
  </ComboboxTrigger>
327
329
  </ComboboxAnchor>
328
330
 
329
- <ComboboxPortal :disabled="!portal">
331
+ <ComboboxPortal v-bind="portalProps">
330
332
  <ComboboxContent :class="b24ui.content({ class: props.b24ui?.content })" v-bind="contentProps">
331
333
  <ComboboxEmpty :class="b24ui.empty({ class: props.b24ui?.empty })">
332
334
  <slot name="empty" :search-term="searchTerm">
@@ -114,7 +114,7 @@ export interface InputMenuProps<T extends ArrayOrNested<InputMenuItem> = ArrayOr
114
114
  * Render the menu in a portal.
115
115
  * @defaultValue true
116
116
  */
117
- portal?: boolean;
117
+ portal?: boolean | string | HTMLElement;
118
118
  /**
119
119
  * When `items` is an array of objects, select the field to use as the value instead of the object itself.
120
120
  * @defaultValue undefined
@@ -8,6 +8,7 @@ import { DialogRoot, DialogTrigger, DialogPortal, DialogOverlay, DialogContent,
8
8
  import { reactivePick } from "@vueuse/core";
9
9
  import { useAppConfig } from "#imports";
10
10
  import { useLocale } from "../composables/useLocale";
11
+ import { usePortal } from "../composables/usePortal";
11
12
  import { tv } from "../utils/tv";
12
13
  import icons from "../dictionary/icons";
13
14
  import B24Button from "./Button.vue";
@@ -19,7 +20,7 @@ const props = defineProps({
19
20
  overlayBlur: { type: null, required: false, default: "auto" },
20
21
  transition: { type: Boolean, required: false, default: true },
21
22
  fullscreen: { type: Boolean, required: false },
22
- portal: { type: Boolean, required: false, default: true },
23
+ portal: { type: [Boolean, String], required: false, skipCheck: true, default: true },
23
24
  close: { type: [Boolean, Object], required: false, default: true },
24
25
  closeIcon: { type: [Function, Object], required: false },
25
26
  dismissible: { type: Boolean, required: false, default: true },
@@ -35,6 +36,7 @@ const slots = defineSlots();
35
36
  const { t } = useLocale();
36
37
  const appConfig = useAppConfig();
37
38
  const rootProps = useForwardPropsEmits(reactivePick(props, "open", "defaultOpen", "modal"), emits);
39
+ const portalProps = usePortal(toRef(() => props.portal));
38
40
  const contentProps = toRef(() => props.content);
39
41
  const contentEvents = computed(() => {
40
42
  const events = {
@@ -63,7 +65,7 @@ const b24ui = computed(() => tv({ extend: tv(theme), ...appConfig.b24ui?.modal |
63
65
  <slot :open="open" />
64
66
  </DialogTrigger>
65
67
 
66
- <DialogPortal :disabled="!portal">
68
+ <DialogPortal v-bind="portalProps">
67
69
  <DialogOverlay v-if="overlay" :class="b24ui.overlay({ class: props.b24ui?.overlay })" />
68
70
 
69
71
  <DialogContent :class="b24ui.content({ class: [!slots.default && props.class, props.b24ui?.content] })" v-bind="contentProps" @after-leave="emits('after:leave')" v-on="contentEvents">
@@ -36,7 +36,7 @@ export interface ModalProps extends DialogRootProps {
36
36
  * Render the modal in a portal.
37
37
  * @defaultValue true
38
38
  */
39
- portal?: boolean;
39
+ portal?: boolean | string | HTMLElement;
40
40
  /**
41
41
  * Display a close button to dismiss the modal.
42
42
  * `{ size: 'xs', color: 'link' }`{lang="ts"}
@@ -93,7 +93,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<im
93
93
  close: boolean | Partial<ButtonProps>;
94
94
  modal: boolean;
95
95
  transition: boolean;
96
- portal: boolean;
96
+ portal: boolean | string | HTMLElement;
97
97
  overlay: boolean;
98
98
  overlayBlur: Modal["variants"]["overlayBlur"];
99
99
  dismissible: boolean;
@@ -9,12 +9,13 @@ import { useForwardPropsEmits } from "reka-ui";
9
9
  import { Popover, HoverCard } from "reka-ui/namespaced";
10
10
  import { reactivePick } from "@vueuse/core";
11
11
  import { useAppConfig } from "#imports";
12
+ import { usePortal } from "../composables/usePortal";
12
13
  import { tv } from "../utils/tv";
13
14
  const props = defineProps({
14
15
  mode: { type: String, required: false, default: "click" },
15
16
  content: { type: Object, required: false },
16
17
  arrow: { type: [Boolean, Object], required: false },
17
- portal: { type: Boolean, required: false, default: true },
18
+ portal: { type: [Boolean, String], required: false, skipCheck: true, default: true },
18
19
  dismissible: { type: Boolean, required: false, default: true },
19
20
  class: { type: null, required: false },
20
21
  b24ui: { type: null, required: false },
@@ -29,6 +30,7 @@ const slots = defineSlots();
29
30
  const appConfig = useAppConfig();
30
31
  const pick = props.mode === "hover" ? reactivePick(props, "defaultOpen", "open", "openDelay", "closeDelay") : reactivePick(props, "defaultOpen", "open", "modal");
31
32
  const rootProps = useForwardPropsEmits(pick, emits);
33
+ const portalProps = usePortal(toRef(() => props.portal));
32
34
  const contentProps = toRef(() => defu(props.content, { side: "bottom", sideOffset: 8, collisionPadding: 8 }));
33
35
  const contentEvents = computed(() => {
34
36
  if (!props.dismissible) {
@@ -53,7 +55,7 @@ const Component = computed(() => props.mode === "hover" ? HoverCard : Popover);
53
55
  <slot :open="open" />
54
56
  </Component.Trigger>
55
57
 
56
- <Component.Portal :disabled="!portal">
58
+ <Component.Portal v-bind="portalProps">
57
59
  <Component.Content v-bind="contentProps" :class="b24ui.content({ class: [!slots.default && props.class, props.b24ui?.content] })" v-on="contentEvents">
58
60
  <slot name="content" />
59
61
 
@@ -24,7 +24,7 @@ export interface PopoverProps extends PopoverRootProps, Pick<HoverCardRootProps,
24
24
  * Render the popover in a portal.
25
25
  * @defaultValue true
26
26
  */
27
- portal?: boolean;
27
+ portal?: boolean | string | HTMLElement;
28
28
  /**
29
29
  * When `false`, the popover will not close when clicking outside or pressing escape.
30
30
  * @defaultValue true
@@ -49,7 +49,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<im
49
49
  dismissible: boolean;
50
50
  }>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, any, string, import("vue").PublicProps, any, {
51
51
  mode: "click" | "hover";
52
- portal: boolean;
52
+ portal: boolean | string | HTMLElement;
53
53
  dismissible: boolean;
54
54
  openDelay: number;
55
55
  closeDelay: number;
@@ -11,6 +11,7 @@ import { useAppConfig } from "#imports";
11
11
  import { useButtonGroup } from "../composables/useButtonGroup";
12
12
  import { useComponentIcons } from "../composables/useComponentIcons";
13
13
  import { useFormField } from "../composables/useFormField";
14
+ import { usePortal } from "../composables/usePortal";
14
15
  import { compare, get, isArrayOfArray } from "../utils";
15
16
  import { tv } from "../utils/tv";
16
17
  import icons from "../dictionary/icons";
@@ -32,7 +33,7 @@ const props = defineProps({
32
33
  selectedIcon: { type: [Function, Object], required: false },
33
34
  content: { type: Object, required: false },
34
35
  arrow: { type: [Boolean, Object], required: false },
35
- portal: { type: Boolean, required: false, default: true },
36
+ portal: { type: [Boolean, String], required: false, skipCheck: true, default: true },
36
37
  valueKey: { type: null, required: false, default: "value" },
37
38
  labelKey: { type: null, required: false, default: "label" },
38
39
  items: { type: null, required: false },
@@ -57,6 +58,7 @@ const emits = defineEmits(["update:open", "change", "blur", "focus", "update:mod
57
58
  const slots = defineSlots();
58
59
  const appConfig = useAppConfig();
59
60
  const rootProps = useForwardPropsEmits(reactivePick(props, "open", "defaultOpen", "disabled", "autocomplete", "required", "multiple"), emits);
61
+ const portalProps = usePortal(toRef(() => props.portal));
60
62
  const contentProps = toRef(() => defu(props.content, { side: "bottom", sideOffset: 8, collisionPadding: 8, position: "popper" }));
61
63
  const arrowProps = toRef(() => props.arrow);
62
64
  const { emitFormChange, emitFormInput, emitFormBlur, emitFormFocus, size: formGroupSize, color, id, name, highlight, disabled, ariaAttrs } = useFormField(props);
@@ -167,7 +169,7 @@ function isSelectItem(item) {
167
169
  </span>
168
170
  </SelectTrigger>
169
171
 
170
- <SelectPortal :disabled="!portal">
172
+ <SelectPortal v-bind="portalProps">
171
173
  <SelectContent :class="b24ui.content({ class: props.b24ui?.content })" v-bind="contentProps">
172
174
  <SelectScrollUpButton :class="b24ui.scrollUpDownButton({ class: props.b24ui?.scrollUpDownButton })">
173
175
  <Component
@@ -89,7 +89,7 @@ export interface SelectProps<T extends ArrayOrNested<SelectItem> = ArrayOrNested
89
89
  * Render the menu in a portal.
90
90
  * @defaultValue true
91
91
  */
92
- portal?: boolean;
92
+ portal?: boolean | string | HTMLElement;
93
93
  /**
94
94
  * When `items` is an array of objects, select the field to use as the value.
95
95
  * @defaultValue 'value'
@@ -31,6 +31,7 @@ import { useButtonGroup } from "../composables/useButtonGroup";
31
31
  import { useComponentIcons } from "../composables/useComponentIcons";
32
32
  import { useFormField } from "../composables/useFormField";
33
33
  import { useLocale } from "../composables/useLocale";
34
+ import { usePortal } from "../composables/usePortal";
34
35
  import { compare, get, isArrayOfArray } from "../utils";
35
36
  import { tv } from "../utils/tv";
36
37
  import icons from "../dictionary/icons";
@@ -55,7 +56,7 @@ const props = defineProps({
55
56
  selectedIcon: { type: [Function, Object], required: false },
56
57
  content: { type: Object, required: false },
57
58
  arrow: { type: [Boolean, Object], required: false },
58
- portal: { type: Boolean, required: false, default: true },
59
+ portal: { type: [Boolean, String], required: false, skipCheck: true, default: true },
59
60
  valueKey: { type: null, required: false },
60
61
  labelKey: { type: null, required: false, default: "label" },
61
62
  items: { type: null, required: false },
@@ -87,6 +88,7 @@ const { t } = useLocale();
87
88
  const appConfig = useAppConfig();
88
89
  const { contains } = useFilter({ sensitivity: "base" });
89
90
  const rootProps = useForwardPropsEmits(reactivePick(props, "modelValue", "defaultValue", "open", "defaultOpen", "required", "multiple", "resetSearchTermOnBlur", "resetSearchTermOnSelect", "highlightOnHover"), emits);
91
+ const portalProps = usePortal(toRef(() => props.portal));
90
92
  const contentProps = toRef(() => defu(props.content, { side: "bottom", sideOffset: 8, collisionPadding: 8, position: "popper" }));
91
93
  const arrowProps = toRef(() => props.arrow);
92
94
  const searchInputProps = toRef(() => defu(props.searchInput, { placeholder: t("selectMenu.search"), type: "search" }));
@@ -278,7 +280,7 @@ function isSelectItem(item) {
278
280
  </ComboboxTrigger>
279
281
  </ComboboxAnchor>
280
282
 
281
- <ComboboxPortal :disabled="!portal">
283
+ <ComboboxPortal v-bind="portalProps">
282
284
  <ComboboxContent :class="b24ui.content({ class: props.b24ui?.content })" v-bind="contentProps">
283
285
  <FocusScope trapped :class="b24ui.focusScope({ class: props.b24ui?.focusScope })">
284
286
  <ComboboxInput v-if="!!searchInput" v-model="searchTerm" :display-value="() => searchTerm" as-child>
@@ -99,7 +99,7 @@ export interface SelectMenuProps<T extends ArrayOrNested<SelectMenuItem> = Array
99
99
  * Render the menu in a portal.
100
100
  * @defaultValue true
101
101
  */
102
- portal?: boolean;
102
+ portal?: boolean | string | HTMLElement;
103
103
  /**
104
104
  * When `items` is an array of objects, select the field to use as the value instead of the object itself.
105
105
  * @defaultValue undefined
@@ -8,6 +8,7 @@ import { DialogRoot, DialogTrigger, DialogPortal, DialogOverlay, DialogContent,
8
8
  import { reactivePick } from "@vueuse/core";
9
9
  import { useAppConfig } from "#imports";
10
10
  import { useLocale } from "../composables/useLocale";
11
+ import { usePortal } from "../composables/usePortal";
11
12
  import { tv } from "../utils/tv";
12
13
  import icons from "../dictionary/icons";
13
14
  import B24Button from "./Button.vue";
@@ -19,7 +20,7 @@ const props = defineProps({
19
20
  overlayBlur: { type: null, required: false, default: "auto" },
20
21
  transition: { type: Boolean, required: false, default: true },
21
22
  side: { type: null, required: false, default: "right" },
22
- portal: { type: Boolean, required: false, default: true },
23
+ portal: { type: [Boolean, String], required: false, skipCheck: true, default: true },
23
24
  close: { type: [Boolean, Object], required: false, default: true },
24
25
  closeIcon: { type: [Function, Object], required: false },
25
26
  dismissible: { type: Boolean, required: false, default: true },
@@ -35,6 +36,7 @@ const slots = defineSlots();
35
36
  const { t } = useLocale();
36
37
  const appConfig = useAppConfig();
37
38
  const rootProps = useForwardPropsEmits(reactivePick(props, "open", "defaultOpen", "modal"), emits);
39
+ const portalProps = usePortal(toRef(() => props.portal));
38
40
  const contentProps = toRef(() => props.content);
39
41
  const contentEvents = computed(() => {
40
42
  const events = {
@@ -63,7 +65,7 @@ const b24ui = computed(() => tv({ extend: tv(theme), ...appConfig.b24ui?.slideov
63
65
  <slot :open="open" />
64
66
  </DialogTrigger>
65
67
 
66
- <DialogPortal :disabled="!portal">
68
+ <DialogPortal v-bind="portalProps">
67
69
  <DialogOverlay v-if="overlay" :class="b24ui.overlay({ class: props.b24ui?.overlay })" />
68
70
 
69
71
  <DialogContent :data-side="side" :class="b24ui.content({ class: [!slots.default && props.class, props.b24ui?.content] })" v-bind="contentProps" @after-leave="emits('after:leave')" v-on="contentEvents">
@@ -36,7 +36,7 @@ export interface SlideoverProps extends DialogRootProps {
36
36
  * Render the slideover in a portal.
37
37
  * @defaultValue true
38
38
  */
39
- portal?: boolean;
39
+ portal?: boolean | string | HTMLElement;
40
40
  /**
41
41
  * Display a close button to dismiss the slideover.
42
42
  * `{ color: 'primary' }`{lang="ts"} for `left`, `right`
@@ -95,7 +95,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<im
95
95
  close: boolean | Partial<ButtonProps>;
96
96
  modal: boolean;
97
97
  transition: boolean;
98
- portal: boolean;
98
+ portal: boolean | string | HTMLElement;
99
99
  overlay: boolean;
100
100
  side: Slideover["variants"]["side"];
101
101
  overlayBlur: Slideover["variants"]["overlayBlur"];
@@ -93,7 +93,7 @@ defineExpose({
93
93
  </slot>
94
94
  </ToastDescription>
95
95
 
96
- <div v-if="orientation === 'vertical' && actions?.length" :class="b24ui.actions({ class: props.b24ui?.actions })">
96
+ <div v-if="orientation === 'vertical' && (actions?.length || !!slots.actions)" :class="b24ui.actions({ class: props.b24ui?.actions })">
97
97
  <slot name="actions">
98
98
  <ToastAction v-for="(action, index) in actions" :key="index" :alt-text="action.label || 'Action'" as-child @click.stop>
99
99
  <B24Button size="xs" :color="color" v-bind="action" />
@@ -102,8 +102,8 @@ defineExpose({
102
102
  </div>
103
103
  </div>
104
104
 
105
- <div v-if="orientation === 'horizontal' && actions?.length || close !== null" :class="b24ui.actions({ class: props.b24ui?.actions, orientation: 'horizontal' })">
106
- <template v-if="orientation === 'horizontal' && actions?.length">
105
+ <div v-if="orientation === 'horizontal' && (actions?.length || !!slots.actions) || close !== null" :class="b24ui.actions({ class: props.b24ui?.actions, orientation: 'horizontal' })">
106
+ <template v-if="orientation === 'horizontal' && (actions?.length || !!slots.actions)">
107
107
  <slot name="actions">
108
108
  <ToastAction v-for="(action, index) in actions" :key="index" :alt-text="action.label || 'Action'" as-child @click.stop>
109
109
  <B24Button size="xs" :color="color" v-bind="action" />
@@ -6,18 +6,19 @@ export default {
6
6
  </script>
7
7
 
8
8
  <script setup>
9
- import { ref, computed } from "vue";
9
+ import { ref, computed, toRef } from "vue";
10
10
  import { ToastProvider, ToastViewport, ToastPortal, useForwardProps } from "reka-ui";
11
11
  import { reactivePick } from "@vueuse/core";
12
12
  import { useAppConfig } from "#imports";
13
13
  import { useToast } from "../composables/useToast";
14
+ import { usePortal } from "../composables/usePortal";
14
15
  import { omit } from "../utils";
15
16
  import { tv } from "../utils/tv";
16
17
  import B24Toast from "./Toast.vue";
17
18
  const props = defineProps({
18
19
  position: { type: null, required: false, default: "top-right" },
19
20
  expand: { type: Boolean, required: false, default: true },
20
- portal: { type: Boolean, required: false, default: true },
21
+ portal: { type: [Boolean, String], required: false, skipCheck: true, default: true },
21
22
  duration: { type: Number, required: false, default: 5e3 },
22
23
  class: { type: null, required: false },
23
24
  b24ui: { type: null, required: false },
@@ -28,6 +29,7 @@ defineSlots();
28
29
  const { toasts, remove } = useToast();
29
30
  const appConfig = useAppConfig();
30
31
  const providerProps = useForwardProps(reactivePick(props, "duration", "label", "swipeThreshold"));
32
+ const portalProps = usePortal(toRef(() => props.portal));
31
33
  const proxyToastProps = (toast) => {
32
34
  return omit(toast, ["id", "close"]);
33
35
  };
@@ -93,7 +95,7 @@ function getOffset(index) {
93
95
  @click="toast.onClick && toast.onClick(toast)"
94
96
  />
95
97
 
96
- <ToastPortal :disabled="!portal">
98
+ <ToastPortal v-bind="portalProps">
97
99
  <ToastViewport
98
100
  :data-expanded="expanded"
99
101
  :class="b24ui.viewport({ class: [props.class, props.b24ui?.viewport] })"
@@ -18,7 +18,7 @@ export interface ToasterProps extends Omit<ToastProviderProps, 'swipeDirection'>
18
18
  * Render the toaster in a portal.
19
19
  * @defaultValue true
20
20
  */
21
- portal?: boolean;
21
+ portal?: boolean | string | HTMLElement;
22
22
  /**
23
23
  * @defaultValue 5000
24
24
  */
@@ -43,7 +43,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<im
43
43
  position: Toaster["variants"]["position"];
44
44
  duration: number;
45
45
  expand: boolean;
46
- portal: boolean;
46
+ portal: boolean | string | HTMLElement;
47
47
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>, Readonly<ToasterSlots> & ToasterSlots>;
48
48
  export default _default;
49
49
  type __VLS_WithDefaults<P, D> = {
@@ -8,6 +8,7 @@ import { defu } from "defu";
8
8
  import { TooltipRoot, TooltipTrigger, TooltipPortal, TooltipContent, TooltipArrow, useForwardPropsEmits } from "reka-ui";
9
9
  import { reactivePick } from "@vueuse/core";
10
10
  import { useAppConfig } from "#imports";
11
+ import { usePortal } from "../composables/usePortal";
11
12
  import { tv } from "../utils/tv";
12
13
  import B24Kbd from "./Kbd.vue";
13
14
  const props = defineProps({
@@ -15,7 +16,7 @@ const props = defineProps({
15
16
  kbds: { type: Array, required: false },
16
17
  content: { type: Object, required: false },
17
18
  arrow: { type: [Boolean, Object], required: false },
18
- portal: { type: Boolean, required: false, default: true },
19
+ portal: { type: [Boolean, String], required: false, skipCheck: true, default: true },
19
20
  class: { type: null, required: false },
20
21
  b24ui: { type: null, required: false },
21
22
  defaultOpen: { type: Boolean, required: false },
@@ -30,6 +31,7 @@ const emits = defineEmits(["update:open"]);
30
31
  const slots = defineSlots();
31
32
  const appConfig = useAppConfig();
32
33
  const rootProps = useForwardPropsEmits(reactivePick(props, "defaultOpen", "open", "delayDuration", "disableHoverableContent", "disableClosingTrigger", "disabled", "ignoreNonKeyboardFocus"), emits);
34
+ const portalProps = usePortal(toRef(() => props.portal));
33
35
  const contentProps = toRef(() => defu(props.content, { side: "bottom", sideOffset: 8, collisionPadding: 8 }));
34
36
  const arrowProps = toRef(() => props.arrow);
35
37
  const b24ui = computed(() => tv({ extend: tv(theme), ...appConfig.b24ui?.tooltip || {} })({
@@ -43,7 +45,7 @@ const b24ui = computed(() => tv({ extend: tv(theme), ...appConfig.b24ui?.tooltip
43
45
  <slot :open="open" />
44
46
  </TooltipTrigger>
45
47
 
46
- <TooltipPortal :disabled="!portal">
48
+ <TooltipPortal v-bind="portalProps">
47
49
  <TooltipContent v-bind="contentProps" :class="b24ui.content({ class: [!slots.default && props.class, props.b24ui?.content] })">
48
50
  <slot name="content">
49
51
  <span v-if="text" :class="b24ui.text({ class: props.b24ui?.text })">{{ text }}</span>