@sabrenski/spire-ui 0.0.6 → 0.0.7

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 (86) hide show
  1. package/dist/index.d.ts +167 -4
  2. package/dist/spire-ui.css +1 -1
  3. package/dist/spire-ui.es.js +7005 -6741
  4. package/dist/spire-ui.umd.js +10 -10
  5. package/package.json +83 -70
  6. package/src/components/Accordion/AccordionContent.vue +5 -2
  7. package/src/components/Accordion/AccordionItem.vue +4 -0
  8. package/src/components/Accordion/AccordionRoot.vue +4 -2
  9. package/src/components/Accordion/AccordionTrigger.vue +4 -1
  10. package/src/components/Avatar/Avatar.vue +4 -0
  11. package/src/components/Badge/Badge.vue +4 -0
  12. package/src/components/BadgeContainer/BadgeContainer.vue +4 -1
  13. package/src/components/Breadcrumb/BreadcrumbLink.vue +4 -1
  14. package/src/components/Breadcrumb/BreadcrumbRoot.vue +4 -1
  15. package/src/components/Button/Button.vue +5 -1
  16. package/src/components/Callout/Callout.vue +4 -0
  17. package/src/components/Card/Card.vue +5 -1
  18. package/src/components/Card/CardContent.vue +5 -1
  19. package/src/components/Card/CardFooter.vue +5 -1
  20. package/src/components/Card/CardHeader.vue +5 -1
  21. package/src/components/Card/CardImage.vue +4 -2
  22. package/src/components/Chart/BarChart.vue +4 -0
  23. package/src/components/Chart/BaseChart.vue +52 -47
  24. package/src/components/Chart/DonutChart.vue +4 -2
  25. package/src/components/Chart/LineChart.vue +4 -0
  26. package/src/components/Checkbox/Checkbox.test.ts +94 -0
  27. package/src/components/Checkbox/Checkbox.vue +170 -1
  28. package/src/components/ChoiceChip/ChoiceChip.vue +11 -5
  29. package/src/components/ChoiceChipGroup/ChoiceChipGroup.vue +4 -2
  30. package/src/components/ColorPicker/ColorArea.vue +4 -2
  31. package/src/components/ColorPicker/ColorPicker.vue +4 -2
  32. package/src/components/ColorPicker/ColorSlider.vue +5 -1
  33. package/src/components/Combobox/Combobox.vue +97 -91
  34. package/src/components/DataTable/DataTable.vue +5 -1
  35. package/src/components/DatePicker/DatePicker.vue +5 -1
  36. package/src/components/Drawer/Drawer.vue +4 -1
  37. package/src/components/Dropdown/Dropdown.vue +4 -2
  38. package/src/components/Dropdown/DropdownItem.vue +4 -0
  39. package/src/components/Dropdown/DropdownSubTrigger.vue +4 -2
  40. package/src/components/EmptyState/EmptyState.vue +5 -1
  41. package/src/components/FileUpload/FileUpload.vue +12 -6
  42. package/src/components/Heading/Heading.vue +4 -0
  43. package/src/components/Icon/Icon.vue +5 -2
  44. package/src/components/Input/Input.vue +5 -1
  45. package/src/components/Layout/Container.vue +4 -0
  46. package/src/components/Layout/Grid.vue +4 -1
  47. package/src/components/Layout/GridItem.vue +4 -1
  48. package/src/components/Layout/Stack.vue +4 -0
  49. package/src/components/Modal/Modal.test.ts +68 -13
  50. package/src/components/Modal/Modal.vue +94 -91
  51. package/src/components/Pagination/Pagination.vue +5 -1
  52. package/src/components/Popover/Popover.vue +4 -1
  53. package/src/components/Progress/Progress.vue +5 -0
  54. package/src/components/Radio/Radio.test.ts +88 -0
  55. package/src/components/Radio/Radio.vue +169 -1
  56. package/src/components/Rating/Rating.vue +5 -1
  57. package/src/components/SegmentedControl/SegmentedControl.vue +5 -1
  58. package/src/components/Select/Select.vue +61 -55
  59. package/src/components/Sidebar/SidebarGroup.vue +4 -0
  60. package/src/components/Sidebar/SidebarItem.vue +4 -0
  61. package/src/components/Sidebar/SidebarLayout.vue +5 -2
  62. package/src/components/Sidebar/SidebarRoot.vue +4 -2
  63. package/src/components/Skeleton/Skeleton.vue +5 -1
  64. package/src/components/Slider/Slider.vue +5 -1
  65. package/src/components/Spinner/Spinner.vue +4 -1
  66. package/src/components/SpireProvider/SpireProvider.vue +4 -1
  67. package/src/components/Stepper/StepperItem.vue +4 -0
  68. package/src/components/Stepper/StepperRoot.vue +4 -2
  69. package/src/components/Stepper/StepperTrigger.vue +6 -2
  70. package/src/components/Switch/Switch.vue +5 -1
  71. package/src/components/Tabs/Tabs.vue +4 -1
  72. package/src/components/Text/Text.vue +4 -0
  73. package/src/components/Textarea/Textarea.vue +13 -7
  74. package/src/components/TimePicker/TimePicker.vue +5 -1
  75. package/src/components/Timeline/Timeline.vue +4 -0
  76. package/src/components/Timeline/TimelineItem.vue +4 -0
  77. package/src/components/Toast/ToastItem.vue +5 -1
  78. package/src/components/Toast/ToastProvider.vue +5 -3
  79. package/src/components/ToggleButton/ToggleButton.vue +5 -1
  80. package/src/components/ToggleGroup/ToggleGroup.vue +5 -1
  81. package/src/components/Tooltip/Tooltip.vue +9 -1
  82. package/src/components/TreeView/TreeView.vue +4 -1
  83. package/src/components/TreeView/TreeViewItem.vue +4 -0
  84. package/src/index.ts +3 -0
  85. package/src/styles/main.css +21 -21
  86. package/src/types/common.ts +4 -0
