@bitrix24/b24ui-nuxt 0.2.3 → 0.2.5

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/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.Ce3hzs_q.cjs');
5
+ const templates = require('./shared/b24ui-nuxt.BfbMerCZ.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.3",
8
+ "version": "0.2.5",
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.DY8ePXC7.mjs';
3
+ import { d as defaultOptions, a as getDefaultUiConfig, b as addTemplates } from './shared/b24ui-nuxt.BYTVBEky.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",
@@ -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>
@@ -155,6 +155,7 @@ import {
155
155
  ComboboxSeparator,
156
156
  ComboboxItem,
157
157
  ComboboxItemIndicator,
158
+ FocusScope,
158
159
  useForwardPropsEmits,
159
160
  useFilter,
160
161
  Primitive
@@ -286,7 +287,7 @@ function onUpdate(value: any) {
286
287
  }
287
288
 
288
289
  function onUpdateOpen(value: boolean) {
289
- let timeoutId
290
+ let timeoutId: ReturnType<typeof setTimeout> | undefined
290
291
 
291
292
  if (!value) {
292
293
  const event = new FocusEvent('blur')
@@ -307,7 +308,9 @@ function onUpdateOpen(value: boolean) {
307
308
  const event = new FocusEvent('focus')
308
309
  emits('focus', event)
309
310
  emitFormFocus()
310
- clearTimeout(timeoutId)
311
+ if (timeoutId) {
312
+ clearTimeout(timeoutId)
313
+ }
311
314
  }
312
315
  }
313
316
  </script>
@@ -387,76 +390,77 @@ function onUpdateOpen(value: boolean) {
387
390
 
388
391
  <ComboboxPortal :disabled="!portal">
389
392
  <ComboboxContent :class="b24ui.content({ class: props.b24ui?.content })" v-bind="contentProps">
390
- <ComboboxInput v-if="!!searchInput" v-model="searchTerm" :display-value="() => searchTerm" as-child>
391
- <B24Input no-border autofocus autocomplete="off" v-bind="searchInputProps" :class="b24ui.input({ class: props.b24ui?.input })" />
392
- </ComboboxInput>
393
-
394
- <ComboboxEmpty :class="b24ui.empty({ class: props.b24ui?.empty })">
395
- <slot name="empty" :search-term="searchTerm">
396
- {{ searchTerm ? t('selectMenu.noMatch', { searchTerm }) : t('selectMenu.noData') }}
397
- </slot>
398
- </ComboboxEmpty>
399
-
400
- <ComboboxViewport :class="b24ui.viewport({ class: props.b24ui?.viewport })">
401
- <ReuseCreateItemTemplate v-if="createItem && createItemPosition === 'top'" />
402
-
403
- <ComboboxGroup v-for="(group, groupIndex) in filteredGroups" :key="`group-${groupIndex}`" :class="b24ui.group({ class: props.b24ui?.group })">
404
- <template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
405
- <ComboboxLabel v-if="item?.type === 'label'" :class="b24ui.label({ class: props.b24ui?.label })">
406
- {{ get(item, props.labelKey as string) }}
407
- </ComboboxLabel>
408
-
409
- <ComboboxSeparator v-else-if="item?.type === 'separator'" :class="b24ui.separator({ class: props.b24ui?.separator })" />
410
-
411
- <ComboboxItem
412
- v-else
413
- :class="b24ui.item({ class: props.b24ui?.item })"
414
- :disabled="item.disabled"
415
- :value="valueKey && typeof item === 'object' ? get(item, props.valueKey as string) : item"
416
- @select="item.onSelect"
417
- >
418
- <slot name="item" :item="(item as T)" :index="index">
419
- <slot name="item-leading" :item="(item as T)" :index="index">
420
- <Component
421
- :is="item.icon"
422
- v-if="item.icon"
423
- :class="b24ui.itemLeadingIcon({ class: props.b24ui?.itemLeadingIcon })"
424
- />
425
- <B24Avatar v-else-if="item.avatar" :size="((props.b24ui?.itemLeadingAvatarSize || b24ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="b24ui.itemLeadingAvatar({ class: props.b24ui?.itemLeadingAvatar })" />
426
- <B24Chip
427
- v-else-if="item.chip"
428
- :size="((props.b24ui?.itemLeadingChipSize || b24ui.itemLeadingChipSize()) as ChipProps['size'])"
429
- inset
430
- standalone
431
- v-bind="item.chip"
432
- :class="b24ui.itemLeadingChip({ class: props.b24ui?.itemLeadingChip })"
433
- />
434
- </slot>
435
-
436
- <span :class="b24ui.itemLabel({ class: props.b24ui?.itemLabel })">
437
- <slot name="item-label" :item="(item as T)" :index="index">
438
- {{ typeof item === 'object' ? get(item, props.labelKey as string) : item }}
439
- </slot>
440
- </span>
441
-
442
- <span :class="b24ui.itemTrailing({ class: props.b24ui?.itemTrailing })">
443
- <slot name="item-trailing" :item="(item as T)" :index="index" />
444
-
445
- <ComboboxItemIndicator as-child>
393
+ <FocusScope trapped :class="b24ui.focusScope({ class: props.b24ui?.focusScope })">
394
+ <ComboboxInput v-if="!!searchInput" v-model="searchTerm" :display-value="() => searchTerm" as-child>
395
+ <B24Input no-border autofocus autocomplete="off" v-bind="searchInputProps" :class="b24ui.input({ class: props.b24ui?.input })" />
396
+ </ComboboxInput>
397
+
398
+ <ComboboxEmpty :class="b24ui.empty({ class: props.b24ui?.empty })">
399
+ <slot name="empty" :search-term="searchTerm">
400
+ {{ searchTerm ? t('selectMenu.noMatch', { searchTerm }) : t('selectMenu.noData') }}
401
+ </slot>
402
+ </ComboboxEmpty>
403
+
404
+ <ComboboxViewport :class="b24ui.viewport({ class: props.b24ui?.viewport })">
405
+ <ReuseCreateItemTemplate v-if="createItem && createItemPosition === 'top'" />
406
+
407
+ <ComboboxGroup v-for="(group, groupIndex) in filteredGroups" :key="`group-${groupIndex}`" :class="b24ui.group({ class: props.b24ui?.group })">
408
+ <template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
409
+ <ComboboxLabel v-if="item?.type === 'label'" :class="b24ui.label({ class: props.b24ui?.label })">
410
+ {{ get(item, props.labelKey as string) }}
411
+ </ComboboxLabel>
412
+
413
+ <ComboboxSeparator v-else-if="item?.type === 'separator'" :class="b24ui.separator({ class: props.b24ui?.separator })" />
414
+
415
+ <ComboboxItem
416
+ v-else
417
+ :class="b24ui.item({ class: props.b24ui?.item })"
418
+ :disabled="item.disabled"
419
+ :value="valueKey && typeof item === 'object' ? get(item, props.valueKey as string) : item"
420
+ @select="item.onSelect"
421
+ >
422
+ <slot name="item" :item="(item as T)" :index="index">
423
+ <slot name="item-leading" :item="(item as T)" :index="index">
446
424
  <Component
447
- :is="selectedIcon || icons.check"
448
- :class="b24ui.itemTrailingIcon({ class: props.b24ui?.itemTrailingIcon })"
425
+ :is="item.icon"
426
+ v-if="item.icon"
427
+ :class="b24ui.itemLeadingIcon({ class: props.b24ui?.itemLeadingIcon })"
428
+ />
429
+ <B24Avatar v-else-if="item.avatar" :size="((props.b24ui?.itemLeadingAvatarSize || b24ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="b24ui.itemLeadingAvatar({ class: props.b24ui?.itemLeadingAvatar })" />
430
+ <B24Chip
431
+ v-else-if="item.chip"
432
+ :size="((props.b24ui?.itemLeadingChipSize || b24ui.itemLeadingChipSize()) as ChipProps['size'])"
433
+ inset
434
+ standalone
435
+ v-bind="item.chip"
436
+ :class="b24ui.itemLeadingChip({ class: props.b24ui?.itemLeadingChip })"
449
437
  />
450
- </ComboboxItemIndicator>
451
- </span>
452
- </slot>
453
- </ComboboxItem>
454
- </template>
455
- </ComboboxGroup>
438
+ </slot>
456
439
 
457
- <ReuseCreateItemTemplate v-if="createItem && createItemPosition === 'bottom'" />
458
- </ComboboxViewport>
440
+ <span :class="b24ui.itemLabel({ class: props.b24ui?.itemLabel })">
441
+ <slot name="item-label" :item="(item as T)" :index="index">
442
+ {{ typeof item === 'object' ? get(item, props.labelKey as string) : item }}
443
+ </slot>
444
+ </span>
445
+
446
+ <span :class="b24ui.itemTrailing({ class: props.b24ui?.itemTrailing })">
447
+ <slot name="item-trailing" :item="(item as T)" :index="index" />
448
+
449
+ <ComboboxItemIndicator as-child>
450
+ <Component
451
+ :is="selectedIcon || icons.check"
452
+ :class="b24ui.itemTrailingIcon({ class: props.b24ui?.itemTrailingIcon })"
453
+ />
454
+ </ComboboxItemIndicator>
455
+ </span>
456
+ </slot>
457
+ </ComboboxItem>
458
+ </template>
459
+ </ComboboxGroup>
459
460
 
461
+ <ReuseCreateItemTemplate v-if="createItem && createItemPosition === 'bottom'" />
462
+ </ComboboxViewport>
463
+ </FocusScope>
460
464
  <ComboboxArrow v-if="!!arrow" v-bind="arrowProps" :class="b24ui.arrow({ class: props.b24ui?.arrow })" />
461
465
  </ComboboxContent>
462
466
  </ComboboxPortal>
@@ -15,6 +15,6 @@ export interface UseComponentIconsProps {
15
15
  export declare function useComponentIcons(componentProps: MaybeRefOrGetter<UseComponentIconsProps>): {
16
16
  isLeading: import("vue").ComputedRef<any>;
17
17
  isTrailing: import("vue").ComputedRef<boolean>;
18
- leadingIconName: import("vue").ComputedRef<import("vue").FunctionalComponent<import("vue").HTMLAttributes & import("vue").VNodeProps, {}, any, {}> | undefined>;
19
- trailingIconName: import("vue").ComputedRef<import("vue").FunctionalComponent<import("vue").HTMLAttributes & import("vue").VNodeProps, {}, any, {}> | undefined>;
18
+ leadingIconName: import("vue").ComputedRef<IconComponent | undefined>;
19
+ trailingIconName: import("vue").ComputedRef<IconComponent | undefined>;
20
20
  };
@@ -15,6 +15,7 @@ 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';
20
21
  export * from '../components/Modal.vue';
@@ -15,6 +15,7 @@ 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";
20
21
  export * from "../components/Modal.vue";