@imaginario27/air-ui-ds 1.12.2 → 1.13.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,28 @@ All notable changes to this package are documented in this file.
5
5
  Historical releases were reconstructed from git history (GitHub repository) and npm publish dates.
6
6
  Future releases will include detailed entries generated with Changesets.
7
7
 
8
+ ## 1.13.0 - 2026-04-22
9
+
10
+ Release type: minor.
11
+ Commits found in range: 1.
12
+
13
+ ### Added
14
+
15
+ 1. update MetricCard with new props ([4841cb3](https://github.com/imaginario27/air-ui/commit/4841cb3e6c0a8385825ff91f505b9e5ca732ca44))
16
+
17
+ - Package: @imaginario27/air-ui-ds.
18
+
19
+ ## 1.12.2 - 2026-04-22
20
+
21
+ Release type: patch.
22
+ Commits found in range: 1.
23
+
24
+ ### Fixed
25
+
26
+ 1. fix focus ring in form fields and icon span rendering when icon is not set ([4b0d548](https://github.com/imaginario27/air-ui/commit/4b0d5484271d25db6902eb1888a532291830fa4d))
27
+
28
+ - Package: @imaginario27/air-ui-ds.
29
+
8
30
  ## 1.12.1 - 2026-04-16
9
31
 
10
32
  Release type: patch.
@@ -1,42 +1,231 @@
1
1
  <template>
2
- <Card>
2
+ <Card :class="['gap-5!', containerClass]">
3
3
  <CardHeader>
4
- <CardTitle
5
- :title
6
- :class="[align === Align.CENTER && 'text-center']"
4
+ <template v-if="icon">
5
+ <Icon
6
+ v-if="
7
+ styleType === DashboardMetricCardStyle.NEUTRAL_FILLED ||
8
+ styleType === DashboardMetricCardStyle.PRIMARY_BRAND_FILLED ||
9
+ styleType === DashboardMetricCardStyle.SECONDARY_BRAND_FILLED ||
10
+ styleType === DashboardMetricCardStyle.CUSTOM_FILLED
11
+ "
12
+ :name="icon"
13
+ :class="textColorClass"
14
+ />
15
+ <ContainedIcon
16
+ v-else
17
+ :icon
18
+ :iconSize="IconSize.SM"
19
+ :color="iconColor"
20
+ :styleType="containedIconStyleType"
21
+ :shape="containedIconShape"
22
+ class="w-6! h-6! min-w-6! min-h-6!"
23
+ />
24
+ </template>
25
+
26
+ <CardTitle
27
+ :title
28
+ :class="textColorClass"
7
29
  />
8
30
  </CardHeader>
9
- <CardBody>
10
- <div :class="['flex flex-col', align === Align.CENTER && 'text-center']">
11
- <span class="font-semibold text-2xl md:text-3xl">
12
- {{ value }}
31
+ <CardBody class="flex flex-col! gap-2!">
32
+ <div :class="['flex', 'items-end', 'gap-1', textColorClass]">
33
+ <span class="text-3xl font-semibold">
34
+ {{ amount }}
13
35
  </span>
14
- <p
15
- v-if="description"
16
- class="text-text-neutral-subtle text-sm"
36
+
37
+ <span
38
+ v-if="unit"
39
+ class="text-lg font-semibold"
17
40
  >
41
+ /{{ unit }}
42
+ </span>
43
+ </div>
44
+
45
+ <div class="flex flex-col gap-0.5">
46
+ <p
47
+ v-if="featuredDescription"
48
+ :class="['text-sm', 'font-semibold', textColorClass]"
49
+ >
50
+ {{ featuredDescription }}
51
+ </p>
52
+
53
+ <p :class="['text-sm', styleType === DashboardMetricCardStyle.DEFAULT ? 'text-text-neutral-subtle' : textColorClass]">
18
54
  {{ description }}
19
55
  </p>
20
56
  </div>
57
+
58
+ <div
59
+ v-if="trend"
60
+ :class="['flex', 'items-center', 'gap-1', trendTextColorClass]"
61
+ >
62
+ <Icon
63
+ :name="trendIcon"
64
+ :size="IconSize.SM"
65
+ />
66
+
67
+ <span class="text-sm mt-0.5">
68
+ {{ trend }}
69
+ </span>
70
+ </div>
21
71
  </CardBody>
22
72
  </Card>
23
73
  </template>
74
+
24
75
  <script setup lang="ts">
25
76
  // Props
26
- defineProps({
77
+ const props = defineProps({
78
+ styleType: {
79
+ type: String as PropType<DashboardMetricCardStyle>,
80
+ default: DashboardMetricCardStyle.DEFAULT,
81
+ validator: (value: DashboardMetricCardStyle) => Object.values(DashboardMetricCardStyle).includes(value),
82
+ },
27
83
  title: {
28
84
  type: String as PropType<string>,
29
- default: 'Card title'
85
+ default: "Metric title",
86
+ },
87
+ icon: String as PropType<string>,
88
+ iconContainerShape: {
89
+ type: String as PropType<IconContainerShape>,
90
+ default: IconContainerShape.SQUARE,
91
+ validator: (value: IconContainerShape) => Object.values(IconContainerShape).includes(value),
92
+ },
93
+ defaultStyleIconColor: {
94
+ type: String as PropType<ColorAccent>,
95
+ default: ColorAccent.NEUTRAL,
96
+ validator: (value: ColorAccent) => Object.values(ColorAccent).includes(value),
30
97
  },
31
- value: {
98
+ defaultStyleIconContainerType: {
99
+ type: String as PropType<IconContainerStyleType>,
100
+ default: IconContainerStyleType.FILLED,
101
+ validator: (value: IconContainerStyleType) => Object.values(IconContainerStyleType).includes(value),
102
+ },
103
+ amount: {
32
104
  type: [String, Number] as PropType<string | number>,
33
- default: 0
105
+ default: 0,
106
+ },
107
+ unit: String as PropType<string>,
108
+ featuredDescription: String as PropType<string>,
109
+ description: {
110
+ type: String as PropType<string>,
111
+ default: "Metric description",
112
+ },
113
+ trend: String as PropType<string>,
114
+ trendDirection: {
115
+ type: String as PropType<DashboardMetricTrendDirection>,
116
+ default: DashboardMetricTrendDirection.UP,
117
+ validator: (value: DashboardMetricTrendDirection) => Object.values(DashboardMetricTrendDirection).includes(value),
34
118
  },
35
- description: String,
36
- align: {
37
- type: String as PropType<Align.LEFT | Align.CENTER>,
38
- default: Align.LEFT,
39
- validator: (value: Align) => [Align.LEFT, Align.CENTER].includes(value),
119
+ customFilledColorClass: {
120
+ type: String as PropType<string>,
121
+ default: "bg-background-neutral-bold",
122
+ },
123
+ });
124
+
125
+ // Computed
126
+ const trendIcon = computed(() => {
127
+ const variant: Record<DashboardMetricTrendDirection, string> = {
128
+ [DashboardMetricTrendDirection.UP]: "mdi:arrow-up",
129
+ [DashboardMetricTrendDirection.DOWN]: "mdi:arrow-down",
130
+ [DashboardMetricTrendDirection.NEUTRAL]: "mdi:minus",
131
+ };
132
+
133
+ return variant[props.trendDirection as DashboardMetricTrendDirection] || "mdi:arrow-up";
134
+ });
135
+
136
+ const containerClass = computed(() => {
137
+ const variant: Record<DashboardMetricCardStyle, string> = {
138
+ [DashboardMetricCardStyle.DEFAULT]: "bg-background-container-surface",
139
+ [DashboardMetricCardStyle.PRIMARY_BRAND_FILLED]: "bg-background-primary-brand-default border-border-primary-brand-default dark",
140
+ [DashboardMetricCardStyle.PRIMARY_BRAND_SOFT]: "bg-background-primary-brand-soft",
141
+ [DashboardMetricCardStyle.SECONDARY_BRAND_FILLED]: "bg-background-secondary-brand-default border-border-secondary-brand dark",
142
+ [DashboardMetricCardStyle.SECONDARY_BRAND_SOFT]: "bg-background-secondary-brand-soft",
143
+ [DashboardMetricCardStyle.NEUTRAL_FILLED]: "bg-background-neutral-bold dark",
144
+ [DashboardMetricCardStyle.NEUTRAL_SOFT]: "bg-background-neutral-subtler",
145
+ [DashboardMetricCardStyle.CUSTOM_FILLED]: props.customFilledColorClass,
146
+ };
147
+
148
+ return variant[props.styleType as DashboardMetricCardStyle] || "bg-background-container-surface";
149
+ });
150
+
151
+ const containedIconStyleType = computed(() => {
152
+ if (props.styleType === DashboardMetricCardStyle.DEFAULT) {
153
+ return props.defaultStyleIconContainerType;
154
+ }
155
+
156
+ return IconContainerStyleType.FILLED;
157
+ });
158
+
159
+ const containedIconShape = computed(() => {
160
+ if (props.styleType === DashboardMetricCardStyle.DEFAULT) {
161
+ return props.iconContainerShape;
162
+ }
163
+
164
+ return IconContainerShape.SQUARE;
165
+ });
166
+
167
+ const iconColor = computed(() => {
168
+ if (props.defaultStyleIconColor && props.styleType === DashboardMetricCardStyle.DEFAULT) {
169
+ return props.defaultStyleIconColor;
40
170
  }
41
- })
42
- </script>
171
+
172
+ const variant: Record<DashboardMetricCardStyle, ColorAccent> = {
173
+ [DashboardMetricCardStyle.DEFAULT]: ColorAccent.NEUTRAL,
174
+ [DashboardMetricCardStyle.PRIMARY_BRAND_FILLED]: ColorAccent.PRIMARY_BRAND,
175
+ [DashboardMetricCardStyle.PRIMARY_BRAND_SOFT]: ColorAccent.PRIMARY_BRAND,
176
+ [DashboardMetricCardStyle.SECONDARY_BRAND_FILLED]: ColorAccent.SECONDARY_BRAND,
177
+ [DashboardMetricCardStyle.SECONDARY_BRAND_SOFT]: ColorAccent.SECONDARY_BRAND,
178
+ [DashboardMetricCardStyle.NEUTRAL_FILLED]: ColorAccent.NEUTRAL,
179
+ [DashboardMetricCardStyle.NEUTRAL_SOFT]: ColorAccent.NEUTRAL,
180
+ [DashboardMetricCardStyle.CUSTOM_FILLED]: ColorAccent.NEUTRAL,
181
+ };
182
+
183
+ return variant[props.styleType as DashboardMetricCardStyle] || ColorAccent.NEUTRAL;
184
+ });
185
+
186
+ const textColorClass = computed(() => {
187
+ const variant: Record<DashboardMetricCardStyle, string> = {
188
+ [DashboardMetricCardStyle.DEFAULT]: "text-text-neutral-default",
189
+ [DashboardMetricCardStyle.PRIMARY_BRAND_FILLED]: "text-text-neutral-on-filled",
190
+ [DashboardMetricCardStyle.PRIMARY_BRAND_SOFT]: "text-text-primary-brand-on-soft-bg",
191
+ [DashboardMetricCardStyle.SECONDARY_BRAND_FILLED]: "text-text-neutral-on-filled",
192
+ [DashboardMetricCardStyle.SECONDARY_BRAND_SOFT]: "text-text-secondary-brand-on-soft-bg",
193
+ [DashboardMetricCardStyle.NEUTRAL_FILLED]: "text-text-neutral-on-filled",
194
+ [DashboardMetricCardStyle.NEUTRAL_SOFT]: "text-text-neutral-on-neutral-bg",
195
+ [DashboardMetricCardStyle.CUSTOM_FILLED]: "text-text-neutral-on-filled",
196
+ };
197
+
198
+ return variant[props.styleType as DashboardMetricCardStyle] || "text-text-neutral-default";
199
+ });
200
+
201
+ const isFilledStyle = computed(() => {
202
+ return [
203
+ DashboardMetricCardStyle.PRIMARY_BRAND_FILLED,
204
+ DashboardMetricCardStyle.SECONDARY_BRAND_FILLED,
205
+ DashboardMetricCardStyle.NEUTRAL_FILLED,
206
+ DashboardMetricCardStyle.CUSTOM_FILLED,
207
+ ].includes(props.styleType as DashboardMetricCardStyle);
208
+ });
209
+
210
+ const trendUpClass = computed(() => {
211
+ return isFilledStyle.value ? "text-text-neutral-on-filled" : "text-text-success";
212
+ });
213
+
214
+ const trendDownClass = computed(() => {
215
+ return isFilledStyle.value ? "text-text-neutral-on-filled" : "text-text-error";
216
+ });
217
+
218
+ const trendNeutralClass = computed(() => {
219
+ return isFilledStyle.value ? "text-text-neutral-on-filled" : "text-text-neutral-subtle";
220
+ });
221
+
222
+ const trendTextColorClass = computed(() => {
223
+ const variant: Record<DashboardMetricTrendDirection, string> = {
224
+ [DashboardMetricTrendDirection.UP]: trendUpClass.value,
225
+ [DashboardMetricTrendDirection.DOWN]: trendDownClass.value,
226
+ [DashboardMetricTrendDirection.NEUTRAL]: trendNeutralClass.value,
227
+ };
228
+
229
+ return variant[props.trendDirection as DashboardMetricTrendDirection] || trendUpClass.value;
230
+ });
231
+ </script>
@@ -20,11 +20,15 @@ const props = defineProps({
20
20
  type: Number as PropType<number>,
21
21
  default: 240,
22
22
  },
23
+ mobileBreakpoint: {
24
+ type: Number as PropType<number>,
25
+ default: 1024,
26
+ },
23
27
  })
24
28
 
25
29
  // Composables
26
30
  const { isMobileSidebarOpen } = useMobileSidebar()
27
- const { isMobile } = useIsMobile()
31
+ const { isMobile } = useIsMobile(() => props.mobileBreakpoint)
28
32
 
29
33
  // Computed dynamic style
30
34
  const containerStyle = computed(() => {
@@ -15,13 +15,17 @@
15
15
 
16
16
  <script setup lang="ts">
17
17
  // Props
18
- defineProps({
18
+ const props = defineProps({
19
19
  tocSidebarWidth: {
20
20
  type: Number as PropType<number>,
21
21
  default: 240
22
- }
22
+ },
23
+ mobileBreakpoint: {
24
+ type: Number as PropType<number>,
25
+ default: 1024,
26
+ },
23
27
  })
24
28
 
25
29
  // Composable
26
- const { isMobile } = useIsMobile()
30
+ const { isMobile } = useIsMobile(() => props.mobileBreakpoint)
27
31
  </script>
@@ -34,12 +34,12 @@
34
34
  && sidebarTogglePosition === SidebarTogglePosition.LOGO_LEFT_SIDE
35
35
  "
36
36
  >
37
- <ActionIconButton
37
+ <ActionIconButton
38
38
  :icon="isMobileSidebarOpen ? 'mdi:menu-open' : 'mdi:menu-close'"
39
- class="lg:hidden shadow-sm"
39
+ :class="['shadow-sm', !isMobile && 'hidden']"
40
40
  @click="toggleMobileSidebar"
41
41
  />
42
- </template>
42
+ </template>
43
43
 
44
44
  <slot name="header-logo" />
45
45
 
@@ -49,20 +49,20 @@
49
49
  && sidebarTogglePosition === SidebarTogglePosition.LOGO_RIGHT_SIDE
50
50
  "
51
51
  >
52
- <ActionIconButton
52
+ <ActionIconButton
53
53
  :icon="isMobileSidebarOpen ? 'mdi:menu-open' : 'mdi:menu-close'"
54
- class="lg:hidden shadow-sm"
54
+ :class="['shadow-sm', !isMobile && 'hidden']"
55
55
  @click="toggleMobileSidebar"
56
56
  />
57
- </template>
57
+ </template>
58
58
  </div>
59
59
 
60
60
  <!-- Navigation -->
61
61
  <div class="flex gap-3 items-center xs:w-auto">
62
62
  <!-- Horizontal menu -->
63
- <NavMenu
64
- v-if="navMenuItems.length"
65
- :menuItems="navMenuItems"
63
+ <NavMenu
64
+ v-if="navMenuItems.length && !isMobile"
65
+ :menuItems="navMenuItems"
66
66
  :detectActive="detectActiveMenuItem"
67
67
  :submenuYOffset
68
68
  :submenuDropdownClass
@@ -74,7 +74,7 @@
74
74
  <!-- Header actions -->
75
75
  <div
76
76
  v-if="$slots['header-actions']"
77
- class="gap-3 items-center hidden lg:flex"
77
+ :class="['gap-3 items-center', isMobile ? 'hidden' : 'flex']"
78
78
  >
79
79
  <slot name="header-actions" />
80
80
  </div>
@@ -117,9 +117,9 @@
117
117
  :positionYOffset="submenuYOffset"
118
118
  >
119
119
  <template #activator>
120
- <ActionIconButton
120
+ <ActionIconButton
121
121
  icon="mdi:menu"
122
- class="lg:hidden shadow-sm"
122
+ class="shadow-sm"
123
123
  />
124
124
  </template>
125
125
  <template #items>
@@ -197,6 +197,10 @@ const props = defineProps({
197
197
  type: Array as PropType<DropdownMenuItem[]>,
198
198
  default: () => [],
199
199
  },
200
+ mobileBreakpoint: {
201
+ type: Number as PropType<number>,
202
+ default: 1024,
203
+ },
200
204
  showMobileMenuToggle: {
201
205
  type: Boolean as PropType<boolean>,
202
206
  default: true,
@@ -232,18 +236,18 @@ const props = defineProps({
232
236
  },
233
237
  navMenuClass: {
234
238
  type: String as PropType<string>,
235
- default: 'hidden lg:flex'
239
+ default: ''
236
240
  },
237
241
  navMobileMenuClass: {
238
242
  type: String as PropType<string>,
239
- default: 'lg:hidden min-w-[280px]'
243
+ default: 'min-w-[280px]'
240
244
  },
241
245
  headerClass: String as PropType<string>,
242
246
  })
243
247
 
244
248
  // Composables
245
249
  const { isMobileSidebarOpen, toggleMobileSidebar } = useMobileSidebar()
246
- const { isMobile } = useIsMobile()
250
+ const { isMobile } = useIsMobile(() => props.mobileBreakpoint)
247
251
 
248
252
  const getSubmenuItems = (item: MenuItem): NonNullable<MenuItem['children']> => {
249
253
  return item.children ?? []
@@ -14,8 +14,7 @@
14
14
  'py-4',
15
15
  'border-r border-border-default',
16
16
  'transition-all duration-300 ease-in-out',
17
- isMobileSidebarOpen ? 'translate-x-0' : '-translate-x-full',
18
- 'lg:translate-x-0', // Always visible on large screens
17
+ (!isMobile || isMobileSidebarOpen) ? 'translate-x-0' : '-translate-x-full',
19
18
  ]"
20
19
  >
21
20
  <!-- Collapse & Close Buttons -->
@@ -32,7 +31,7 @@
32
31
  <ActionIconButton
33
32
  v-if="showMobileSidebarClose && isMobile && !isCollapsed"
34
33
  :icon="mobileSidebarCloseIcon"
35
- class="flex sm:hidden"
34
+ class="flex"
36
35
  :size="ButtonSize.SM"
37
36
  @click="toggleMobileSidebar()"
38
37
  />
@@ -294,6 +293,10 @@ const props = defineProps({
294
293
  type: String as PropType<string>,
295
294
  default: 'mdi:close-circle',
296
295
  },
296
+ mobileBreakpoint: {
297
+ type: Number as PropType<number>,
298
+ default: 1024,
299
+ },
297
300
  isFixed: {
298
301
  type: Boolean as PropType<boolean>,
299
302
  default: true,
@@ -354,7 +357,7 @@ const {
354
357
  setSidebarCollapsed,
355
358
  toggleSidebarState,
356
359
  } = useSidebar()
357
- const { isMobile } = useIsMobile()
360
+ const { isMobile } = useIsMobile(() => props.mobileBreakpoint)
358
361
 
359
362
  const MAX_NESTING_LEVEL = 3
360
363
 
@@ -5,8 +5,7 @@
5
5
  'justify-between',
6
6
  'items-center',
7
7
  'gap-3',
8
- 'flex-col-reverse',
9
- 'lg:flex-row',
8
+ isMobile ? 'flex-col-reverse' : 'flex-row',
10
9
  'w-full'
11
10
  ]"
12
11
  >
@@ -26,7 +25,7 @@
26
25
  v-model="itemsPerPage"
27
26
  :rowsLabel="rowsPerPageLabel"
28
27
  :rowsOptions="rowsPerPageOptions"
29
- class="flex lg:hidden"
28
+ :class="[isMobile ? 'flex' : 'hidden']"
30
29
  /> <!-- Mobile position -->
31
30
  </div>
32
31
 
@@ -35,10 +34,7 @@
35
34
  :class="[
36
35
  'flex',
37
36
  'gap-6',
38
- 'flex-col',
39
- 'w-full',
40
- 'lg:flex-row',
41
- 'lg:w-auto'
37
+ isMobile ? 'flex-col w-full' : 'flex-row w-auto'
42
38
  ]"
43
39
  >
44
40
  <RowsPerPage
@@ -46,7 +42,7 @@
46
42
  v-model="itemsPerPage"
47
43
  :rowsLabel="rowsPerPageLabel"
48
44
  :rowsOptions="rowsPerPageOptions"
49
- class="hidden lg:flex"
45
+ :class="[isMobile ? 'hidden' : 'flex']"
50
46
  />
51
47
  <nav
52
48
  v-if="totalItems > itemsPerPage"
@@ -168,10 +164,14 @@ const props = defineProps({
168
164
  type: String as PropType<string>,
169
165
  default: 'Showing {total} result',
170
166
  },
167
+ mobileBreakpoint: {
168
+ type: Number as PropType<number>,
169
+ default: 1024,
170
+ },
171
171
  })
172
172
 
173
173
  // Composables
174
- const { isMobile } = useIsMobile()
174
+ const { isMobile } = useIsMobile(() => props.mobileBreakpoint)
175
175
 
176
176
  // States
177
177
  const itemsPerPage = ref(props.itemsPerPage)
@@ -1,27 +1,32 @@
1
- export const useIsMobile = (breakpoint: number = 1024) => {
2
- const isMobile = ref(false) // Initial value for SSR
3
-
4
- // Function to update `isMobile`
5
- const updateIsMobile = () => {
6
- if (typeof window !== 'undefined') {
7
- isMobile.value = window.innerWidth < breakpoint
8
- }
9
- }
10
-
11
- // Attach resize listener on the client
12
- onMounted(() => {
13
- updateIsMobile() // Initialize the value
14
- window.addEventListener('resize', updateIsMobile)
15
- })
16
-
17
- // Cleanup listener when unmounted
18
- onUnmounted(() => {
19
- if (typeof window !== 'undefined') {
20
- window.removeEventListener('resize', updateIsMobile)
21
- }
22
- })
23
-
24
- return {
25
- isMobile,
26
- }
27
- }
1
+ import { toValue, type MaybeRefOrGetter } from 'vue'
2
+
3
+ export const useIsMobile = (breakpoint: MaybeRefOrGetter<number> = 1024) => {
4
+ const isMobile = ref(false) // Initial value for SSR
5
+
6
+ // Function to update `isMobile`
7
+ const updateIsMobile = () => {
8
+ if (typeof window !== 'undefined') {
9
+ isMobile.value = window.innerWidth < toValue(breakpoint)
10
+ }
11
+ }
12
+
13
+ // Attach resize listener on the client
14
+ onMounted(() => {
15
+ updateIsMobile() // Initialize the value
16
+ window.addEventListener('resize', updateIsMobile)
17
+ })
18
+
19
+ // Re-evaluate when the breakpoint itself changes
20
+ watch(() => toValue(breakpoint), updateIsMobile)
21
+
22
+ // Cleanup listener when unmounted
23
+ onUnmounted(() => {
24
+ if (typeof window !== 'undefined') {
25
+ window.removeEventListener('resize', updateIsMobile)
26
+ }
27
+ })
28
+
29
+ return {
30
+ isMobile,
31
+ }
32
+ }
@@ -0,0 +1,16 @@
1
+ export enum DashboardMetricCardStyle {
2
+ DEFAULT = "default",
3
+ PRIMARY_BRAND_FILLED = "primary-brand-filled",
4
+ PRIMARY_BRAND_SOFT = "primary-brand-soft",
5
+ SECONDARY_BRAND_FILLED = "secondary-brand-filled",
6
+ SECONDARY_BRAND_SOFT = "secondary-brand-soft",
7
+ NEUTRAL_FILLED = "neutral-filled",
8
+ NEUTRAL_SOFT = "neutral-soft",
9
+ CUSTOM_FILLED = "custom-filled",
10
+ }
11
+
12
+ export enum DashboardMetricTrendDirection {
13
+ UP = "up",
14
+ DOWN = "down",
15
+ NEUTRAL = "neutral",
16
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imaginario27/air-ui-ds",
3
- "version": "1.12.2",
3
+ "version": "1.13.1",
4
4
  "author": "imaginario27",
5
5
  "type": "module",
6
6
  "homepage": "https://air-ui.netlify.app/",