@bitrix24/b24ui-nuxt 0.2.2 → 0.2.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 (41) hide show
  1. package/.nuxt/b24ui/button.ts +9 -2
  2. package/.nuxt/b24ui/checkbox.ts +1 -1
  3. package/.nuxt/b24ui/index.ts +2 -0
  4. package/.nuxt/b24ui/input-menu.ts +1 -1
  5. package/.nuxt/b24ui/input-number.ts +417 -0
  6. package/.nuxt/b24ui/modal.ts +28 -0
  7. package/.nuxt/b24ui/radio-group.ts +1 -1
  8. package/.nuxt/b24ui/range.ts +1 -1
  9. package/.nuxt/b24ui/select-menu.ts +1 -1
  10. package/.nuxt/b24ui/select.ts +1 -1
  11. package/.nuxt/b24ui/switch.ts +1 -1
  12. package/.nuxt/b24ui/tabs.ts +2 -2
  13. package/.nuxt/b24ui/toaster.ts +4 -4
  14. package/README.md +1 -1
  15. package/dist/meta.cjs +4306 -655
  16. package/dist/meta.d.cts +4306 -655
  17. package/dist/meta.d.mts +4306 -655
  18. package/dist/meta.d.ts +4306 -655
  19. package/dist/meta.mjs +4306 -655
  20. package/dist/module.cjs +2 -1
  21. package/dist/module.json +1 -1
  22. package/dist/module.mjs +2 -1
  23. package/dist/runtime/components/App.vue +2 -2
  24. package/dist/runtime/components/DropdownMenu.vue +3 -3
  25. package/dist/runtime/components/InputNumber.vue +218 -0
  26. package/dist/runtime/components/Modal.vue +179 -0
  27. package/dist/runtime/components/ModalDialogClose.vue +17 -0
  28. package/dist/runtime/components/ModalProvider.vue +12 -0
  29. package/dist/runtime/composables/useModal.d.ts +17 -0
  30. package/dist/runtime/composables/useModal.js +46 -0
  31. package/dist/runtime/plugins/modal.d.ts +2 -0
  32. package/dist/runtime/plugins/modal.js +10 -0
  33. package/dist/runtime/types/index.d.ts +3 -0
  34. package/dist/runtime/types/index.js +3 -0
  35. package/dist/shared/{b24ui-nuxt.DgnM0VWe.cjs → b24ui-nuxt.DGjopCKm.cjs} +478 -26
  36. package/dist/shared/{b24ui-nuxt.CYvh5VlN.mjs → b24ui-nuxt.V9TzyCqH.mjs} +478 -26
  37. package/dist/unplugin.cjs +1 -1
  38. package/dist/unplugin.mjs +1 -1
  39. package/dist/vite.cjs +1 -1
  40. package/dist/vite.mjs +1 -1
  41. package/package.json +6 -4
package/dist/module.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  const defu = require('defu');
4
4
  const kit = require('@nuxt/kit');
5
- const templates = require('./shared/b24ui-nuxt.DgnM0VWe.cjs');
5
+ const templates = require('./shared/b24ui-nuxt.DGjopCKm.cjs');
6
6
  require('node:url');
7
7
  require('scule');
8
8
 
