@a-vision-software/vue-input-components 1.2.4 → 1.2.6

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/src/types.ts ADDED
@@ -0,0 +1,108 @@
1
+ import type { Component } from 'vue'
2
+
3
+ export interface TextInputProps {
4
+ modelValue: string
5
+ type?: 'text' | 'password' | 'email' | 'number' | 'tel' | 'url' | 'date'
6
+ label?: string
7
+ placeholder?: string
8
+ icon?: string
9
+ disabled?: boolean
10
+ readonly?: boolean
11
+ maxlength?: number
12
+ error?: string
13
+ min?: string
14
+ max?: string
15
+ required?: boolean
16
+ success?: string
17
+ labelPosition?: 'top' | 'left'
18
+ labelAlign?: 'left' | 'right' | 'center'
19
+ totalWidth?: string
20
+ inputWidth?: string
21
+ labelWidth?: string
22
+ autosave?: (value: string) => Promise<void>
23
+ isTextarea?: boolean
24
+ maxHeight?: string
25
+ height?: string
26
+ }
27
+
28
+ export interface FileUploadProps {
29
+ modelValue: File[]
30
+ label?: string
31
+ placeholder?: string
32
+ error?: string
33
+ disabled?: boolean
34
+ required?: boolean
35
+ multiple?: boolean
36
+ accept?: string
37
+ maxSize?: number
38
+ uploadUrl?: string
39
+ }
40
+
41
+ export interface FileUploadEmits {
42
+ (e: 'update:modelValue', files: File[]): void
43
+ (e: 'files-selected', files: File[]): void
44
+ (e: 'start-upload', files: File[]): void
45
+ (e: 'upload-progress', progress: number): void
46
+ (e: 'upload-success', response: any): void
47
+ (e: 'upload-error', error: Error): void
48
+ }
49
+
50
+ export type TextInputComponent = {
51
+ focus: () => void
52
+ blur: () => void
53
+ }
54
+
55
+ export type FileUploadComponent = Component<FileUploadProps>
56
+
57
+ export interface ActionProps {
58
+ icon?: string
59
+ label?: string
60
+ href?: string
61
+ type?: 'button' | 'submit' | 'reset'
62
+ disabled?: boolean
63
+ color?: string
64
+ size?: 'small' | 'regular' | 'large'
65
+ variant?: 'solid' | 'transparent'
66
+ }
67
+
68
+ export type ActionComponent = {
69
+ focus: () => void
70
+ blur: () => void
71
+ }
72
+
73
+ export interface NavigationItem {
74
+ id: string
75
+ label: string
76
+ icon?: string
77
+ url?: string
78
+ children?: NavigationItem[]
79
+ type?: 'tile' | 'tab' | 'dropdown'
80
+ color?: string
81
+ disabled?: boolean
82
+ alignment?: 'start' | 'end'
83
+ }
84
+
85
+ export interface NavigationProps {
86
+ items: NavigationItem[]
87
+ type?: 'tiles' | 'tabs' | 'dropdowns'
88
+ orientation?: 'horizontal' | 'vertical'
89
+ activeItem?: string
90
+ color?: string
91
+ hoverColor?: string
92
+ activeColor?: string
93
+ disabledColor?: string
94
+ iconSize?: string
95
+ gap?: string
96
+ padding?: string
97
+ borderRadius?: string
98
+ showIcons?: boolean
99
+ activeItemAlignment?: 'start' | 'end'
100
+ }
101
+
102
+ export interface NavigationComponent {
103
+ props: NavigationProps
104
+ emits: {
105
+ (e: 'item-click', item: NavigationItem): void
106
+ (e: 'update:activeItem', id: string): void
107
+ }
108
+ }
@@ -0,0 +1,307 @@
1
+ <template>
2
+ <div class="action-test">
3
+ <div class="navigation">
4
+ <router-link to="/" class="back-link">
5
+ <font-awesome-icon icon="arrow-left" />
6
+ <span>Back to Dashboard</span>
7
+ </router-link>
8
+ </div>
9
+
10
+ <div class="content">
11
+ <h1>Action Component Test</h1>
12
+
13
+ <div class="color-controls">
14
+ <div class="color-picker">
15
+ <label for="action-color">Action Color:</label>
16
+ <input type="color" id="action-color" v-model="actionColor" />
17
+ </div>
18
+ </div>
19
+
20
+ <div class="test-section">
21
+ <h2>Basic Actions</h2>
22
+ <div class="action-group">
23
+ <Action
24
+ icon="save"
25
+ label="Save"
26
+ :color="actionColor"
27
+ variant="transparent"
28
+ @click="handleActionClick('Save')"
29
+ />
30
+ <Action
31
+ icon="trash"
32
+ label="Delete"
33
+ :color="actionColor"
34
+ @click="handleActionClick('Delete')"
35
+ />
36
+ <Action
37
+ icon="edit"
38
+ label="Edit"
39
+ :color="actionColor"
40
+ @click="handleActionClick('Edit')"
41
+ />
42
+ </div>
43
+ </div>
44
+
45
+ <div class="test-section">
46
+ <h2>Icon Only Actions</h2>
47
+ <div class="action-group">
48
+ <Action icon="plus" :color="actionColor" @click="handleActionClick('Add')" />
49
+ <Action icon="search" :color="actionColor" @click="handleActionClick('Search')" />
50
+ <Action icon="cog" :color="actionColor" @click="handleActionClick('Settings')" />
51
+ </div>
52
+ </div>
53
+
54
+ <div class="test-section">
55
+ <h2>Label Only Actions</h2>
56
+ <div class="action-group">
57
+ <Action
58
+ label="Submit"
59
+ type="submit"
60
+ :color="actionColor"
61
+ size="large"
62
+ @click="handleActionClick('Submit')"
63
+ />
64
+ <Action label="Cancel" :color="actionColor" @click="handleActionClick('Cancel')" />
65
+ <Action
66
+ label="Reset"
67
+ type="reset"
68
+ :color="actionColor"
69
+ size="small"
70
+ @click="handleActionClick('Reset')"
71
+ />
72
+ </div>
73
+ </div>
74
+
75
+ <div class="test-section">
76
+ <h2>Link Actions</h2>
77
+ <div class="action-group">
78
+ <Action
79
+ icon="external-link"
80
+ label="View Details"
81
+ href="/details"
82
+ :color="actionColor"
83
+ size="large"
84
+ @click="handleActionClick('View Details')"
85
+ />
86
+ <Action
87
+ icon="download"
88
+ label="Download"
89
+ href="/download"
90
+ :color="actionColor"
91
+ @click="handleActionClick('Download')"
92
+ />
93
+ <Action
94
+ label="Share"
95
+ href="/share"
96
+ :color="actionColor"
97
+ size="small"
98
+ @click="handleActionClick('Share')"
99
+ />
100
+ </div>
101
+ </div>
102
+
103
+ <div class="test-section">
104
+ <h2>Disabled Actions</h2>
105
+ <div class="action-group">
106
+ <Action
107
+ icon="lock"
108
+ label="Locked"
109
+ disabled
110
+ :color="actionColor"
111
+ @click="handleActionClick('Locked')"
112
+ />
113
+ <Action
114
+ icon="check"
115
+ label="Completed"
116
+ disabled
117
+ :color="actionColor"
118
+ @click="handleActionClick('Completed')"
119
+ />
120
+ <Action
121
+ icon="ban"
122
+ label="Disabled"
123
+ disabled
124
+ :color="actionColor"
125
+ @click="handleActionClick('Disabled')"
126
+ />
127
+ </div>
128
+ </div>
129
+
130
+ <div class="test-section">
131
+ <h2>Mixed Actions</h2>
132
+ <div class="action-group">
133
+ <Action
134
+ icon="plus"
135
+ label="Add New"
136
+ :color="actionColor"
137
+ @click="handleActionClick('Add New')"
138
+ />
139
+ <Action icon="trash" :color="actionColor" @click="handleActionClick('Delete')" />
140
+ <Action label="Cancel" :color="actionColor" @click="handleActionClick('Cancel')" />
141
+ <Action
142
+ icon="external-link"
143
+ label="View"
144
+ href="/view"
145
+ :color="actionColor"
146
+ @click="handleActionClick('View')"
147
+ />
148
+ </div>
149
+ </div>
150
+
151
+ <div class="test-section">
152
+ <h2>Action Log</h2>
153
+ <div class="action-log">
154
+ <div v-for="(log, index) in actionLog" :key="index" class="log-entry">
155
+ {{ log }}
156
+ </div>
157
+ </div>
158
+ </div>
159
+ </div>
160
+ </div>
161
+ </template>
162
+
163
+ <script setup lang="ts">
164
+ import { ref } from 'vue'
165
+ import Action from '../components/Action.vue'
166
+
167
+ const actionLog = ref<string[]>([])
168
+ const actionColor = ref('#4CAF50')
169
+
170
+ const handleActionClick = (action: string) => {
171
+ actionLog.value.unshift(`[${new Date().toLocaleTimeString()}] Clicked: ${action}`)
172
+ if (actionLog.value.length > 10) {
173
+ actionLog.value.pop()
174
+ }
175
+ }
176
+ </script>
177
+
178
+ <style scoped>
179
+ .action-test {
180
+ min-height: 100vh;
181
+ background-image: url('https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?auto=format&fit=crop&w=1920&q=80');
182
+ background-size: cover;
183
+ background-position: center;
184
+ background-attachment: fixed;
185
+ position: relative;
186
+ }
187
+
188
+ .action-test::before {
189
+ content: '';
190
+ position: absolute;
191
+ top: 0;
192
+ left: 0;
193
+ right: 0;
194
+ bottom: 0;
195
+ background: rgba(0, 0, 0, 0.5);
196
+ backdrop-filter: blur(4px);
197
+ }
198
+
199
+ .content {
200
+ position: relative;
201
+ z-index: 1;
202
+ max-width: 1200px;
203
+ margin: 0 auto;
204
+ padding: 2rem;
205
+ }
206
+
207
+ .navigation {
208
+ position: relative;
209
+ z-index: 2;
210
+ padding: 2rem;
211
+ }
212
+
213
+ .back-link {
214
+ display: inline-flex;
215
+ align-items: center;
216
+ gap: 0.5rem;
217
+ color: white;
218
+ text-decoration: none;
219
+ font-size: 0.875rem;
220
+ transition: opacity 0.2s ease;
221
+ }
222
+
223
+ .back-link:hover {
224
+ opacity: 0.8;
225
+ }
226
+
227
+ .color-controls {
228
+ display: grid;
229
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
230
+ gap: 1rem;
231
+ margin-bottom: 2rem;
232
+ padding: 1rem;
233
+ background-color: rgba(255, 255, 255, 0.1);
234
+ backdrop-filter: blur(8px);
235
+ border-radius: 0.5rem;
236
+ border: 1px solid rgba(255, 255, 255, 0.1);
237
+ }
238
+
239
+ .color-picker {
240
+ display: flex;
241
+ flex-direction: column;
242
+ gap: 0.5rem;
243
+ }
244
+
245
+ .color-picker label {
246
+ font-size: 0.875rem;
247
+ color: white;
248
+ }
249
+
250
+ .color-picker input[type='color'] {
251
+ width: 100%;
252
+ height: 2.5rem;
253
+ padding: 0.25rem;
254
+ border: 1px solid rgba(255, 255, 255, 0.2);
255
+ border-radius: 0.25rem;
256
+ cursor: pointer;
257
+ background-color: rgba(255, 255, 255, 0.1);
258
+ }
259
+
260
+ .test-section {
261
+ margin-bottom: 3rem;
262
+ background-color: rgba(255, 255, 255, 0.1);
263
+ backdrop-filter: blur(8px);
264
+ border-radius: 0.5rem;
265
+ border: 1px solid rgba(255, 255, 255, 0.1);
266
+ padding: 1.5rem;
267
+ }
268
+
269
+ h1 {
270
+ margin-bottom: 2rem;
271
+ color: white;
272
+ text-align: center;
273
+ }
274
+
275
+ h2 {
276
+ margin-bottom: 1rem;
277
+ color: white;
278
+ }
279
+
280
+ .action-group {
281
+ display: flex;
282
+ flex-wrap: wrap;
283
+ gap: 1rem;
284
+ margin-bottom: 1rem;
285
+ }
286
+
287
+ .action-log {
288
+ background-color: rgba(0, 0, 0, 0.2);
289
+ border: 1px solid rgba(255, 255, 255, 0.1);
290
+ border-radius: 0.375rem;
291
+ padding: 1rem;
292
+ max-height: 200px;
293
+ overflow-y: auto;
294
+ }
295
+
296
+ .log-entry {
297
+ padding: 0.5rem;
298
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
299
+ font-family: monospace;
300
+ font-size: 0.875rem;
301
+ color: white;
302
+ }
303
+
304
+ .log-entry:last-child {
305
+ border-bottom: none;
306
+ }
307
+ </style>
@@ -0,0 +1,98 @@
1
+ <template>
2
+ <div class="dashboard">
3
+ <h1>Vue Input Components</h1>
4
+ <div class="tile-grid">
5
+ <router-link to="/text-input" class="tile">
6
+ <div class="tile-content">
7
+ <font-awesome-icon icon="keyboard" class="tile-icon" />
8
+ <h2>Text Input</h2>
9
+ <p>Test the text input component with various configurations</p>
10
+ </div>
11
+ </router-link>
12
+ <router-link to="/file-upload" class="tile">
13
+ <div class="tile-content">
14
+ <font-awesome-icon icon="file-upload" class="tile-icon" />
15
+ <h2>File Upload</h2>
16
+ <p>Test the file upload component with drag and drop support</p>
17
+ </div>
18
+ </router-link>
19
+ <router-link to="/action" class="tile">
20
+ <div class="tile-content">
21
+ <font-awesome-icon icon="hand-pointer" class="tile-icon" />
22
+ <h2>Action</h2>
23
+ <p>Test the action component with various button and link styles</p>
24
+ </div>
25
+ </router-link>
26
+ <router-link to="/navigation" class="tile">
27
+ <div class="tile-content">
28
+ <font-awesome-icon icon="bars" class="tile-icon" />
29
+ <h2>Navigation</h2>
30
+ <p>Test the navigation component</p>
31
+ </div>
32
+ </router-link>
33
+ </div>
34
+ </div>
35
+ </template>
36
+
37
+ <script setup lang="ts"></script>
38
+
39
+ <style scoped>
40
+ .dashboard {
41
+ max-width: 1200px;
42
+ margin: 0 auto;
43
+ padding: 2rem;
44
+ }
45
+
46
+ h1 {
47
+ text-align: center;
48
+ margin-bottom: 2rem;
49
+ color: var(--text-primary);
50
+ }
51
+
52
+ .tile-grid {
53
+ display: grid;
54
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
55
+ gap: 2rem;
56
+ }
57
+
58
+ .tile {
59
+ text-decoration: none;
60
+ color: inherit;
61
+ background-color: white;
62
+ border-radius: 0.5rem;
63
+ overflow: hidden;
64
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
65
+ transition:
66
+ transform 0.2s ease-in-out,
67
+ box-shadow 0.2s ease-in-out;
68
+ }
69
+
70
+ .tile:hover {
71
+ transform: translateY(-4px);
72
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
73
+ }
74
+
75
+ .tile-content {
76
+ padding: 2rem;
77
+ text-align: center;
78
+ }
79
+
80
+ .tile-icon {
81
+ font-size: 2.5rem;
82
+ margin-bottom: 1rem;
83
+ color: var(--primary);
84
+ }
85
+
86
+ .tile h2 {
87
+ margin: 0 0 0.5rem 0;
88
+ font-size: 1.5rem;
89
+ color: var(--text-primary);
90
+ }
91
+
92
+ .tile p {
93
+ margin: 0;
94
+ color: var(--text-secondary);
95
+ font-size: 1rem;
96
+ line-height: 1.5;
97
+ }
98
+ </style>
@@ -0,0 +1,177 @@
1
+ <template>
2
+ <div class="file-upload-test">
3
+ <div class="header">
4
+ <router-link to="/" class="back-link">
5
+ <font-awesome-icon icon="home" />
6
+ <span>Back to Dashboard</span>
7
+ </router-link>
8
+ <h1>File Upload Test</h1>
9
+ </div>
10
+ <div class="file-upload-grid">
11
+ <div class="upload-section">
12
+ <h2>Basic Upload</h2>
13
+ <FileUpload
14
+ icon="upload"
15
+ upload-url="https://httpbin.org/post"
16
+ @upload-complete="handleUploadComplete"
17
+ @upload-error="handleUploadError"
18
+ />
19
+ <div
20
+ v-if="uploadStatus.basic && uploadStatus.basic.message"
21
+ :class="['status-message', uploadStatus.basic.type]"
22
+ >
23
+ {{ uploadStatus.basic.message }}
24
+ </div>
25
+ </div>
26
+ <div class="upload-section">
27
+ <h2>Image Upload</h2>
28
+ <FileUpload
29
+ icon="image"
30
+ @files-selected="handleFilesSelected"
31
+ @start-upload="handleStartUpload"
32
+ />
33
+ </div>
34
+ <div class="upload-section">
35
+ <h2>Document Upload</h2>
36
+ <FileUpload icon="file" />
37
+ </div>
38
+ </div>
39
+ </div>
40
+ </template>
41
+
42
+ <script setup lang="ts">
43
+ import { ref } from 'vue'
44
+ import FileUpload from '@/components/FileUpload.vue'
45
+
46
+ interface UploadStatus {
47
+ type: 'success' | 'error'
48
+ message: string
49
+ }
50
+
51
+ const uploadStatus = ref<Record<string, UploadStatus>>({
52
+ basic: { type: 'success', message: '' },
53
+ })
54
+
55
+ const handleUploadComplete = (files: File[]) => {
56
+ uploadStatus.value.basic = {
57
+ type: 'success',
58
+ message: `Successfully uploaded ${files.length} file(s)`,
59
+ }
60
+ // Clear status after 3 seconds
61
+ setTimeout(() => {
62
+ uploadStatus.value.basic.message = ''
63
+ }, 3000)
64
+ }
65
+
66
+ const handleUploadError = (error: string) => {
67
+ uploadStatus.value.basic = {
68
+ type: 'error',
69
+ message: error,
70
+ }
71
+ // Clear status after 3 seconds
72
+ setTimeout(() => {
73
+ uploadStatus.value.basic.message = ''
74
+ }, 3000)
75
+ }
76
+
77
+ const handleFilesSelected = (files: File[]) => {
78
+ console.log('Files selected:', files)
79
+ }
80
+
81
+ const handleStartUpload = (files: File[]) => {
82
+ console.log('Start upload:', files)
83
+ }
84
+ </script>
85
+
86
+ <style scoped>
87
+ .file-upload-test {
88
+ padding: 2rem;
89
+ min-height: 100vh;
90
+ background-image: url('https://images.unsplash.com/photo-1519681393784-d120267933ba?auto=format&fit=crop&q=80&w=2070');
91
+ background-size: cover;
92
+ background-position: center;
93
+ background-attachment: fixed;
94
+ }
95
+
96
+ .file-upload-grid {
97
+ display: grid;
98
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
99
+ gap: 2rem;
100
+ margin-top: 2rem;
101
+ }
102
+
103
+ .upload-section {
104
+ background: rgba(255, 255, 255, 0.8);
105
+ padding: 2rem;
106
+ border-radius: 0.75rem;
107
+ border: 1px solid rgba(255, 255, 255, 0.2);
108
+ backdrop-filter: blur(5px);
109
+ }
110
+
111
+ .upload-section h2 {
112
+ margin-bottom: 1rem;
113
+ color: #495057;
114
+ }
115
+
116
+ .status-message {
117
+ margin-top: 1rem;
118
+ padding: 0.5rem;
119
+ border-radius: 0.25rem;
120
+ font-size: 0.875rem;
121
+ }
122
+
123
+ .status-message.success {
124
+ background-color: #d4edda;
125
+ color: #155724;
126
+ border: 1px solid #c3e6cb;
127
+ }
128
+
129
+ .status-message.error {
130
+ background-color: #f8d7da;
131
+ color: #721c24;
132
+ border: 1px solid #f5c6cb;
133
+ }
134
+
135
+ .group {
136
+ display: flex;
137
+ flex-direction: column;
138
+ gap: 1rem;
139
+ padding: 2rem;
140
+ border-radius: 1rem;
141
+ background-color: rgba(255, 255, 255, 0.8);
142
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
143
+ backdrop-filter: blur(5px);
144
+ }
145
+
146
+ .error {
147
+ color: var(--error-color);
148
+ background-color: var(--error-color-light);
149
+ border: 1px solid var(--error-color);
150
+ }
151
+
152
+ .header {
153
+ display: flex;
154
+ align-items: center;
155
+ gap: 0.5rem;
156
+ margin-bottom: 1rem;
157
+ }
158
+
159
+ .back-link {
160
+ display: flex;
161
+ align-items: center;
162
+ gap: 0.25rem;
163
+ color: var(--text-color);
164
+ text-decoration: none;
165
+ font-size: 1rem;
166
+ transition: color 0.2s;
167
+ }
168
+
169
+ .back-link:hover {
170
+ color: var(--primary-color);
171
+ }
172
+
173
+ h1 {
174
+ margin: 0;
175
+ color: #212529;
176
+ }
177
+ </style>