package/package.json CHANGED
@@ -1,70 +1,83 @@
1
- {
2
- "name": "@sabrenski/spire-ui",
3
- "version": "0.0.6",
4
- "description": "A dependency-free Vue 3 component library built with pure CSS and OKLCH colors",
5
- "type": "module",
6
- "license": "MIT",
7
- "author": "Sabri Stratos",
8
- "repository": {
9
- "type": "git",
10
- "url": "git+https://github.com/sabristratos/spire-ui.git"
11
- },
12
- "homepage": "https://github.com/sabristratos/spire-ui#readme",
13
- "bugs": {
14
- "url": "https://github.com/sabristratos/spire-ui/issues"
15
- },
16
- "keywords": [
17
- "vue",
18
- "vue3",
19
- "components",
20
- "ui",
21
- "component-library",
22
- "design-system",
23
- "typescript",
24
- "oklch",
25
- "css"
26
- ],
27
- "files": [
28
- "dist",
29
- "src"
30
- ],
31
- "main": "./dist/spire-ui.umd.js",
32
- "module": "./dist/spire-ui.es.js",
33
- "types": "./dist/index.d.ts",
34
- "exports": {
35
- ".": {
36
- "import": "./dist/spire-ui.es.js",
37
- "require": "./dist/spire-ui.umd.js",
38
- "types": "./dist/index.d.ts"
39
- },
40
- "./style.css": "./dist/spire-ui.css"
41
- },
42
- "peerDependencies": {
43
- "chart.js": "^4.4.0",
44
- "vue": "^3.3.0"
45
- },
46
- "peerDependenciesMeta": {
47
- "chart.js": {
48
- "optional": true
49
- }
50
- },
51
- "devDependencies": {
52
- "@vitejs/plugin-vue": "^5.2.1",
53
- "@vue/test-utils": "^2.4.6",
54
- "chart.js": "^4.5.1",
55
- "happy-dom": "^20.3.0",
56
- "typescript": "^5.7.2",
57
- "vite": "^6.0.7",
58
- "vite-plugin-dts": "^4.4.0",
59
- "vitest": "^4.0.17",
60
- "vue": "^3.5.13",
61
- "vue-tsc": "^2.2.0"
62
- },
63
- "scripts": {
64
- "build": "vite build",
65
- "test": "vitest run",
66
- "test:watch": "vitest",
67
- "typecheck": "vue-tsc --noEmit",
68
- "docs:tokens": "npx tsx scripts/generate-token-docs.ts"
69
- }
70
- }
1
+ {
2
+ "name": "@sabrenski/spire-ui",
3
+ "version": "0.0.7",
4
+ "description": "A dependency-free Vue 3 component library built with pure CSS and OKLCH colors",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Sabri Stratos",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/sabristratos/spire-ui.git"
11
+ },
12
+ "homepage": "https://github.com/sabristratos/spire-ui#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/sabristratos/spire-ui/issues"
15
+ },
16
+ "keywords": [
17
+ "vue",
18
+ "vue3",
19
+ "components",
20
+ "ui",
21
+ "component-library",
22
+ "design-system",
23
+ "typescript",
24
+ "oklch",
25
+ "css"
26
+ ],
27
+ "files": [
28
+ "dist",
29
+ "src"
30
+ ],
31
+ "main": "./src/index.ts",
32
+ "module": "./src/index.ts",
33
+ "types": "./src/index.ts",
34
+ "exports": {
35
+ ".": {
36
+ "import": "./src/index.ts",
37
+ "types": "./src/index.ts"
38
+ },
39
+ "./style.css": "./src/styles/main.css",
40
+ "./src/*": "./src/*"
41
+ },
42
+ "publishConfig": {
43
+ "main": "./dist/spire-ui.umd.js",
44
+ "module": "./dist/spire-ui.es.js",
45
+ "types": "./dist/index.d.ts",
46
+ "exports": {
47
+ ".": {
48
+ "import": "./dist/spire-ui.es.js",
49
+ "require": "./dist/spire-ui.umd.js",
50
+ "types": "./dist/index.d.ts"
51
+ },
52
+ "./style.css": "./dist/spire-ui.css"
53
+ }
54
+ },
55
+ "scripts": {
56
+ "build": "vite build",
57
+ "test": "vitest run",
58
+ "test:watch": "vitest",
59
+ "typecheck": "vue-tsc --noEmit",
60
+ "docs:tokens": "npx tsx scripts/generate-token-docs.ts"
61
+ },
62
+ "peerDependencies": {
63
+ "chart.js": "^4.4.0",
64
+ "vue": "^3.3.0"
65
+ },
66
+ "peerDependenciesMeta": {
67
+ "chart.js": {
68
+ "optional": true
69
+ }
70
+ },
71
+ "devDependencies": {
72
+ "@vitejs/plugin-vue": "^5.2.1",
73
+ "@vue/test-utils": "^2.4.6",
74
+ "chart.js": "^4.5.1",
75
+ "happy-dom": "^20.3.0",
76
+ "typescript": "^5.7.2",
77
+ "vite": "^6.0.7",
78
+ "vite-plugin-dts": "^4.4.0",
79
+ "vitest": "^4.0.17",
80
+ "vue": "^3.5.13",
81
+ "vue-tsc": "^2.2.0"
82
+ }
83
+ }
@@ -1,8 +1,11 @@
1
1
  <script setup lang="ts">
