nicklabs-ui 1.0.25 → 1.0.26
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 +397 -121
- package/dist/index.mjs +699 -702
- package/dist/src/composables/sharedRouter.d.ts +3 -0
- package/dist/src/composables/useBreadcrumb.d.ts +1 -2
- package/dist/src/index.d.ts +5 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A Vue 3 component library with glassmorphism design, built for modern web applications.
|
|
4
4
|
|
|
5
|
-
**Version**: 1.0.
|
|
5
|
+
**Version**: 1.0.26 | **Framework**: Vue 3.5+
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -19,6 +19,7 @@ A Vue 3 component library with glassmorphism design, built for modern web applic
|
|
|
19
19
|
- [NSelect](#nselect)
|
|
20
20
|
- [NFileSelect](#nfileselect)
|
|
21
21
|
- [NSwitch](#nswitch)
|
|
22
|
+
- [NDatePicker](#ndatepicker)
|
|
22
23
|
- [Data Display](#data-display)
|
|
23
24
|
- [NTable](#ntable)
|
|
24
25
|
- [NList](#nlist)
|
|
@@ -46,7 +47,9 @@ A Vue 3 component library with glassmorphism design, built for modern web applic
|
|
|
46
47
|
- [useToast](#usetoast)
|
|
47
48
|
- [useAlert](#usealert)
|
|
48
49
|
- [useDisclosure](#usedisclosure)
|
|
50
|
+
- [useBreadcrumb](#usebreadcrumb)
|
|
49
51
|
- [useSidebarManager](#usesidebarmanager)
|
|
52
|
+
- [useRouteModal](#useroutemodal)
|
|
50
53
|
- [Type Reference](#type-reference)
|
|
51
54
|
- [CSS Variables](#css-variables)
|
|
52
55
|
|
|
@@ -90,6 +93,22 @@ Import components individually as needed:
|
|
|
90
93
|
import { NButton, NInput, NModal, useToast } from 'nicklabs-ui'
|
|
91
94
|
```
|
|
92
95
|
|
|
96
|
+
### 3. Register All Components (Optional)
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import { createApp } from 'vue'
|
|
100
|
+
import App from './App.vue'
|
|
101
|
+
import router from './router'
|
|
102
|
+
import { NickLabsUI } from 'nicklabs-ui'
|
|
103
|
+
|
|
104
|
+
const app = createApp(App)
|
|
105
|
+
app.use(router)
|
|
106
|
+
app.use(NickLabsUI, { router })
|
|
107
|
+
app.mount('#app')
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
> Passing `router` enables `useBreadcrumb` and `useRouteModal` without any additional setup.
|
|
111
|
+
|
|
93
112
|
---
|
|
94
113
|
|
|
95
114
|
## Components
|
|
@@ -394,10 +413,6 @@ const cities = [
|
|
|
394
413
|
{ label: 'Tokyo', value: 'tokyo' },
|
|
395
414
|
{ label: 'Seoul', value: 'seoul' },
|
|
396
415
|
]
|
|
397
|
-
const countries = [
|
|
398
|
-
{ label: 'Taiwan', value: 'TW' },
|
|
399
|
-
{ label: 'Japan', value: 'JP' },
|
|
400
|
-
]
|
|
401
416
|
const tagOptions = [
|
|
402
417
|
{ label: 'Frontend', value: 'frontend' },
|
|
403
418
|
{ label: 'Backend', value: 'backend' },
|
|
@@ -500,50 +515,110 @@ const darkMode = ref(false)
|
|
|
500
515
|
|
|
501
516
|
---
|
|
502
517
|
|
|
518
|
+
#### NDatePicker
|
|
519
|
+
|
|
520
|
+
Date picker with range selection and custom format support.
|
|
521
|
+
|
|
522
|
+
**Props**
|
|
523
|
+
|
|
524
|
+
| Prop | Type | Default | Description |
|
|
525
|
+
|------|------|---------|-------------|
|
|
526
|
+
| `modelValue` | `string \| Date` | — | Bound value (v-model) for single date |
|
|
527
|
+
| `start` | `string` | — | Range start (v-model:start) |
|
|
528
|
+
| `end` | `string` | — | Range end (v-model:end) |
|
|
529
|
+
| `placeholder` | `string` | `"請選擇日期"` | Placeholder text |
|
|
530
|
+
| `disabled` | `boolean` | `false` | Disable picker |
|
|
531
|
+
| `clearable` | `boolean` | `false` | Show clear button |
|
|
532
|
+
| `title` | `string` | — | Label above picker |
|
|
533
|
+
| `format` | `string` | `"YYYY-MM-DD"` | Date format string (supports `YYYY`, `MM`, `DD`, `HH`, `mm`) |
|
|
534
|
+
| `range` | `boolean` | `false` | Enable range selection mode |
|
|
535
|
+
|
|
536
|
+
**Events**
|
|
537
|
+
|
|
538
|
+
| Event | Payload | Description |
|
|
539
|
+
|-------|---------|-------------|
|
|
540
|
+
| `update:modelValue` | `string` | Single date value changed |
|
|
541
|
+
| `change` | `string` | Date changed |
|
|
542
|
+
| `clear` | — | Clear button clicked |
|
|
543
|
+
| `update:start` | `string` | Range start changed |
|
|
544
|
+
| `update:end` | `string` | Range end changed |
|
|
545
|
+
|
|
546
|
+
**Usage**
|
|
547
|
+
|
|
548
|
+
```vue
|
|
549
|
+
<template>
|
|
550
|
+
<!-- Single date -->
|
|
551
|
+
<NDatePicker v-model="date" title="Select Date" clearable />
|
|
552
|
+
|
|
553
|
+
<!-- With time format -->
|
|
554
|
+
<NDatePicker v-model="datetime" format="YYYY-MM-DD HH:mm" title="Date & Time" />
|
|
555
|
+
|
|
556
|
+
<!-- Date range -->
|
|
557
|
+
<NDatePicker
|
|
558
|
+
range
|
|
559
|
+
v-model:start="startDate"
|
|
560
|
+
v-model:end="endDate"
|
|
561
|
+
title="Date Range"
|
|
562
|
+
/>
|
|
563
|
+
</template>
|
|
564
|
+
|
|
565
|
+
<script setup>
|
|
566
|
+
import { ref } from 'vue'
|
|
567
|
+
import { NDatePicker } from 'nicklabs-ui'
|
|
568
|
+
|
|
569
|
+
const date = ref('')
|
|
570
|
+
const datetime = ref('')
|
|
571
|
+
const startDate = ref('')
|
|
572
|
+
const endDate = ref('')
|
|
573
|
+
</script>
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
---
|
|
577
|
+
|
|
503
578
|
### Data Display
|
|
504
579
|
|
|
505
580
|
---
|
|
506
581
|
|
|
507
582
|
#### NTable
|
|
508
583
|
|
|
509
|
-
A type-safe, sortable data table with support for
|
|
584
|
+
A type-safe, sortable data table with support for batch selection and action slots.
|
|
510
585
|
|
|
511
586
|
**Props**
|
|
512
587
|
|
|
513
588
|
| Prop | Type | Default | Description |
|
|
514
589
|
|------|------|---------|-------------|
|
|
515
|
-
| `columns` | `NTableColumn
|
|
516
|
-
| `
|
|
517
|
-
| `striped` | `boolean` | `false` | Alternating row colors |
|
|
590
|
+
| `columns` | `NTableColumn[]` | `[]` | Column definitions |
|
|
591
|
+
| `items` | `T[]` | `[]` | Row data |
|
|
518
592
|
| `bordered` | `boolean` | `false` | Show borders |
|
|
519
593
|
| `hoverable` | `boolean` | `true` | Highlight rows on hover |
|
|
520
594
|
| `loading` | `boolean` | `false` | Show loading state |
|
|
521
|
-
| `
|
|
522
|
-
| `
|
|
595
|
+
| `emptyTitle` | `string` | `"目前沒有資料"` | Title when no data |
|
|
596
|
+
| `emptyDescription` | `string` | — | Description when no data |
|
|
597
|
+
| `itemKey` | `string` | `"id"` | Unique key field |
|
|
523
598
|
|
|
524
599
|
**Events**
|
|
525
600
|
|
|
526
601
|
| Event | Payload | Description |
|
|
527
602
|
|-------|---------|-------------|
|
|
528
603
|
| `sort` | `NTableSortState` | Column sort changed |
|
|
529
|
-
| `
|
|
604
|
+
| `click` | `T` | Row was clicked |
|
|
530
605
|
|
|
531
606
|
**Slots**
|
|
532
607
|
|
|
533
608
|
| Slot | Description |
|
|
534
609
|
|------|-------------|
|
|
535
|
-
| `
|
|
610
|
+
| `batch` | Content in the batch selection header column |
|
|
611
|
+
| `actions-header` | Custom header text for the actions column (default: "操作") |
|
|
612
|
+
| `actions` | Custom action buttons per row (scoped: `{ item, column, index }`) |
|
|
613
|
+
| `empty` | Custom empty state content |
|
|
536
614
|
|
|
537
615
|
**NTableColumn Interface**
|
|
538
616
|
|
|
539
617
|
```typescript
|
|
540
|
-
interface NTableColumn
|
|
541
|
-
key: string
|
|
542
|
-
label: string
|
|
543
|
-
|
|
544
|
-
align?: "left" | "center" | "right"
|
|
545
|
-
sortable?: boolean // Enable column sorting
|
|
546
|
-
formatter?: (value: any, row: T) => string // Custom cell renderer
|
|
618
|
+
interface NTableColumn {
|
|
619
|
+
key: string // Data field key
|
|
620
|
+
label: string // Column header text
|
|
621
|
+
sortable?: boolean
|
|
547
622
|
}
|
|
548
623
|
```
|
|
549
624
|
|
|
@@ -553,15 +628,14 @@ interface NTableColumn<T = any> {
|
|
|
553
628
|
<template>
|
|
554
629
|
<NTable
|
|
555
630
|
:columns="columns"
|
|
556
|
-
:
|
|
557
|
-
striped
|
|
631
|
+
:items="users"
|
|
558
632
|
hoverable
|
|
559
633
|
@sort="handleSort"
|
|
560
|
-
@
|
|
634
|
+
@click="handleItemClick"
|
|
561
635
|
>
|
|
562
|
-
<template #
|
|
563
|
-
<NButton size="sm" variant="ghost" intent="primary" @click="edit(
|
|
564
|
-
<NButton size="sm" variant="ghost" intent="error" @click="remove(
|
|
636
|
+
<template #actions="{ item }">
|
|
637
|
+
<NButton size="sm" variant="ghost" intent="primary" @click="edit(item)">Edit</NButton>
|
|
638
|
+
<NButton size="sm" variant="ghost" intent="error" @click="remove(item)">Delete</NButton>
|
|
565
639
|
</template>
|
|
566
640
|
</NTable>
|
|
567
641
|
</template>
|
|
@@ -576,31 +650,25 @@ interface User {
|
|
|
576
650
|
name: string
|
|
577
651
|
email: string
|
|
578
652
|
role: string
|
|
579
|
-
createdAt: string
|
|
580
653
|
}
|
|
581
654
|
|
|
582
|
-
const columns: NTableColumn
|
|
655
|
+
const columns: NTableColumn[] = [
|
|
583
656
|
{ key: 'name', label: 'Name', sortable: true },
|
|
584
657
|
{ key: 'email', label: 'Email' },
|
|
585
|
-
{ key: 'role', label: 'Role'
|
|
586
|
-
{
|
|
587
|
-
key: 'createdAt',
|
|
588
|
-
label: 'Created',
|
|
589
|
-
formatter: (value) => new Date(value).toLocaleDateString(),
|
|
590
|
-
},
|
|
658
|
+
{ key: 'role', label: 'Role' },
|
|
591
659
|
]
|
|
592
660
|
|
|
593
661
|
const users = ref<User[]>([
|
|
594
|
-
{ id: 1, name: 'Alice', email: 'alice@example.com', role: 'Admin'
|
|
595
|
-
{ id: 2, name: 'Bob', email: 'bob@example.com', role: 'User'
|
|
662
|
+
{ id: 1, name: 'Alice', email: 'alice@example.com', role: 'Admin' },
|
|
663
|
+
{ id: 2, name: 'Bob', email: 'bob@example.com', role: 'User' },
|
|
596
664
|
])
|
|
597
665
|
|
|
598
666
|
function handleSort(state: NTableSortState) {
|
|
599
667
|
console.log('Sort by:', state.key, state.order)
|
|
600
668
|
}
|
|
601
669
|
|
|
602
|
-
function
|
|
603
|
-
console.log('Clicked:',
|
|
670
|
+
function handleItemClick(item: User) {
|
|
671
|
+
console.log('Clicked:', item)
|
|
604
672
|
}
|
|
605
673
|
</script>
|
|
606
674
|
```
|
|
@@ -615,55 +683,77 @@ A full-featured data management component combining table, pagination, filtering
|
|
|
615
683
|
|
|
616
684
|
| Prop | Type | Default | Description |
|
|
617
685
|
|------|------|---------|-------------|
|
|
618
|
-
| `
|
|
619
|
-
| `
|
|
686
|
+
| `title` | `string` | — | Section title displayed in hero header |
|
|
687
|
+
| `description` | `string` | — | Section description displayed in hero header |
|
|
688
|
+
| `items` | `T[]` | `[]` | Data items (T must extend `{ id: number }`) |
|
|
689
|
+
| `columns` | `NTableColumn[]` | `[]` | Column definitions |
|
|
690
|
+
| `itemKey` | `string` | `"id"` | Unique key field |
|
|
620
691
|
| `pageSize` | `number` | `10` | Items per page |
|
|
621
|
-
| `maxPageButtons` | `number` | `
|
|
622
|
-
| `filterable` | `boolean` | `false` | Show filter
|
|
623
|
-
| `
|
|
624
|
-
| `
|
|
692
|
+
| `maxPageButtons` | `number` | `7` | Visible page buttons |
|
|
693
|
+
| `filterable` | `boolean` | `false` | Show filter button |
|
|
694
|
+
| `updatable` | `boolean` | `false` | Show row edit button |
|
|
695
|
+
| `deletable` | `boolean` | `false` | Show row delete button |
|
|
625
696
|
| `creatable` | `boolean` | `false` | Show create button |
|
|
626
|
-
| `batchDeletable` | `boolean` | `false` | Enable batch delete |
|
|
697
|
+
| `batchDeletable` | `boolean` | `false` | Enable batch delete with checkboxes |
|
|
627
698
|
| `refreshable` | `boolean` | `false` | Show refresh button |
|
|
699
|
+
| `emptyTitle` | `string` | `"目前沒有資料"` | Empty state title |
|
|
700
|
+
| `emptyDescription` | `string` | — | Empty state description |
|
|
701
|
+
| `emptyIcon` | `string` | — | Custom SVG string for empty state |
|
|
628
702
|
|
|
629
703
|
**Events**
|
|
630
704
|
|
|
631
705
|
| Event | Payload | Description |
|
|
632
706
|
|-------|---------|-------------|
|
|
633
|
-
| `
|
|
634
|
-
| `
|
|
635
|
-
| `
|
|
636
|
-
| `
|
|
637
|
-
| `
|
|
638
|
-
| `
|
|
639
|
-
| `
|
|
640
|
-
| `
|
|
707
|
+
| `update` | `T` | Row edit clicked |
|
|
708
|
+
| `delete` | `T` | Row delete clicked |
|
|
709
|
+
| `pageChange` | `number` | Page changed |
|
|
710
|
+
| `create` | — | Create clicked |
|
|
711
|
+
| `batchDelete` | `number[]` | Batch delete with selected IDs |
|
|
712
|
+
| `refresh` | — | Refresh clicked |
|
|
713
|
+
| `filter` | — | Filter clicked |
|
|
714
|
+
| `click` | `T` | Row clicked |
|
|
641
715
|
| `sort` | `NTableSortState` | Sort changed |
|
|
642
716
|
|
|
717
|
+
**Slots**
|
|
718
|
+
|
|
719
|
+
| Slot | Description |
|
|
720
|
+
|------|-------------|
|
|
721
|
+
| `toolbar` | Extra toolbar content (alongside create/refresh buttons) |
|
|
722
|
+
| `item` | Custom cell renderer (scoped: `{ item, column, index }`) |
|
|
723
|
+
| `actions` | Custom action buttons per row (scoped: `{ item, index }`) |
|
|
724
|
+
| `actions-header` | Custom header text for the actions column |
|
|
725
|
+
|
|
643
726
|
**Usage**
|
|
644
727
|
|
|
645
728
|
```vue
|
|
646
729
|
<template>
|
|
647
730
|
<NList
|
|
731
|
+
title="User Management"
|
|
648
732
|
:items="users"
|
|
649
733
|
:columns="columns"
|
|
650
734
|
:page-size="20"
|
|
651
735
|
filterable
|
|
652
|
-
|
|
653
|
-
|
|
736
|
+
updatable
|
|
737
|
+
deletable
|
|
654
738
|
creatable
|
|
655
739
|
refreshable
|
|
656
|
-
@
|
|
657
|
-
@
|
|
658
|
-
@
|
|
659
|
-
@
|
|
740
|
+
@update="handleEdit"
|
|
741
|
+
@delete="handleDelete"
|
|
742
|
+
@create="handleCreate"
|
|
743
|
+
@refresh="loadUsers"
|
|
744
|
+
@filter="openFilter"
|
|
660
745
|
/>
|
|
661
746
|
</template>
|
|
662
747
|
|
|
663
748
|
<script setup lang="ts">
|
|
664
749
|
import { NList } from 'nicklabs-ui'
|
|
665
750
|
|
|
666
|
-
//
|
|
751
|
+
// T must extend { id: number }
|
|
752
|
+
interface User {
|
|
753
|
+
id: number
|
|
754
|
+
name: string
|
|
755
|
+
email: string
|
|
756
|
+
}
|
|
667
757
|
</script>
|
|
668
758
|
```
|
|
669
759
|
|
|
@@ -829,7 +919,6 @@ const isOpen = ref(false)
|
|
|
829
919
|
|
|
830
920
|
function open() { isOpen.value = true }
|
|
831
921
|
function confirm() {
|
|
832
|
-
// do something
|
|
833
922
|
isOpen.value = false
|
|
834
923
|
}
|
|
835
924
|
</script>
|
|
@@ -960,37 +1049,29 @@ const isSubmitting = ref(false)
|
|
|
960
1049
|
|
|
961
1050
|
#### NLayout
|
|
962
1051
|
|
|
963
|
-
Main application shell integrating sidebar and
|
|
1052
|
+
Main application shell integrating sidebar and main content area.
|
|
964
1053
|
|
|
965
1054
|
**Props**
|
|
966
1055
|
|
|
967
1056
|
| Prop | Type | Default | Description |
|
|
968
1057
|
|------|------|---------|-------------|
|
|
969
|
-
| `menus` | `Menu[]` |
|
|
1058
|
+
| `menus` | `Menu[]` | — | Sidebar menu items |
|
|
970
1059
|
| `isShowSidebar` | `boolean` | `true` | Show/hide sidebar |
|
|
971
1060
|
| `copyright` | `string` | — | Footer copyright text |
|
|
972
|
-
| `currentPath` | `string` |
|
|
1061
|
+
| `currentPath` | `string` | `""` | Active route path |
|
|
973
1062
|
|
|
974
1063
|
**Events**
|
|
975
1064
|
|
|
976
|
-
| Event | Description |
|
|
977
|
-
|
|
978
|
-
| `logout` | Logout triggered |
|
|
979
|
-
| `navigate` | Menu item clicked |
|
|
1065
|
+
| Event | Payload | Description |
|
|
1066
|
+
|-------|---------|-------------|
|
|
1067
|
+
| `logout` | — | Logout triggered |
|
|
1068
|
+
| `navigate` | `MenuChild` | Menu item clicked |
|
|
980
1069
|
|
|
981
|
-
**
|
|
1070
|
+
**Slots**
|
|
982
1071
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
title: string
|
|
987
|
-
children?: {
|
|
988
|
-
icon: string
|
|
989
|
-
title: string
|
|
990
|
-
route: string
|
|
991
|
-
}[]
|
|
992
|
-
}
|
|
993
|
-
```
|
|
1072
|
+
| Slot | Description |
|
|
1073
|
+
|------|-------------|
|
|
1074
|
+
| `default` | Main page content |
|
|
994
1075
|
|
|
995
1076
|
**Usage**
|
|
996
1077
|
|
|
@@ -1048,23 +1129,25 @@ Top navigation bar with sidebar toggle, fullscreen, and user controls.
|
|
|
1048
1129
|
|
|
1049
1130
|
#### NSidebar
|
|
1050
1131
|
|
|
1051
|
-
Collapsible side navigation menu.
|
|
1132
|
+
Collapsible side navigation menu with hover-expand behavior.
|
|
1052
1133
|
|
|
1053
1134
|
**Props**
|
|
1054
1135
|
|
|
1055
1136
|
| Prop | Type | Default | Description |
|
|
1056
1137
|
|------|------|---------|-------------|
|
|
1057
|
-
| `isOpen` | `boolean` | `
|
|
1058
|
-
| `menus` | `Menu[]` |
|
|
1059
|
-
| `currentPath` | `string` |
|
|
1138
|
+
| `isOpen` | `boolean` | `false` | Sidebar open state |
|
|
1139
|
+
| `menus` | `Menu[]` | — | Menu items |
|
|
1140
|
+
| `currentPath` | `string` | `""` | Active route path |
|
|
1141
|
+
| `userName` | `string` | — | Display name shown in user area |
|
|
1142
|
+
| `userAvatarUrl` | `string` | — | Avatar image URL |
|
|
1060
1143
|
|
|
1061
1144
|
**Events**
|
|
1062
1145
|
|
|
1063
|
-
| Event | Description |
|
|
1064
|
-
|
|
1065
|
-
| `update:isOpen` | Open state changed |
|
|
1066
|
-
| `logout` | Logout triggered |
|
|
1067
|
-
| `navigate` | Menu item clicked |
|
|
1146
|
+
| Event | Payload | Description |
|
|
1147
|
+
|-------|---------|-------------|
|
|
1148
|
+
| `update:isOpen` | `boolean` | Open state changed |
|
|
1149
|
+
| `logout` | — | Logout triggered |
|
|
1150
|
+
| `navigate` | `MenuChild` | Menu item clicked |
|
|
1068
1151
|
|
|
1069
1152
|
---
|
|
1070
1153
|
|
|
@@ -1077,7 +1160,7 @@ Content card with glassmorphism styling.
|
|
|
1077
1160
|
| Prop | Type | Default | Description |
|
|
1078
1161
|
|------|------|---------|-------------|
|
|
1079
1162
|
| `size` | `"none" \| "sm" \| "md" \| "lg"` | `"md"` | Padding size |
|
|
1080
|
-
| `radius` | `"none" \| "sm" \| "md" \| "lg" \| "xl"` | `"
|
|
1163
|
+
| `radius` | `"none" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` | Border radius |
|
|
1081
1164
|
|
|
1082
1165
|
**Usage**
|
|
1083
1166
|
|
|
@@ -1104,18 +1187,29 @@ Form wrapper with optional tab navigation and hero section header.
|
|
|
1104
1187
|
|
|
1105
1188
|
| Prop | Type | Default | Description |
|
|
1106
1189
|
|------|------|---------|-------------|
|
|
1107
|
-
| `model` | `object` |
|
|
1190
|
+
| `model` | `object` | `{}` | Form data object |
|
|
1108
1191
|
| `disabled` | `boolean` | `false` | Disable all inputs |
|
|
1109
1192
|
| `title` | `string` | — | Form header title |
|
|
1193
|
+
| `description` | `string` | — | Form header description |
|
|
1110
1194
|
| `icon` | `string` | — | Header icon (SVG string) |
|
|
1111
|
-
| `tabs` | `string[]` |
|
|
1195
|
+
| `tabs` | `string[]` | `[]` | Tab labels for multi-section forms |
|
|
1112
1196
|
|
|
1113
1197
|
**Events**
|
|
1114
1198
|
|
|
1115
|
-
| Event | Description |
|
|
1116
|
-
|
|
1117
|
-
| `submit` | Form submitted |
|
|
1118
|
-
| `reset` | Form reset |
|
|
1199
|
+
| Event | Payload | Description |
|
|
1200
|
+
|-------|---------|-------------|
|
|
1201
|
+
| `submit` | `Record<string, any>` | Form submitted with model data |
|
|
1202
|
+
| `reset` | — | Form reset |
|
|
1203
|
+
|
|
1204
|
+
**Slots**
|
|
1205
|
+
|
|
1206
|
+
| Slot | Description |
|
|
1207
|
+
|------|-------------|
|
|
1208
|
+
| `toolbar` | Toolbar area in the hero header (buttons, etc.) |
|
|
1209
|
+
| `description` | Custom description content in hero header |
|
|
1210
|
+
| `tab0` | Content for first tab (or only content when no tabs) |
|
|
1211
|
+
| `tab1`, `tab2`, ... | Content for subsequent tabs |
|
|
1212
|
+
| `footer` | Form footer (submit/cancel buttons) |
|
|
1119
1213
|
|
|
1120
1214
|
**Usage**
|
|
1121
1215
|
|
|
@@ -1124,22 +1218,37 @@ Form wrapper with optional tab navigation and hero section header.
|
|
|
1124
1218
|
<NForm
|
|
1125
1219
|
:model="formData"
|
|
1126
1220
|
title="User Profile"
|
|
1221
|
+
description="Manage your account details"
|
|
1127
1222
|
:tabs="['Basic Info', 'Security', 'Preferences']"
|
|
1128
1223
|
@submit="handleSubmit"
|
|
1129
1224
|
>
|
|
1130
|
-
|
|
1131
|
-
|
|
1225
|
+
<template #toolbar>
|
|
1226
|
+
<NButton variant="ghost" @click="cancel">Cancel</NButton>
|
|
1227
|
+
</template>
|
|
1228
|
+
|
|
1229
|
+
<template #tab0>
|
|
1230
|
+
<NInput v-model="formData.name" title="Name" />
|
|
1231
|
+
<NInput v-model="formData.email" title="Email" />
|
|
1232
|
+
</template>
|
|
1233
|
+
|
|
1234
|
+
<template #tab1>
|
|
1235
|
+
<NInput v-model="formData.password" type="password" title="Password" />
|
|
1236
|
+
</template>
|
|
1237
|
+
|
|
1238
|
+
<template #footer>
|
|
1239
|
+
<NButton type="submit" intent="primary">Save</NButton>
|
|
1240
|
+
</template>
|
|
1132
1241
|
</NForm>
|
|
1133
1242
|
</template>
|
|
1134
1243
|
|
|
1135
1244
|
<script setup>
|
|
1136
1245
|
import { reactive } from 'vue'
|
|
1137
|
-
import { NForm, NInput } from 'nicklabs-ui'
|
|
1246
|
+
import { NForm, NInput, NButton } from 'nicklabs-ui'
|
|
1138
1247
|
|
|
1139
|
-
const formData = reactive({ name: '' })
|
|
1248
|
+
const formData = reactive({ name: '', email: '', password: '' })
|
|
1140
1249
|
|
|
1141
|
-
function handleSubmit() {
|
|
1142
|
-
console.log('Submitted:',
|
|
1250
|
+
function handleSubmit(model) {
|
|
1251
|
+
console.log('Submitted:', model)
|
|
1143
1252
|
}
|
|
1144
1253
|
</script>
|
|
1145
1254
|
```
|
|
@@ -1154,8 +1263,8 @@ Full-screen login page wrapper with animated card.
|
|
|
1154
1263
|
|
|
1155
1264
|
| Prop | Type | Default | Description |
|
|
1156
1265
|
|------|------|---------|-------------|
|
|
1157
|
-
| `backgroundImage` | `string` | — | Background image URL |
|
|
1158
|
-
| `logo` | `string` | — | Logo image URL or SVG |
|
|
1266
|
+
| `backgroundImage` | `string` | — | Background image URL (falls back to `--bg-gradient`) |
|
|
1267
|
+
| `logo` | `string` | — | Logo image URL or SVG string |
|
|
1159
1268
|
| `title` | `string` | — | Application name |
|
|
1160
1269
|
| `description` | `string` | — | Subtitle/tagline |
|
|
1161
1270
|
|
|
@@ -1188,7 +1297,9 @@ const password = ref('')
|
|
|
1188
1297
|
|
|
1189
1298
|
#### NBreadcrumb
|
|
1190
1299
|
|
|
1191
|
-
|
|
1300
|
+
Breadcrumb navigation driven by `useBreadcrumb`. No props — reads from the composable's state automatically.
|
|
1301
|
+
|
|
1302
|
+
> Configure breadcrumbs via [useBreadcrumb](#usebreadcrumb).
|
|
1192
1303
|
|
|
1193
1304
|
**Usage**
|
|
1194
1305
|
|
|
@@ -1212,9 +1323,9 @@ Pagination control with smart ellipsis.
|
|
|
1212
1323
|
|
|
1213
1324
|
| Prop | Type | Default | Description |
|
|
1214
1325
|
|------|------|---------|-------------|
|
|
1215
|
-
| `totalItems` | `number` |
|
|
1216
|
-
| `pageSize` | `number` |
|
|
1217
|
-
| `maxPageButtons` | `number` | `
|
|
1326
|
+
| `totalItems` | `number` | — | Total number of items |
|
|
1327
|
+
| `pageSize` | `number` | — | Items per page |
|
|
1328
|
+
| `maxPageButtons` | `number` | `7` | Max visible page buttons (min: 5) |
|
|
1218
1329
|
|
|
1219
1330
|
**Events**
|
|
1220
1331
|
|
|
@@ -1250,27 +1361,31 @@ function loadPage(page: number) {
|
|
|
1250
1361
|
|
|
1251
1362
|
#### NHeroSection
|
|
1252
1363
|
|
|
1253
|
-
Page header with icon, title, breadcrumb, and toolbar slot.
|
|
1364
|
+
Page header with icon, title, description, breadcrumb, and toolbar slot.
|
|
1254
1365
|
|
|
1255
1366
|
**Props**
|
|
1256
1367
|
|
|
1257
1368
|
| Prop | Type | Default | Description |
|
|
1258
1369
|
|------|------|---------|-------------|
|
|
1259
1370
|
| `title` | `string` | — | Section title |
|
|
1371
|
+
| `description` | `string` | — | Section description |
|
|
1260
1372
|
| `icon` | `string` | — | Icon (SVG string) |
|
|
1261
1373
|
|
|
1262
1374
|
**Slots**
|
|
1263
1375
|
|
|
1264
1376
|
| Slot | Description |
|
|
1265
1377
|
|------|-------------|
|
|
1266
|
-
| `
|
|
1378
|
+
| `toolbar` | Toolbar content (buttons, filters, etc.) |
|
|
1379
|
+
| `description` | Custom description content |
|
|
1267
1380
|
|
|
1268
1381
|
**Usage**
|
|
1269
1382
|
|
|
1270
1383
|
```vue
|
|
1271
1384
|
<template>
|
|
1272
|
-
<NHeroSection title="User Management" :icon="userIcon">
|
|
1273
|
-
<
|
|
1385
|
+
<NHeroSection title="User Management" description="Manage system users" :icon="userIcon">
|
|
1386
|
+
<template #toolbar>
|
|
1387
|
+
<NButton intent="primary" @click="create">New User</NButton>
|
|
1388
|
+
</template>
|
|
1274
1389
|
</NHeroSection>
|
|
1275
1390
|
</template>
|
|
1276
1391
|
|
|
@@ -1291,7 +1406,7 @@ A slide-out side drawer for filter interfaces.
|
|
|
1291
1406
|
|
|
1292
1407
|
| Prop | Type | Default | Description |
|
|
1293
1408
|
|------|------|---------|-------------|
|
|
1294
|
-
| `open` | `boolean` |
|
|
1409
|
+
| `open` | `boolean` | — | Open state (v-model:open) |
|
|
1295
1410
|
| `title` | `string` | — | Drawer title |
|
|
1296
1411
|
|
|
1297
1412
|
**Events**
|
|
@@ -1471,9 +1586,83 @@ const [isOpen, open, close] = useDisclosure()
|
|
|
1471
1586
|
|
|
1472
1587
|
---
|
|
1473
1588
|
|
|
1589
|
+
### useBreadcrumb
|
|
1590
|
+
|
|
1591
|
+
Manage breadcrumb navigation state. `NBreadcrumb` reads from this composable automatically.
|
|
1592
|
+
|
|
1593
|
+
```typescript
|
|
1594
|
+
import { useBreadcrumb } from 'nicklabs-ui'
|
|
1595
|
+
|
|
1596
|
+
const {
|
|
1597
|
+
breadcrumbs,
|
|
1598
|
+
setLabelResolver,
|
|
1599
|
+
setBreadcrumbSuffix,
|
|
1600
|
+
clearSuffix,
|
|
1601
|
+
navigate,
|
|
1602
|
+
} = useBreadcrumb()
|
|
1603
|
+
```
|
|
1604
|
+
|
|
1605
|
+
**Methods**
|
|
1606
|
+
|
|
1607
|
+
| Method | Signature | Description |
|
|
1608
|
+
|--------|-----------|-------------|
|
|
1609
|
+
| `setLabelResolver` | `(fn: (route) => string) => void` | Custom function to extract label from a route record |
|
|
1610
|
+
| `setBreadcrumbSuffix` | `(fn: (label: string) => string) => void` | Transform the last breadcrumb label (e.g. append a record name) |
|
|
1611
|
+
| `clearSuffix` | `() => void` | Reset the suffix transform |
|
|
1612
|
+
| `navigate` | `(path: string) => void` | Navigate to a breadcrumb path |
|
|
1613
|
+
|
|
1614
|
+
**BreadcrumbItem**
|
|
1615
|
+
|
|
1616
|
+
```typescript
|
|
1617
|
+
interface BreadcrumbItem {
|
|
1618
|
+
label: string
|
|
1619
|
+
path?: string // undefined for the last (active) crumb
|
|
1620
|
+
}
|
|
1621
|
+
```
|
|
1622
|
+
|
|
1623
|
+
**Setup**
|
|
1624
|
+
|
|
1625
|
+
Pass `router` when installing the plugin (see [Setup](#setup)). The label is read from `route.meta.breadcrumb` by default — no additional configuration needed.
|
|
1626
|
+
|
|
1627
|
+
**Route meta**
|
|
1628
|
+
|
|
1629
|
+
```typescript
|
|
1630
|
+
const routes = [
|
|
1631
|
+
{
|
|
1632
|
+
path: '/users',
|
|
1633
|
+
component: UserList,
|
|
1634
|
+
meta: { breadcrumb: 'Users' },
|
|
1635
|
+
children: [
|
|
1636
|
+
{
|
|
1637
|
+
path: ':id',
|
|
1638
|
+
component: UserDetail,
|
|
1639
|
+
meta: { breadcrumb: 'Detail' },
|
|
1640
|
+
},
|
|
1641
|
+
],
|
|
1642
|
+
},
|
|
1643
|
+
]
|
|
1644
|
+
```
|
|
1645
|
+
|
|
1646
|
+
**Dynamic suffix example**
|
|
1647
|
+
|
|
1648
|
+
```vue
|
|
1649
|
+
<script setup>
|
|
1650
|
+
import { onMounted, onUnmounted } from 'vue'
|
|
1651
|
+
import { useBreadcrumb } from 'nicklabs-ui'
|
|
1652
|
+
|
|
1653
|
+
const { setBreadcrumbSuffix, clearSuffix } = useBreadcrumb()
|
|
1654
|
+
|
|
1655
|
+
// Show user name as the last breadcrumb label
|
|
1656
|
+
onMounted(() => setBreadcrumbSuffix(() => user.value.name))
|
|
1657
|
+
onUnmounted(() => clearSuffix())
|
|
1658
|
+
</script>
|
|
1659
|
+
```
|
|
1660
|
+
|
|
1661
|
+
---
|
|
1662
|
+
|
|
1474
1663
|
### useSidebarManager
|
|
1475
1664
|
|
|
1476
|
-
Manage sidebar open/close state and expandable menu
|
|
1665
|
+
Manage sidebar open/close state and expandable menu groups, persisted to localStorage.
|
|
1477
1666
|
|
|
1478
1667
|
```typescript
|
|
1479
1668
|
import { useSidebarManager } from 'nicklabs-ui'
|
|
@@ -1503,6 +1692,77 @@ const {
|
|
|
1503
1692
|
|
|
1504
1693
|
---
|
|
1505
1694
|
|
|
1695
|
+
### useRouteModal
|
|
1696
|
+
|
|
1697
|
+
Open and close route-based modals using Vue Router's nested routes.
|
|
1698
|
+
|
|
1699
|
+
```typescript
|
|
1700
|
+
import { useRouteModal } from 'nicklabs-ui'
|
|
1701
|
+
|
|
1702
|
+
const { isOpen, open, close, params } = useRouteModal({
|
|
1703
|
+
routeName: 'user-detail',
|
|
1704
|
+
parentRouteName: 'users', // optional fallback when no history
|
|
1705
|
+
})
|
|
1706
|
+
```
|
|
1707
|
+
|
|
1708
|
+
**Options**
|
|
1709
|
+
|
|
1710
|
+
| Option | Type | Required | Description |
|
|
1711
|
+
|--------|------|----------|-------------|
|
|
1712
|
+
| `routeName` | `string` | Yes | Named route that represents the open modal state |
|
|
1713
|
+
| `parentRouteName` | `string` | No | Fallback route to navigate to on close when there is no browser history |
|
|
1714
|
+
|
|
1715
|
+
**Returns**
|
|
1716
|
+
|
|
1717
|
+
| Property | Type | Description |
|
|
1718
|
+
|----------|------|-------------|
|
|
1719
|
+
| `isOpen` | `ComputedRef<boolean>` | `true` when the named route is in the matched stack |
|
|
1720
|
+
| `open` | `(params?) => void` | Navigate to the modal route |
|
|
1721
|
+
| `close` | `() => void` | Navigate back (uses `router.back()` or parent route) |
|
|
1722
|
+
| `params` | `ComputedRef<RouteParams>` | Current route params |
|
|
1723
|
+
|
|
1724
|
+
**Usage**
|
|
1725
|
+
|
|
1726
|
+
```typescript
|
|
1727
|
+
// router/index.ts
|
|
1728
|
+
const routes = [
|
|
1729
|
+
{
|
|
1730
|
+
path: '/users',
|
|
1731
|
+
name: 'users',
|
|
1732
|
+
component: UserList,
|
|
1733
|
+
children: [
|
|
1734
|
+
{
|
|
1735
|
+
path: ':id',
|
|
1736
|
+
name: 'user-detail',
|
|
1737
|
+
component: UserDetail,
|
|
1738
|
+
},
|
|
1739
|
+
],
|
|
1740
|
+
},
|
|
1741
|
+
]
|
|
1742
|
+
```
|
|
1743
|
+
|
|
1744
|
+
```vue
|
|
1745
|
+
<template>
|
|
1746
|
+
<NButton @click="open({ id: user.id })">View</NButton>
|
|
1747
|
+
|
|
1748
|
+
<NModal v-model:show="isOpen" title="User Detail" @close="close">
|
|
1749
|
+
<p>ID: {{ params.id }}</p>
|
|
1750
|
+
</NModal>
|
|
1751
|
+
</template>
|
|
1752
|
+
|
|
1753
|
+
<script setup>
|
|
1754
|
+
import { useRouteModal } from 'nicklabs-ui'
|
|
1755
|
+
import { NModal, NButton } from 'nicklabs-ui'
|
|
1756
|
+
|
|
1757
|
+
const { isOpen, open, close, params } = useRouteModal({
|
|
1758
|
+
routeName: 'user-detail',
|
|
1759
|
+
parentRouteName: 'users',
|
|
1760
|
+
})
|
|
1761
|
+
</script>
|
|
1762
|
+
```
|
|
1763
|
+
|
|
1764
|
+
---
|
|
1765
|
+
|
|
1506
1766
|
## Type Reference
|
|
1507
1767
|
|
|
1508
1768
|
```typescript
|
|
@@ -1512,34 +1772,50 @@ interface OptionItem {
|
|
|
1512
1772
|
value: any
|
|
1513
1773
|
}
|
|
1514
1774
|
|
|
1775
|
+
type NSize = 'sm' | 'md' | 'lg'
|
|
1776
|
+
|
|
1515
1777
|
// Table
|
|
1516
|
-
interface NTableColumn
|
|
1778
|
+
interface NTableColumn {
|
|
1517
1779
|
key: string
|
|
1518
1780
|
label: string
|
|
1519
|
-
width?: string
|
|
1520
|
-
align?: 'left' | 'center' | 'right'
|
|
1521
1781
|
sortable?: boolean
|
|
1522
|
-
formatter?: (value: any, row: T) => string
|
|
1523
1782
|
}
|
|
1524
1783
|
|
|
1784
|
+
type NTableSortOrder = 'asc' | 'desc' | null
|
|
1785
|
+
|
|
1525
1786
|
interface NTableSortState {
|
|
1526
1787
|
key: string
|
|
1527
|
-
order:
|
|
1788
|
+
order: NTableSortOrder
|
|
1528
1789
|
}
|
|
1529
1790
|
|
|
1530
1791
|
// Layout
|
|
1792
|
+
type MenuChild = {
|
|
1793
|
+
icon: string
|
|
1794
|
+
title: string
|
|
1795
|
+
route: string
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1531
1798
|
type Menu = {
|
|
1532
1799
|
icon: string
|
|
1533
1800
|
title: string
|
|
1534
|
-
children?:
|
|
1801
|
+
children?: MenuChild[]
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
// Breadcrumb
|
|
1805
|
+
interface BreadcrumbItem {
|
|
1806
|
+
label: string
|
|
1807
|
+
path?: string
|
|
1535
1808
|
}
|
|
1536
1809
|
|
|
1537
1810
|
// Sizes / Variants
|
|
1538
|
-
type NSize = 'sm' | 'md' | 'lg'
|
|
1539
1811
|
type NButtonVariant = 'none' | 'solid' | 'outline' | 'ghost' | 'mute'
|
|
1540
1812
|
type NButtonIntent = 'none' | 'primary' | 'error' | 'success' | 'warning' | 'info'
|
|
1813
|
+
type NButtonRadiusSize = 'sm' | 'md' | 'lg' | 'xl' | 'full'
|
|
1814
|
+
type NButtonSize = 'sm' | 'md' | 'lg'
|
|
1541
1815
|
type NTagIntent = 'none' | 'primary' | 'success' | 'warning' | 'error' | 'info'
|
|
1542
1816
|
type NTagVariant = 'solid' | 'light' | 'outline'
|
|
1817
|
+
type PaddingSize = 'none' | 'sm' | 'md' | 'lg'
|
|
1818
|
+
type RadiusSize = 'none' | 'sm' | 'md' | 'lg' | 'xl'
|
|
1543
1819
|
```
|
|
1544
1820
|
|
|
1545
1821
|
---
|