@veristone/nuxt-v-app 0.1.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.
Files changed (136) hide show
  1. package/README.md +42 -0
  2. package/app/app.vue +7 -0
  3. package/app/assets/css/v-app.css +313 -0
  4. package/app/components/V/A/Badge.vue +75 -0
  5. package/app/components/V/A/Btn/Add.vue +17 -0
  6. package/app/components/V/A/Btn/Back.vue +25 -0
  7. package/app/components/V/A/Btn/ConfirmDelete.vue +45 -0
  8. package/app/components/V/A/Btn/Edit.vue +35 -0
  9. package/app/components/V/A/Btn/Export.vue +28 -0
  10. package/app/components/V/A/Btn/Refresh.vue +21 -0
  11. package/app/components/V/A/Btn/Submit.vue +45 -0
  12. package/app/components/V/A/Btn/View.vue +23 -0
  13. package/app/components/V/A/Card.legacy.vue +291 -0
  14. package/app/components/V/A/Card.vue +108 -0
  15. package/app/components/V/A/CompanyMenu.vue +83 -0
  16. package/app/components/V/A/Data/KeyValue.vue +98 -0
  17. package/app/components/V/A/Data/StatusBadge.vue +44 -0
  18. package/app/components/V/A/DataField.vue +140 -0
  19. package/app/components/V/A/DataGrid.vue +43 -0
  20. package/app/components/V/A/DataTable.vue +144 -0
  21. package/app/components/V/A/EmptyState.vue +154 -0
  22. package/app/components/V/A/Fmt/Currency.vue +36 -0
  23. package/app/components/V/A/Fmt/DateTime.vue +34 -0
  24. package/app/components/V/A/Fmt/Percent.vue +47 -0
  25. package/app/components/V/A/LoadingState.vue +140 -0
  26. package/app/components/V/A/MetricCard.vue +129 -0
  27. package/app/components/V/A/Modal/Base.vue +195 -0
  28. package/app/components/V/A/Modal/Confirm.vue +92 -0
  29. package/app/components/V/A/Modal/Form.vue +105 -0
  30. package/app/components/V/A/Navigation.vue +110 -0
  31. package/app/components/V/A/QuickActions.vue +169 -0
  32. package/app/components/V/A/Slide.vue +109 -0
  33. package/app/components/V/A/Slideover.vue +259 -0
  34. package/app/components/V/A/State/Empty.vue +20 -0
  35. package/app/components/V/A/State/Error.vue +34 -0
  36. package/app/components/V/A/State/Loading.vue +33 -0
  37. package/app/components/V/A/StatsCard.vue +215 -0
  38. package/app/components/V/A/StatusBadge.vue +215 -0
  39. package/app/components/V/A/Table.vue +674 -0
  40. package/app/components/V/A/UserMenu.vue +127 -0
  41. package/app/components/V/A/WelcomeHeader.vue +96 -0
  42. package/app/components/V/Modal.vue +36 -0
  43. package/app/components/Va/Blocks/VaBlockGridCharts.vue +32 -0
  44. package/app/components/Va/Blocks/VaBlockGridKPI.vue +32 -0
  45. package/app/components/Va/Blocks/VaBlockGridTables.vue +23 -0
  46. package/app/components/Va/Blocks/VaBlockKpiGrid.vue +8 -0
  47. package/app/components/Va/Blocks/VaBlockSessionFilterBar.vue +8 -0
  48. package/app/components/Va/Cards/VaCardDonutChart.vue +59 -0
  49. package/app/components/Va/Cards/VaCardHeader.vue +10 -0
  50. package/app/components/Va/Cards/VaCardKpi.vue +17 -0
  51. package/app/components/Va/Cards/VaCardKpi2.vue +55 -0
  52. package/app/components/Va/Cards/VaCardLatestOrders.vue +82 -0
  53. package/app/components/Va/Cards/VaCardPopularProducts.vue +88 -0
  54. package/app/components/Va/Cards/VaCardRevenueBarChart.vue +49 -0
  55. package/app/components/Va/Cards/VaCardSubtitle.vue +5 -0
  56. package/app/components/Va/Cards/VaCardTitle.vue +5 -0
  57. package/app/components/Va/Cards/VaCardWithActiveUsers.vue +41 -0
  58. package/app/components/Va/Cards/VaCardWithChart.vue +135 -0
  59. package/app/components/Va/Cards/VaCardWithChartBlock.vue +26 -0
  60. package/app/components/Va/Cards/VaCardWithIndicator.vue +39 -0
  61. package/app/components/Va/Cards/VaCardWithProgressCircle.vue +34 -0
  62. package/app/components/Va/Cards/types.ts +11 -0
  63. package/app/components/Va/Charts/VaChartAppPerformanceBar.vue +118 -0
  64. package/app/components/Va/Charts/VaChartAppPerformanceBarChart.vue +118 -0
  65. package/app/components/Va/Charts/VaChartAreaMini.vue +127 -0
  66. package/app/components/Va/Charts/VaChartBarMini.vue +68 -0
  67. package/app/components/Va/Charts/VaChartCardinalMulti.vue +108 -0
  68. package/app/components/Va/Charts/VaChartColorBarChart.vue +78 -0
  69. package/app/components/Va/Charts/VaChartDonutHalf.vue +35 -0
  70. package/app/components/Va/Charts/VaChartDonutMini.vue +77 -0
  71. package/app/components/Va/Charts/VaChartExpensesBar.vue +58 -0
  72. package/app/components/Va/Charts/VaChartFinanceSummary.vue +96 -0
  73. package/app/components/Va/Charts/VaChartGoogleSearchConsole.vue +90 -0
  74. package/app/components/Va/Charts/VaChartIncomeBar.vue +82 -0
  75. package/app/components/Va/Charts/VaChartLegend.vue +25 -0
  76. package/app/components/Va/Charts/VaChartLineMini.vue +205 -0
  77. package/app/components/Va/Charts/VaChartRealtimeTraffic.vue +182 -0
  78. package/app/components/Va/Charts/VaChartRevenue.vue +43 -0
  79. package/app/components/Va/Charts/VaChartRevenueLine.vue +42 -0
  80. package/app/components/Va/Charts/VaChartRevenuevsCost.vue +84 -0
  81. package/app/components/Va/Charts/VaChartSearchIntent.vue +179 -0
  82. package/app/components/Va/Charts/VaChartSpendingTrend.vue +127 -0
  83. package/app/components/Va/Charts/VaChartStackedHorizontal.vue +64 -0
  84. package/app/components/Va/Charts/VaChartStepMinimal.vue +109 -0
  85. package/app/components/Va/Charts/VaChartStockComparisonLine.vue +86 -0
  86. package/app/components/Va/Charts/VaChartStocksPortfolioLine.vue +161 -0
  87. package/app/components/Va/Charts/VaChartStocksSectorLine.vue +223 -0
  88. package/app/components/Va/Charts/VaChartTasksCategories.vue +96 -0
  89. package/app/components/Va/Charts/VaChartTasksProgress.vue +130 -0
  90. package/app/components/Va/Charts/VaChartTrafficOverview.vue +112 -0
  91. package/app/components/Va/Charts/VaChartWebPerformanceLineChart.vue +114 -0
  92. package/app/components/Va/Charts/VaChartWinLostBar.vue +110 -0
  93. package/app/components/Va/Charts/VaChartWinLostDonut.vue +107 -0
  94. package/app/components/Va/Charts/VaChartWinLostLine.vue +111 -0
  95. package/app/components/Va/Charts/types.ts +10 -0
  96. package/app/components/Va/Dashboard/Navigation/types.ts +8 -0
  97. package/app/components/Va/Dashboard/VaDashboardKPICard.vue +31 -0
  98. package/app/components/Va/Dashboard/VaDashboardNavigation.vue +50 -0
  99. package/app/components/Va/Dashboard/VaDashboardPricePlan.vue +102 -0
  100. package/app/components/Va/Dashboard/VaDashboardUsageChart.vue +84 -0
  101. package/app/components/Va/Dashboard/VaDashboardUsageRequestChart.vue +46 -0
  102. package/app/components/Va/Layout/NotificationsSlideover.vue +169 -0
  103. package/app/components/Va/Layout/SideNav/types.ts +5 -0
  104. package/app/components/Va/Layout/SideNav.vue +108 -0
  105. package/app/components/Va/Layout/TeamsMenu.vue +57 -0
  106. package/app/components/Va/Layout/UserMenu.vue +57 -0
  107. package/app/composables/useDashboard.ts +25 -0
  108. package/app/composables/useVAAnimation.ts +324 -0
  109. package/app/composables/useVAUtils.ts +118 -0
  110. package/app/composables/useVCrud.ts +647 -0
  111. package/app/composables/useVFetch.ts +46 -0
  112. package/app/composables/useVFileUpload.ts +45 -0
  113. package/app/composables/useVToast.ts +73 -0
  114. package/app/composables/useXATableColumns.ts +456 -0
  115. package/app/data/BillingStats.ts +65 -0
  116. package/app/data/SearchData.ts +58 -0
  117. package/app/data/TasksData.ts +101 -0
  118. package/app/data/dashboardData.ts +113 -0
  119. package/app/layouts/default.vue +171 -0
  120. package/app/layouts/legacy.vue +61 -0
  121. package/app/pages/playground/base.vue +498 -0
  122. package/app/pages/playground/blocks.vue +108 -0
  123. package/app/pages/playground/buttons.vue +237 -0
  124. package/app/pages/playground/cards.vue +326 -0
  125. package/app/pages/playground/charts.vue +338 -0
  126. package/app/pages/playground/dashboard.vue +315 -0
  127. package/app/pages/playground/formatters.vue +329 -0
  128. package/app/pages/playground/index.vue +109 -0
  129. package/app/pages/playground/layout.vue +159 -0
  130. package/app/pages/playground/modals.vue +606 -0
  131. package/app/pages/playground/states.vue +282 -0
  132. package/app/pages/playground/tables.vue +618 -0
  133. package/app/pages/test-layout.vue +10 -0
  134. package/nuxt.config.ts +12 -0
  135. package/package.json +71 -0
  136. package/tsconfig.json +18 -0
