@bitrix24/b24ui-nuxt 0.5.7 → 0.5.9

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.BsnG7poi.cjs');
5
+ const templates = require('./shared/b24ui-nuxt.BVg3rkkG.cjs');
6
6
  require('node:url');
7
7
  require('scule');
8
8
 
package/dist/module.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "nuxt": ">=3.16.0"
6
6
  },
7
7
  "docs": "https://bitrix24.github.io/b24ui/guide/installation-nuxt-app.html",
8
- "version": "0.5.7",
8
+ "version": "0.5.9",
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.CMCKw62O.mjs';
3
+ import { d as defaultOptions, a as getDefaultUiConfig, b as addTemplates } from './shared/b24ui-nuxt.C1lGF53R.mjs';
4
4
  import 'node:url';
5
5
  import 'scule';
6
6
 
@@ -38,6 +38,7 @@ import { computed } from 'vue'
38
38
  import { DropdownMenu } from 'reka-ui/namespaced'
39
39
  import { useForwardPropsEmits } from 'reka-ui'
40
40
  import { reactiveOmit, createReusableTemplate } from '@vueuse/core'
41
+ import { useLocale } from '../composables/useLocale'
41
42
  import { omit, get, isArrayOfArray } from '../utils'
42
43
  import { pickLinkProps } from '../utils/link'
43
44
  import icons from '../dictionary/icons'
@@ -52,11 +53,13 @@ const props = defineProps<DropdownMenuContentProps<T>>()
52
53
  const emits = defineEmits<DropdownMenuContentEmits>()
53
54
  const slots = defineSlots<DropdownMenuContentSlots<T>>()
54
55
 
56
+ const { dir } = useLocale()
55
57
  const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'labelKey', 'checkedIcon', 'externalIcon', 'class', 'b24ui', 'b24uiOverride'), emits)
56
58
  const proxySlots = omit(slots, ['default'])
57
59
 
58
60
  const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate<{ item: DropdownMenuItem, active?: boolean, index: number }>()
59
61
 