2
2
  import { inject } from 'vue'
3
3
  import { AccordionItemKey } from './keys'
4
+ import type { ClassValue } from '../../types/common'
4
5
 
5
6
  export interface AccordionContentProps {
7
+ /** Additional CSS classes */
8
+ class?: ClassValue
6
9
  /** Lazy render - use v-if instead of v-show. Better performance but breaks Ctrl+F search. */
7
10
  lazy?: boolean
8
11
  }
@@ -59,7 +62,7 @@ function onAfterLeave(el: Element) {
59
62
  <div
60
63
  v-if="item.isOpen.value"
61
64
  :id="item.contentId"
62
- class="ui-accordion__content"
65
+ :class="[props.class, 'ui-accordion__content']"
63
66
  role="region"
64
67
  :aria-labelledby="item.triggerId"
65
68
  >
@@ -81,7 +84,7 @@ function onAfterLeave(el: Element) {
81
84
  <div
82
85
  v-show="item.isOpen.value"
83
86
  :id="item.contentId"
84
- class="ui-accordion__content"
87
+ :class="[props.class, 'ui-accordion__content']"
85
88
  role="region"
86
89
  :aria-labelledby="item.triggerId"
87
90
  >
@@ -2,8 +2,11 @@
2
2
  import { computed, provide, inject } from 'vue'
3
3
  import { useId } from '../../composables'
4
4
  import { AccordionKey, AccordionItemKey } from './keys'
5
+ import type { ClassValue } from '../../types/common'
5
6
 
6
7
  export interface AccordionItemProps {
8
+ /** Additional CSS classes */
9
+ class?: ClassValue
7
10
  /** Unique identifier for this item */
8
11
  value: string
9
12
  /** Disable this item */
@@ -40,6 +43,7 @@ provide(AccordionItemKey, {
40
43
  })
41
44
 
42
45
  const itemClasses = computed(() => [
46
+ props.class,
43
47
  'ui-accordion__item',
44
48
  `ui-accordion__item--${accordion.variant.value}`,
45
49
  {
@@ -2,8 +2,11 @@
2
2
  import { computed, provide, toRef, ref, watch } from 'vue'
3
3
  import { AccordionKey } from './keys'
4
4
  import type { AccordionVariant } from './keys'
5
+ import type { ClassValue } from '../../types/common'
5
6
 
6
7
  export interface AccordionRootProps {
8
+ /** Additional CSS classes */
9
+ class?: ClassValue
7
10
  /** Currently open item(s) - single value or array for multiple mode */
8
11
  modelValue?: string | string[]
9
12
  /** Allow all items to be collapsed */
@@ -84,8 +87,7 @@ provide(AccordionKey, {
84
87
 
85
88
  <template>
86
89
  <div
87
- class="ui-accordion"
88
- :class="[`ui-accordion--${variant}`]"
90
+ :class="[props.class, 'ui-accordion', `ui-accordion--${variant}`]"
89
91
  >
90
92
  <slot />
91
93
  </div>
@@ -1,8 +1,11 @@
1
1
  <script setup lang="ts">
2
2
  import { inject, useSlots } from 'vue'
3
3
  import { AccordionItemKey } from './keys'
4
+ import type { ClassValue } from '../../types/common'
4
5
 
5
6
  export interface AccordionTriggerProps {
7
+ /** Additional CSS classes */
8
+ class?: ClassValue
6
9
  /** Hide the default chevron indicator */
7
10
  hideIndicator?: boolean
8
11
  }
@@ -23,7 +26,7 @@ const hasIconSlot = !!slots.icon
23
26
  </script>
24
27
 
25
28
  <template>
26
- <h3 class="ui-accordion__heading">
29
+ <h3 :class="[props.class, 'ui-accordion__heading']">
27
30
  <button
28
31
  type="button"
29
32
  class="ui-accordion__trigger"
@@ -1,12 +1,15 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, ref, watch } from 'vue'
3
3
  import { getInitials } from '../../utils/string'
4
+ import type { ClassValue } from '../../types/common'
4
5
 
5
6
  type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
6
7
  type AvatarShape = 'circle' | 'square'
7
8
  type AvatarVariant = 'neutral' | 'primary' | 'soft'
8
9
 
9
10
  export interface AvatarProps {
11
+ /** Additional CSS classes */
12
+ class?: ClassValue
10
13
  /** Image source URL */
11
14
  src?: string
12
15
  /** User name - used for alt text AND initials fallback */
@@ -49,6 +52,7 @@ const showInitials = computed(() => !showImage.value && initials.value)
49
52
  const showFallback = computed(() => !showImage.value && !initials.value)
50
53
 
51
54
  const classes = computed(() => [
55
+ props.class,
52
56
  'ui-avatar',
53
57
  `ui-avatar--${props.size}`,
54
58
  `ui-avatar--${props.shape}`,
@@ -1,9 +1,12 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, useSlots } from 'vue'
3
+ import type { ClassValue } from '../../types/common'
3
4
 
4
5
  type BadgeVariant = 'default' | 'success' | 'warning' | 'danger' | 'info'
5
6
 
6
7
  export interface BadgeProps {
8
+ /** Additional CSS classes */
9
+ class?: ClassValue
7
10
  /** Color variant */
8
11
  variant?: BadgeVariant
9
12
  /** Render as dot indicator instead of pill */
@@ -39,6 +42,7 @@ const ariaLabel = computed(() => {
39
42
  })
40
43
 
41
44
  const classes = computed(() => [
45
+ props.class,
42
46
  'ui-badge',
43
47
  `ui-badge--${props.variant}`,
44
48
  {
@@ -1,9 +1,12 @@
1
1
  <script setup lang="ts">
2
2
  import { computed } from 'vue'
3
+ import type { ClassValue } from '../../types/common'
3
4
 
4
5
  type BadgePosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'
5
6
 
6
7
  export interface BadgeContainerProps {
8
+ /** Additional CSS classes */
9
+ class?: ClassValue
7
10
  /** Badge position relative to content */
8
11
  position?: BadgePosition
9
12
  /** Horizontal offset adjustment (CSS value) */
@@ -54,7 +57,7 @@ const badgeClasses = computed(() => [
54
57
  </script>
55
58
 
56
59
  <template>
57
- <span class="ui-badge-container">
60
+ <span :class="[props.class, 'ui-badge-container']">
58
61
  <!-- Content (Button, Avatar, etc.) -->
59
62
  <slot />
60
63
 
@@ -1,7 +1,10 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, type Component } from 'vue'
3
+ import type { ClassValue } from '../../types/common'
3
4
 
4
5
  export interface BreadcrumbLinkProps {
6
+ /** Additional CSS classes */
7
+ class?: ClassValue
5
8
  /** URL for standard anchor */
6
9
  href?: string
7
10
  /** Route location for vue-router (string or route object) */
@@ -34,7 +37,7 @@ const linkProps = computed(() => {
34
37
  <component
35
38
  :is="componentType"
36
39
  v-bind="linkProps"
37
- class="ui-breadcrumb__link"
40
+ :class="[props.class, 'ui-breadcrumb__link']"
38
41
  >
39
42
  <slot />
40
43
  </component>
@@ -2,8 +2,11 @@
2
2
  import { provide, useSlots } from 'vue'
3
3
  import { BreadcrumbKey } from './keys'
4
4
  import type { Component, VNode } from 'vue'
5
+ import type { ClassValue } from '../../types/common'
5
6
 
6
7
  export interface BreadcrumbRootProps {
8
+ /** Additional CSS classes */
9
+ class?: ClassValue
7
10
  /** Custom separator component or string */
8
11
  separator?: Component | string | (() => VNode)
9
12
  }
@@ -27,7 +30,7 @@ provide(BreadcrumbKey, {
27
30
  </script>
28
31
 
29
32
  <template>
30
- <nav aria-label="Breadcrumb" class="ui-breadcrumb">
33
+ <nav aria-label="Breadcrumb" :class="[props.class, 'ui-breadcrumb']">
31
34
  <slot />
32
35
  </nav>
33
36
  </template>
@@ -3,8 +3,11 @@ import { computed, useSlots, type Component, type Slots } from 'vue'
3
3
  import Spinner from '../Spinner/Spinner.vue'
4
4
  import Icon from '../Icon/Icon.vue'
5
5
  import type { IconInput } from '../Icon/Icon.vue'
6
+ import type { ClassValue } from '../../types/common'
6
7
 
7
8
  export interface ButtonProps {
9
+ /** Additional CSS classes */
10
+ class?: ClassValue
8
11
  /** Visual style variant */
9
12
  variant?: 'primary' | 'secondary' | 'destructive' | 'ghost' | 'outline'
10
13
  /** Button size */
@@ -70,8 +73,9 @@ const iconSize = computed(() => iconSizeMap[props.size])
70
73
  :disabled="as === 'button' ? isDisabled : undefined"
71
74
  :aria-disabled="isDisabled"
72
75
  :aria-busy="loading"
73
- class="ui-button"
74
76
  :class="[
77
+ props.class,
78
+ 'ui-button',
75
79
  `ui-button--${variant}`,
76
80
  `ui-button--${size}`,
77
81
  {
@@ -1,9 +1,12 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, useSlots } from 'vue'
3
+ import type { ClassValue } from '../../types/common'
3
4
 
4
5
  export type CalloutVariant = 'info' | 'success' | 'warning' | 'error' | 'neutral'
5
6
 
6
7
  export interface CalloutProps {
8
+ /** Additional CSS classes */
9
+ class?: ClassValue
7
10
  /** Visual variant determining color and icon */
8
11
  variant?: CalloutVariant
9
12
  /** Title text (alternative to #title slot) */
@@ -44,6 +47,7 @@ const ariaRole = computed(() => {
44
47
  })
45
48
 
46
49
  const calloutClasses = computed(() => [
50
+ props.class,
47
51
  'ui-callout',
48
52
  `ui-callout--${props.variant}`,
49
53
  {
@@ -1,10 +1,13 @@
1
1
  <script setup lang="ts">
2
2
  import { provide, ref, toRef, computed, type Component } from 'vue'
3
+ import type { ClassValue } from '../../types/common'
3
4
 
4
5
  export type CardVariant = 'elevated' | 'outline' | 'ghost'
5
6
  export type CardPadding = 'none' | 'sm' | 'md' | 'lg'
6
7
 
7
8
  export interface CardProps {
9
+ /** Additional CSS classes */
10
+ class?: ClassValue
8
11
  /** Visual style variant */
9
12
  variant?: CardVariant
10
13
  /** Render as different element (article, section, aside, etc.) */
@@ -78,8 +81,9 @@ const isClickable = computed(() => props.interactive && !props.disabled && !prop
78
81
  <template>
79
82
  <component
80
83
  :is="as"
81
- class="ui-card"
82
84
  :class="[
85
+ props.class,
86
+ 'ui-card',
83
87
  `ui-card--${variant}`,
84
88
  `ui-card--padding-${padding}`,
85
89
  {
@@ -1,8 +1,11 @@
1
1
  <script setup lang="ts">
2
2
  import { inject, computed, type Ref } from 'vue'
3
3
  import type { CardPadding } from './Card.vue'
4
+ import type { ClassValue } from '../../types/common'
4
5
 
5
6
  export interface CardContentProps {
7
+ /** Additional CSS classes */
8
+ class?: ClassValue
6
9
  /** Remove default padding */
7
10
  flush?: boolean
8
11
  }
@@ -23,8 +26,9 @@ const paddingSize = computed(() => cardContext?.padding?.value ?? 'md')
23
26
 
24
27
  <template>
25
28
  <div
26
- class="ui-card__content"
27
29
  :class="[
30
+ props.class,
31
+ 'ui-card__content',
28
32
  `ui-card__content--padding-${paddingSize}`,
29
33
  {
30
34
  'ui-card__content--flush': flush,
@@ -1,8 +1,11 @@
1
1
  <script setup lang="ts">
2
2
  import { inject, computed, type Ref } from 'vue'
3
3
  import type { CardPadding } from './Card.vue'
4
+ import type { ClassValue } from '../../types/common'
4
5
 
5
6
  export interface CardFooterProps {
7
+ /** Additional CSS classes */
8
+ class?: ClassValue
6
9
  /** Content alignment */
7
10
  align?: 'start' | 'center' | 'end' | 'between'
8
11
  /** Remove separator border */
@@ -23,8 +26,9 @@ const paddingSize = computed(() => cardContext?.padding?.value ?? 'md')
23
26
 
24
27
  <template>
25
28
  <div
26
- class="ui-card__footer"
27
29
  :class="[
30
+ props.class,
31
+ 'ui-card__footer',
28
32
  `ui-card__footer--${align}`,
29
33
  `ui-card__footer--padding-${paddingSize}`,
30
34
  { 'ui-card__footer--borderless': borderless }
@@ -1,8 +1,11 @@
1
1
  <script setup lang="ts">
2
2
  import { inject, onMounted, useSlots, computed, type Ref } from 'vue'
3
3
  import type { CardPadding } from './Card.vue'
4
+ import type { ClassValue } from '../../types/common'
4
5
 
5
6
  export interface CardHeaderProps {
7
+ /** Additional CSS classes */
8
+ class?: ClassValue
6
9
  /** Title text (alternative to slot) */
7
10
  title?: string
8
11
  /** Subtitle text (alternative to slot) */
@@ -32,8 +35,9 @@ const paddingSize = computed(() => cardContext?.padding?.value ?? 'md')
32
35
 
33
36
  <template>
34
37
  <div
35
- class="ui-card__header"
36
38
  :class="[
39
+ props.class,
40
+ 'ui-card__header',
37
41
  `ui-card__header--${align}`,
38
42
  `ui-card__header--padding-${paddingSize}`
39
43
  ]"
@@ -1,11 +1,14 @@
1
1
  <script setup lang="ts">
2
2
  import { inject, onMounted, computed } from 'vue'
3
+ import type { ClassValue } from '../../types/common'
3
4
 
4
5
  export type CardImagePosition = 'top' | 'bottom' | 'left' | 'right' | 'background'
5
6
  export type CardImageAspectRatio = '16:9' | '4:3' | '3:2' | '1:1' | 'auto'
6
7
  export type CardImageFit = 'cover' | 'contain' | 'fill'
7
8
 
8
9
  export interface CardImageProps {
10
+ /** Additional CSS classes */
11
+ class?: ClassValue
9
12
  /** Image source URL */
10
13
  src: string
11
14
  /** Alt text for accessibility */
@@ -52,8 +55,7 @@ const aspectRatioValue = computed(() => {
52
55
 
53
56
  <template>
54
57
  <div
55
- class="ui-card__image"
56
- :class="[`ui-card__image--${position}`]"
58
+ :class="[props.class, 'ui-card__image', `ui-card__image--${position}`]"
57
59
  :style="aspectRatio !== 'auto' ? { '--aspect-ratio': aspectRatioValue } : undefined"
58
60
  >
59
61
  <img
@@ -4,6 +4,7 @@ import type { ChartData, ChartOptions } from 'chart.js'
4
4
  import BaseChart from './BaseChart.vue'
5
5
  import type { LegendItem, TooltipData, PointClickData } from './BaseChart.vue'
6
6
  import { useChartTheme } from './useChartTheme'
7
+ import type { ClassValue } from '../../types/common'
7
8
 
8
9
  type BarChartData = ChartData<'bar'>
9
10
  type BarChartOptions = ChartOptions<'bar'>
@@ -14,6 +15,8 @@ export interface BarChartSeries {
14
15
  }
15
16
 
16
17
  export interface BarChartProps {
18
+ /** Additional CSS classes */
19
+ class?: ClassValue
17
20
  /** X-axis labels */
18
21
  labels: string[]
19
22
  /** Data series */
@@ -123,6 +126,7 @@ const chartOptions = computed(() => ({
123
126
 
124
127
  <template>
125
128
  <BaseChart
129
+ :class="props.class"
126
130
  type="bar"
127
131
  :data="chartData"
128
132
  :options="chartOptions"