@meistrari/tela-build 1.29.3 → 1.30.1

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.
@@ -41,8 +41,8 @@ const variantStyle = computed(() => (({
41
41
  'secondary': fold`
42
42
  bg-white text-gray-900 border border-0.5px
43
43
  [box-shadow:0_1px_6px_0_rgba(103,127,148,0.05)]
44
- hover:bg-gray-50 hover:border-gray-300
45
- active:bg-gray-100 active:border-gray-400/60
44
+ hover:bg-subtle hover:border-gray-300
45
+ active:bg-muted active:border-gray-400/60
46
46
  focus-visible:ring-0.5px focus-visible:ring-cyan-600
47
47
  `,
48
48
  'ghost': fold`
@@ -21,7 +21,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
21
21
  <template>
22
22
  <ComboboxItem
23
23
  v-bind="forwarded"
24
- :class="cn('relative flex cursor-pointer gap-2 select-none justify-between items-center rounded-lg px-2 py-1.5 text-sm font-medium outline-none data-[highlighted]:bg-gray-100 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0', props.class)"
24
+ :class="cn('relative flex cursor-pointer gap-2 select-none justify-between items-center rounded-lg px-2 py-1.5 text-sm font-medium outline-none data-[highlighted]:bg-muted data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0', props.class)"
25
25
  >
26
26
  <slot />
27
27
  </ComboboxItem>
@@ -41,7 +41,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
41
41
  <ComboboxPortal v-else>
42
42
  <ComboboxContent
43
43
  v-bind="forwarded"
44
- :class="cn('ComboboxContent z-50 shadow-lg outline-none rounded-xl bg-white-1000 border-[0.5px] border-gray-200 pointer-events-auto', props.class)"
44
+ :class="cn('ComboboxContent z-[9999] shadow-lg outline-none rounded-xl bg-white-1000 border-[0.5px] border-gray-200 pointer-events-auto', props.class)"
45
45
  >
46
46
  <ComboboxViewport>
47
47
  <slot />
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { ref, computed } from 'vue'
3
- import type { Component, Ref } from 'vue'
3
+ import type { Component, ComponentPublicInstance, Ref } from 'vue'
4
4
  import { useMagicKeys } from '@vueuse/core'
5
5
 
6
6
  import ComboboxRoot from './combobox-root.vue'
@@ -29,6 +29,8 @@ interface ComboboxOption {
29
29
  isMultiModal?: boolean
30
30
  features?: Array<{ text: string }>
31
31
  cost?: number
32
+ children?: ComboboxOption[]
33
+ triggerLabel?: string
32
34
  }
33
35
 
34
36
  type ComboboxOptions = ComboboxOption[]
@@ -111,9 +113,21 @@ const currentOption = computed(() => {
111
113
  return { label: props.placeholder, value: '' }
112
114
  }
113
115
 
114
- const found = props.options.find(option => option.value === innerValue.value || option.value === props.modelValue)
116
+ const rawInner = innerValue.value
117
+ const value = (rawInner && typeof rawInner === 'object' ? (rawInner as any).value : rawInner) || props.modelValue
118
+ const found = props.options.find(option => option.value === value)
119
+ if (found)
120
+ return found
121
+
122
+ for (const option of props.options) {
123
+ if (option.children) {
124
+ const child = option.children.find(c => c.value === value)
125
+ if (child)
126
+ return child
127
+ }
128
+ }
115
129
 
116
- return found ?? props.options[0] ?? { label: props.placeholder || props.labelSelect, value: '' }
130
+ return props.options[0] ?? { label: props.placeholder || props.labelSelect, value: '' }
117
131
  })
118
132
 
119
133
  const tabs = computed(() => {
@@ -219,23 +233,89 @@ function renderCostIndicator(cost: number | undefined) {
219
233
  return { blackSymbols, graySymbols }
220
234
  }
221
235
 
236
+ const expandedItem = ref<string | null>(null)
237
+ const submenuStyle = ref<Record<string, string>>({})
238
+ const nestedItemRefs = ref<Record<string, HTMLElement>>({})
239
+
240
+ function setNestedItemRef(value: string, el: Element | ComponentPublicInstance | null) {
241
+ if (!el)
242
+ return
243
+ const htmlEl = '$el' in el ? el.$el as HTMLElement : el as HTMLElement
244
+ nestedItemRefs.value[value] = htmlEl
245
+ }
246
+
247
+ function updateSubmenuPosition(itemValue: string) {
248
+ const el = nestedItemRefs.value[itemValue]
249
+ if (!el)
250
+ return
251
+
252
+ const rect = el.getBoundingClientRect()
253
+ const item = props.options.find(o => o.value === itemValue)
254
+ const childCount = item?.children?.length ?? 0
255
+ const estimatedHeight = childCount * 52 + 8
256
+ const viewportHeight = window.innerHeight
257
+ let top = rect.top
258
+ if (top + estimatedHeight > viewportHeight - 8) {
259
+ top = Math.max(8, viewportHeight - estimatedHeight - 8)
260
+ }
261
+ submenuStyle.value = {
262
+ position: 'fixed',
263
+ left: `${rect.right + 2}px`,
264
+ top: `${top}px`,
265
+ zIndex: '9999',
266
+ }
267
+ }
268
+
222
269
  function onOpenChange(open: boolean) {
223
270
  isOpen.value = open
271
+ if (!open) {
272
+ expandedItem.value = null
273
+ }
274
+ }
275
+
276
+ function handleItemMouseEnter(item: ComboboxOption) {
277
+ if (item.children?.length) {
278
+ expandedItem.value = item.value
279
+ updateSubmenuPosition(item.value)
280
+ }
281
+ else {
282
+ expandedItem.value = null
283
+ }
284
+ }
285
+
286
+ function handleChildSelect(child: ComboboxOption, event: Event) {
287
+ event.preventDefault()
288
+ event.stopPropagation()
289
+ expandedItem.value = null
290
+ isOpen.value = false
291
+ emit('select', child.value)
292
+ emit('update:modelValue', child.value)
224
293
  }
225
294
 
226
295
  function handleSelect(option: any) {
227
- emit('select', option.value)
228
- emit('update:modelValue', option.value)
296
+ const value = typeof option === 'string' ? option : option?.value
297
+ const found = props.options.find(o => o.value === value)
298
+ if (found?.children?.length)
299
+ return
300
+ emit('select', value)
301
+ emit('update:modelValue', value)
229
302
  }
230
303
 
231
- watch(innerValue, (value) => {
304
+ watch(innerValue, (raw) => {
305
+ if (!raw)
306
+ return
307
+
308
+ const value = typeof raw === 'string' ? raw : (raw as any)?.value
232
309
  if (!value)
233
310
  return
234
311
 
235
- const option = props.options.find(option => option.value === value)
312
+ const option = props.options.find(o => o.value === value)
236
313
  if (!option)
237
314
  return
238
315
 
316
+ if (option.children?.length)
317
+ return
318
+
239
319
  innerValue.value = ''
240
320
 
241
321
  emit('select', value)
@@ -253,7 +333,8 @@ watch(innerValue, (value) => {
253
333
  as="button"
254
334
  tabindex="0"
255
335
  :class="cn(
256
- 'group select-none flex items-center justify-between gap-3 rounded-10px px-8px py-7px bg-white border-[0.5px] border-gray-300 transition hover:bg-gray-100 data-[state=open]:bg-gray-100',
336
+ 'group select-none flex items-center justify-between gap-3 rounded-10px px-8px py-7px bg-white border-0.5px border transition hover:border-strong hover:bg-subtle data-[state=open]:border-strong data-[state=open]:bg-subtle',
337
+ '[box-shadow:0_1px_6px_0_rgba(103,127,148,0.05)]',
257
338
  !compact && 'w-full !py-2.5 pl-3 pr-3',
258
339
  props.triggerClass,
259
340
  )"
@@ -273,16 +354,16 @@ watch(innerValue, (value) => {
273
354
  </div>
274
355
  </div>
275
356
  <span
276
- :class="cn('truncate max-w-120px text-gray-900 group-data-[state=open]:text-gray-500',
357
+ :class="cn('truncate text-primary group-data-[state=open]:text-secondary',
277
358
  compact ? 'text-sm font-580' : 'text-body-14-regular', props.labelClass)"
278
359
  >
279
- {{ currentOption?.label }}
360
+ {{ currentOption?.triggerLabel || currentOption?.label }}
280
361
  </span>
281
362
  </div>
282
- <TelaIcon name="i-ph-caret-down" :class="cn('op-60 transition-all ease-out duration-150', isOpen && 'rotate-180')" size="12px" />
363
+ <TelaIcon name="i-ph-caret-down-bold" color="icon-secondary" :class="cn('transition-all ease-out duration-150', isOpen && 'rotate-180')" size="15px" />
283
364
  </ComboboxTrigger>
284
365
  </ComboboxAnchor>
285
- <ComboboxList :class="cn('z-999', compact ? 'w-440px' : 'w-327px!', props.contentClass)" :disable-portal="props.disablePortal" align="start">
366
+ <ComboboxList :class="cn('z-999', compact ? 'w-440px' : 'w-327px', props.contentClass)" :disable-portal="props.disablePortal" align="start">
286
367
  <div v-if="hasSearchbar" class="relative">
287
368
  <span class="absolute inset-y-0 start-0 flex items-center justify-center px-2.5">
288
369
  <TelaIcon name="i-ph-magnifying-glass" :size="compact ? '12px' : '14px'" class="text-gray-400" />
@@ -440,65 +521,113 @@ watch(innerValue, (value) => {
440
521
  <ComboboxLabel v-if="!search.trim() && hasGroupingLabels">
441
522
  {{ group.heading }}
442
523
  </ComboboxLabel>
443
- <ComboboxItem v-for="item in group.children" :key="item.value" :value="item" :class="cn('group py-2', !compact && '!px-1.5')">
444
- <div class="flex items-center">
445
- <div :class="cn('flex items-center w-250px', compact ? 'gap-2' : 'gap-1.5')">
446
- <div v-if="item.icon" class="w-5 h-5 shrink-0 flex items-center justify-center">
447
- <TelaIcon
448
- v-if="typeof item.icon === 'string'" :name="item.icon" :color="colorIcon" :size="iconWithBackground?.size"
449
- :background-class="iconWithBackground?.backgroundClass"
450
- />
451
- <Component
452
- :is="item.icon"
453
- v-else
454
- :class="cn((item?.label.startsWith('DeepSeek') || item?.label.startsWith('Gemini')) && 'scale-75')"
455
- />
456
- </div>
457
- <div v-if="!item.icon && item?.externalIconSrc">
458
- <img :src="item.externalIconSrc" :alt="item.label" class="w-5 h-5">
524
+ <template v-for="item in group.children" :key="item.value">
525
+ <ComboboxItem
526
+ :ref="(el) => item.children?.length && setNestedItemRef(item.value, el)"
527
+ :value="item"
528
+ :class="cn('group/item py-2', !compact && '!px-1.5')"
529
+ @mouseenter="handleItemMouseEnter(item)"
530
+ @select="(e) => item.children?.length && e.preventDefault()"
531
+ >
532
+ <div class="flex items-center">
533
+ <div :class="cn('flex items-center w-250px', compact ? 'gap-2' : 'gap-1.5')">
534
+ <div v-if="item.icon" class="w-5 h-5 shrink-0 flex items-center justify-center">
535
+ <TelaIcon
536
+ v-if="typeof item.icon === 'string'" :name="item.icon" :color="colorIcon" :size="iconWithBackground?.size"
537
+ :background-class="iconWithBackground?.backgroundClass"
538
+ />
539
+ <Component
540
+ :is="item.icon"
541
+ v-else
542
+ :class="cn((item?.label.startsWith('DeepSeek') || item?.label.startsWith('Gemini')) && 'scale-75')"
543
+ />
544
+ </div>
545
+ <div v-if="!item.icon && item?.externalIconSrc">
546
+ <img :src="item.externalIconSrc" :alt="item.label" class="w-5 h-5">
547
+ </div>
548
+ <div class="flex flex-col">
549
+ <div class="flex items-center gap-1">
550
+ <span :class="cn('font-medium truncate max-w-140px', compact ? 'text-sm font-580' : 'text-body-14-regular', labelItemClass)">{{ item.label }}</span>
551
+ <TelaBadge v-if="item.isMultiModal" variant="filled" class="py-[2px] bg-gray-100" text-class="leading-none">
552
+ {{ labelMultimodal }}
553
+ </TelaBadge>
554
+ <span v-if="item.cost !== undefined" class="text-10px font-580 ml-1px">
555
+ <span class="text-black-900">{{ renderCostIndicator(item.cost)?.blackSymbols }}</span>
556
+ <span class="text-gray-300">{{ renderCostIndicator(item.cost)?.graySymbols }}</span>
557
+ </span>
558
+ </div>
559
+ <span v-if="item.description" :class="cn('font-normal text-sm leading-none text-gray-500', descriptionClass)">
560
+ {{ item.description }}
561
+ </span>
562
+ <slot name="tags" :option="item" />
563
+ </div>
459
564
  </div>
460
- <div class="flex flex-col">
461
- <div class="flex items-center gap-1">
462
- <span :class="cn('font-medium truncate max-w-140px', compact ? 'text-sm font-580' : 'text-body-14-regular', labelItemClass)">{{ item.label }}</span>
463
- <TelaBadge v-if="item.isMultiModal" variant="filled" class="py-[2px] bg-gray-100" text-class="leading-none">
464
- {{ labelMultimodal }}
465
- </TelaBadge>
466
- <span v-if="item.cost !== undefined" class="text-10px font-580 ml-1px">
467
- <span class="text-black-900">{{ renderCostIndicator(item.cost)?.blackSymbols }}</span>
468
- <span class="text-gray-300">{{ renderCostIndicator(item.cost)?.graySymbols }}</span>
565
+ <div v-if="item.maxInputTokens || item.maxOutputTokens" class="flex gap-3">
566
+ <div class="flex flex-col gap-1.5">
567
+ <span class="text-gray-400 leading-none text-9px uppercase tracking-wider font-semibold">
568
+ {{ labelInputMax }}
569
+ </span>
570
+ <span class="text-gray-400 leading-none text-11px uppercase font-semibold group-data-[highlighted]:text-gray-700">
571
+ {{ handleFormatNumber(item.maxInputTokens) }}
572
+ </span>
573
+ </div>
574
+ <div class="flex flex-col gap-1.5">
575
+ <span class="text-gray-400 leading-none text-9px uppercase tracking-wider font-semibold">
576
+ {{ labelOutputMax }}
577
+ </span>
578
+ <span class="text-gray-400 leading-none text-11px uppercase font-semibold group-data-[highlighted]:text-gray-700">
579
+ {{ handleFormatNumber(item.maxOutputTokens) }}
469
580
  </span>
470
581
  </div>
471
- <span v-if="item.description" :class="cn('font-normal text-sm leading-none text-gray-500', descriptionClass)">
472
- {{ item.description }}
473
- </span>
474
- <slot name="tags" :option="item" />
475
582
  </div>
476
583
  </div>
477
- <div v-if="item.maxInputTokens || item.maxOutputTokens" class="flex gap-3">
478
- <div class="flex flex-col gap-1.5">
479
- <span class="text-gray-400 leading-none text-9px uppercase tracking-wider font-semibold">
480
- {{ labelInputMax }}
481
- </span>
482
- <span class="text-gray-400 leading-none text-11px uppercase font-semibold group-data-[highlighted]:text-gray-700">
483
- {{ handleFormatNumber(item.maxInputTokens) }}
484
- </span>
485
- </div>
486
- <div class="flex flex-col gap-1.5">
487
- <span class="text-gray-400 leading-none text-9px uppercase tracking-wider font-semibold">
488
- {{ labelOutputMax }}
489
- </span>
490
- <span class="text-gray-400 leading-none text-11px uppercase font-semibold group-data-[highlighted]:text-gray-700">
491
- {{ handleFormatNumber(item.maxOutputTokens) }}
492
- </span>
584
+ <div class="flex gap-2 items-center">
585
+ <TelaIcon v-if="item.children?.length" name="i-ph-caret-right" size="14px" class="text-gray-400" />
586
+ <ComboboxItemIndicator v-else>
587
+ <TelaIcon name="i-ph-check" size="14px" />
588
+ </ComboboxItemIndicator>
589
+ </div>
590
+ </ComboboxItem>
591
+ <!-- Nested submenu -->
592
+ <Teleport v-if="item.children?.length" to="body">
593
+ <div
594
+ v-if="expandedItem === item.value"
595
+ :style="submenuStyle"
596
+ class="min-w-200px bg-white border border-strong rounded-12px shadow-[0_10px_15px_-3px_rgba(0,0,0,0.1),0_4px_6px_-4px_rgba(0,0,0,0.1)] pointer-events-auto"
597
+ @mouseenter="expandedItem = item.value"
598
+ @pointerdown.stop
599
+ >
600
+ <div p-4px>
601
+ <div
602
+ v-for="child in item.children"
603
+ :key="child.value"
604
+ :class="cn(
605
+ 'relative flex cursor-pointer select-none justify-between items-center rounded-lg px-2 py-2 text-sm font-medium text-gray-900 outline-none hover:bg-gray-100',
606
+ !compact && '!px-1.5',
607
+ )"
608
+ @click.stop="handleChildSelect(child, $event)"
609
+ >
610
+ <div :class="cn('flex items-center', compact ? 'gap-2' : 'gap-1.5')">
611
+ <div v-if="child.icon" class="w-5 h-5 shrink-0 flex items-center justify-center">
612
+ <TelaIcon
613
+ v-if="typeof child.icon === 'string'" :name="child.icon" :color="colorIcon" :size="iconWithBackground?.size"
614
+ :background-class="iconWithBackground?.backgroundClass"
615
+ />
616
+ <Component :is="child.icon" v-else />
617
+ </div>
618
+ <div class="flex flex-col">
619
+ <span :class="cn('font-medium truncate max-w-140px', compact ? 'text-sm font-580' : 'text-body-14-regular', labelItemClass)">{{ child.label }}</span>
620
+ <span v-if="child.description" :class="cn('font-normal text-sm leading-none text-gray-500', descriptionClass)">
621
+ {{ child.description }}
622
+ </span>
623
+ </div>
624
+ </div>
625
+ <TelaIcon v-if="child.value === (modelValue || innerValue)" name="i-ph-check" size="14px" />
626
+ </div>
493
627
  </div>
494
628
  </div>
495
- </div>
496
- <div class="flex gap-2 items-center">
497
- <ComboboxItemIndicator>
498
- <TelaIcon name="i-ph-check" size="14px" />
499
- </ComboboxItemIndicator>
500
- </div>
501
- </ComboboxItem>
629
+ </Teleport>
630
+ </template>
502
631
  </ComboboxGroup>
503
632
  </template>
504
633
  </div>
@@ -521,3 +650,16 @@ watch(innerValue, (value) => {
521
650
  }
522
651
  }
523
652
  </style>
653
+
654
+ <style>
655
+ @keyframes combobox-submenuFadeIn {
656
+ from {
657
+ opacity: 0;
658
+ transform: translateX(-4px);
659
+ }
660
+ to {
661
+ opacity: 1;
662
+ transform: translateX(0);
663
+ }
664
+ }
665
+ </style>
@@ -31,11 +31,13 @@ const props = withDefaults(defineProps<{
31
31
  isCloseIconAbsolute?: boolean
32
32
  smallTitle?: boolean
33
33
  titleClass?: string
34
+ hideEnterAnimation?: boolean
34
35
  }>(), {
35
36
  modalWidth: 'md',
36
37
  isCloseIcon: true,
37
38
  isCloseIconAbsolute: false,
38
39
  smallTitle: false,
40
+ hideEnterAnimation: false,
39
41
  })
40
42
  const emit = defineEmits<{
41
43
  close: []
@@ -85,6 +87,7 @@ function handlePointerDownOutside(event: any) {
85
87
  <DialogPortal>
86
88
  <DialogOverlay :class="`DialogOverlay ${overlayClass ?? ''}`" bg="#000/35" z-600 overflow-y-auto flex items-center justify-center :p-16px="!fullscreen">
87
89
  <DialogContent
90
+ :data-animation="hideEnterAnimation"
88
91
  :class="cn('DialogContent shadow-xl', modalMaxWidth, dialogContentClass)"
89
92
  z-101
90
93
  rounded-16px
@@ -199,12 +202,12 @@ function handlePointerDownOutside(event: any) {
199
202
  width: 400px;
200
203
  padding: 24px;
201
204
 
202
- &[data-state="open"] {
205
+ [data-animation="false"]&[data-state="open"] {
203
206
  animation: contentShow 0.12s ease-out forwards;
204
207
  overflow: visible;
205
208
  }
206
209
 
207
- &[data-state="closed"] {
210
+ [data-animation="false"]&[data-state="closed"] {
208
211
  animation: contentHide 0.12s ease-out forwards;
209
212
  animation-delay: 0s;
210
213
  }
@@ -930,8 +930,8 @@ watch([() => props.highlightText, () => props.highlightPage, () => props.highlig
930
930
  v-for="pageNum in 2" :key="pageNum"
931
931
  relative bg-white rounded-12px overflow-hidden mx-auto
932
932
  :class="cn({
933
- 'w-446px min-h-631px': variant === 'default',
934
- 'w-256px min-h-363px': variant === 'minimal',
933
+ 'w-full max-w-446px min-h-631px': variant === 'default',
934
+ 'w-full max-w-256px min-h-363px': variant === 'minimal',
935
935
  })"
936
936
  >
937
937
  <!-- Page badge -->
@@ -970,7 +970,7 @@ watch([() => props.highlightText, () => props.highlightPage, () => props.highlig
970
970
  <div
971
971
  v-else
972
972
  :class="cn({
973
- 'px-46px': variant === 'default',
973
+ 'px-36px': variant === 'default',
974
974
  'px-32px': variant === 'minimal',
975
975
  })"
976
976
  >
@@ -978,8 +978,8 @@ watch([() => props.highlightText, () => props.highlightPage, () => props.highlig
978
978
  bg-white rounded-12px
979
979
  flex="~ col" justify-between mx-auto relative
980
980
  :class="cn({
981
- 'w-446px min-h-631px px-32px py-28px': variant === 'default',
982
- 'w-256px min-h-363px px-16px py-14px': variant === 'minimal',
981
+ 'w-full max-w-446px min-h-631px px-32px py-28px': variant === 'default',
982
+ 'w-full max-w-256px min-h-363px px-16px py-14px': variant === 'minimal',
983
983
  })"
984
984
  >
985
985
  <div flex="~ col" gap-16px>
@@ -1041,7 +1041,7 @@ watch([() => props.highlightText, () => props.highlightPage, () => props.highlig
1041
1041
  data-markdown
1042
1042
  :data-variant="variant"
1043
1043
  :class="cn({
1044
- 'px-46px': variant === 'default',
1044
+ 'px-36px': variant === 'default',
1045
1045
  'px-32px': variant === 'minimal',
1046
1046
  'pt-88px': variant === 'default' && props.segmentTab && props.file.fileType === 'application/pdf',
1047
1047
  'pt-42px': variant === 'minimal' && props.segmentTab && props.file.fileType === 'application/pdf',
@@ -1058,8 +1058,8 @@ watch([() => props.highlightText, () => props.highlightPage, () => props.highlig
1058
1058
  <div
1059
1059
  bg-white rounded-12px
1060
1060
  :class="cn({
1061
- 'w-446px min-h-631px px-32px py-28px': variant === 'default',
1062
- 'w-256px min-h-363px px-16px py-14px': variant === 'minimal',
1061
+ 'w-full max-w-446px min-h-631px px-32px py-28px': variant === 'default',
1062
+ 'w-full max-w-256px min-h-363px px-16px py-14px': variant === 'minimal',
1063
1063
  'h-full overflow-y-auto no-scrollbar': variant === 'default' && props.segmentTab !== 'processed',
1064
1064
  })"
1065
1065
  mx-auto relative
@@ -1172,7 +1172,7 @@ watch([() => props.highlightText, () => props.highlightPage, () => props.highlig
1172
1172
  data-pdf-page-card
1173
1173
  :data-page-num="pageNum"
1174
1174
  relative bg-white rounded-12px overflow-hidden mx-auto
1175
- :class="cn(variant === 'minimal' && 'w-256px pdf-page-card--minimal')"
1175
+ :class="cn(variant === 'minimal' && 'w-full max-w-256px pdf-page-card--minimal')"
1176
1176
  :style="getPagePlaceholderStyle(pageNum)"
1177
1177
  >
1178
1178
  <canvas />
@@ -1229,7 +1229,7 @@ watch([() => props.highlightText, () => props.highlightPage, () => props.highlig
1229
1229
  <template v-else>
1230
1230
  <div
1231
1231
  :class="cn({
1232
- 'px-46px w-446px': variant === 'default',
1232
+ 'px-36px w-446px': variant === 'default',
1233
1233
  'w-256px': variant === 'minimal',
1234
1234
  })"
1235
1235
  flex items-center justify-center mx-auto
@@ -80,10 +80,6 @@ function handleDeleteSearchValue() {
80
80
  search.value = ''
81
81
  }
82
82
 
83
- const totalOptions = computed(() => {
84
- return groupedOptions.value.map(group => group.children.length).reduce((a, b) => a + b, 0)
85
- })
86
-
87
83
  const firstColumnWidth = computed(() => {
88
84
  const allVariableNames = [...new Set(props.options.map(opt => opt.variable))]
89
85
  const allTexts = [
@@ -155,7 +151,7 @@ function iconSrc(option: PreviewVariableOption): string {
155
151
  <TelaComboboxTrigger
156
152
  as="button"
157
153
  tabindex="0"
158
- class="w-full bg border-0.5px border-strong rounded-10px px-12px py-7px flex items-center justify-between"
154
+ class="w-full bg border-0.5px border-strong rounded-10px px-12px py-7px flex items-center justify-between gap-10px"
159
155
  >
160
156
  <div class="grid items-center gap-22px w-full min-w-0 grid-cols-[var(--first-col-width,minmax(82px,auto))_1fr]">
161
157
  <p body-14-semibold text-start text-primary min-w-0>
@@ -163,8 +159,9 @@ function iconSrc(option: PreviewVariableOption): string {
163
159
  </p>
164
160
  <div v-if="selectedOption?.file" flex items-center gap-6px min-w-0>
165
161
  <img :src="iconSrc(selectedOption)" class="h-16px! w-16px!" alt="">
166
- <p truncate body-14-medium text-primary flex-shrink-0>
167
- {{ selectedOption.file }}
162
+ <p flex min-w-0 body-14-medium text-primary>
163
+ <span truncate>{{ selectedOption.file.includes('.') ? `${selectedOption.file.replace(/\.[^.]+$/, '')}.` : selectedOption.file }}</span>
164
+ <span flex-shrink-0>{{ selectedOption.file.includes('.') ? (selectedOption.file.match(/[^.]+$/)?.[0] ?? '') : '' }}</span>
168
165
  </p>
169
166
  </div>
170
167
  </div>
@@ -178,7 +175,7 @@ function iconSrc(option: PreviewVariableOption): string {
178
175
  </div>
179
176
  </TelaComboboxTrigger>
180
177
  </TelaComboboxAnchor>
181
- <TelaComboboxList :class="cn('z-999 w-full', popoverClass)" :disable-portal="true" align="center">
178
+ <TelaComboboxList :class="cn('z-999 w-full max-w-[var(--reka-combobox-trigger-width)]', popoverClass)" :disable-portal="true" align="center">
182
179
  <div class="relative">
183
180
  <div class="absolute inset-y-0 flex items-center justify-center px-2.5">
184
181
  <TelaIcon name="i-ph-magnifying-glass-bold" size="13px" color="neutral-300" />
@@ -229,14 +226,6 @@ function iconSrc(option: PreviewVariableOption): string {
229
226
  {{ labels.clear }}
230
227
  </TelaButton>
231
228
  </TelaComboboxEmpty>
232
- <div v-if="totalOptions > 0" class="grid items-center gap-22px h-28px px-12px border-b-0.5px border grid-cols-[var(--first-col-width,minmax(82px,auto))_1fr]">
233
- <span body-12-medium text-secondary lowercase min-w-0>
234
- {{ labels.variablesLabel }}
235
- </span>
236
- <span body-12-medium text-secondary lowercase min-w-0>
237
- {{ totalOptions }} {{ labels.filesLabel }}
238
- </span>
239
- </div>
240
229
  <div class="divide-y-0.5px divide-border">
241
230
  <div v-for="group in groupedOptions" :key="group.heading" mx-12px>
242
231
  <TelaComboboxGroup
@@ -247,14 +236,17 @@ function iconSrc(option: PreviewVariableOption): string {
247
236
  v-for="(item, index) in group.children"
248
237
  :key="item.value"
249
238
  :value="item.value"
250
- class="grid items-center gap-22px grid-cols-[var(--first-col-width,minmax(82px,auto))_1fr] h-32px w-full"
239
+ class="grid items-center gap-22px grid-cols-[var(--first-col-width,minmax(82px,auto))_minmax(0,1fr)] h-32px w-full"
251
240
  >
252
241
  <span v-if="index === 0" body-14-semibold text-primary min-w-0>{{ group.heading }}</span>
253
242
  <span v-else />
254
- <div flex items-center justify-between w-full min-w-0>
255
- <div v-if="item.file" flex items-center gap-6px min-w-0>
243
+ <div flex items-center justify-between w-full min-w-0 overflow-hidden>
244
+ <div v-if="item.file" flex items-center gap-6px min-w-0 overflow-hidden pr-12px>
256
245
  <img :src="iconSrc(item)" class="h-16px! w-16px!" alt="">
257
- <span body-14-medium text-primary truncate>{{ item.file }}</span>
246
+ <p flex min-w-0 body-14-medium text-primary>
247
+ <span truncate>{{ item.file.includes('.') ? `${item.file.replace(/\.[^.]+$/, '')}.` : item.file }}</span>
248
+ <span flex-shrink-0>{{ item.file.includes('.') ? (item.file.match(/[^.]+$/)?.[0] ?? '') : '' }}</span>
249
+ </p>
258
250
  </div>
259
251
  <div v-if="props.modelValue === item.value" class="flex gap-2 items-center">
260
252
  <TelaComboboxItemIndicator>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/tela-build",
3
- "version": "1.29.3",
3
+ "version": "1.30.1",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "app.config.ts",