62
+ const childrenIcon = computed(() => dir.value === 'rtl' ? icons.chevronLeft : icons.chevronRight)
60
63
  const groups = computed<DropdownMenuItem[][]>(() =>
61
64
  props.items?.length
62
65
  ? isArrayOfArray(props.items)
@@ -102,7 +105,7 @@ const groups = computed<DropdownMenuItem[][]>(() =>
102
105
  <span :class="b24ui.itemTrailing({ class: b24uiOverride?.itemTrailing })">
103
106
  <slot :name="((item.slot ? `${item.slot}-trailing`: 'item-trailing') as keyof DropdownMenuContentSlots<T>)" :item="(item as Extract<NestedItem<T>, { slot: string; }>)" :active="active" :index="index">
104
107
  <Component
105
- :is="icons.chevronRight"
108
+ :is="childrenIcon"
106
109
  v-if="item.children?.length"
107
110
  :class="b24ui.itemTrailingIcon({ class: b24uiOverride?.itemTrailingIcon, color: item?.color, active })"
108
111
  />
@@ -147,7 +150,6 @@ const groups = computed<DropdownMenuItem[][]>(() =>
147
150
  :b24ui-override="b24uiOverride"
148
151
  :portal="portal"
149
152
  :items="(item.children as T)"
150
- side="right"
151
153
  align="start"
152
154
  :align-offset="-4"
153
155
  :side-offset="3"
@@ -155,12 +155,6 @@ const b24ui = computed(() => input({
155
155
 
156
156
  const inputRef = ref<HTMLInputElement | null>(null)
157
157
 
158
- function autoFocus() {
159
- if (props.autofocus) {
160
- inputRef.value?.focus()
161
- }
162
- }
163
-
164
158
  // Custom function to handle the v-model properties
165
159
  function updateInput(value: string | null) {
166
160
  if (modelModifiers.trim) {
@@ -206,15 +200,21 @@ function onBlur(event: FocusEvent) {
206
200
  emits('blur', event)
207
201
  }
208
202
 
209
- defineExpose({
210
- inputRef
211
- })
203
+ function autoFocus() {
204
+ if (props.autofocus) {
205
+ inputRef.value?.focus()
206
+ }
207
+ }
212
208
 
213
209
  onMounted(() => {
214
210
  setTimeout(() => {
215
211
  autoFocus()
216
212
  }, props.autofocusDelay)
217
213
  })
214
+
215
+ defineExpose({
216
+ inputRef
217
+ })
218
218
  </script>
219
219
 
220
220
  <template>
@@ -397,6 +397,7 @@ function onRemoveTag(event: any) {
397
397
  const modelValue = props.modelValue as GetModelValue<T, VK, true>
398
398
  const filteredValue = modelValue.filter(value => !isEqual(value, event))
399
399
  emits('update:modelValue', filteredValue as GetModelValue<T, VK, M>)
400
+ onUpdate(filteredValue)
400
401
  }
401
402
  }
402
403
 
@@ -547,7 +548,7 @@ defineExpose({
547
548
  :class="b24ui.item({ class: props.b24ui?.item, colorItem: isInputItem(item) ? item?.color : undefined })"
548
549
  :disabled="isInputItem(item) && item.disabled"
549
550
  :value="props.valueKey && isInputItem(item) ? get(item, String(props.valueKey)) : item"
550
- @select="isInputItem(item) && item.onSelect"
551
+ @select="isInputItem(item) && item.onSelect?.($event)"
551
552
  >
552
553
  <slot name="item" :item="(item as NestedItem<T>)" :index="index">
553
554
  <slot name="item-leading" :item="(item as NestedItem<T>)" :index="index">
@@ -14,7 +14,7 @@ const inputNumber = tv({ extend: tv(theme), ...(appConfigInputNumber.b24ui?.inpu
14
14
 
15
15
  type InputNumberVariants = VariantProps<typeof inputNumber>
16
16
 
17
- export interface InputNumberProps extends Pick<NumberFieldRootProps, 'modelValue' | 'defaultValue' | 'min' | 'max' | 'step' | 'disabled' | 'required' | 'id' | 'name' | 'formatOptions'> {
17
+ export interface InputNumberProps extends Pick<NumberFieldRootProps, 'modelValue' | 'defaultValue' | 'min' | 'max' | 'stepSnapping' | 'step' | 'disabled' | 'required' | 'id' | 'name' | 'formatOptions' | 'disableWheelChange'> {
18
18
  /**
19
19
  * The element or component this component should render as.
20
20
  * @defaultValue 'div'
@@ -137,7 +137,7 @@ const props = withDefaults(defineProps<InputNumberProps>(), {
137
137
  const emits = defineEmits<InputNumberEmits>()
138
138
  defineSlots<InputNumberSlots>()
139
139
 
140
- const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'min', 'max', 'step', 'formatOptions'), emits)
140
+ const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'min', 'max', 'step', 'stepSnapping', 'formatOptions', 'disableWheelChange'), emits)
141
141
 
142
142
  const { emitFormBlur, emitFormFocus, emitFormChange, emitFormInput, id, color, size, name, highlight, disabled, ariaAttrs } = useFormField<InputNumberProps>(props)
143
143
 
@@ -165,18 +165,6 @@ const decrementIcon = computed(() => props.decrementIcon || (props.orientation =
165
165
 
166
166
  const inputRef = ref<InstanceType<typeof NumberFieldInput> | null>(null)
167
167
 
168
- function autoFocus() {
169
- if (props.autofocus) {
170
- inputRef.value?.$el?.focus()
171
- }
172
- }
173
-
174
- onMounted(() => {
175
- setTimeout(() => {
176
- autoFocus()
177
- }, props.autofocusDelay)
178
- })
179
-
180
168
  function onUpdate(value: number) {
181
169
  // @ts-expect-error - 'target' does not exist in type 'EventInit'
182
170
  const event = new Event('change', { target: { value } })
@@ -191,6 +179,18 @@ function onBlur(event: FocusEvent) {
191
179
  emits('blur', event)
192
180
  }
193
181
 
182
+ function autoFocus() {
183
+ if (props.autofocus) {
184
+ inputRef.value?.$el?.focus()
185
+ }
186
+ }
187
+
188
+ onMounted(() => {
189
+ setTimeout(() => {
190
+ autoFocus()
191
+ }, props.autofocusDelay)
192
+ })
193
+
194
194
  defineExpose({
195
195
  inputRef
196
196
  })
@@ -49,6 +49,10 @@ export interface RadioGroupProps<T extends RadioGroupItem = RadioGroupItem> exte
49
49
  * @defaultValue 'md'
50
50
  */
51
51
  size?: RadioGroupVariants['size']
52
+ /**
53
+ * @defaultValue 'list'
54
+ */
55
+ variant?: RadioGroupVariants['variant']
52
56
  /**
53
57
  * @defaultValue 'primary'
54
58
  */
@@ -58,6 +62,11 @@ export interface RadioGroupProps<T extends RadioGroupItem = RadioGroupItem> exte
58
62
  * @defaultValue 'vertical'
59
63
  */
60
64
  orientation?: RadioGroupRootProps['orientation']
65
+ /**
66
+ * Position of the indicator.
67
+ * @defaultValue 'start'
68
+ */
69
+ indicator?: RadioGroupVariants['indicator']
61
70
  class?: any
62
71
  b24ui?: Partial<typeof radioGroup.slots>
63
72
  }
@@ -101,7 +110,9 @@ const b24ui = computed(() => radioGroup({
101
110
  color: color.value,
102
111
  disabled: disabled.value,
103
112
  required: props.required,
104
- orientation: props.orientation
113
+ orientation: props.orientation,
114
+ variant: props.variant,
115
+ indicator: props.indicator
105
116
  }))
106
117
 
107
118
  function normalizeItem(item: any) {
@@ -167,7 +178,7 @@ function onUpdate(value: any) {
167
178
  {{ legend }}
168
179
  </slot>
169
180
  </legend>
170
- <div v-for="item in normalizedItems" :key="item.value" :class="b24ui.item({ class: props.b24ui?.item })">
181
+ <component :is="variant === 'list' ? 'div' : Label" v-for="item in normalizedItems" :key="item.value" :class="b24ui.item({ class: props.b24ui?.item })">
171
182
  <div :class="b24ui.container({ class: props.b24ui?.container })">
172
183
  <RadioGroupItem
173
184
  :id="item.id"
@@ -180,18 +191,18 @@ function onUpdate(value: any) {
180
191
  </div>
181
192
 
182
193
  <div :class="b24ui.wrapper({ class: props.b24ui?.wrapper })">
183
- <Label :class="b24ui.label({ class: props.b24ui?.label })" :for="item.id">
194
+ <component :is="variant === 'list' ? Label : 'p'" :class="b24ui.label({ class: props.b24ui?.label })" :for="item.id">
184
195
  <slot name="label" :item="item" :model-value="(modelValue as RadioGroupValue)">
185
196
  {{ item.label }}
186
197
  </slot>
187
- </Label>
198
+ </component>
188
199
  <p v-if="item.description || !!slots.description" :class="b24ui.description({ class: props.b24ui?.description })">
189
200
  <slot name="description" :item="item" :model-value="(modelValue as RadioGroupValue)">
190
201
  {{ item.description }}
191
202
  </slot>
192
203
  </p>
193
204
  </div>
194
- </div>
205
+ </component>
195
206
  </fieldset>
196
207
  </RadioGroupRoot>
197
208
  </template>
@@ -495,7 +495,7 @@ function isSelectItem(item: SelectMenuItem): item is _SelectMenuItem {
495
495
  :class="b24ui.item({ class: props.b24ui?.item, colorItem: isSelectItem(item) ? item?.color : undefined })"
496
496
  :disabled="isSelectItem(item) && item.disabled"
497
497
  :value="props.valueKey && isSelectItem(item) ? get(item, props.valueKey as string) : item"
498
- @select="isSelectItem(item) && item.onSelect"
498
+ @select="isSelectItem(item) && item.onSelect?.($event)"
499
499
  >
500
500
  <slot name="item" :item="(item as NestedItem<T>)" :index="index">
501
501
  <slot name="item-leading" :item="(item as NestedItem<T>)" :index="index">
@@ -3,7 +3,9 @@ import type { VariantProps } from 'tailwind-variants'
3
3
  import type { AppConfig } from '@nuxt/schema'
4
4
  import _appConfig from '#build/app.config'
5
5
  import theme from '#build/b24ui/textarea'
6
+ import type { UseComponentIconsProps } from '../composables/useComponentIcons'
6
7
  import { tv } from '../utils/tv'
8
+ import type { AvatarProps } from '../types'
7
9
  import type { PartialString } from '../types/utils'
8
10
 
9
11
  const appConfigTextarea = _appConfig as AppConfig & { b24ui: { textarea: Partial<typeof theme> } }
@@ -12,7 +14,7 @@ const textarea = tv({ extend: tv(theme), ...(appConfigTextarea.b24ui?.textarea |
12
14
 
13
15
  type TextareaVariants = VariantProps<typeof textarea>
14
16
 
15
- export interface TextareaProps {
17
+ export interface TextareaProps extends UseComponentIconsProps {
16
18
  /**
17
19
  * The element or component this component should render as.
18
20
  * @defaultValue 'div'
@@ -60,6 +62,14 @@ export interface TextareaProps {
60
62
  * @defaultValue 0
61
63
  */
62
64
  autofocusDelay?: number
65
+ /**
66
+ * @defaultValue false
67
+ */
68
+ autoresize?: boolean
69
+ /**
70
+ * @defaultValue 0
71
+ */
72
+ autoresizeDelay?: number
63
73
  /**
64
74
  * @defaultValue false
65
75
  */
@@ -72,10 +82,6 @@ export interface TextareaProps {
72
82
  * @defaultValue 5
73
83
  */
74
84
  maxrows?: number
75
- /**
76
- * @defaultValue false
77
- */
78
- autoresize?: boolean
79
85
  tag?: string
80
86
  /**
81
87
  * @defaultValue 'primary'
@@ -97,29 +103,35 @@ export interface TextareaEmits {
97
103
  }
98
104
 
99
105
  export interface TextareaSlots {
106
+ leading(props?: {}): any
100
107
  default(props?: {}): any
108
+ trailing(props?: {}): any
101
109
  }
102
110
  </script>
103
111
 
104
112
  <script setup lang="ts">
105
113
  import { ref, computed, onMounted, nextTick, watch } from 'vue'
106
114
  import { Primitive } from 'reka-ui'
115
+ import { useComponentIcons } from '../composables/useComponentIcons'
107
116
  import { useFormField } from '../composables/useFormField'
108
117
  import { looseToNumber } from '../utils'
118
+ import B24Avatar from './Avatar.vue'
109
119
 
110
120
  defineOptions({ inheritAttrs: false })
111
121
 
112
122
  const props = withDefaults(defineProps<TextareaProps>(), {
113
123
  rows: 3,
114
124
  maxrows: 5,
115
- autofocusDelay: 0
125
+ autofocusDelay: 0,
126
+ autoresizeDelay: 0
116
127
  })
117
- defineSlots<TextareaSlots>()
128
+ const slots = defineSlots<TextareaSlots>()
118
129
  const emits = defineEmits<TextareaEmits>()
119
130
 
120
131
  const [modelValue, modelModifiers] = defineModel<string | number | null>()
121
132
 
122
133
  const { emitFormFocus, emitFormBlur, emitFormInput, emitFormChange, color, id, name, highlight, disabled, ariaAttrs } = useFormField<TextareaProps>(props, { deferInputValidation: true })
134
+ const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(props)
123
135
 
124
136
  const isTag = computed(() => {
125
137
  return props.tag
@@ -127,22 +139,20 @@ const isTag = computed(() => {
127
139
 
128
140
  const b24ui = computed(() => textarea({
129
141
  color: color.value,
142
+ loading: props.loading,
130
143
  highlight: highlight.value,
144
+ autoresize: Boolean(props.autoresize),
131
145
  tagColor: props.tagColor,
132
146
  rounded: Boolean(props.rounded),
133
147
  noPadding: Boolean(props.noPadding),
134
148
  noBorder: Boolean(props.noBorder),
135
- underline: Boolean(props.underline)
149
+ underline: Boolean(props.underline),
150
+ leading: Boolean(isLeading.value || !!props.avatar || !!slots.leading),
151
+ trailing: Boolean(isTrailing.value || !!slots.trailing)
136
152
  }))
137
153
 
138
154
  const textareaRef = ref<HTMLTextAreaElement | null>(null)
139
155
 
140
- function autoFocus() {
141
- if (props.autofocus) {
142
- textareaRef.value?.focus()
143
- }
144
- }
145
-
146
156
  // Custom function to handle the v-model properties
147
157
  function updateInput(value: string | null) {
148
158
  if (modelModifiers.trim) {
@@ -190,18 +200,14 @@ function onBlur(event: FocusEvent) {
190
200
  emits('blur', event)
191
201
  }
192
202
 
193
- onMounted(() => {
194
- setTimeout(() => {
195
- autoFocus()
196
- }, props.autofocusDelay)
197
- })
203
+ function autoFocus() {
204
+ if (props.autofocus) {
205
+ textareaRef.value?.focus()
206
+ }
207
+ }
198
208
 
199
209
  function autoResize() {
200
- if (props.autoresize) {
201
- if (!textareaRef.value) {
202
- return
203
- }
204
-
210
+ if (props.autoresize && textareaRef.value) {
205
211
  textareaRef.value.rows = props.rows
206
212
  const overflow = textareaRef.value.style.overflow
207
213
  textareaRef.value.style.overflow = 'hidden'
@@ -226,14 +232,18 @@ watch(modelValue, () => {
226
232
  nextTick(autoResize)
227
233
  })
228
234
 
229
- defineExpose({
230
- textareaRef
231
- })
232
-
233
235
  onMounted(() => {
236
+ setTimeout(() => {
237
+ autoFocus()
238
+ }, props.autofocusDelay)
239
+
234
240
  setTimeout(() => {
235
241
  autoResize()
236
- }, 100)
242
+ }, props.autoresizeDelay)
243
+ })
244
+
245
+ defineExpose({
246
+ textareaRef
237
247
  })
238
248
  </script>
239
249
 
@@ -261,5 +271,31 @@ onMounted(() => {
261
271
  />
262
272
 
263
273
  <slot />
274
+
275
+ <span v-if="isLeading || !!avatar || !!slots.leading" :class="b24ui.leading({ class: props.b24ui?.leading })">
276
+ <slot name="leading">
277
+ <Component
278
+ :is="leadingIconName"
279
+ v-if="isLeading && leadingIconName"
280
+ :class="b24ui.leadingIcon({ class: props.b24ui?.leadingIcon })"
281
+ />
282
+ <B24Avatar
283
+ v-else-if="!!avatar"
284
+ :size="((props.b24ui?.leadingAvatarSize || b24ui.leadingAvatarSize()) as AvatarProps['size'])"
285
+ v-bind="avatar"
286
+ :class="b24ui.leadingAvatar({ class: props.b24ui?.leadingAvatar })"
287
+ />
288
+ </slot>
289
+ </span>
290
+
291
+ <span v-if="isTrailing || !!slots.trailing" :class="b24ui.trailing({ class: props.b24ui?.trailing })">
292
+ <slot name="trailing">
293
+ <Component
294
+ :is="trailingIconName"
295
+ v-if="trailingIconName"
296
+ :class="b24ui.trailingIcon({ class: props.b24ui?.trailingIcon })"
297
+ />
298
+ </slot>
299
+ </span>
264
300
  </Primitive>
265
301
  </template>
@@ -22,6 +22,6 @@ export interface UseComponentIconsProps {
22
22
  export declare function useComponentIcons(componentProps: MaybeRefOrGetter<UseComponentIconsProps>): {
23
23
  isLeading: import("vue").ComputedRef<any>;
24
24
  isTrailing: import("vue").ComputedRef<boolean>;
25
- leadingIconName: import("vue").ComputedRef<IconComponent | undefined>;
26
- trailingIconName: import("vue").ComputedRef<IconComponent | undefined>;
25
+ leadingIconName: import("vue").ComputedRef<import("vue").FunctionalComponent<import("vue").HTMLAttributes & import("vue").VNodeProps, {}, any, {}> | undefined>;
26
+ trailingIconName: import("vue").ComputedRef<import("vue").FunctionalComponent<import("vue").HTMLAttributes & import("vue").VNodeProps, {}, any, {}> | undefined>;
27
27
  };
@@ -9,10 +9,10 @@ export { useConfetti } from '../composables/useConfetti';
9
9
  export { useOverlay } from '../composables/useOverlay';
10
10
  export declare const useColorMode: () => {
11
11
  forced: boolean;
12
- preference?: "dark" | "light" | "system";
12
+ preference?: "light" | "dark" | "system";
13
13
  readonly value?: import("@vueuse/core").BasicColorMode;
14
14
  } | {
15
- preference: "dark" | "light" | "system";
15
+ preference: "light" | "dark" | "system";
16
16
  readonly value: import("@vueuse/core").BasicColorMode;
17
17
  forced: boolean;
18
18
  };