@gameap/ui 1.1.1 → 1.3.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.
- package/README.md +899 -0
- package/components/GCard.vue +53 -0
- package/components/GDataTable.vue +63 -0
- package/components/GDivider.vue +9 -0
- package/components/GEmpty.vue +38 -0
- package/components/GGameIcon.vue +98 -0
- package/components/GInput.vue +66 -0
- package/components/GModal.vue +56 -0
- package/components/GSwitch.vue +46 -0
- package/components/GTable.vue +41 -0
- package/index.js +27 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,899 @@
|
|
|
1
|
+
# @gameap/ui
|
|
2
|
+
|
|
3
|
+
A Vue 3 component library providing GameAP-styled UI components. Built as a wrapper around [Naive UI](https://www.naiveui.com/) with sensible defaults and additional custom components.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 19 reusable Vue 3 components
|
|
8
|
+
- Wrapper components for Naive UI with GameAP defaults
|
|
9
|
+
- Flexible icon system with 150+ predefined icons
|
|
10
|
+
- Custom menu system with keyboard navigation
|
|
11
|
+
- Tailwind CSS integration
|
|
12
|
+
- Full TypeScript-friendly props
|
|
13
|
+
- Accessibility support (ARIA attributes, keyboard navigation)
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @gameap/ui
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Setup
|
|
22
|
+
|
|
23
|
+
Register the plugin in your Vue application:
|
|
24
|
+
|
|
25
|
+
```javascript
|
|
26
|
+
import { createApp } from 'vue'
|
|
27
|
+
import gameapUI from '@gameap/ui'
|
|
28
|
+
import '@gameap/ui/style.css'
|
|
29
|
+
|
|
30
|
+
const app = createApp(App)
|
|
31
|
+
app.use(gameapUI)
|
|
32
|
+
app.mount('#app')
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Or import components individually:
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
import { GCard, GModal, GIcon } from '@gameap/ui'
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Components
|
|
42
|
+
|
|
43
|
+
### GCard
|
|
44
|
+
|
|
45
|
+
Card container component wrapping Naive UI's NCard.
|
|
46
|
+
|
|
47
|
+
**Props:**
|
|
48
|
+
|
|
49
|
+
| Prop | Type | Default | Description |
|
|
50
|
+
|------|------|---------|-------------|
|
|
51
|
+
| title | string | `''` | Card title |
|
|
52
|
+
| size | string | `'small'` | Card size |
|
|
53
|
+
| bordered | boolean | `true` | Show border |
|
|
54
|
+
| segmented | boolean \| object | `{ content: true, footer: 'soft' }` | Content segmentation |
|
|
55
|
+
| headerClass | string | `'g-card-header'` | Header CSS class |
|
|
56
|
+
|
|
57
|
+
Supports all [Naive UI NCard props](https://www.naiveui.com/en-US/os-theme/components/card).
|
|
58
|
+
|
|
59
|
+
**Example:**
|
|
60
|
+
|
|
61
|
+
```vue
|
|
62
|
+
<template>
|
|
63
|
+
<GCard title="Server Status">
|
|
64
|
+
<p>Server is running normally.</p>
|
|
65
|
+
|
|
66
|
+
<template #footer>
|
|
67
|
+
<button>Restart Server</button>
|
|
68
|
+
</template>
|
|
69
|
+
</GCard>
|
|
70
|
+
</template>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
### GDataTable
|
|
76
|
+
|
|
77
|
+
Data table component wrapping Naive UI's NDataTable.
|
|
78
|
+
|
|
79
|
+
**Props:**
|
|
80
|
+
|
|
81
|
+
| Prop | Type | Default | Description |
|
|
82
|
+
|------|------|---------|-------------|
|
|
83
|
+
| bordered | boolean | `false` | Show border |
|
|
84
|
+
| singleLine | boolean | `true` | Single line rows |
|
|
85
|
+
| columns | array | `[]` | Column definitions |
|
|
86
|
+
| data | array | `[]` | Table data |
|
|
87
|
+
| loading | boolean | `false` | Loading state |
|
|
88
|
+
| pagination | object \| boolean | `false` | Pagination config |
|
|
89
|
+
| remote | boolean | `false` | Remote data mode |
|
|
90
|
+
|
|
91
|
+
Supports all [Naive UI NDataTable props](https://www.naiveui.com/en-US/os-theme/components/data-table).
|
|
92
|
+
|
|
93
|
+
**Example:**
|
|
94
|
+
|
|
95
|
+
```vue
|
|
96
|
+
<script setup>
|
|
97
|
+
const columns = [
|
|
98
|
+
{ title: 'Name', key: 'name' },
|
|
99
|
+
{ title: 'Status', key: 'status' },
|
|
100
|
+
{ title: 'Players', key: 'players' }
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
const data = [
|
|
104
|
+
{ name: 'Server 1', status: 'Online', players: 12 },
|
|
105
|
+
{ name: 'Server 2', status: 'Offline', players: 0 }
|
|
106
|
+
]
|
|
107
|
+
</script>
|
|
108
|
+
|
|
109
|
+
<template>
|
|
110
|
+
<GDataTable :columns="columns" :data="data" />
|
|
111
|
+
</template>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**With Pagination:**
|
|
115
|
+
|
|
116
|
+
```vue
|
|
117
|
+
<script setup>
|
|
118
|
+
import { ref } from 'vue'
|
|
119
|
+
|
|
120
|
+
const pagination = ref({
|
|
121
|
+
page: 1,
|
|
122
|
+
pageSize: 10,
|
|
123
|
+
itemCount: 100,
|
|
124
|
+
showSizePicker: true,
|
|
125
|
+
pageSizes: [10, 20, 50]
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
function handlePageChange(page) {
|
|
129
|
+
pagination.value.page = page
|
|
130
|
+
fetchData()
|
|
131
|
+
}
|
|
132
|
+
</script>
|
|
133
|
+
|
|
134
|
+
<template>
|
|
135
|
+
<GDataTable
|
|
136
|
+
:columns="columns"
|
|
137
|
+
:data="data"
|
|
138
|
+
:pagination="pagination"
|
|
139
|
+
:remote="true"
|
|
140
|
+
@update:page="handlePageChange"
|
|
141
|
+
/>
|
|
142
|
+
</template>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
### GTable
|
|
148
|
+
|
|
149
|
+
Simple table component wrapping Naive UI's NTable.
|
|
150
|
+
|
|
151
|
+
**Props:**
|
|
152
|
+
|
|
153
|
+
| Prop | Type | Default | Description |
|
|
154
|
+
|------|------|---------|-------------|
|
|
155
|
+
| bordered | boolean | `false` | Show border |
|
|
156
|
+
| singleLine | boolean | `true` | Single line rows |
|
|
157
|
+
| size | string | - | Table size |
|
|
158
|
+
|
|
159
|
+
**Example:**
|
|
160
|
+
|
|
161
|
+
```vue
|
|
162
|
+
<template>
|
|
163
|
+
<GTable>
|
|
164
|
+
<thead>
|
|
165
|
+
<tr>
|
|
166
|
+
<th>Name</th>
|
|
167
|
+
<th>Value</th>
|
|
168
|
+
</tr>
|
|
169
|
+
</thead>
|
|
170
|
+
<tbody>
|
|
171
|
+
<tr>
|
|
172
|
+
<td>CPU Usage</td>
|
|
173
|
+
<td>45%</td>
|
|
174
|
+
</tr>
|
|
175
|
+
<tr>
|
|
176
|
+
<td>Memory</td>
|
|
177
|
+
<td>2.4 GB</td>
|
|
178
|
+
</tr>
|
|
179
|
+
</tbody>
|
|
180
|
+
</GTable>
|
|
181
|
+
</template>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
### GModal
|
|
187
|
+
|
|
188
|
+
Modal dialog component wrapping Naive UI's NModal.
|
|
189
|
+
|
|
190
|
+
**Props:**
|
|
191
|
+
|
|
192
|
+
| Prop | Type | Default | Description |
|
|
193
|
+
|------|------|---------|-------------|
|
|
194
|
+
| show | boolean | `false` | Modal visibility |
|
|
195
|
+
| preset | string | `'card'` | Modal preset |
|
|
196
|
+
| bordered | boolean | `false` | Show border |
|
|
197
|
+
| title | string | `''` | Modal title |
|
|
198
|
+
| segmented | object | `{ content: 'soft', footer: 'soft' }` | Content segmentation |
|
|
199
|
+
|
|
200
|
+
**Emits:**
|
|
201
|
+
|
|
202
|
+
| Event | Payload | Description |
|
|
203
|
+
|-------|---------|-------------|
|
|
204
|
+
| update:show | boolean | Emitted when modal should close |
|
|
205
|
+
|
|
206
|
+
Supports all [Naive UI NModal props](https://www.naiveui.com/en-US/os-theme/components/modal).
|
|
207
|
+
|
|
208
|
+
**Example:**
|
|
209
|
+
|
|
210
|
+
```vue
|
|
211
|
+
<script setup>
|
|
212
|
+
import { ref } from 'vue'
|
|
213
|
+
|
|
214
|
+
const showModal = ref(false)
|
|
215
|
+
</script>
|
|
216
|
+
|
|
217
|
+
<template>
|
|
218
|
+
<button @click="showModal = true">Open Modal</button>
|
|
219
|
+
|
|
220
|
+
<GModal
|
|
221
|
+
v-model:show="showModal"
|
|
222
|
+
title="Confirm Action"
|
|
223
|
+
>
|
|
224
|
+
<p>Are you sure you want to proceed?</p>
|
|
225
|
+
|
|
226
|
+
<template #footer>
|
|
227
|
+
<button @click="showModal = false">Cancel</button>
|
|
228
|
+
<button @click="confirmAction">Confirm</button>
|
|
229
|
+
</template>
|
|
230
|
+
</GModal>
|
|
231
|
+
</template>
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
### GInput
|
|
237
|
+
|
|
238
|
+
Input field component wrapping Naive UI's NInput.
|
|
239
|
+
|
|
240
|
+
**Props:**
|
|
241
|
+
|
|
242
|
+
| Prop | Type | Default | Description |
|
|
243
|
+
|------|------|---------|-------------|
|
|
244
|
+
| value | string \| array | - | Input value |
|
|
245
|
+
| type | string | `'text'` | Input type |
|
|
246
|
+
| placeholder | string | `''` | Placeholder text |
|
|
247
|
+
| disabled | boolean | `false` | Disabled state |
|
|
248
|
+
| readonly | boolean | `false` | Read-only state |
|
|
249
|
+
| clearable | boolean | `false` | Show clear button |
|
|
250
|
+
| size | string | - | Input size |
|
|
251
|
+
|
|
252
|
+
**Emits:**
|
|
253
|
+
|
|
254
|
+
| Event | Payload | Description |
|
|
255
|
+
|-------|---------|-------------|
|
|
256
|
+
| update:value | string | Emitted when value changes |
|
|
257
|
+
|
|
258
|
+
Supports all [Naive UI NInput props](https://www.naiveui.com/en-US/os-theme/components/input).
|
|
259
|
+
|
|
260
|
+
**Example:**
|
|
261
|
+
|
|
262
|
+
```vue
|
|
263
|
+
<script setup>
|
|
264
|
+
import { ref } from 'vue'
|
|
265
|
+
|
|
266
|
+
const serverName = ref('')
|
|
267
|
+
</script>
|
|
268
|
+
|
|
269
|
+
<template>
|
|
270
|
+
<GInput
|
|
271
|
+
v-model:value="serverName"
|
|
272
|
+
placeholder="Enter server name"
|
|
273
|
+
clearable
|
|
274
|
+
/>
|
|
275
|
+
</template>
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
**Password Input:**
|
|
279
|
+
|
|
280
|
+
```vue
|
|
281
|
+
<template>
|
|
282
|
+
<GInput
|
|
283
|
+
v-model:value="password"
|
|
284
|
+
type="password"
|
|
285
|
+
placeholder="Enter password"
|
|
286
|
+
show-password-on="click"
|
|
287
|
+
/>
|
|
288
|
+
</template>
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
### GSwitch
|
|
294
|
+
|
|
295
|
+
Toggle switch component wrapping Naive UI's NSwitch.
|
|
296
|
+
|
|
297
|
+
**Props:**
|
|
298
|
+
|
|
299
|
+
| Prop | Type | Default | Description |
|
|
300
|
+
|------|------|---------|-------------|
|
|
301
|
+
| value | boolean | `false` | Switch state |
|
|
302
|
+
| disabled | boolean | `false` | Disabled state |
|
|
303
|
+
| size | string | - | Switch size |
|
|
304
|
+
|
|
305
|
+
**Emits:**
|
|
306
|
+
|
|
307
|
+
| Event | Payload | Description |
|
|
308
|
+
|-------|---------|-------------|
|
|
309
|
+
| update:value | boolean | Emitted when state changes |
|
|
310
|
+
|
|
311
|
+
**Example:**
|
|
312
|
+
|
|
313
|
+
```vue
|
|
314
|
+
<script setup>
|
|
315
|
+
import { ref } from 'vue'
|
|
316
|
+
|
|
317
|
+
const autoStart = ref(true)
|
|
318
|
+
</script>
|
|
319
|
+
|
|
320
|
+
<template>
|
|
321
|
+
<label>
|
|
322
|
+
Auto-start server
|
|
323
|
+
<GSwitch v-model:value="autoStart" />
|
|
324
|
+
</label>
|
|
325
|
+
</template>
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
### GEmpty
|
|
331
|
+
|
|
332
|
+
Empty state component wrapping Naive UI's NEmpty.
|
|
333
|
+
|
|
334
|
+
**Props:**
|
|
335
|
+
|
|
336
|
+
| Prop | Type | Default | Description |
|
|
337
|
+
|------|------|---------|-------------|
|
|
338
|
+
| description | string | - | Description text |
|
|
339
|
+
| size | string | - | Component size |
|
|
340
|
+
|
|
341
|
+
**Example:**
|
|
342
|
+
|
|
343
|
+
```vue
|
|
344
|
+
<template>
|
|
345
|
+
<GEmpty description="No servers found">
|
|
346
|
+
<template #extra>
|
|
347
|
+
<button>Add Server</button>
|
|
348
|
+
</template>
|
|
349
|
+
</GEmpty>
|
|
350
|
+
</template>
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
### GDivider
|
|
356
|
+
|
|
357
|
+
Visual divider component wrapping Naive UI's NDivider.
|
|
358
|
+
|
|
359
|
+
**Example:**
|
|
360
|
+
|
|
361
|
+
```vue
|
|
362
|
+
<template>
|
|
363
|
+
<div>Section 1</div>
|
|
364
|
+
<GDivider />
|
|
365
|
+
<div>Section 2</div>
|
|
366
|
+
|
|
367
|
+
<!-- With label -->
|
|
368
|
+
<GDivider>Or</GDivider>
|
|
369
|
+
</template>
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
### GIcon
|
|
375
|
+
|
|
376
|
+
Flexible icon component supporting Font Awesome classes and Vue components.
|
|
377
|
+
|
|
378
|
+
**Props:**
|
|
379
|
+
|
|
380
|
+
| Prop | Type | Default | Description |
|
|
381
|
+
|------|------|---------|-------------|
|
|
382
|
+
| name | string | *required* | Icon name from registry |
|
|
383
|
+
| size | string | `'md'` | Size: `'sm'`, `'md'`, `'lg'`, `'xl'` |
|
|
384
|
+
| class | string | `''` | Additional CSS classes |
|
|
385
|
+
|
|
386
|
+
**Size Mappings:**
|
|
387
|
+
|
|
388
|
+
| Size | Font Awesome | Component |
|
|
389
|
+
|------|--------------|-----------|
|
|
390
|
+
| sm | fa-sm | 0.875em |
|
|
391
|
+
| md | (default) | 1em |
|
|
392
|
+
| lg | fa-lg | 1.25em |
|
|
393
|
+
| xl | fa-2x | 2em |
|
|
394
|
+
|
|
395
|
+
**Example:**
|
|
396
|
+
|
|
397
|
+
```vue
|
|
398
|
+
<template>
|
|
399
|
+
<!-- Basic usage -->
|
|
400
|
+
<GIcon name="server" />
|
|
401
|
+
|
|
402
|
+
<!-- With size -->
|
|
403
|
+
<GIcon name="warning" size="lg" />
|
|
404
|
+
|
|
405
|
+
<!-- With custom class -->
|
|
406
|
+
<GIcon name="delete" class="text-red-500" />
|
|
407
|
+
</template>
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
### GGameIcon
|
|
413
|
+
|
|
414
|
+
Game-specific icon component that displays icons based on game codes.
|
|
415
|
+
|
|
416
|
+
**Props:**
|
|
417
|
+
|
|
418
|
+
| Prop | Type | Default | Description |
|
|
419
|
+
|------|------|---------|-------------|
|
|
420
|
+
| game | string | `'minecraft'` | Game code identifier |
|
|
421
|
+
|
|
422
|
+
**Supported Games:**
|
|
423
|
+
|
|
424
|
+
The component includes built-in icon mappings for popular games:
|
|
425
|
+
- Counter-Strike series: `cs2`, `csgo`, `css`, `cstrike`, `cs15`, `czero`
|
|
426
|
+
- Valve games: `halflife`, `tf2`, `l4d`, `l4d2`, `dod`, `dods`, `garrysmod`
|
|
427
|
+
- Other popular games: `minecraft`, `rust`, `ark`, `arma2`, `arma3`, `7d2d`, `dst`, `fivem`, `gta`, `hurtworld`, `quake`, `quake2`, `quake3`, `samp`, `teamspeak`
|
|
428
|
+
|
|
429
|
+
For unknown game codes, the component automatically assigns a consistent fallback icon from a set of common gaming icons.
|
|
430
|
+
|
|
431
|
+
**Example:**
|
|
432
|
+
|
|
433
|
+
```vue
|
|
434
|
+
<template>
|
|
435
|
+
<!-- Basic usage -->
|
|
436
|
+
<GGameIcon game="minecraft" />
|
|
437
|
+
|
|
438
|
+
<!-- In a table -->
|
|
439
|
+
<GDataTable :columns="columns" :data="servers">
|
|
440
|
+
<template #game="{ row }">
|
|
441
|
+
<GGameIcon :game="row.gameCode" class="mr-2" />
|
|
442
|
+
{{ row.gameName }}
|
|
443
|
+
</template>
|
|
444
|
+
</GDataTable>
|
|
445
|
+
</template>
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
**With render function:**
|
|
449
|
+
|
|
450
|
+
```vue
|
|
451
|
+
<script setup>
|
|
452
|
+
import { h } from 'vue'
|
|
453
|
+
import { GGameIcon } from '@gameap/ui'
|
|
454
|
+
|
|
455
|
+
const renderGameLabel = (option) => {
|
|
456
|
+
return [
|
|
457
|
+
h(GGameIcon, { game: option.value, class: 'mr-2' }),
|
|
458
|
+
option.label
|
|
459
|
+
]
|
|
460
|
+
}
|
|
461
|
+
</script>
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
### GBreadcrumbs
|
|
467
|
+
|
|
468
|
+
Breadcrumb navigation component with support for links, router links, and icons.
|
|
469
|
+
|
|
470
|
+
**Props:**
|
|
471
|
+
|
|
472
|
+
| Prop | Type | Default | Description |
|
|
473
|
+
|------|------|---------|-------------|
|
|
474
|
+
| items | array | *required* | Breadcrumb items |
|
|
475
|
+
|
|
476
|
+
**Item Structure:**
|
|
477
|
+
|
|
478
|
+
```typescript
|
|
479
|
+
interface BreadcrumbItem {
|
|
480
|
+
text: string // Display text
|
|
481
|
+
link?: string // External URL
|
|
482
|
+
route?: string // Vue Router route
|
|
483
|
+
icon?: string // Icon class name
|
|
484
|
+
render?: () => VNode // Custom render function
|
|
485
|
+
}
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
**Example:**
|
|
489
|
+
|
|
490
|
+
```vue
|
|
491
|
+
<script setup>
|
|
492
|
+
const breadcrumbs = [
|
|
493
|
+
{ text: 'Home', route: '/', icon: 'fa-solid fa-home' },
|
|
494
|
+
{ text: 'Servers', route: '/servers' },
|
|
495
|
+
{ text: 'Server 1' }
|
|
496
|
+
]
|
|
497
|
+
</script>
|
|
498
|
+
|
|
499
|
+
<template>
|
|
500
|
+
<GBreadcrumbs :items="breadcrumbs" />
|
|
501
|
+
</template>
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
**With Custom Render:**
|
|
505
|
+
|
|
506
|
+
```vue
|
|
507
|
+
<script setup>
|
|
508
|
+
import { h } from 'vue'
|
|
509
|
+
|
|
510
|
+
const breadcrumbs = [
|
|
511
|
+
{ text: 'Home', route: '/' },
|
|
512
|
+
{
|
|
513
|
+
text: 'Status',
|
|
514
|
+
render: () => h('span', { class: 'text-green-500' }, 'Online')
|
|
515
|
+
}
|
|
516
|
+
]
|
|
517
|
+
</script>
|
|
518
|
+
|
|
519
|
+
<template>
|
|
520
|
+
<GBreadcrumbs :items="breadcrumbs" />
|
|
521
|
+
</template>
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
---
|
|
525
|
+
|
|
526
|
+
### GStatusBadge
|
|
527
|
+
|
|
528
|
+
Status indicator badge with predefined color schemes.
|
|
529
|
+
|
|
530
|
+
**Props:**
|
|
531
|
+
|
|
532
|
+
| Prop | Type | Default | Description |
|
|
533
|
+
|------|------|---------|-------------|
|
|
534
|
+
| status | string | *required* | Status type |
|
|
535
|
+
| text | string | - | Override default text |
|
|
536
|
+
|
|
537
|
+
**Available Statuses:**
|
|
538
|
+
|
|
539
|
+
| Status | Color | Default Text |
|
|
540
|
+
|--------|-------|--------------|
|
|
541
|
+
| waiting | Stone (light) | waiting |
|
|
542
|
+
| working | Blue | working |
|
|
543
|
+
| error | Red | error |
|
|
544
|
+
| success | Green | success |
|
|
545
|
+
| canceled | Stone | canceled |
|
|
546
|
+
|
|
547
|
+
**Example:**
|
|
548
|
+
|
|
549
|
+
```vue
|
|
550
|
+
<template>
|
|
551
|
+
<GStatusBadge status="success" />
|
|
552
|
+
|
|
553
|
+
<!-- With custom text -->
|
|
554
|
+
<GStatusBadge status="working" text="Installing..." />
|
|
555
|
+
|
|
556
|
+
<!-- In a table -->
|
|
557
|
+
<GDataTable :columns="columns" :data="data">
|
|
558
|
+
<template #status="{ row }">
|
|
559
|
+
<GStatusBadge :status="row.status" />
|
|
560
|
+
</template>
|
|
561
|
+
</GDataTable>
|
|
562
|
+
</template>
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
---
|
|
566
|
+
|
|
567
|
+
### GDeletableList
|
|
568
|
+
|
|
569
|
+
List component with delete buttons for each item.
|
|
570
|
+
|
|
571
|
+
**Props:**
|
|
572
|
+
|
|
573
|
+
| Prop | Type | Default | Description |
|
|
574
|
+
|------|------|---------|-------------|
|
|
575
|
+
| items | array | *required* | List items |
|
|
576
|
+
| clickCallback | function | - | Called on item click: `(gameCode, id) => void` |
|
|
577
|
+
| deleteCallback | function | - | Called on delete click: `(id) => void` |
|
|
578
|
+
|
|
579
|
+
**Item Structure:**
|
|
580
|
+
|
|
581
|
+
```typescript
|
|
582
|
+
interface ListItem {
|
|
583
|
+
id: any // Unique identifier
|
|
584
|
+
name: string // Display name
|
|
585
|
+
gameCode: string // Game code identifier
|
|
586
|
+
}
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
**Example:**
|
|
590
|
+
|
|
591
|
+
```vue
|
|
592
|
+
<script setup>
|
|
593
|
+
const games = [
|
|
594
|
+
{ id: 1, name: 'Counter-Strike 2', gameCode: 'cs2' },
|
|
595
|
+
{ id: 2, name: 'Minecraft', gameCode: 'minecraft' },
|
|
596
|
+
{ id: 3, name: 'Rust', gameCode: 'rust' }
|
|
597
|
+
]
|
|
598
|
+
|
|
599
|
+
function handleClick(gameCode, id) {
|
|
600
|
+
console.log(`Clicked ${gameCode} with id ${id}`)
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
function handleDelete(id) {
|
|
604
|
+
console.log(`Delete item ${id}`)
|
|
605
|
+
}
|
|
606
|
+
</script>
|
|
607
|
+
|
|
608
|
+
<template>
|
|
609
|
+
<GDeletableList
|
|
610
|
+
:items="games"
|
|
611
|
+
:click-callback="handleClick"
|
|
612
|
+
:delete-callback="handleDelete"
|
|
613
|
+
/>
|
|
614
|
+
</template>
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
---
|
|
618
|
+
|
|
619
|
+
### Menu System
|
|
620
|
+
|
|
621
|
+
A set of components for building accessible dropdown menus with keyboard navigation.
|
|
622
|
+
|
|
623
|
+
#### GMenu
|
|
624
|
+
|
|
625
|
+
Container component that provides menu context to children.
|
|
626
|
+
|
|
627
|
+
**Props:**
|
|
628
|
+
|
|
629
|
+
| Prop | Type | Default | Description |
|
|
630
|
+
|------|------|---------|-------------|
|
|
631
|
+
| as | string | `'div'` | HTML element tag |
|
|
632
|
+
|
|
633
|
+
#### GMenuButton
|
|
634
|
+
|
|
635
|
+
Button to toggle menu visibility.
|
|
636
|
+
|
|
637
|
+
#### GMenuItems
|
|
638
|
+
|
|
639
|
+
Container for menu items with visibility control.
|
|
640
|
+
|
|
641
|
+
**Props:**
|
|
642
|
+
|
|
643
|
+
| Prop | Type | Default | Description |
|
|
644
|
+
|------|------|---------|-------------|
|
|
645
|
+
| unmount | boolean | `true` | Unmount when closed (false uses v-show) |
|
|
646
|
+
|
|
647
|
+
#### GMenuItem
|
|
648
|
+
|
|
649
|
+
Individual menu item with slot props.
|
|
650
|
+
|
|
651
|
+
**Slot Props:**
|
|
652
|
+
|
|
653
|
+
| Prop | Type | Description |
|
|
654
|
+
|------|------|-------------|
|
|
655
|
+
| active | boolean | Item is currently focused |
|
|
656
|
+
| close | function | Close the menu |
|
|
657
|
+
|
|
658
|
+
**Features:**
|
|
659
|
+
- Click-outside detection
|
|
660
|
+
- ESC key closes menu
|
|
661
|
+
- Enter/Space/ArrowDown opens menu
|
|
662
|
+
- Hover state tracking
|
|
663
|
+
- ARIA attributes for accessibility
|
|
664
|
+
|
|
665
|
+
**Example:**
|
|
666
|
+
|
|
667
|
+
```vue
|
|
668
|
+
<template>
|
|
669
|
+
<GMenu>
|
|
670
|
+
<GMenuButton class="btn btn-primary">
|
|
671
|
+
Actions
|
|
672
|
+
<GIcon name="chevron-down" size="sm" />
|
|
673
|
+
</GMenuButton>
|
|
674
|
+
|
|
675
|
+
<GMenuItems class="dropdown-menu">
|
|
676
|
+
<GMenuItem v-slot="{ active, close }">
|
|
677
|
+
<button
|
|
678
|
+
:class="{ 'bg-blue-100': active }"
|
|
679
|
+
@click="startServer(); close()"
|
|
680
|
+
>
|
|
681
|
+
<GIcon name="play" /> Start
|
|
682
|
+
</button>
|
|
683
|
+
</GMenuItem>
|
|
684
|
+
|
|
685
|
+
<GMenuItem v-slot="{ active, close }">
|
|
686
|
+
<button
|
|
687
|
+
:class="{ 'bg-blue-100': active }"
|
|
688
|
+
@click="stopServer(); close()"
|
|
689
|
+
>
|
|
690
|
+
<GIcon name="stop" /> Stop
|
|
691
|
+
</button>
|
|
692
|
+
</GMenuItem>
|
|
693
|
+
|
|
694
|
+
<GMenuItem v-slot="{ active, close }">
|
|
695
|
+
<button
|
|
696
|
+
:class="{ 'bg-red-100': active }"
|
|
697
|
+
@click="deleteServer(); close()"
|
|
698
|
+
>
|
|
699
|
+
<GIcon name="delete" /> Delete
|
|
700
|
+
</button>
|
|
701
|
+
</GMenuItem>
|
|
702
|
+
</GMenuItems>
|
|
703
|
+
</GMenu>
|
|
704
|
+
</template>
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
---
|
|
708
|
+
|
|
709
|
+
### Loading
|
|
710
|
+
|
|
711
|
+
Animated loading spinner component.
|
|
712
|
+
|
|
713
|
+
**Example:**
|
|
714
|
+
|
|
715
|
+
```vue
|
|
716
|
+
<template>
|
|
717
|
+
<Loading v-if="isLoading" />
|
|
718
|
+
<div v-else>
|
|
719
|
+
Content loaded
|
|
720
|
+
</div>
|
|
721
|
+
</template>
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
---
|
|
725
|
+
|
|
726
|
+
### Progressbar
|
|
727
|
+
|
|
728
|
+
Linear progress bar with percentage display.
|
|
729
|
+
|
|
730
|
+
**Props:**
|
|
731
|
+
|
|
732
|
+
| Prop | Type | Default | Description |
|
|
733
|
+
|------|------|---------|-------------|
|
|
734
|
+
| progress | number | `0` | Progress percentage (0-100) |
|
|
735
|
+
|
|
736
|
+
**Example:**
|
|
737
|
+
|
|
738
|
+
```vue
|
|
739
|
+
<script setup>
|
|
740
|
+
import { ref } from 'vue'
|
|
741
|
+
|
|
742
|
+
const downloadProgress = ref(45)
|
|
743
|
+
</script>
|
|
744
|
+
|
|
745
|
+
<template>
|
|
746
|
+
<Progressbar :progress="downloadProgress" />
|
|
747
|
+
</template>
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
---
|
|
751
|
+
|
|
752
|
+
## Icon System
|
|
753
|
+
|
|
754
|
+
The package includes a flexible icon registry system.
|
|
755
|
+
|
|
756
|
+
### Icon Registry API
|
|
757
|
+
|
|
758
|
+
```javascript
|
|
759
|
+
import {
|
|
760
|
+
registerIcons,
|
|
761
|
+
getIcon,
|
|
762
|
+
hasIcon,
|
|
763
|
+
iconRegistry,
|
|
764
|
+
defaultIconMap
|
|
765
|
+
} from '@gameap/ui'
|
|
766
|
+
|
|
767
|
+
// Register custom icons
|
|
768
|
+
registerIcons({
|
|
769
|
+
'my-icon': 'fa-solid fa-star',
|
|
770
|
+
'custom-component': MyIconComponent
|
|
771
|
+
})
|
|
772
|
+
|
|
773
|
+
// Check if icon exists
|
|
774
|
+
if (hasIcon('server')) {
|
|
775
|
+
const icon = getIcon('server')
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// Access all icons
|
|
779
|
+
console.log(iconRegistry)
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
### Default Icon Categories
|
|
783
|
+
|
|
784
|
+
The package includes 150+ predefined icon mappings:
|
|
785
|
+
|
|
786
|
+
**Action Icons:**
|
|
787
|
+
`delete`, `edit`, `save`, `add`, `close`, `copy`, `paste`, `cut`, `refresh`, `download`, `upload`, `search`, `view`, `clear`, `eraser`, `ban`, `move`
|
|
788
|
+
|
|
789
|
+
**Navigation Icons:**
|
|
790
|
+
`chevron-left`, `chevron-right`, `chevron-up`, `chevron-down`, `arrow-up`, `arrow-down`, `sort-asc`, `sort-desc`, `external-link`
|
|
791
|
+
|
|
792
|
+
**Status Icons:**
|
|
793
|
+
`check`, `warning`, `error`, `info`, `question`, `online`, `offline`, `certificate`, `heart-pulse`, `power-off`
|
|
794
|
+
|
|
795
|
+
**UI/State Icons:**
|
|
796
|
+
`loading`, `spinner`, `play`, `pause`, `stop`, `restart`
|
|
797
|
+
|
|
798
|
+
**Server/Infrastructure Icons:**
|
|
799
|
+
`server`, `node`, `hard-drive`, `terminal`, `console`, `gamepad`, `tasks`, `plug`, `memory`, `cpu`
|
|
800
|
+
|
|
801
|
+
**User/Auth Icons:**
|
|
802
|
+
`user`, `users`, `user-edit`, `login`, `logout`, `key`, `lock`, `address-card`, `profile`
|
|
803
|
+
|
|
804
|
+
**File Icons:**
|
|
805
|
+
`file`, `file-code`, `file-text`, `file-pdf`, `file-word`, `file-excel`, `folder`, `folder-open`, `clipboard`, `ftp`
|
|
806
|
+
|
|
807
|
+
**Brand Icons:**
|
|
808
|
+
`linux`, `windows`, `apple`, `telegram`, `discord`, `vk`, `reddit`, `patreon`, `teamspeak`
|
|
809
|
+
|
|
810
|
+
**Game Icons:**
|
|
811
|
+
`dice`, `dice-one` through `dice-six`, `cat`, `mods`
|
|
812
|
+
|
|
813
|
+
**Theme Icons:**
|
|
814
|
+
`sun`, `moon`
|
|
815
|
+
|
|
816
|
+
### Custom Icon Registration
|
|
817
|
+
|
|
818
|
+
Register custom icons at app initialization:
|
|
819
|
+
|
|
820
|
+
```javascript
|
|
821
|
+
import { registerIcons } from '@gameap/ui'
|
|
822
|
+
import CustomIcon from './components/CustomIcon.vue'
|
|
823
|
+
|
|
824
|
+
// Register Font Awesome classes
|
|
825
|
+
registerIcons({
|
|
826
|
+
'rocket': 'fa-solid fa-rocket',
|
|
827
|
+
'database': 'fa-solid fa-database'
|
|
828
|
+
})
|
|
829
|
+
|
|
830
|
+
// Register Vue components
|
|
831
|
+
registerIcons({
|
|
832
|
+
'custom-logo': CustomIcon
|
|
833
|
+
})
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
---
|
|
837
|
+
|
|
838
|
+
## CSS Utilities
|
|
839
|
+
|
|
840
|
+
The package provides Tailwind CSS utility classes in `style.css`.
|
|
841
|
+
|
|
842
|
+
### Badge Classes
|
|
843
|
+
|
|
844
|
+
```html
|
|
845
|
+
<span class="badge-red">Error</span>
|
|
846
|
+
<span class="badge-green">Success</span>
|
|
847
|
+
<span class="badge-orange">Warning</span>
|
|
848
|
+
<span class="badge-blue">Info</span>
|
|
849
|
+
<span class="badge-stone">Neutral</span>
|
|
850
|
+
<span class="badge-light">Light</span>
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
All badge classes include dark mode support.
|
|
854
|
+
|
|
855
|
+
### Progress Classes
|
|
856
|
+
|
|
857
|
+
```html
|
|
858
|
+
<div class="progress">
|
|
859
|
+
<div class="progress-bar progress-bar-info" style="width: 50%">
|
|
860
|
+
50%
|
|
861
|
+
</div>
|
|
862
|
+
</div>
|
|
863
|
+
```
|
|
864
|
+
|
|
865
|
+
---
|
|
866
|
+
|
|
867
|
+
## Dependencies
|
|
868
|
+
|
|
869
|
+
### Peer Dependencies
|
|
870
|
+
|
|
871
|
+
| Package | Version | Required |
|
|
872
|
+
|---------|---------|----------|
|
|
873
|
+
| vue | ^3.5.0 | Yes |
|
|
874
|
+
| vue-router | ^4.0.0 | Optional |
|
|
875
|
+
|
|
876
|
+
### Runtime Dependencies
|
|
877
|
+
|
|
878
|
+
- **naive-ui** - Base UI component library
|
|
879
|
+
|
|
880
|
+
### Styling Requirements
|
|
881
|
+
|
|
882
|
+
- **Tailwind CSS** - Must be configured in the consuming application
|
|
883
|
+
- **Font Awesome** - Required for default icon mappings
|
|
884
|
+
|
|
885
|
+
---
|
|
886
|
+
|
|
887
|
+
## Browser Support
|
|
888
|
+
|
|
889
|
+
Supports all modern browsers that support Vue 3:
|
|
890
|
+
- Chrome (latest)
|
|
891
|
+
- Firefox (latest)
|
|
892
|
+
- Safari (latest)
|
|
893
|
+
- Edge (latest)
|
|
894
|
+
|
|
895
|
+
---
|
|
896
|
+
|
|
897
|
+
## License
|
|
898
|
+
|
|
899
|
+
Part of the GameAP project.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<n-card
|
|
3
|
+
v-bind="mergedProps"
|
|
4
|
+
v-on="$attrs"
|
|
5
|
+
>
|
|
6
|
+
<template v-for="(_, slotName) in $slots" :key="slotName" #[slotName]="slotProps">
|
|
7
|
+
<slot :name="slotName" v-bind="slotProps || {}" />
|
|
8
|
+
</template>
|
|
9
|
+
</n-card>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup>
|
|
13
|
+
import { computed, useAttrs } from 'vue'
|
|
14
|
+
import { NCard } from 'naive-ui'
|
|
15
|
+
|
|
16
|
+
const props = defineProps({
|
|
17
|
+
title: {
|
|
18
|
+
type: String,
|
|
19
|
+
default: ''
|
|
20
|
+
},
|
|
21
|
+
size: {
|
|
22
|
+
type: String,
|
|
23
|
+
default: 'small'
|
|
24
|
+
},
|
|
25
|
+
bordered: {
|
|
26
|
+
type: Boolean,
|
|
27
|
+
default: true
|
|
28
|
+
},
|
|
29
|
+
segmented: {
|
|
30
|
+
type: [Boolean, Object],
|
|
31
|
+
default: () => ({ content: true, footer: 'soft' })
|
|
32
|
+
},
|
|
33
|
+
headerClass: {
|
|
34
|
+
type: String,
|
|
35
|
+
default: 'g-card-header'
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
defineOptions({
|
|
40
|
+
inheritAttrs: false
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const attrs = useAttrs()
|
|
44
|
+
|
|
45
|
+
const mergedProps = computed(() => ({
|
|
46
|
+
title: props.title,
|
|
47
|
+
size: props.size,
|
|
48
|
+
bordered: props.bordered,
|
|
49
|
+
segmented: props.segmented,
|
|
50
|
+
headerClass: props.headerClass,
|
|
51
|
+
...attrs
|
|
52
|
+
}))
|
|
53
|
+
</script>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<n-data-table
|
|
3
|
+
v-bind="mergedProps"
|
|
4
|
+
v-on="$attrs"
|
|
5
|
+
>
|
|
6
|
+
<template v-for="(_, slotName) in $slots" :key="slotName" #[slotName]="slotProps">
|
|
7
|
+
<slot :name="slotName" v-bind="slotProps || {}" />
|
|
8
|
+
</template>
|
|
9
|
+
</n-data-table>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup>
|
|
13
|
+
import { computed, useAttrs } from 'vue'
|
|
14
|
+
import { NDataTable } from 'naive-ui'
|
|
15
|
+
|
|
16
|
+
const props = defineProps({
|
|
17
|
+
bordered: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
default: false
|
|
20
|
+
},
|
|
21
|
+
singleLine: {
|
|
22
|
+
type: Boolean,
|
|
23
|
+
default: true
|
|
24
|
+
},
|
|
25
|
+
columns: {
|
|
26
|
+
type: Array,
|
|
27
|
+
default: () => []
|
|
28
|
+
},
|
|
29
|
+
data: {
|
|
30
|
+
type: Array,
|
|
31
|
+
default: () => []
|
|
32
|
+
},
|
|
33
|
+
loading: {
|
|
34
|
+
type: Boolean,
|
|
35
|
+
default: false
|
|
36
|
+
},
|
|
37
|
+
pagination: {
|
|
38
|
+
type: [Object, Boolean],
|
|
39
|
+
default: false
|
|
40
|
+
},
|
|
41
|
+
remote: {
|
|
42
|
+
type: Boolean,
|
|
43
|
+
default: false
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
defineOptions({
|
|
48
|
+
inheritAttrs: false
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
const attrs = useAttrs()
|
|
52
|
+
|
|
53
|
+
const mergedProps = computed(() => ({
|
|
54
|
+
bordered: props.bordered,
|
|
55
|
+
singleLine: props.singleLine,
|
|
56
|
+
columns: props.columns,
|
|
57
|
+
data: props.data,
|
|
58
|
+
loading: props.loading,
|
|
59
|
+
pagination: props.pagination,
|
|
60
|
+
remote: props.remote,
|
|
61
|
+
...attrs
|
|
62
|
+
}))
|
|
63
|
+
</script>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<n-empty
|
|
3
|
+
v-bind="mergedProps"
|
|
4
|
+
v-on="$attrs"
|
|
5
|
+
>
|
|
6
|
+
<template v-for="(_, slotName) in $slots" :key="slotName" #[slotName]="slotProps">
|
|
7
|
+
<slot :name="slotName" v-bind="slotProps || {}" />
|
|
8
|
+
</template>
|
|
9
|
+
</n-empty>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup>
|
|
13
|
+
import { computed, useAttrs } from 'vue'
|
|
14
|
+
import { NEmpty } from 'naive-ui'
|
|
15
|
+
|
|
16
|
+
const props = defineProps({
|
|
17
|
+
description: {
|
|
18
|
+
type: String,
|
|
19
|
+
default: undefined
|
|
20
|
+
},
|
|
21
|
+
size: {
|
|
22
|
+
type: String,
|
|
23
|
+
default: undefined
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
defineOptions({
|
|
28
|
+
inheritAttrs: false
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const attrs = useAttrs()
|
|
32
|
+
|
|
33
|
+
const mergedProps = computed(() => ({
|
|
34
|
+
...(props.description && { description: props.description }),
|
|
35
|
+
...(props.size && { size: props.size }),
|
|
36
|
+
...attrs
|
|
37
|
+
}))
|
|
38
|
+
</script>
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<i :class="[gameIconClass, $attrs.class]"></i>
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script setup>
|
|
6
|
+
import { computed } from 'vue'
|
|
7
|
+
|
|
8
|
+
const icons = {
|
|
9
|
+
'7d2d': 'fa-solid fa-7',
|
|
10
|
+
'7days2die': 'fa-solid fa-7',
|
|
11
|
+
ark: 'gicon gicon-ark-survival-evolved',
|
|
12
|
+
arma2: 'gicon gicon-arma-2',
|
|
13
|
+
arma2oa: 'gicon gicon-arma-2',
|
|
14
|
+
arma3: 'gicon gicon-arma-3',
|
|
15
|
+
blackmesasource: 'gicon gicon-black-mesa',
|
|
16
|
+
bms: 'gicon gicon-black-mesa',
|
|
17
|
+
counterstrike: 'gicon gicon-counter-strike1',
|
|
18
|
+
cs15: 'gicon gicon-counter-strike1',
|
|
19
|
+
cs2: 'gicon gicon-counter-strike',
|
|
20
|
+
csgo: 'gicon gicon-counter-strike',
|
|
21
|
+
css: 'gicon gicon-counter-strike-source',
|
|
22
|
+
cssource: 'gicon gicon-counter-strike-source',
|
|
23
|
+
cssv34: 'gicon gicon-counter-strike-source',
|
|
24
|
+
cstrike: 'gicon gicon-counter-strike1',
|
|
25
|
+
czero: 'gicon gicon-counter-strike1',
|
|
26
|
+
dod: 'gicon gicon-day-of-defeat',
|
|
27
|
+
dods: 'gicon gicon-day-of-defeat',
|
|
28
|
+
dontstarve: 'gicon gicon-dont-starve',
|
|
29
|
+
dontstarvetogether: 'gicon gicon-dont-starve',
|
|
30
|
+
dst: 'gicon gicon-dont-starve',
|
|
31
|
+
fivem: 'gicon gicon-fivem',
|
|
32
|
+
garrysmod: 'gicon gicon-garrys-mod',
|
|
33
|
+
grandtheftauto: 'gicon gicon-grand-theft-auto',
|
|
34
|
+
gta: 'gicon gicon-grand-theft-auto',
|
|
35
|
+
halflife: 'gicon gicon-half-life',
|
|
36
|
+
hurtworld: 'gicon gicon-hurtworld',
|
|
37
|
+
l4d2: 'gicon gicon-left-4-dead',
|
|
38
|
+
l4d: 'gicon gicon-left-4-dead',
|
|
39
|
+
minecraft: 'gicon gicon-minecraft',
|
|
40
|
+
mta: 'gicon gicon-grand-theft-auto',
|
|
41
|
+
op4: 'gicon gicon-half-life',
|
|
42
|
+
pmmp: 'gicon gicon-minecraft-creeper',
|
|
43
|
+
qw: 'gicon gicon-quake',
|
|
44
|
+
q1: 'gicon gicon-quake',
|
|
45
|
+
quake: 'gicon gicon-quake',
|
|
46
|
+
q2: 'gicon gicon-quake-2',
|
|
47
|
+
quake2: 'gicon gicon-quake-2',
|
|
48
|
+
q3: 'gicon gicon-quake-3',
|
|
49
|
+
quake3: 'gicon gicon-quake-3',
|
|
50
|
+
q4: 'gicon gicon-quake',
|
|
51
|
+
quake4: 'gicon gicon-quake',
|
|
52
|
+
rust: 'gicon gicon-rust',
|
|
53
|
+
samp: 'gicon gicon-rockstar',
|
|
54
|
+
teamfortress2: 'gicon gicon-team-fortress-2',
|
|
55
|
+
teamspeak3: 'fa-brands fa-teamspeak',
|
|
56
|
+
teamspeak: 'fa-brands fa-teamspeak',
|
|
57
|
+
tf2: 'gicon gicon-team-fortress-2',
|
|
58
|
+
valve: 'gicon gicon-half-life',
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const commonIcons = [
|
|
62
|
+
"fa-solid fa-gamepad",
|
|
63
|
+
"fa-solid fa-dice-one",
|
|
64
|
+
"fa-solid fa-dice-two",
|
|
65
|
+
"fa-solid fa-dice-three",
|
|
66
|
+
"fa-solid fa-dice-four",
|
|
67
|
+
"fa-solid fa-dice-five",
|
|
68
|
+
"fa-solid fa-dice-six",
|
|
69
|
+
"fa-solid fa-dice",
|
|
70
|
+
"fa-solid fa-puzzle-piece",
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
const props = defineProps({
|
|
74
|
+
game: {
|
|
75
|
+
type: String,
|
|
76
|
+
default: 'minecraft',
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
const gameIconClass = computed(() => {
|
|
81
|
+
if (icons[props.game] !== undefined) {
|
|
82
|
+
return icons[props.game]
|
|
83
|
+
}
|
|
84
|
+
return defineCommonIcon(props.game)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
function defineCommonIcon(game) {
|
|
88
|
+
return commonIcons[checksum(game)]
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function checksum(data) {
|
|
92
|
+
let c = 0
|
|
93
|
+
for (let i = 0; i < data.length; i++) {
|
|
94
|
+
c += data.charCodeAt(i)
|
|
95
|
+
}
|
|
96
|
+
return c % commonIcons.length
|
|
97
|
+
}
|
|
98
|
+
</script>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<n-input
|
|
3
|
+
v-bind="mergedProps"
|
|
4
|
+
v-on="$attrs"
|
|
5
|
+
>
|
|
6
|
+
<template v-for="(_, slotName) in $slots" :key="slotName" #[slotName]="slotProps">
|
|
7
|
+
<slot :name="slotName" v-bind="slotProps || {}" />
|
|
8
|
+
</template>
|
|
9
|
+
</n-input>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup>
|
|
13
|
+
import { computed, useAttrs } from 'vue'
|
|
14
|
+
import { NInput } from 'naive-ui'
|
|
15
|
+
|
|
16
|
+
const props = defineProps({
|
|
17
|
+
value: {
|
|
18
|
+
type: [String, Array],
|
|
19
|
+
default: undefined
|
|
20
|
+
},
|
|
21
|
+
type: {
|
|
22
|
+
type: String,
|
|
23
|
+
default: 'text'
|
|
24
|
+
},
|
|
25
|
+
placeholder: {
|
|
26
|
+
type: String,
|
|
27
|
+
default: ''
|
|
28
|
+
},
|
|
29
|
+
disabled: {
|
|
30
|
+
type: Boolean,
|
|
31
|
+
default: false
|
|
32
|
+
},
|
|
33
|
+
readonly: {
|
|
34
|
+
type: Boolean,
|
|
35
|
+
default: false
|
|
36
|
+
},
|
|
37
|
+
clearable: {
|
|
38
|
+
type: Boolean,
|
|
39
|
+
default: false
|
|
40
|
+
},
|
|
41
|
+
size: {
|
|
42
|
+
type: String,
|
|
43
|
+
default: undefined
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
defineOptions({
|
|
48
|
+
inheritAttrs: false
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
const emit = defineEmits(['update:value'])
|
|
52
|
+
|
|
53
|
+
const attrs = useAttrs()
|
|
54
|
+
|
|
55
|
+
const mergedProps = computed(() => ({
|
|
56
|
+
value: props.value,
|
|
57
|
+
'onUpdate:value': (val) => emit('update:value', val),
|
|
58
|
+
type: props.type,
|
|
59
|
+
placeholder: props.placeholder,
|
|
60
|
+
disabled: props.disabled,
|
|
61
|
+
readonly: props.readonly,
|
|
62
|
+
clearable: props.clearable,
|
|
63
|
+
...(props.size && { size: props.size }),
|
|
64
|
+
...attrs
|
|
65
|
+
}))
|
|
66
|
+
</script>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<n-modal
|
|
3
|
+
v-bind="mergedProps"
|
|
4
|
+
>
|
|
5
|
+
<template v-for="(_, slotName) in $slots" :key="slotName" #[slotName]="slotProps">
|
|
6
|
+
<slot :name="slotName" v-bind="slotProps || {}" />
|
|
7
|
+
</template>
|
|
8
|
+
</n-modal>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<script setup>
|
|
12
|
+
import { computed, useAttrs } from 'vue'
|
|
13
|
+
import { NModal } from 'naive-ui'
|
|
14
|
+
|
|
15
|
+
const props = defineProps({
|
|
16
|
+
show: {
|
|
17
|
+
type: Boolean,
|
|
18
|
+
default: false
|
|
19
|
+
},
|
|
20
|
+
preset: {
|
|
21
|
+
type: String,
|
|
22
|
+
default: 'card'
|
|
23
|
+
},
|
|
24
|
+
bordered: {
|
|
25
|
+
type: Boolean,
|
|
26
|
+
default: false
|
|
27
|
+
},
|
|
28
|
+
title: {
|
|
29
|
+
type: String,
|
|
30
|
+
default: ''
|
|
31
|
+
},
|
|
32
|
+
segmented: {
|
|
33
|
+
type: Object,
|
|
34
|
+
default: () => ({ content: 'soft', footer: 'soft' })
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
defineOptions({
|
|
39
|
+
inheritAttrs: false
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const emit = defineEmits(['update:show'])
|
|
43
|
+
|
|
44
|
+
const attrs = useAttrs()
|
|
45
|
+
|
|
46
|
+
const mergedProps = computed(() => ({
|
|
47
|
+
show: props.show,
|
|
48
|
+
'onUpdate:show': (value) => emit('update:show', value),
|
|
49
|
+
preset: props.preset,
|
|
50
|
+
bordered: props.bordered,
|
|
51
|
+
title: props.title,
|
|
52
|
+
segmented: props.segmented,
|
|
53
|
+
class: 'custom-card',
|
|
54
|
+
...attrs
|
|
55
|
+
}))
|
|
56
|
+
</script>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<n-switch
|
|
3
|
+
v-bind="mergedProps"
|
|
4
|
+
v-on="$attrs"
|
|
5
|
+
>
|
|
6
|
+
<template v-for="(_, slotName) in $slots" :key="slotName" #[slotName]="slotProps">
|
|
7
|
+
<slot :name="slotName" v-bind="slotProps || {}" />
|
|
8
|
+
</template>
|
|
9
|
+
</n-switch>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup>
|
|
13
|
+
import { computed, useAttrs } from 'vue'
|
|
14
|
+
import { NSwitch } from 'naive-ui'
|
|
15
|
+
|
|
16
|
+
const props = defineProps({
|
|
17
|
+
value: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
default: false
|
|
20
|
+
},
|
|
21
|
+
disabled: {
|
|
22
|
+
type: Boolean,
|
|
23
|
+
default: false
|
|
24
|
+
},
|
|
25
|
+
size: {
|
|
26
|
+
type: String,
|
|
27
|
+
default: undefined
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
defineOptions({
|
|
32
|
+
inheritAttrs: false
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const emit = defineEmits(['update:value'])
|
|
36
|
+
|
|
37
|
+
const attrs = useAttrs()
|
|
38
|
+
|
|
39
|
+
const mergedProps = computed(() => ({
|
|
40
|
+
value: props.value,
|
|
41
|
+
'onUpdate:value': (val) => emit('update:value', val),
|
|
42
|
+
disabled: props.disabled,
|
|
43
|
+
...(props.size && { size: props.size }),
|
|
44
|
+
...attrs
|
|
45
|
+
}))
|
|
46
|
+
</script>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<n-table
|
|
3
|
+
v-bind="mergedProps"
|
|
4
|
+
v-on="$attrs"
|
|
5
|
+
>
|
|
6
|
+
<slot />
|
|
7
|
+
</n-table>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script setup>
|
|
11
|
+
import { computed, useAttrs } from 'vue'
|
|
12
|
+
import { NTable } from 'naive-ui'
|
|
13
|
+
|
|
14
|
+
const props = defineProps({
|
|
15
|
+
bordered: {
|
|
16
|
+
type: Boolean,
|
|
17
|
+
default: false
|
|
18
|
+
},
|
|
19
|
+
singleLine: {
|
|
20
|
+
type: Boolean,
|
|
21
|
+
default: true
|
|
22
|
+
},
|
|
23
|
+
size: {
|
|
24
|
+
type: String,
|
|
25
|
+
default: undefined
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
defineOptions({
|
|
30
|
+
inheritAttrs: false
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const attrs = useAttrs()
|
|
34
|
+
|
|
35
|
+
const mergedProps = computed(() => ({
|
|
36
|
+
bordered: props.bordered,
|
|
37
|
+
singleLine: props.singleLine,
|
|
38
|
+
...(props.size && { size: props.size }),
|
|
39
|
+
...attrs
|
|
40
|
+
}))
|
|
41
|
+
</script>
|
package/index.js
CHANGED
|
@@ -8,6 +8,15 @@ export { default as GMenuButton } from './components/GMenuButton.vue'
|
|
|
8
8
|
export { default as GMenuItems } from './components/GMenuItems.vue'
|
|
9
9
|
export { default as GMenuItem } from './components/GMenuItem.vue'
|
|
10
10
|
export { default as GIcon } from './components/GIcon.vue'
|
|
11
|
+
export { default as GDataTable } from './components/GDataTable.vue'
|
|
12
|
+
export { default as GModal } from './components/GModal.vue'
|
|
13
|
+
export { default as GInput } from './components/GInput.vue'
|
|
14
|
+
export { default as GCard } from './components/GCard.vue'
|
|
15
|
+
export { default as GTable } from './components/GTable.vue'
|
|
16
|
+
export { default as GEmpty } from './components/GEmpty.vue'
|
|
17
|
+
export { default as GSwitch } from './components/GSwitch.vue'
|
|
18
|
+
export { default as GDivider } from './components/GDivider.vue'
|
|
19
|
+
export { default as GGameIcon } from './components/GGameIcon.vue'
|
|
11
20
|
|
|
12
21
|
export { registerIcons, iconRegistry, getIcon, hasIcon } from './icons/registry.js'
|
|
13
22
|
export { defaultIconMap } from './icons/iconMap.js'
|
|
@@ -22,6 +31,15 @@ import GMenuButton from './components/GMenuButton.vue'
|
|
|
22
31
|
import GMenuItems from './components/GMenuItems.vue'
|
|
23
32
|
import GMenuItem from './components/GMenuItem.vue'
|
|
24
33
|
import GIcon from './components/GIcon.vue'
|
|
34
|
+
import GDataTable from './components/GDataTable.vue'
|
|
35
|
+
import GModal from './components/GModal.vue'
|
|
36
|
+
import GInput from './components/GInput.vue'
|
|
37
|
+
import GCard from './components/GCard.vue'
|
|
38
|
+
import GTable from './components/GTable.vue'
|
|
39
|
+
import GEmpty from './components/GEmpty.vue'
|
|
40
|
+
import GSwitch from './components/GSwitch.vue'
|
|
41
|
+
import GDivider from './components/GDivider.vue'
|
|
42
|
+
import GGameIcon from './components/GGameIcon.vue'
|
|
25
43
|
|
|
26
44
|
export function install(app) {
|
|
27
45
|
app.component('GBreadcrumbs', GBreadcrumbs)
|
|
@@ -34,6 +52,15 @@ export function install(app) {
|
|
|
34
52
|
app.component('GMenuItems', GMenuItems)
|
|
35
53
|
app.component('GMenuItem', GMenuItem)
|
|
36
54
|
app.component('GIcon', GIcon)
|
|
55
|
+
app.component('GDataTable', GDataTable)
|
|
56
|
+
app.component('GModal', GModal)
|
|
57
|
+
app.component('GInput', GInput)
|
|
58
|
+
app.component('GCard', GCard)
|
|
59
|
+
app.component('GTable', GTable)
|
|
60
|
+
app.component('GEmpty', GEmpty)
|
|
61
|
+
app.component('GSwitch', GSwitch)
|
|
62
|
+
app.component('GDivider', GDivider)
|
|
63
|
+
app.component('GGameIcon', GGameIcon)
|
|
37
64
|
}
|
|
38
65
|
|
|
39
66
|
export default { install }
|