@meistrari/tela-build 1.20.0 → 1.22.0

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.
@@ -0,0 +1,62 @@
1
+ # TelaCard
2
+
3
+ A surface container component used to group related content with consistent visual boundaries.
4
+
5
+ ## Size Prop
6
+
7
+ Always use the `size` prop to control card padding — it maps directly to the standardized values. Never apply padding manually to `<TelaCard>` or its inner elements.
8
+
9
+ | `size` | Applied classes | Use for |
10
+ |--------|------------------|---------|
11
+ | `md` *(default)* | `p-32px sm:p-48px rounded-24px` | Standard and large cards |
12
+ | `sm` | `p-24px rounded-12px` | Small cards, inner containers |
13
+
14
+ ```vue
15
+ <!-- Correct — use size prop -->
16
+ <TelaCard size="md">...</TelaCard>
17
+ <TelaCard size="sm">...</TelaCard>
18
+ <TelaCard>...</TelaCard> <!-- md is the default -->
19
+
20
+ <!-- Incorrect — never apply padding manually -->
21
+ <TelaCard class="p-20px">...</TelaCard>
22
+ <TelaCard>
23
+ <div class="p-20px">...</div>
24
+ </TelaCard>
25
+ ```
26
+
27
+ ## Examples
28
+
29
+ ### Standard Card (default)
30
+
31
+ ```vue
32
+ <TelaCard>
33
+ <h2 class="heading-h4-semibold text-contrast">Title</h2>
34
+ <p class="body-14-regular text-secondary">Supporting description text.</p>
35
+ </TelaCard>
36
+ ```
37
+
38
+ ### Minor / Inner Card
39
+
40
+ ```vue
41
+ <TelaCard size="sm">
42
+ <span class="body-12-medium text-secondary">Compact content</span>
43
+ </TelaCard>
44
+ ```
45
+
46
+ ### Card Grid
47
+
48
+ ```vue
49
+ <div class="grid grid-cols-3 gap-4">
50
+ <TelaCard v-for="item in items" :key="item.id">...</TelaCard>
51
+ </div>
52
+ ```
53
+
54
+ ## Props
55
+
56
+ | Prop | Type | Default | Description |
57
+ |------|------|---------|-------------|
58
+ | `size` | `'sm' \| 'md'` | `'md'` | `md` = `p-32px sm:p-48px rounded-24px`, `sm` = `p-24px rounded-12px` |
59
+
60
+ ## Slots
61
+
62
+ - `default` — Card body content
@@ -0,0 +1,143 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import Card from './card.vue'
3
+
4
+ const meta: Meta<typeof Card> = {
5
+ title: 'Core/Card',
6
+ component: Card,
7
+ parameters: {
8
+ layout: 'centered',
9
+ docs: {
10
+ description: {
11
+ component: 'A surface container that groups related content with consistent visual boundaries. Use the `size` prop to control padding — `md` for standard cards, `sm` for minor or inner containers.',
12
+ },
13
+ },
14
+ },
15
+ argTypes: {
16
+ size: {
17
+ control: 'select',
18
+ options: ['md', 'sm'],
19
+ description: '`md` applies standard card padding. `sm` applies minor/inner container padding.',
20
+ },
21
+ },
22
+ }
23
+
24
+ export default meta
25
+
26
+ type Story = StoryObj<typeof meta>
27
+
28
+ export const Default: Story = {
29
+ render: args => ({
30
+ components: { Card },
31
+ setup() {
32
+ return { args }
33
+ },
34
+ template: `
35
+ <Card :size="args.size">
36
+ <div style="display: flex; flex-direction: column; gap: 8px; min-width: 280px;">
37
+ <p class="heading-h4-semibold text-contrast">Card Title</p>
38
+ <p class="body-14-regular text-secondary">This is supporting content inside the card. It adapts to the selected size.</p>
39
+ </div>
40
+ </Card>
41
+ `,
42
+ }),
43
+ args: {
44
+ size: 'md',
45
+ },
46
+ }
47
+
48
+ export const Standard: Story = {
49
+ render: () => ({
50
+ components: { Card },
51
+ template: `
52
+ <Card size="md">
53
+ <div style="display: flex; flex-direction: column; gap: 8px; min-width: 280px;">
54
+ <p class="heading-h4-semibold text-contrast">Standard Card</p>
55
+ <p class="body-14-regular text-secondary">Used for large, standard, and medium cards.</p>
56
+ </div>
57
+ </Card>
58
+ `,
59
+ }),
60
+ parameters: {
61
+ docs: {
62
+ description: {
63
+ story: 'Default size (`md`). Use for primary content surfaces.',
64
+ },
65
+ },
66
+ },
67
+ }
68
+
69
+ export const Minor: Story = {
70
+ render: () => ({
71
+ components: { Card },
72
+ template: `
73
+ <Card size="sm">
74
+ <div style="display: flex; flex-direction: column; gap: 8px; min-width: 240px;">
75
+ <p class="heading-h5-semibold text-contrast">Minor Card</p>
76
+ <p class="body-12-regular text-secondary">Used for small cards and inner containers.</p>
77
+ </div>
78
+ </Card>
79
+ `,
80
+ }),
81
+ parameters: {
82
+ docs: {
83
+ description: {
84
+ story: 'Small size (`sm`). Use for compact cards or nested inner containers.',
85
+ },
86
+ },
87
+ },
88
+ }
89
+
90
+ export const SizeComparison: Story = {
91
+ render: () => ({
92
+ components: { Card },
93
+ template: `
94
+ <div style="display: flex; gap: 16px; align-items: flex-start;">
95
+ <Card size="md">
96
+ <div style="display: flex; flex-direction: column; gap: 6px; min-width: 200px;">
97
+ <p class="body-12-medium text-secondary">size="md"</p>
98
+ <p class="heading-h4-semibold text-contrast">Standard</p>
99
+ <p class="body-14-regular text-tertiary">p-32px sm:p-48px padding</p>
100
+ </div>
101
+ </Card>
102
+ <Card size="sm">
103
+ <div style="display: flex; flex-direction: column; gap: 6px; min-width: 200px;">
104
+ <p class="body-12-medium text-secondary">size="sm"</p>
105
+ <p class="heading-h4-semibold text-contrast">Minor</p>
106
+ <p class="body-14-regular text-tertiary">p-24px padding</p>
107
+ </div>
108
+ </Card>
109
+ </div>
110
+ `,
111
+ }),
112
+ parameters: {
113
+ docs: {
114
+ description: {
115
+ story: 'Side-by-side comparison of both size variants.',
116
+ },
117
+ },
118
+ },
119
+ }
120
+
121
+ export const Grid: Story = {
122
+ render: () => ({
123
+ components: { Card },
124
+ template: `
125
+ <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; width: 640px;">
126
+ <Card v-for="n in 3" :key="n">
127
+ <div style="display: flex; flex-direction: column; gap: 4px;">
128
+ <p class="heading-h5-semibold text-contrast">Card {{ n }}</p>
129
+ <p class="body-12-regular text-secondary">Grid item</p>
130
+ </div>
131
+ </Card>
132
+ </div>
133
+ `,
134
+ }),
135
+ parameters: {
136
+ layout: 'padded',
137
+ docs: {
138
+ description: {
139
+ story: 'Cards used in a grid layout. No padding override needed — `size="md"` is the default.',
140
+ },
141
+ },
142
+ },
143
+ }
@@ -0,0 +1,33 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from 'vue'
3
+
4
+ const props = withDefaults(defineProps<{
5
+ size?: 'sm' | 'md'
6
+ class?: HTMLAttributes['class']
7
+ /** @deprecated Use `class` instead */
8
+ contentPadding?: HTMLAttributes['class']
9
+ /** @deprecated Use `class` instead */
10
+ borderRadius?: HTMLAttributes['class']
11
+ }>(), {
12
+ size: 'md',
13
+ })
14
+
15
+ const sizeStyles = computed(() => (({
16
+ sm: { padding: 'p-24px', rounded: 'rounded-12px' },
17
+ md: { padding: 'p-32px sm:p-48px', rounded: 'rounded-24px' },
18
+ }) as Record<string, { padding: string, rounded: string }>)[props.size ?? 'md'] ?? { padding: '', rounded: '' })
19
+
20
+ const paddingClass = computed(() => props.contentPadding ?? sizeStyles.value.padding)
21
+ const borderRadiusClass = computed(() => props.borderRadius ?? sizeStyles.value.rounded)
22
+ const rootEl = ref<HTMLElement | null>(null)
23
+
24
+ defineExpose({
25
+ el: rootEl,
26
+ })
27
+ </script>
28
+
29
+ <template>
30
+ <div ref="rootEl" :class="cn('bg border-0.5px border', paddingClass, borderRadiusClass, props.class)">
31
+ <slot />
32
+ </div>
33
+ </template>
@@ -0,0 +1,130 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import ScrollArea from './scroll-area.vue'
3
+
4
+ const meta: Meta<typeof ScrollArea> = {
5
+ title: 'Utility/ScrollArea',
6
+ component: ScrollArea,
7
+ tags: ['autodocs'],
8
+ parameters: {
9
+ layout: 'centered',
10
+ docs: {
11
+ description: {
12
+ component: 'A scroll area component that provides custom-styled scrollbars. Built on reka-ui for consistent scrollbar appearance across browsers. Useful for creating scrollable containers with better visual consistency than native scrollbars.',
13
+ },
14
+ },
15
+ },
16
+ argTypes: {
17
+ type: {
18
+ control: 'select',
19
+ options: ['auto', 'always', 'scroll', 'hover'],
20
+ description: 'Scrollbar visibility behavior.',
21
+ },
22
+ orientation: {
23
+ control: 'select',
24
+ options: ['vertical', 'horizontal', 'both'],
25
+ description: 'Direction(s) of scrolling.',
26
+ },
27
+ scrollHideDelay: {
28
+ control: 'number',
29
+ description: 'Delay in ms before scrollbars are hidden (when type is hover or scroll).',
30
+ },
31
+ },
32
+ args: {
33
+ type: 'hover',
34
+ orientation: 'vertical',
35
+ },
36
+ }
37
+
38
+ export default meta
39
+
40
+ type Story = StoryObj<typeof meta>
41
+
42
+ export const Default: Story = {
43
+ render: args => ({
44
+ components: { ScrollArea },
45
+ setup() {
46
+ const items = Array.from({ length: 30 }, (_, i) => `Item ${i + 1}`)
47
+ return { args, items }
48
+ },
49
+ template: `
50
+ <ScrollArea v-bind="args" class="h-200px w-300px border border-gray-200 rounded-md">
51
+ <div class="p-4 flex flex-col gap-2">
52
+ <div v-for="item in items" :key="item" class="text-sm py-1 border-b border-gray-100 last:border-0">
53
+ {{ item }}
54
+ </div>
55
+ </div>
56
+ </ScrollArea>
57
+ `,
58
+ }),
59
+ }
60
+
61
+ export const AlwaysVisible: Story = {
62
+ args: {
63
+ type: 'always',
64
+ },
65
+ render: args => ({
66
+ components: { ScrollArea },
67
+ setup() {
68
+ const items = Array.from({ length: 30 }, (_, i) => `Item ${i + 1}`)
69
+ return { args, items }
70
+ },
71
+ template: `
72
+ <ScrollArea v-bind="args" class="h-200px w-300px border border-gray-200 rounded-md">
73
+ <div class="p-4 flex flex-col gap-2">
74
+ <div v-for="item in items" :key="item" class="text-sm py-1 border-b border-gray-100 last:border-0">
75
+ {{ item }}
76
+ </div>
77
+ </div>
78
+ </ScrollArea>
79
+ `,
80
+ }),
81
+ }
82
+
83
+ export const Horizontal: Story = {
84
+ args: {
85
+ orientation: 'horizontal',
86
+ type: 'always',
87
+ },
88
+ render: args => ({
89
+ components: { ScrollArea },
90
+ setup() {
91
+ const items = Array.from({ length: 20 }, (_, i) => `Card ${i + 1}`)
92
+ return { args, items }
93
+ },
94
+ template: `
95
+ <ScrollArea v-bind="args" class="w-400px border border-gray-200 rounded-md">
96
+ <div class="flex gap-3 p-4" style="width: 1200px">
97
+ <div v-for="item in items" :key="item" class="flex-shrink-0 w-120px h-80px bg-gray-100 rounded flex items-center justify-center text-sm text-gray-600">
98
+ {{ item }}
99
+ </div>
100
+ </div>
101
+ </ScrollArea>
102
+ `,
103
+ }),
104
+ }
105
+
106
+ export const Both: Story = {
107
+ args: {
108
+ orientation: 'both',
109
+ type: 'always',
110
+ },
111
+ render: args => ({
112
+ components: { ScrollArea },
113
+ setup() {
114
+ const rows = Array.from({ length: 20 }, (_, i) => `Row ${i + 1}`)
115
+ return { args, rows }
116
+ },
117
+ template: `
118
+ <ScrollArea v-bind="args" class="h-250px w-400px border border-gray-200 rounded-md">
119
+ <div style="width: 900px">
120
+ <div v-for="row in rows" :key="row" class="flex items-center px-4 py-2 border-b border-gray-100 text-sm gap-4">
121
+ <span class="w-100px flex-shrink-0 font-medium">{{ row }}</span>
122
+ <span class="w-200px flex-shrink-0 text-gray-500">Column B content here</span>
123
+ <span class="w-200px flex-shrink-0 text-gray-500">Column C content here</span>
124
+ <span class="w-200px flex-shrink-0 text-gray-500">Column D content here</span>
125
+ </div>
126
+ </div>
127
+ </ScrollArea>
128
+ `,
129
+ }),
130
+ }
@@ -0,0 +1,89 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as SegmentToggleStories from './segment-toggle.stories.ts';
3
+
4
+ <Meta of={SegmentToggleStories} />
5
+
6
+ # TelaSegmentToggle
7
+
8
+ A segment toggle component that displays multiple options as connected segments. Only one option can be selected at a time. Supports v-model binding, different sizes, and disabled states. Useful for mutually exclusive option selection with a modern segmented control interface.
9
+
10
+ ## Examples
11
+
12
+ ### Default
13
+
14
+ <Canvas of={SegmentToggleStories.Default} />
15
+
16
+ ### Small Size
17
+
18
+ <Canvas of={SegmentToggleStories.Small} />
19
+
20
+ ### Disabled
21
+
22
+ <Canvas of={SegmentToggleStories.Disabled} />
23
+
24
+ ### Two Options
25
+
26
+ <Canvas of={SegmentToggleStories.TwoOptions} />
27
+
28
+ ### Preselected Middle
29
+
30
+ <Canvas of={SegmentToggleStories.PreselectedMiddle} />
31
+
32
+ ## Basic Usage
33
+
34
+ ```vue
35
+ <script setup>
36
+ import { ref } from 'vue'
37
+
38
+ const alignment = ref('left')
39
+ const options = [
40
+ { label: 'Left', value: 'left' },
41
+ { label: 'Center', value: 'center' },
42
+ { label: 'Right', value: 'right' },
43
+ ]
44
+ </script>
45
+
46
+ <template>
47
+ <TelaSegmentToggle v-model="alignment" :options="options" />
48
+ </template>
49
+ ```
50
+
51
+ ### Small Size
52
+
53
+ ```vue
54
+ <TelaSegmentToggle v-model="value" :options="options" size="small" />
55
+ ```
56
+
57
+ ### Disabled State
58
+
59
+ ```vue
60
+ <TelaSegmentToggle v-model="value" :options="options" disabled />
61
+ ```
62
+
63
+ ## Props
64
+
65
+ <ArgTypes />
66
+
67
+ ```typescript
68
+ interface Option {
69
+ label: string
70
+ value: string
71
+ }
72
+
73
+ type SegmentToggleProps = {
74
+ modelValue: string
75
+ options: Option[]
76
+ size?: 'small' | 'medium'
77
+ disabled?: boolean
78
+ class?: string
79
+ buttonsClass?: string
80
+ }
81
+ ```
82
+
83
+ ## Features
84
+
85
+ - **Two-way Binding**: Full v-model support for reactive state
86
+ - **Multiple Sizes**: Small and medium size options
87
+ - **Animated Selection**: Spring-animated indicator for smooth transitions
88
+ - **Disabled State**: Proper disabled styling and interaction prevention
89
+ - **Accessible**: Keyboard navigation support via native button elements
@@ -110,7 +110,7 @@ function handleOpenChange(open: boolean) {
110
110
  v-if="currentOption?.icon && !(currentOption.value === '')"
111
111
  shrink-0 rounded-4px flex items-center justify-center
112
112
  >
113
- <Icon v-if="typeof currentOption.icon === 'string'" :name="currentOption.icon" />
113
+ <TelaIcon v-if="typeof currentOption.icon === 'string'" :name="currentOption.icon" />
114
114
  <Component :is="currentOption.icon" v-else />
115
115
  </div>
116
116
  <div v-if="!currentOption?.icon && currentOption?.externalIconSrc" mr-4px flex h-20px w-16px shrink-0 items-center justify-center rounded-4px>
@@ -336,7 +336,11 @@ watch(
336
336
  { immediate: true },
337
337
  )
338
338
 
339
- onMounted(measureContentWidth)
339
+ onMounted(() => {
340
+ requestAnimationFrame(() => {
341
+ requestAnimationFrame(measureContentWidth)
342
+ })
343
+ })
340
344
 
341
345
  const shineClass = computed(() => {
342
346
  const baseColor = currentStatus.value.textColor.replace('text-', '')
@@ -5,9 +5,9 @@ import { TabsTrigger, useForwardProps } from 'reka-ui'
5
5
  import type { TabsTriggerProps } from 'reka-ui'
6
6
  import { cn } from '@/lib/utils'
7
7
 
8
- const props = defineProps<TabsTriggerProps & { class?: HTMLAttributes['class'] }>()
8
+ const props = defineProps<TabsTriggerProps & { class?: HTMLAttributes['class'], textClass?: HTMLAttributes['class'] }>()
9
9
 
10
- const delegatedProps = reactiveOmit(props, 'class')
10
+ const delegatedProps = reactiveOmit(props, 'class', 'textClass')
11
11
 
12
12
  const forwardedProps = useForwardProps(delegatedProps)
13
13
  </script>
@@ -20,7 +20,7 @@ const forwardedProps = useForwardProps(delegatedProps)
20
20
  props.class,
21
21
  )"
22
22
  >
23
- <span class="truncate">
23
+ <span :class="cn('truncate', props.textClass)">
24
24
  <slot />
25
25
  </span>
26
26
  </TabsTrigger>
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { TooltipContent, TooltipPortal, useForwardPropsEmits } from 'reka-ui'
3
3
  import type { TooltipContentEmits, TooltipContentProps } from 'reka-ui'
4
- import { computed } from 'vue'
4
+ import { reactiveOmit } from '@vueuse/core'
5
5
  import type { HTMLAttributes } from 'vue'
6
6
 
7
7
  defineOptions({
@@ -16,11 +16,7 @@ const emits = defineEmits<TooltipContentEmits & {
16
16
  click: [event: Event]
17
17
  }>()
18
18
 
19
- const delegatedProps = computed(() => {
20
- const { class: _, ...delegated } = props
21
-
22
- return delegated
23
- })
19
+ const delegatedProps = reactiveOmit(props, 'class')
24
20
 
25
21
  const forwarded = useForwardPropsEmits(delegatedProps, emits)
26
22
  </script>
@@ -1,10 +1,12 @@
1
1
  /* eslint-disable no-console */
2
2
  import { join, resolve, relative, dirname, basename } from 'pathe'
3
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs'
3
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync } from 'node:fs'
4
4
  import { parse as parseVue } from 'vue-docgen-api'
5
5
  // Load glob dynamically for compatibility across versions (v8 vs v11)
6
- import { getTypeResolver, type TypeResolver } from './type-resolver'
7
- import { createVolarExtractor, type VolarExtractor } from './extractors/volar-extract'
6
+ import { getTypeResolver } from './type-resolver'
7
+ import type { TypeResolver } from './type-resolver'
8
+ import { createVolarExtractor } from './extractors/volar-extract'
9
+ import type { VolarExtractor } from './extractors/volar-extract'
8
10
 
9
11
  const colors = {
10
12
  gray: '\x1B[90m',
@@ -544,20 +546,23 @@ export function generateDocsToDirectory(componentDocs: ComponentDoc[], typeResol
544
546
  componentLinks.push(`- [${title}](components/${groupSlug}.md)`)
545
547
  }
546
548
 
547
- // Read design-tokens.md content if it exists
548
- let designTokensContent = ''
549
+ // Read all .md files from docs/ and append them to SKILL.md
550
+ let docsSection = ''
549
551
  if (layerPath) {
550
- const designTokensSourcePath = join(layerPath, 'docs', 'design-tokens.md')
551
- if (existsSync(designTokensSourcePath)) {
552
- designTokensContent = readFileSync(designTokensSourcePath, 'utf-8')
552
+ const docsDir = join(layerPath, 'docs')
553
+ if (existsSync(docsDir)) {
554
+ const docFiles = readdirSync(docsDir)
555
+ .filter(f => f.endsWith('.md'))
556
+ .sort()
557
+ for (const file of docFiles) {
558
+ const content = readFileSync(join(docsDir, file), 'utf-8')
559
+ docsSection += `\n\n---\n\n${content}`
560
+ }
553
561
  }
554
562
  }
555
563
 
556
564
  // Create SKILL.md describing Tela Build with links to supporting md
557
565
  const skillDescription = buildTelaBuildSkillDescription()
558
- const designTokensSection = designTokensContent
559
- ? `\n\n---\n\n${designTokensContent}`
560
- : ''
561
566
  const body = dedent`
562
567
  # Tela Build
563
568
 
@@ -574,7 +579,7 @@ Use it when building, refactoring, or using Tela components — props, events, s
574
579
 
575
580
  ## Components Index
576
581
 
577
- ${componentLinks.join('\n')}${designTokensSection}
582
+ ${componentLinks.join('\n')}${docsSection}
578
583
  `
579
584
 
580
585
  const skillMd = wrapWithSkillFrontmatter({ name: 'tela-build', description: skillDescription }, body)
@@ -675,13 +680,13 @@ function toKebabFromTag(tagName: string): string {
675
680
  return tagName
676
681
  .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
677
682
  .replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
678
- .replace(/[^a-zA-Z0-9-]/g, '-')
683
+ .replace(/[^a-z0-9-]/gi, '-')
679
684
  .toLowerCase()
680
- .replace(/--+/g, '-')
685
+ .replace(/-{2,}/g, '-')
681
686
  .replace(/^-+|-+$/g, '')
682
687
  }
683
688
 
684
- function wrapWithSkillFrontmatter(meta: { name: string; description: string; allowedTools?: string[] }, body: string): string {
689
+ function wrapWithSkillFrontmatter(meta: { name: string, description: string, allowedTools?: string[] }, body: string): string {
685
690
  const { name, description, allowedTools } = meta
686
691
  const lines: string[] = []
687
692
  lines.push('---')
@@ -700,7 +705,7 @@ function wrapWithSkillFrontmatter(meta: { name: string; description: string; all
700
705
 
701
706
  function sanitizeSkillName(name: string): string {
702
707
  // Lowercase + hyphens + digits only, max 64 chars
703
- return name.toLowerCase().replace(/[^a-z0-9-]/g, '-').slice(0, 64).replace(/--+/g, '-')
708
+ return name.toLowerCase().replace(/[^a-z0-9-]/g, '-').slice(0, 64).replace(/-{2,}/g, '-')
704
709
  }
705
710
 
706
711
  function sanitizeDescription(desc: string): string {
@@ -804,7 +809,7 @@ function sanitizeInlineComment(value?: string): string {
804
809
  if (!value)
805
810
  return ''
806
811
 
807
- const withoutMarkdown = value.replace(/\[([^\]]+)\]\([^\)]+\)/g, '$1')
812
+ const withoutMarkdown = value.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
808
813
  const singleLine = withoutMarkdown.replace(/\s+/g, ' ').trim()
809
814
  if (!singleLine)
810
815
  return ''
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/tela-build",
3
- "version": "1.20.0",
3
+ "version": "1.22.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "app.config.ts",
@@ -1,28 +0,0 @@
1
- <script setup lang="ts">
2
- defineProps<{
3
- contentPadding?: string
4
- borderRadius?: string
5
- }>()
6
-
7
- const rootEl = ref<HTMLElement | null>(null)
8
-
9
- defineExpose({
10
- el: rootEl,
11
- })
12
- </script>
13
-
14
- <template>
15
- <div
16
- ref="rootEl"
17
- bg-white
18
- :class="borderRadius ? `rounded-${borderRadius}` : 'rounded-16px'"
19
- b=".5 gray-200"
20
- >
21
- <div :class="contentPadding ?? 'p-32px'">
22
- <slot />
23
- </div>
24
- <div v-if="$slots.footer" p-19px b="t-1 #EBEBEB">
25
- <slot name="footer" />
26
- </div>
27
- </div>
28
- </template>