@@ -41,6 +41,7 @@ const module$1 = kit.defineNuxtModule({
41
41
  await registerModule("@nuxtjs/color-mode", { classSuffix: "", disableTransition: true });
42
42
  }
43
43
  kit.addPlugin({ src: resolve("./runtime/plugins/colors") });
44
+ kit.addPlugin({ src: resolve("./runtime/plugins/modal") });
44
45
  kit.addComponentsDir({
45
46
  path: resolve("./runtime/components"),
46
47
  prefix: "B24",
package/dist/module.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "nuxt": ">=3.13.1"
6
6
  },
7
7
  "docs": "https://bitrix24.github.io/b24ui/guide/installation-nuxt-app.html",
8
- "version": "0.2.2",
8
+ "version": "0.2.4",
9
9
  "builder": {
10
10
  "@nuxt/module-builder": "0.8.4",
11
11
  "unbuild": "2.0.0"
package/dist/module.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { defu } from 'defu';
2
2
  import { defineNuxtModule, createResolver, addVitePlugin, addPlugin, addComponentsDir, addImportsDir, hasNuxtModule, installModule } from '@nuxt/kit';
3
- import { d as defaultOptions, a as getDefaultUiConfig, b as addTemplates } from './shared/b24ui-nuxt.CYvh5VlN.mjs';
3
+ import { d as defaultOptions, a as getDefaultUiConfig, b as addTemplates } from './shared/b24ui-nuxt.V9TzyCqH.mjs';
4
4
  import 'node:url';
5
5
  import 'scule';
6
6
 
@@ -38,6 +38,7 @@ const module = defineNuxtModule({
38
38
  await registerModule("@nuxtjs/color-mode", { classSuffix: "", disableTransition: true });
39
39
  }
40
40
  addPlugin({ src: resolve("./runtime/plugins/colors") });
41
+ addPlugin({ src: resolve("./runtime/plugins/modal") });
41
42
  addComponentsDir({
42
43
  path: resolve("./runtime/components"),
43
44
  prefix: "B24",
@@ -23,7 +23,7 @@ import { toRef, useId, provide } from 'vue'
23
23
  import { ConfigProvider, TooltipProvider, useForwardProps } from 'reka-ui'
24
24
  import { reactivePick } from '@vueuse/core'
25
25
  import B24Toaster from './Toaster.vue'
26
- // import B24ModalProvider from './ModalProvider.vue'
26
+ import B24ModalProvider from './ModalProvider.vue'
27
27
  // import B24SlideoverProvider from './SlideoverProvider.vue'
28
28
 
29
29
  const props = defineProps<AppProps>()
@@ -44,7 +44,7 @@ provide(localeContextInjectionKey, locale)
44
44
  <slot />
45
45
  </B24Toaster>
46
46
  <slot v-else />
47
- <!-- B24ModalProvider / -->
47
+ <B24ModalProvider />
48
48
  <!-- B24SlideoverProvider / -->
49
49
  </TooltipProvider>
50
50
  </ConfigProvider>
@@ -89,7 +89,7 @@ import { defu } from 'defu'
89
89
  import { DropdownMenuRoot, DropdownMenuTrigger, DropdownMenuArrow, useForwardPropsEmits } from 'reka-ui'
90
90
  import { reactivePick } from '@vueuse/core'
91
91
  import { omit } from '../utils'
92
- import UDropdownMenuContent from './DropdownMenuContent.vue'
92
+ import B24DropdownMenuContent from './DropdownMenuContent.vue'
93
93
 
94
94
  const props = withDefaults(defineProps<DropdownMenuProps<T>>(), {
95
95
  portal: true,
@@ -115,7 +115,7 @@ const b24ui = computed(() => dropdownMenu({
115
115
  <slot :open="open" />
116
116
  </DropdownMenuTrigger>
117
117
 
118
- <UDropdownMenuContent
118
+ <B24DropdownMenuContent
119
119
  :class="b24ui.content({ class: [!slots.default && props.class, props.b24ui?.content] })"
120
120
  :b24ui="b24ui"
121
121
  :b24ui-override="props.b24ui"
@@ -130,6 +130,6 @@ const b24ui = computed(() => dropdownMenu({
130
130
  </template>
131
131
 
132
132
  <DropdownMenuArrow v-if="!!arrow" v-bind="arrowProps" :class="b24ui.arrow({ class: props.b24ui?.arrow })" />
133
- </UDropdownMenuContent>
133
+ </B24DropdownMenuContent>
134
134
  </DropdownMenuRoot>
135
135
  </template>
@@ -0,0 +1,218 @@
1
+ <script lang="ts">
2
+ import type { VariantProps } from 'tailwind-variants'
3
+ import type { NumberFieldRootProps } from 'reka-ui'
4
+ import type { AppConfig } from '@nuxt/schema'
5
+ import _appConfig from '#build/app.config'
6
+ import theme from '#build/b24ui/input-number'
7
+ import { tv } from '../utils/tv'
8
+ import type { ButtonProps, IconComponent } from '../types'
9
+
10
+ const appConfigInputNumber = _appConfig as AppConfig & { b24ui: { inputNumber: Partial<typeof theme> } }
11
+
12
+ const inputNumber = tv({ extend: tv(theme), ...(appConfigInputNumber.b24ui?.inputNumber || {}) })
13
+
14
+ type InputNumberVariants = VariantProps<typeof inputNumber>
15
+
16
+ export interface InputNumberProps extends Pick<NumberFieldRootProps, 'modelValue' | 'defaultValue' | 'min' | 'max' | 'step' | 'disabled' | 'required' | 'id' | 'name' | 'formatOptions'> {
17
+ /**
18
+ * The element or component this component should render as.
19
+ * @defaultValue 'div'
20
+ */
21
+ as?: any
22
+ /** The placeholder text when the input is empty. */
23
+ placeholder?: string
24
+ color?: InputNumberVariants['color']
25
+ size?: InputNumberVariants['size']
26
+ /** Removes padding from input. */
27
+ noPadding?: boolean
28
+ /** removes all borders (rings). */
29
+ noBorder?: boolean
30
+ /** removes all borders (rings) except the bottom one. */
31
+ underline?: boolean
32
+ /** Rounds the corners of the button. */
33
+ rounded?: boolean
34
+ tag?: string
35
+ tagColor?: InputNumberVariants['tagColor']
36
+ /** Highlight the ring color like a focus state. */
37
+ highlight?: boolean
38
+ class?: any
39
+ b24ui?: Partial<typeof inputNumber.slots>
40
+ /**
41
+ * The orientation of the input menu.
42
+ * @defaultValue 'horizontal'
43
+ */
44
+ orientation?: 'vertical' | 'horizontal'
45
+ /**
46
+ * Configure the increment button. The `size` is inherited.
47
+ * @defaultValue { color: 'link', depth: 'light' }
48
+ */
49
+ increment?: ButtonProps
50
+ /**
51
+ * The icon displayed to increment the value.
52
+ * @defaultValue icons.plus = Plus30Icon
53
+ */
54
+ incrementIcon?: IconComponent
55
+ /**
56
+ * Configure the decrement button. The `size` is inherited.
57
+ * @defaultValue { color: 'link', depth: 'light' }
58
+ */
59
+ decrement?: ButtonProps
60
+ /**
61
+ * The icon displayed to decrement the value.
62
+ * @defaultValue icons.minus = Minus30Icon
63
+ */
64
+ decrementIcon?: IconComponent
65
+ autofocus?: boolean
66
+ autofocusDelay?: number
67
+ /**
68
+ * The locale to use for formatting and parsing numbers.
69
+ * @defaultValue B24App.locale.code
70
+ */
71
+ locale?: string
72
+ }
73
+
74
+ export interface InputNumberEmits {
75
+ (e: 'update:modelValue', payload: number): void
76
+ (e: 'blur', event: FocusEvent): void
77
+ (e: 'change', payload: Event): void
78
+ }
79
+
80
+ export interface InputNumberSlots {
81
+ increment(props?: {}): any
82
+ decrement(props?: {}): any
83
+ }
84
+ </script>
85
+
86
+ <script setup lang="ts">
87
+ import { onMounted, ref, computed } from 'vue'
88
+ import { NumberFieldRoot, NumberFieldInput, NumberFieldDecrement, NumberFieldIncrement, useForwardPropsEmits } from 'reka-ui'
89
+ import { reactivePick } from '@vueuse/core'
90
+ import { useFormField } from '../composables/useFormField'
91
+ import { useLocale } from '../composables/useLocale'
92
+ import icons from '../dictionary/icons'
93
+ import B24Button from './Button.vue'
94
+
95
+ defineOptions({ inheritAttrs: false })
96
+
97
+ const props = withDefaults(defineProps<InputNumberProps>(), {
98
+ orientation: 'horizontal',
99
+ color: 'primary',
100
+ size: 'md'
101
+ })
102
+ const emits = defineEmits<InputNumberEmits>()
103
+ defineSlots<InputNumberSlots>()
104
+
105
+ const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'min', 'max', 'step', 'formatOptions'), emits)
106
+
107
+ const { emitFormBlur, emitFormFocus, emitFormChange, emitFormInput, id, color, size, name, highlight, disabled, ariaAttrs } = useFormField<InputNumberProps>(props)
108
+
109
+ const { t, code: codeLocale } = useLocale()
110
+ const locale = computed(() => props.locale || codeLocale.value)
111
+
112
+ const isTag = computed(() => {
113
+ return props.tag
114
+ })
115
+
116
+ const b24ui = computed(() => inputNumber({
117
+ color: color.value,
118
+ size: size.value,
119
+ tagColor: props.tagColor,
120
+ highlight: highlight.value,
121
+ rounded: Boolean(props.rounded),
122
+ noPadding: Boolean(props.noPadding),
123
+ noBorder: Boolean(props.noBorder),
124
+ underline: Boolean(props.underline),
125
+ orientation: props.orientation
126
+ }))
127
+
128
+ const incrementIcon = computed(() => props.incrementIcon || (props.orientation === 'horizontal' ? icons.plus : icons.chevronUp))
129
+ const decrementIcon = computed(() => props.decrementIcon || (props.orientation === 'horizontal' ? icons.minus : icons.chevronDown))
130
+
131
+ const inputRef = ref<InstanceType<typeof NumberFieldInput> | null>(null)
132
+
133
+ function autoFocus() {
134
+ if (props.autofocus) {
135
+ inputRef.value?.$el?.focus()
136
+ }
137
+ }
138
+
139
+ onMounted(() => {
140
+ setTimeout(() => {
141
+ autoFocus()
142
+ }, props.autofocusDelay)
143
+ })
144
+
145
+ function onUpdate(value: number) {
146
+ // @ts-expect-error - 'target' does not exist in type 'EventInit'
147
+ const event = new Event('change', { target: { value } })
148
+ emits('change', event)
149
+
150
+ emitFormChange()
151
+ emitFormInput()
152
+ }
153
+
154
+ function onBlur(event: FocusEvent) {
155
+ emitFormBlur()
156
+ emits('blur', event)
157
+ }
158
+
159
+ defineExpose({
160
+ inputRef
161
+ })
162
+ </script>
163
+
164
+ <template>
165
+ <NumberFieldRoot
166
+ v-bind="rootProps"
167
+ :id="id"
168
+ :class="b24ui.root({ class: [props.class, props.b24ui?.root] })"
169
+ :name="name"
170
+ :disabled="disabled"
171
+ :locale="locale"
172
+ @update:model-value="onUpdate"
173
+ >
174
+ <div v-if="isTag" :class="b24ui.tag({ class: props.b24ui?.tag })">
175
+ {{ props.tag }}
176
+ </div>
177
+
178
+ <NumberFieldInput
179
+ v-bind="{ ...$attrs, ...ariaAttrs }"
180
+ ref="inputRef"
181
+ :placeholder="placeholder"
182
+ :required="required"
183
+ :class="b24ui.base({ class: props.b24ui?.base })"
184
+ @blur="onBlur"
185
+ @focus="emitFormFocus"
186
+ />
187
+
188
+ <div :class="b24ui.increment({ class: props.b24ui?.increment })">
189
+ <NumberFieldIncrement as-child :disabled="disabled">
190
+ <slot name="increment">
191
+ <B24Button
192
+ :icon="incrementIcon"
193
+ :size="size"
194
+ color="link"
195
+ depth="light"
196
+ :aria-label="t('inputNumber.increment')"
197
+ v-bind="typeof increment === 'object' ? increment : undefined"
198
+ />
199
+ </slot>
200
+ </NumberFieldIncrement>
201
+ </div>
202
+
203
+ <div :class="b24ui.decrement({ class: props.b24ui?.decrement })">
204
+ <NumberFieldDecrement as-child :disabled="disabled">
205
+ <slot name="decrement">
206
+ <B24Button
207
+ :icon="decrementIcon"
208
+ :size="size"
209
+ color="link"
210
+ depth="light"
211
+ :aria-label="t('inputNumber.decrement')"
212
+ v-bind="typeof decrement === 'object' ? decrement : undefined"
213
+ />
214
+ </slot>
215
+ </NumberFieldDecrement>
216
+ </div>
217
+ </NumberFieldRoot>
218
+ </template>
@@ -0,0 +1,179 @@
1
+ <script lang="ts">
2
+ import type { DialogRootProps, DialogRootEmits, DialogContentProps } from 'reka-ui'
3
+ import type { AppConfig } from '@nuxt/schema'
4
+ import _appConfig from '#build/app.config'
5
+ import theme from '#build/b24ui/modal'
6
+ import { tv } from '../utils/tv'
7
+ import type { ButtonProps, IconComponent } from '../types'
8
+
9
+ const appConfigModal = _appConfig as AppConfig & { b24ui: { modal: Partial<typeof theme> } }
10
+
11
+ const modal = tv({ extend: tv(theme), ...(appConfigModal.b24ui?.modal || {}) })
12
+
13
+ export interface ModalProps extends DialogRootProps {
14
+ title?: string
15
+ description?: string
16
+ /** The content of the modal. */
17
+ content?: Omit<DialogContentProps, 'as' | 'asChild' | 'forceMount'>
18
+ /**
19
+ * Render an overlay behind the modal.
20
+ * @defaultValue true
21
+ */
22
+ overlay?: boolean
23
+ /**
24
+ * Animate the modal when opening or closing.
25
+ * @defaultValue true
26
+ */
27
+ transition?: boolean
28
+ /**
29
+ * When `true`, the modal will take up the full screen.
30
+ * @defaultValue false
31
+ */
32
+ fullscreen?: boolean
33
+ /**
34
+ * Render the modal in a portal.
35
+ * @defaultValue true
36
+ */
37
+ portal?: boolean
38
+ /**
39
+ * Display a close button to dismiss the modal.
40
+ * `{ size: 'xs', color: 'link' }`{lang="ts-type"}
41
+ * @defaultValue true
42
+ */
43
+ close?: ButtonProps | boolean
44
+ /**
45
+ * The icon displayed in the close button.
46
+ * @defaultValue icons.close
47
+ */
48
+ closeIcon?: IconComponent
49
+ /**
50
+ * When `false`, the modal will not close when clicking outside or pressing escape.
51
+ * @defaultValue true
52
+ */
53
+ dismissible?: boolean
54
+ class?: any
55
+ b24ui?: Partial<typeof modal.slots>
56
+ }
57
+
58
+ export interface ModalEmits extends DialogRootEmits {}
59
+
60
+ export interface ModalSlots {
61
+ default(props: { open: boolean }): any
62
+ content(props?: {}): any
63
+ header(props?: {}): any
64
+ title(props?: {}): any
65
+ description(props?: {}): any
66
+ close(props: { b24ui: any }): any
67
+ body(props?: {}): any
68
+ footer(props?: {}): any
69
+ }
70
+ </script>
71
+
72
+ <script setup lang="ts">
73
+ import { computed, toRef } from 'vue'
74
+ import { DialogRoot, DialogTrigger, DialogPortal, DialogOverlay, DialogContent, DialogTitle, DialogDescription, DialogClose, VisuallyHidden, useForwardPropsEmits } from 'reka-ui'
75
+ import { reactivePick } from '@vueuse/core'
76
+ import { useLocale } from '../composables/useLocale'
77
+ import icons from '../dictionary/icons'
78
+ import B24Button from './Button.vue'
79
+
80
+ const props = withDefaults(defineProps<ModalProps>(), {
81
+ close: true,
82
+ portal: true,
83
+ overlay: true,
84
+ transition: true,
85
+ modal: true,
86
+ dismissible: true
87
+ })
88
+ const emits = defineEmits<ModalEmits>()
89
+ const slots = defineSlots<ModalSlots>()
90
+
91
+ const { t } = useLocale()
92
+
93
+ const rootProps = useForwardPropsEmits(reactivePick(props, 'open', 'defaultOpen', 'modal'), emits)
94
+ const contentProps = toRef(() => props.content)
95
+ const contentEvents = computed(() => {
96
+ if (!props.dismissible) {
97
+ return {
98
+ pointerDownOutside: (e: Event) => e.preventDefault(),
99
+ interactOutside: (e: Event) => e.preventDefault(),
100
+ escapeKeyDown: (e: Event) => e.preventDefault()
101
+ }
102
+ }
103
+
104
+ return {}
105
+ })
106
+
107
+ const b24ui = computed(() => modal({
108
+ transition: props.transition,
109
+ fullscreen: props.fullscreen
110
+ }))
111
+ </script>
112
+
113
+ <template>
114
+ <DialogRoot v-slot="{ open }" v-bind="rootProps">
115
+ <DialogTrigger v-if="!!slots.default" as-child :class="props.class">
116
+ <slot :open="open" />
117
+ </DialogTrigger>
118
+
119
+ <DialogPortal :disabled="!portal">
120
+ <DialogOverlay v-if="overlay" :class="b24ui.overlay({ class: props.b24ui?.overlay })" />
121
+
122
+ <DialogContent :class="b24ui.content({ class: [!slots.default && props.class, props.b24ui?.content] })" v-bind="contentProps" v-on="contentEvents">
123
+ <VisuallyHidden v-if="!!slots.content && ((title || !!slots.title) || (description || !!slots.description))">
124
+ <DialogTitle v-if="title || !!slots.title">
125
+ <slot name="title">
126
+ {{ title }}
127
+ </slot>
128
+ </DialogTitle>
129
+
130
+ <DialogDescription v-if="description || !!slots.description">
131
+ <slot name="description">
132
+ {{ description }}
133
+ </slot>
134
+ </DialogDescription>
135
+ </VisuallyHidden>
136
+
137
+ <slot name="content">
138
+ <div v-if="!!slots.header || (title || !!slots.title) || (description || !!slots.description) || (close || !!slots.close)" :class="b24ui.header({ class: props.b24ui?.header })">
139
+ <slot name="header">
140
+ <DialogTitle v-if="title || !!slots.title" :class="b24ui.title({ class: props.b24ui?.title })">
141
+ <slot name="title">
142
+ {{ title }}
143
+ </slot>
144
+ </DialogTitle>
145
+
146
+ <DialogDescription v-if="description || !!slots.description" :class="b24ui.description({ class: props.b24ui?.description })">
147
+ <slot name="description">
148
+ {{ description }}
149
+ </slot>
150
+ </DialogDescription>
151
+
152
+ <DialogClose as-child>
153
+ <slot name="close" :b24ui="b24ui">
154
+ <B24Button
155
+ v-if="close"
156
+ :icon="closeIcon || icons.close"
157
+ size="xs"
158
+ color="link"
159
+ :aria-label="t('modal.close')"
160
+ v-bind="typeof close === 'object' ? close : undefined"
161
+ :class="b24ui.close({ class: props.b24ui?.close })"
162
+ />
163
+ </slot>
164
+ </DialogClose>
165
+ </slot>
166
+ </div>
167
+
168
+ <div v-if="!!slots.body" :class="b24ui.body({ class: props.b24ui?.body })">
169
+ <slot name="body" />
170
+ </div>
171
+
172
+ <div v-if="!!slots.footer" :class="b24ui.footer({ class: props.b24ui?.footer })">
173
+ <slot name="footer" />
174
+ </div>
175
+ </slot>
176
+ </DialogContent>
177
+ </DialogPortal>
178
+ </DialogRoot>
179
+ </template>
@@ -0,0 +1,17 @@
1
+ <script lang="ts">
2
+ export interface ModalDialogCloseSlots {
3
+ default(props: {}): any
4
+ }
5
+ </script>
6
+
7
+ <script setup lang="ts">
8
+ import { DialogClose } from 'reka-ui'
9
+
10
+ defineSlots<ModalDialogCloseSlots>()
11
+ </script>
12
+
13
+ <template>
14
+ <DialogClose as-child>
15
+ <slot />
16
+ </DialogClose>
17
+ </template>
@@ -0,0 +1,12 @@
1
+ <script setup lang="ts">
2
+ import { inject } from 'vue'
3
+ import { useModal, modalInjectionKey } from '../composables/useModal'
4
+
5
+ const modalState = inject(modalInjectionKey)
6
+
7
+ const { isOpen } = useModal()
8
+ </script>
9
+
10
+ <template>
11
+ <component :is="modalState.component" v-if="modalState" v-bind="modalState.props" v-model:open="isOpen" />
12
+ </template>
@@ -0,0 +1,17 @@
1
+ import type { ShallowRef, Component, InjectionKey } from 'vue';
2
+ import type { ComponentProps } from 'vue-component-type-helpers';
3
+ import type { ModalProps } from '../types';
4
+ export interface ModalState {
5
+ component: Component | string;
6
+ props: ModalProps;
7
+ }
8
+ export declare const modalInjectionKey: InjectionKey<ShallowRef<ModalState>>;
9
+ declare function _useModal(): {
10
+ open: <T extends Component>(component: T, props?: ModalProps & ComponentProps<T>) => void;
11
+ close: () => Promise<void>;
12
+ reset: () => void;
13
+ patch: <T extends Component = Record<string, never>>(props: Partial<ModalProps & ComponentProps<T>>) => void;
14
+ isOpen: import("vue").Ref<boolean, boolean>;
15
+ };
16
+ export declare const useModal: typeof _useModal;
17
+ export {};
@@ -0,0 +1,46 @@
1
+ import { ref, inject } from "vue";
2
+ import { createSharedComposable } from "@vueuse/core";
3
+ export const modalInjectionKey = Symbol("bitrix24-ui.modal");
4
+ function _useModal() {
5
+ const modalState = inject(modalInjectionKey);
6
+ const isOpen = ref(false);
7
+ function open(component, props) {
8
+ if (!modalState) {
9
+ throw new Error("useModal() is called without provider");
10
+ }
11
+ modalState.value = {
12
+ component,
13
+ props: props ?? {}
14
+ };
15
+ isOpen.value = true;
16
+ }
17
+ async function close() {
18
+ if (!modalState) return;
19
+ isOpen.value = false;
20
+ }
21
+ function reset() {
22
+ if (!modalState) return;
23
+ modalState.value = {
24
+ component: "div",
25
+ props: {}
26
+ };
27
+ }
28
+ function patch(props) {
29
+ if (!modalState) return;
30
+ modalState.value = {
31
+ ...modalState.value,
32
+ props: {
33
+ ...modalState.value.props,
34
+ ...props
35
+ }
36
+ };
37
+ }
38
+ return {
39
+ open,
40
+ close,
41
+ reset,
42
+ patch,
43
+ isOpen
44
+ };
45
+ }
46
+ export const useModal = createSharedComposable(_useModal);
@@ -0,0 +1,2 @@
1
+ declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
2
+ export default _default;
@@ -0,0 +1,10 @@
1
+ import { shallowRef } from "vue";
2
+ import { defineNuxtPlugin } from "#imports";
3
+ import { modalInjectionKey } from "../composables/useModal.js";
4
+ export default defineNuxtPlugin((nuxtApp) => {
5
+ const modalState = shallowRef({
6
+ component: "div",
7
+ props: {}
8
+ });
9
+ nuxtApp.vueApp.provide(modalInjectionKey, modalState);
10
+ });
@@ -15,8 +15,11 @@ export * from '../components/Form.vue';
15
15
  export * from '../components/FormField.vue';
16
16
  export * from '../components/Input.vue';
17
17
  export * from '../components/InputMenu.vue';
18
+ export * from '../components/InputNumber.vue';
18
19
  export * from '../components/Kbd.vue';
19
20
  export * from '../components/Link.vue';
21
+ export * from '../components/Modal.vue';
22
+ export * from '../components/ModalDialogClose.vue';
20
23
  export * from '../components/Progress.vue';
21
24
  export * from '../components/RadioGroup.vue';
22
25
  export * from '../components/Range.vue';
@@ -15,8 +15,11 @@ export * from "../components/Form.vue";
15
15
  export * from "../components/FormField.vue";
16
16
  export * from "../components/Input.vue";
17
17
  export * from "../components/InputMenu.vue";
18
+ export * from "../components/InputNumber.vue";
18
19
  export * from "../components/Kbd.vue";
19
20
  export * from "../components/Link.vue";
21
+ export * from "../components/Modal.vue";
22
+ export * from "../components/ModalDialogClose.vue";
20
23
  export * from "../components/Progress.vue";
21
24
  export * from "../components/RadioGroup.vue";
22
25
  export * from "../components/Range.vue";