@@ -0,0 +1,324 @@
1
+ /**
2
+ * useVAAnimation - Animation utilities for Veristone components
3
+ * Provides stagger delays, scroll reveal, and animated counters
4
+ */
5
+
6
+ export interface RevealOptions {
7
+ threshold?: number
8
+ rootMargin?: string
9
+ once?: boolean
10
+ }
11
+
12
+ export interface CountUpOptions {
13
+ duration?: number
14
+ easing?: (t: number) => number
15
+ separator?: string
16
+ decimal?: string
17
+ decimals?: number
18
+ prefix?: string
19
+ suffix?: string
20
+ }
21
+
22
+ export function useVAAnimation() {
23
+ /**
24
+ * Calculate stagger delay for list animations
25
+ * @param index - Item index in the list
26
+ * @param baseDelay - Base delay in milliseconds (default: 50)
27
+ * @returns CSS delay string
28
+ */
29
+ const staggerDelay = (index: number, baseDelay = 50): string => {
30
+ return `${index * baseDelay}ms`
31
+ }
32
+
33
+ /**
34
+ * Generate stagger delay style object for v-bind
35
+ * @param index - Item index
36
+ * @param baseDelay - Base delay in ms
37
+ */
38
+ const staggerStyle = (index: number, baseDelay = 50) => ({
39
+ animationDelay: staggerDelay(index, baseDelay)
40
+ })
41
+
42
+ /**
43
+ * Intersection Observer hook for scroll reveal animations
44
+ * @param options - Observer options
45
+ */
46
+ const useRevealOnScroll = (options: RevealOptions = {}) => {
47
+ const {
48
+ threshold = 0.1,
49
+ rootMargin = '0px 0px -50px 0px',
50
+ once = true
51
+ } = options
52
+
53
+ const elementRef = shallowRef<HTMLElement | null>(null)
54
+ const isVisible = ref(false)
55
+
56
+ let observer: IntersectionObserver | null = null
57
+
58
+ const observe = () => {
59
+ const el = elementRef.value
60
+ if (!el || typeof IntersectionObserver === 'undefined') {
61
+ isVisible.value = true
62
+ return
63
+ }
64
+
65
+ observer = new IntersectionObserver(
66
+ (entries) => {
67
+ entries.forEach((entry) => {
68
+ if (entry.isIntersecting) {
69
+ isVisible.value = true
70
+ if (once && observer) {
71
+ observer.disconnect()
72
+ }
73
+ } else if (!once) {
74
+ isVisible.value = false
75
+ }
76
+ })
77
+ },
78
+ { threshold, rootMargin }
79
+ )
80
+
81
+ observer.observe(el)
82
+ }
83
+
84
+ const unobserve = () => {
85
+ if (observer) {
86
+ observer.disconnect()
87
+ observer = null
88
+ }
89
+ }
90
+
91
+ onMounted(observe)
92
+ onUnmounted(unobserve)
93
+
94
+ return {
95
+ elementRef,
96
+ isVisible
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Animated number counter
102
+ * @param endValue - Target value to count to
103
+ * @param options - Animation options
104
+ */
105
+ const useCountUp = (
106
+ endValue: Ref<number> | number,
107
+ options: CountUpOptions = {}
108
+ ) => {
109
+ const {
110
+ duration = 1000,
111
+ easing = easeOutExpo,
112
+ separator = ',',
113
+ decimal = '.',
114
+ decimals = 0,
115
+ prefix = '',
116
+ suffix = ''
117
+ } = options
118
+
119
+ const displayValue = ref('0')
120
+ const currentValue = ref(0)
121
+ let animationFrame: number | null = null
122
+ let startTime: number | null = null
123
+ let startValue = 0
124
+
125
+ const formatNumber = (num: number): string => {
126
+ const fixed = num.toFixed(decimals)
127
+ const parts = fixed.split('.')
128
+ const intPart = parts[0] || '0'
129
+ const decPart = parts[1]
130
+
131
+ const formattedInt = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, separator)
132
+
133
+ if (decimals > 0 && decPart) {
134
+ return `${prefix}${formattedInt}${decimal}${decPart}${suffix}`
135
+ }
136
+ return `${prefix}${formattedInt}${suffix}`
137
+ }
138
+
139
+ const animate = (timestamp: number) => {
140
+ if (!startTime) startTime = timestamp
141
+
142
+ const elapsed = timestamp - startTime
143
+ const progress = Math.min(elapsed / duration, 1)
144
+ const easedProgress = easing(progress)
145
+
146
+ const end = unref(endValue)
147
+ currentValue.value = startValue + (end - startValue) * easedProgress
148
+ displayValue.value = formatNumber(currentValue.value)
149
+
150
+ if (progress < 1) {
151
+ animationFrame = requestAnimationFrame(animate)
152
+ }
153
+ }
154
+
155
+ const start = (from = 0) => {
156
+ if (animationFrame) {
157
+ cancelAnimationFrame(animationFrame)
158
+ }
159
+ startValue = from
160
+ startTime = null
161
+ animationFrame = requestAnimationFrame(animate)
162
+ }
163
+
164
+ const reset = () => {
165
+ if (animationFrame) {
166
+ cancelAnimationFrame(animationFrame)
167
+ }
168
+ currentValue.value = 0
169
+ displayValue.value = formatNumber(0)
170
+ }
171
+
172
+ // Watch for value changes
173
+ if (isRef(endValue)) {
174
+ watch(endValue, (_newVal, oldVal) => {
175
+ start(oldVal || 0)
176
+ })
177
+ }
178
+
179
+ onMounted(() => {
180
+ start(0)
181
+ })
182
+
183
+ onUnmounted(() => {
184
+ if (animationFrame) {
185
+ cancelAnimationFrame(animationFrame)
186
+ }
187
+ })
188
+
189
+ return {
190
+ displayValue,
191
+ currentValue,
192
+ start,
193
+ reset
194
+ }
195
+ }
196
+
197
+ /**
198
+ * Animate a list of items with staggered entrance
199
+ * @param items - Reactive array of items
200
+ * @param delay - Delay between items in ms
201
+ */
202
+ const useStaggeredList = <T>(items: Ref<T[]>, delay = 50) => {
203
+ const visibleItems = shallowRef<T[]>([])
204
+ let timeouts: ReturnType<typeof setTimeout>[] = []
205
+
206
+ const animateIn = () => {
207
+ // Clear existing timeouts
208
+ timeouts.forEach(clearTimeout)
209
+ timeouts = []
210
+ visibleItems.value = []
211
+
212
+ items.value.forEach((item, index) => {
213
+ const timeout = setTimeout(() => {
214
+ visibleItems.value = [...visibleItems.value, item]
215
+ }, index * delay)
216
+ timeouts.push(timeout)
217
+ })
218
+ }
219
+
220
+ const animateOut = () => {
221
+ timeouts.forEach(clearTimeout)
222
+ timeouts = []
223
+ visibleItems.value = []
224
+ }
225
+
226
+ watch(items, animateIn, { immediate: true, deep: true })
227
+
228
+ onUnmounted(() => {
229
+ timeouts.forEach(clearTimeout)
230
+ })
231
+
232
+ return {
233
+ visibleItems,
234
+ animateIn,
235
+ animateOut
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Typewriter effect for text
241
+ * @param text - Text to type
242
+ * @param speed - Characters per second
243
+ */
244
+ const useTypewriter = (text: Ref<string> | string, speed = 50) => {
245
+ const displayText = ref('')
246
+ let index = 0
247
+ let interval: ReturnType<typeof setInterval> | null = null
248
+
249
+ const start = () => {
250
+ const fullText = unref(text)
251
+ index = 0
252
+ displayText.value = ''
253
+
254
+ if (interval) clearInterval(interval)
255
+
256
+ interval = setInterval(() => {
257
+ if (index < fullText.length) {
258
+ displayText.value += fullText[index]
259
+ index++
260
+ } else {
261
+ if (interval) clearInterval(interval)
262
+ }
263
+ }, 1000 / speed)
264
+ }
265
+
266
+ const reset = () => {
267
+ if (interval) clearInterval(interval)
268
+ displayText.value = ''
269
+ index = 0
270
+ }
271
+
272
+ if (isRef(text)) {
273
+ watch(text, start)
274
+ }
275
+
276
+ onMounted(start)
277
+ onUnmounted(() => {
278
+ if (interval) clearInterval(interval)
279
+ })
280
+
281
+ return {
282
+ displayText,
283
+ start,
284
+ reset
285
+ }
286
+ }
287
+
288
+ return {
289
+ staggerDelay,
290
+ staggerStyle,
291
+ useRevealOnScroll,
292
+ useCountUp,
293
+ useStaggeredList,
294
+ useTypewriter
295
+ }
296
+ }
297
+
298
+ // Easing functions
299
+ function easeOutExpo(x: number): number {
300
+ return x === 1 ? 1 : 1 - Math.pow(2, -10 * x)
301
+ }
302
+
303
+ function easeOutCubic(x: number): number {
304
+ return 1 - Math.pow(1 - x, 3)
305
+ }
306
+
307
+ function easeOutQuart(x: number): number {
308
+ return 1 - Math.pow(1 - x, 4)
309
+ }
310
+
311
+ function easeInOutQuad(x: number): number {
312
+ return x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2
313
+ }
314
+
315
+ // Export easing functions for custom use
316
+ export const easings = {
317
+ easeOutExpo,
318
+ easeOutCubic,
319
+ easeOutQuart,
320
+ easeInOutQuad
321
+ }
322
+
323
+ // Default export for convenience
324
+ export default useVAAnimation
@@ -0,0 +1,118 @@
1
+ /**
2
+ * VA Utility Composable
3
+ * Common utility functions for the V-App layer
4
+ */
5
+ export function useVAUtils() {
6
+ /**
7
+ * Format a number with thousand separators
8
+ */
9
+ const formatNumber = (value: number): string => {
10
+ return new Intl.NumberFormat().format(value)
11
+ }
12
+
13
+ /**
14
+ * Format currency
15
+ */
16
+ const formatCurrency = (value: number, currency = 'USD'): string => {
17
+ return new Intl.NumberFormat('en-US', {
18
+ style: 'currency',
19
+ currency,
20
+ minimumFractionDigits: 0,
21
+ maximumFractionDigits: 0
22
+ }).format(value)
23
+ }
24
+
25
+ /**
26
+ * Format percentage
27
+ */
28
+ const formatPercent = (value: number, decimals = 1): string => {
29
+ const sign = value >= 0 ? '+' : ''
30
+ return `${sign}${value.toFixed(decimals)}%`
31
+ }
32
+
33
+ /**
34
+ * Format relative time (e.g., "2 min ago")
35
+ */
36
+ const formatRelativeTime = (date: Date | string): string => {
37
+ const now = new Date()
38
+ const then = new Date(date)
39
+ const diffMs = now.getTime() - then.getTime()
40
+ const diffMins = Math.floor(diffMs / 60000)
41
+ const diffHours = Math.floor(diffMs / 3600000)
42
+ const diffDays = Math.floor(diffMs / 86400000)
43
+
44
+ if (diffMins < 1) return 'Just now'
45
+ if (diffMins < 60) return `${diffMins} min ago`
46
+ if (diffHours < 24) return `${diffHours} hour${diffHours > 1 ? 's' : ''} ago`
47
+ if (diffDays < 7) return `${diffDays} day${diffDays > 1 ? 's' : ''} ago`
48
+ return then.toLocaleDateString()
49
+ }
50
+
51
+ /**
52
+ * Truncate text with ellipsis
53
+ */
54
+ const truncate = (text: string, length: number): string => {
55
+ if (text.length <= length) return text
56
+ return text.slice(0, length) + '...'
57
+ }
58
+
59
+ /**
60
+ * Generate initials from name
61
+ */
62
+ const getInitials = (name: string): string => {
63
+ return name
64
+ .split(' ')
65
+ .map(part => part[0])
66
+ .join('')
67
+ .toUpperCase()
68
+ .slice(0, 2)
69
+ }
70
+
71
+ const debounce = <T extends (...args: unknown[]) => unknown>(
72
+ fn: T,
73
+ delay: number
74
+ ): ((...args: Parameters<T>) => void) => {
75
+ let timeoutId: ReturnType<typeof setTimeout>
76
+ return (...args: Parameters<T>) => {
77
+ clearTimeout(timeoutId)
78
+ timeoutId = setTimeout(() => fn(...args), delay)
79
+ }
80
+ }
81
+
82
+ type StatusColor = 'success' | 'warning' | 'error' | 'neutral' | 'info'
83
+ const statusColorMap: Record<string, StatusColor> = {
84
+ performing: 'success',
85
+ current: 'success',
86
+ default_30: 'warning',
87
+ default_60: 'warning',
88
+ default_90: 'error',
89
+ default_120: 'error',
90
+ default_maturity: 'error',
91
+ delinquent: 'error',
92
+ paid_off: 'neutral',
93
+ pending: 'warning',
94
+ approved: 'success',
95
+ rejected: 'error',
96
+ expired: 'neutral',
97
+ paid: 'success',
98
+ processing: 'info',
99
+ active: 'success',
100
+ inactive: 'neutral',
101
+ draft: 'neutral'
102
+ }
103
+
104
+ const getStatusColor = (status: string): StatusColor => {
105
+ return statusColorMap[status] || 'neutral'
106
+ }
107
+
108
+ return {
109
+ formatNumber,
110
+ formatCurrency,
111
+ formatPercent,
112
+ formatRelativeTime,
113
+ truncate,
114
+ getInitials,
115
+ debounce,
116
+ getStatusColor
117
+ }
118
+ }