@nexxtmove/ui 0.1.31 → 0.1.32
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/dist/index.d.ts +104 -17
- package/dist/index.js +132 -128
- package/package.json +1 -1
- package/src/components/Calendar/_CalendarDayView.vue +1 -1
- package/src/components/Chip/Chip.vue +9 -4
- package/src/components/Table/Table.vue +2 -2
- package/src/components/AnimatedNumber/AnimatedNumber.stories.ts +0 -15
- package/src/components/AnimatedNumber/AnimatedNumber.test.ts +0 -56
- package/src/components/Avatar/Avatar.stories.ts +0 -28
- package/src/components/Avatar/Avatar.test.ts +0 -55
- package/src/components/Button/Button.stories.ts +0 -212
- package/src/components/Button/Button.test.ts +0 -318
- package/src/components/Calendar/Calendar.stories.ts +0 -91
- package/src/components/Calendar/Calendar.test.ts +0 -279
- package/src/components/Calendar/_CalendarDayView.test.ts +0 -104
- package/src/components/Calendar/_CalendarHeader.test.ts +0 -86
- package/src/components/Calendar/_CalendarMonthView.test.ts +0 -52
- package/src/components/Calendar/_CalendarYearView.test.ts +0 -56
- package/src/components/Checkbox/Checkbox.stories.ts +0 -35
- package/src/components/Checkbox/Checkbox.test.ts +0 -55
- package/src/components/Chip/Chip.stories.ts +0 -42
- package/src/components/Chip/Chip.test.ts +0 -51
- package/src/components/CustomerJourneyTile/CustomerJourneyTile.stories.ts +0 -86
- package/src/components/CustomerJourneyTile/CustomerJourneyTile.test.ts +0 -178
- package/src/components/DatePicker/DatePicker.stories.ts +0 -149
- package/src/components/DatePicker/DatePicker.test.ts +0 -191
- package/src/components/DropdownButton/DropdownButton.stories.ts +0 -68
- package/src/components/DropdownButton/DropdownButton.test.ts +0 -124
- package/src/components/Header/Header.stories.ts +0 -54
- package/src/components/Header/Header.test.ts +0 -183
- package/src/components/Icon/Icon.stories.ts +0 -50
- package/src/components/Icon/Icon.test.ts +0 -73
- package/src/components/InfoBlock/InfoBlock.stories.ts +0 -90
- package/src/components/InfoBlock/InfoBlock.test.ts +0 -101
- package/src/components/ProgressBar/ProgressBar.stories.ts +0 -30
- package/src/components/ProgressBar/ProgressBar.test.ts +0 -314
- package/src/components/SocialIcons/SocialIcons.stories.ts +0 -34
- package/src/components/SocialIcons/SocialIcons.test.ts +0 -58
- package/src/components/SocialMediaCustomTemplate/SocialMediaCustomTemplate.stories.ts +0 -11
- package/src/components/SocialMediaCustomTemplate/SocialMediaCustomTemplate.test.ts +0 -131
- package/src/components/SocialMediaTemplate/SocialMediaTemplate.stories.ts +0 -71
- package/src/components/SocialMediaTemplate/SocialMediaTemplate.test.ts +0 -466
- package/src/components/SocialMediaType/SocialMediaType.stories.ts +0 -43
- package/src/components/SocialMediaType/SocialMediaType.test.ts +0 -126
- package/src/components/StepperHeader/StepperHeader.stories.ts +0 -47
- package/src/components/StepperHeader/StepperHeader.test.ts +0 -244
- package/src/components/Table/Table.stories.ts +0 -283
- package/src/components/Table/Table.test.ts +0 -220
- package/src/components/TimelineEvent/TimelineEvent.stories.ts +0 -291
- package/src/components/TimelineEvent/TimelineEvent.test.ts +0 -166
- package/src/components/TimelinePhaseblock/TimelinePhaseblock.stories.ts +0 -198
- package/src/components/TimelinePhaseblock/TimelinePhaseblock.test.ts +0 -283
- package/src/components/Tooltip/Tooltip.stories.ts +0 -146
- package/src/components/Tooltip/Tooltip.test.ts +0 -122
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest'
|
|
2
|
-
import { mount } from '@vue/test-utils'
|
|
3
|
-
import StepperHeader from './StepperHeader.vue'
|
|
4
|
-
import Header from '../Header/Header.vue'
|
|
5
|
-
import ProgressBar from '../ProgressBar/ProgressBar.vue'
|
|
6
|
-
|
|
7
|
-
describe('StepperHeader', () => {
|
|
8
|
-
const defaultProps = {
|
|
9
|
-
title: 'Test Title',
|
|
10
|
-
currentStep: 0,
|
|
11
|
-
steps: ['Step 1', 'Step 2', 'Step 3'],
|
|
12
|
-
backButtonAction: vi.fn(),
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
it('renders the header component', () => {
|
|
16
|
-
const wrapper = mount(StepperHeader, {
|
|
17
|
-
props: defaultProps,
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
const header = wrapper.findComponent(Header)
|
|
21
|
-
expect(header.exists()).toBe(true)
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
it('passes title prop to Header component', () => {
|
|
25
|
-
const wrapper = mount(StepperHeader, {
|
|
26
|
-
props: defaultProps,
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
const header = wrapper.findComponent(Header)
|
|
30
|
-
expect(header.props('title')).toBe('Test Title')
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('passes backButtonAction to Header component', () => {
|
|
34
|
-
const backButtonAction = vi.fn()
|
|
35
|
-
const wrapper = mount(StepperHeader, {
|
|
36
|
-
props: {
|
|
37
|
-
...defaultProps,
|
|
38
|
-
backButtonAction,
|
|
39
|
-
},
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
const header = wrapper.findComponent(Header)
|
|
43
|
-
expect(header.props('backButtonAction')).toBe(backButtonAction)
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it('passes backButtonText to Header component when provided', () => {
|
|
47
|
-
const wrapper = mount(StepperHeader, {
|
|
48
|
-
props: {
|
|
49
|
-
...defaultProps,
|
|
50
|
-
backButtonText: 'Go Back',
|
|
51
|
-
},
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
const header = wrapper.findComponent(Header)
|
|
55
|
-
expect(header.props('backButtonText')).toBe('Go Back')
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
it('renders ProgressBar component when steps are provided', () => {
|
|
59
|
-
const wrapper = mount(StepperHeader, {
|
|
60
|
-
props: defaultProps,
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
const progressBar = wrapper.findComponent(ProgressBar)
|
|
64
|
-
expect(progressBar.exists()).toBe(true)
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
it('passes correct props to ProgressBar component', () => {
|
|
68
|
-
const wrapper = mount(StepperHeader, {
|
|
69
|
-
props: {
|
|
70
|
-
...defaultProps,
|
|
71
|
-
currentStep: 2,
|
|
72
|
-
steps: ['Step 1', 'Step 2', 'Step 3', 'Step 4'],
|
|
73
|
-
},
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
const progressBar = wrapper.findComponent(ProgressBar)
|
|
77
|
-
expect(progressBar.props('steps')).toBe(4)
|
|
78
|
-
expect(progressBar.props('stepTitles')).toEqual(['Step 1', 'Step 2', 'Step 3', 'Step 4'])
|
|
79
|
-
expect(progressBar.props('currentStep')).toBe(2)
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
it('does not render ProgressBar when steps is null or undefined', () => {
|
|
83
|
-
const wrapper = mount(StepperHeader, {
|
|
84
|
-
props: {
|
|
85
|
-
title: 'Test',
|
|
86
|
-
currentStep: 0,
|
|
87
|
-
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
|
88
|
-
steps: null as any,
|
|
89
|
-
backButtonAction: vi.fn(),
|
|
90
|
-
},
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
const progressBar = wrapper.findComponent(ProgressBar)
|
|
94
|
-
expect(progressBar.exists()).toBe(false)
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
it('renders default slot content in Header right slot', () => {
|
|
98
|
-
const wrapper = mount(StepperHeader, {
|
|
99
|
-
props: defaultProps,
|
|
100
|
-
slots: {
|
|
101
|
-
default: '<button class="test-button">Next</button>',
|
|
102
|
-
},
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
expect(wrapper.find('.test-button').exists()).toBe(true)
|
|
106
|
-
expect(wrapper.find('.test-button').text()).toBe('Next')
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
it('does not render right slot when default slot is empty', () => {
|
|
110
|
-
const wrapper = mount(StepperHeader, {
|
|
111
|
-
props: defaultProps,
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
// When no default slot is provided, the right slot in Header should not exist
|
|
115
|
-
expect(wrapper.find('.ml-auto').exists()).toBe(false)
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
it('applies w-full class to ProgressBar', () => {
|
|
119
|
-
const wrapper = mount(StepperHeader, {
|
|
120
|
-
props: defaultProps,
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
const progressBar = wrapper.findComponent(ProgressBar)
|
|
124
|
-
expect(progressBar.classes()).toContain('w-full')
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
it('renders with all props and slots correctly', () => {
|
|
128
|
-
const backButtonAction = vi.fn()
|
|
129
|
-
const wrapper = mount(StepperHeader, {
|
|
130
|
-
props: {
|
|
131
|
-
title: 'Complete Header',
|
|
132
|
-
currentStep: 1,
|
|
133
|
-
steps: ['One', 'Two', 'Three'],
|
|
134
|
-
backButtonText: 'Previous',
|
|
135
|
-
backButtonAction,
|
|
136
|
-
},
|
|
137
|
-
slots: {
|
|
138
|
-
default: '<button>Continue</button>',
|
|
139
|
-
},
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
const header = wrapper.findComponent(Header)
|
|
143
|
-
expect(header.props('title')).toBe('Complete Header')
|
|
144
|
-
expect(header.props('backButtonText')).toBe('Previous')
|
|
145
|
-
expect(header.props('backButtonAction')).toBe(backButtonAction)
|
|
146
|
-
|
|
147
|
-
const progressBar = wrapper.findComponent(ProgressBar)
|
|
148
|
-
expect(progressBar.props('currentStep')).toBe(1)
|
|
149
|
-
expect(progressBar.props('steps')).toBe(3)
|
|
150
|
-
expect(progressBar.props('stepTitles')).toEqual(['One', 'Two', 'Three'])
|
|
151
|
-
|
|
152
|
-
expect(wrapper.text()).toContain('Continue')
|
|
153
|
-
})
|
|
154
|
-
|
|
155
|
-
it('renders without steps and without default slot', () => {
|
|
156
|
-
const wrapper = mount(StepperHeader, {
|
|
157
|
-
props: {
|
|
158
|
-
title: 'Test',
|
|
159
|
-
currentStep: 0,
|
|
160
|
-
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
|
161
|
-
steps: null as any,
|
|
162
|
-
backButtonAction: vi.fn(),
|
|
163
|
-
},
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
const progressBar = wrapper.findComponent(ProgressBar)
|
|
167
|
-
expect(progressBar.exists()).toBe(false)
|
|
168
|
-
expect(wrapper.find('.ml-auto').exists()).toBe(false)
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
it('renders with steps but without default slot', () => {
|
|
172
|
-
const wrapper = mount(StepperHeader, {
|
|
173
|
-
props: defaultProps,
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
const progressBar = wrapper.findComponent(ProgressBar)
|
|
177
|
-
expect(progressBar.exists()).toBe(true)
|
|
178
|
-
expect(wrapper.find('.ml-auto').exists()).toBe(false)
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
it('renders without steps but with default slot', () => {
|
|
182
|
-
const wrapper = mount(StepperHeader, {
|
|
183
|
-
props: {
|
|
184
|
-
title: 'Test',
|
|
185
|
-
currentStep: 0,
|
|
186
|
-
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
|
187
|
-
steps: null as any,
|
|
188
|
-
backButtonAction: vi.fn(),
|
|
189
|
-
},
|
|
190
|
-
slots: {
|
|
191
|
-
default: '<button class="action-button">Action</button>',
|
|
192
|
-
},
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
const progressBar = wrapper.findComponent(ProgressBar)
|
|
196
|
-
expect(progressBar.exists()).toBe(false)
|
|
197
|
-
expect(wrapper.find('.action-button').exists()).toBe(true)
|
|
198
|
-
expect(wrapper.find('.ml-auto').exists()).toBe(true)
|
|
199
|
-
})
|
|
200
|
-
|
|
201
|
-
it('renders with empty steps array', () => {
|
|
202
|
-
const wrapper = mount(StepperHeader, {
|
|
203
|
-
props: {
|
|
204
|
-
title: 'Test',
|
|
205
|
-
currentStep: 0,
|
|
206
|
-
steps: [],
|
|
207
|
-
backButtonAction: vi.fn(),
|
|
208
|
-
},
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
// Empty array is truthy, so ProgressBar should still render
|
|
212
|
-
const progressBar = wrapper.findComponent(ProgressBar)
|
|
213
|
-
expect(progressBar.exists()).toBe(true)
|
|
214
|
-
expect(progressBar.props('steps')).toBe(0)
|
|
215
|
-
expect(progressBar.props('stepTitles')).toEqual([])
|
|
216
|
-
})
|
|
217
|
-
|
|
218
|
-
it('renders with undefined steps', () => {
|
|
219
|
-
const wrapper = mount(StepperHeader, {
|
|
220
|
-
props: {
|
|
221
|
-
title: 'Test',
|
|
222
|
-
currentStep: 0,
|
|
223
|
-
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
|
224
|
-
steps: undefined as any,
|
|
225
|
-
backButtonAction: vi.fn(),
|
|
226
|
-
},
|
|
227
|
-
})
|
|
228
|
-
|
|
229
|
-
const progressBar = wrapper.findComponent(ProgressBar)
|
|
230
|
-
expect(progressBar.exists()).toBe(false)
|
|
231
|
-
})
|
|
232
|
-
|
|
233
|
-
it('emits update:currentStep when ProgressBar emits it', async () => {
|
|
234
|
-
const wrapper = mount(StepperHeader, {
|
|
235
|
-
props: defaultProps,
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
const progressBar = wrapper.findComponent(ProgressBar)
|
|
239
|
-
await progressBar.vm.$emit('update:currentStep', 1)
|
|
240
|
-
|
|
241
|
-
expect(wrapper.emitted('update:currentStep')).toBeTruthy()
|
|
242
|
-
expect(wrapper.emitted('update:currentStep')![0]).toEqual([1])
|
|
243
|
-
})
|
|
244
|
-
})
|
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
|
2
|
-
import { computed, ref, type ConcreteComponent } from 'vue'
|
|
3
|
-
import Table, { type TableColumn } from './Table.vue'
|
|
4
|
-
|
|
5
|
-
type RowKey = 'name' | 'email' | 'role' | 'status' | 'department' | 'lastLogin'
|
|
6
|
-
|
|
7
|
-
interface TableStoryProps {
|
|
8
|
-
columns: TableColumn<RowKey>[]
|
|
9
|
-
rows: Record<RowKey, string>[]
|
|
10
|
-
selectable?: boolean
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const meta: Meta<TableStoryProps> = {
|
|
14
|
-
title: 'Components/Atoms/Table',
|
|
15
|
-
component: Table as ConcreteComponent<TableStoryProps>,
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export default meta
|
|
19
|
-
type Story = StoryObj<TableStoryProps>
|
|
20
|
-
|
|
21
|
-
const columns: TableColumn<RowKey>[] = [
|
|
22
|
-
{ key: 'name', label: 'Name', sortable: true },
|
|
23
|
-
{ key: 'email', label: 'Email', sortable: true },
|
|
24
|
-
{ key: 'department', label: 'Department' },
|
|
25
|
-
{ key: 'role', label: 'Role', sortable: true, width: '0.5fr' },
|
|
26
|
-
{ key: 'lastLogin', label: 'lastLogin' },
|
|
27
|
-
{ key: 'status', label: 'Status', width: '0.5fr' },
|
|
28
|
-
]
|
|
29
|
-
|
|
30
|
-
const allRows = [
|
|
31
|
-
{
|
|
32
|
-
name: 'Alice Johnson',
|
|
33
|
-
email: 'alice@example.com',
|
|
34
|
-
role: 'Admin',
|
|
35
|
-
status: 'Active',
|
|
36
|
-
department: 'HR',
|
|
37
|
-
lastLogin: '2026-03-25',
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
name: 'Bob Smith',
|
|
41
|
-
email: 'bob@example.com',
|
|
42
|
-
role: 'Editor',
|
|
43
|
-
status: 'Active',
|
|
44
|
-
department: 'Marketing',
|
|
45
|
-
lastLogin: '2026-03-27',
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
name: 'Carol White',
|
|
49
|
-
email: 'carol@example.com',
|
|
50
|
-
role: 'Viewer',
|
|
51
|
-
status: 'Inactive',
|
|
52
|
-
department: 'Finance',
|
|
53
|
-
lastLogin: '2026-02-12',
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
name: 'David Brown',
|
|
57
|
-
email: 'david@example.com',
|
|
58
|
-
role: 'Editor',
|
|
59
|
-
status: 'Active',
|
|
60
|
-
department: 'IT',
|
|
61
|
-
lastLogin: '2026-03-30',
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
name: 'Eve Turner',
|
|
65
|
-
email: 'eve@example.com',
|
|
66
|
-
role: 'Admin',
|
|
67
|
-
status: 'Active',
|
|
68
|
-
department: 'HR',
|
|
69
|
-
lastLogin: '2026-03-28',
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
name: 'Frank Miller',
|
|
73
|
-
email: 'frank@example.com',
|
|
74
|
-
role: 'Viewer',
|
|
75
|
-
status: 'Active',
|
|
76
|
-
department: 'Support',
|
|
77
|
-
lastLogin: '2026-03-26',
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
name: 'Grace Lee',
|
|
81
|
-
email: 'grace@example.com',
|
|
82
|
-
role: 'Editor',
|
|
83
|
-
status: 'Active',
|
|
84
|
-
department: 'Product',
|
|
85
|
-
lastLogin: '2026-03-29',
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
name: 'Henry Wilson',
|
|
89
|
-
email: 'henry@example.com',
|
|
90
|
-
role: 'Viewer',
|
|
91
|
-
status: 'Inactive',
|
|
92
|
-
department: 'Finance',
|
|
93
|
-
lastLogin: '2026-01-10',
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
name: 'Ivy Clark',
|
|
97
|
-
email: 'ivy@example.com',
|
|
98
|
-
role: 'Admin',
|
|
99
|
-
status: 'Active',
|
|
100
|
-
department: 'IT',
|
|
101
|
-
lastLogin: '2026-03-20',
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
name: 'Jack Davis',
|
|
105
|
-
email: 'jack@example.com',
|
|
106
|
-
role: 'Editor',
|
|
107
|
-
status: 'Active',
|
|
108
|
-
department: 'Marketing',
|
|
109
|
-
lastLogin: '2026-03-23',
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
name: 'Karen Harris',
|
|
113
|
-
email: 'karen@example.com',
|
|
114
|
-
role: 'Viewer',
|
|
115
|
-
status: 'Active',
|
|
116
|
-
department: 'Support',
|
|
117
|
-
lastLogin: '2026-03-19',
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
name: 'Leo King',
|
|
121
|
-
email: 'leo@example.com',
|
|
122
|
-
role: 'Editor',
|
|
123
|
-
status: 'Active',
|
|
124
|
-
department: 'Product',
|
|
125
|
-
lastLogin: '2026-03-28',
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
name: 'Mia Scott',
|
|
129
|
-
email: 'mia@example.com',
|
|
130
|
-
role: 'Admin',
|
|
131
|
-
status: 'Active',
|
|
132
|
-
department: 'HR',
|
|
133
|
-
lastLogin: '2026-03-30',
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
name: 'Nick Evans',
|
|
137
|
-
email: 'nick@example.com',
|
|
138
|
-
role: 'Viewer',
|
|
139
|
-
status: 'Inactive',
|
|
140
|
-
department: 'Finance',
|
|
141
|
-
lastLogin: '2026-02-05',
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
name: 'Olivia Foster',
|
|
145
|
-
email: 'olivia@example.com',
|
|
146
|
-
role: 'Editor',
|
|
147
|
-
status: 'Active',
|
|
148
|
-
department: 'Product',
|
|
149
|
-
lastLogin: '2026-03-27',
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
name: 'Paul Green',
|
|
153
|
-
email: 'paul@example.com',
|
|
154
|
-
role: 'Viewer',
|
|
155
|
-
status: 'Active',
|
|
156
|
-
department: 'Support',
|
|
157
|
-
lastLogin: '2026-03-18',
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
name: 'Quincy Adams',
|
|
161
|
-
email: 'quincy@example.com',
|
|
162
|
-
role: 'Editor',
|
|
163
|
-
status: 'Active',
|
|
164
|
-
department: 'Marketing',
|
|
165
|
-
lastLogin: '2026-03-25',
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
name: 'Rachel Lewis',
|
|
169
|
-
email: 'rachel@example.com',
|
|
170
|
-
role: 'Admin',
|
|
171
|
-
status: 'Active',
|
|
172
|
-
department: 'HR',
|
|
173
|
-
lastLogin: '2026-03-29',
|
|
174
|
-
},
|
|
175
|
-
{
|
|
176
|
-
name: 'Sam Nelson',
|
|
177
|
-
email: 'sam@example.com',
|
|
178
|
-
role: 'Viewer',
|
|
179
|
-
status: 'Inactive',
|
|
180
|
-
department: 'Finance',
|
|
181
|
-
lastLogin: '2026-01-15',
|
|
182
|
-
},
|
|
183
|
-
{
|
|
184
|
-
name: 'Tina Brooks',
|
|
185
|
-
email: 'tina@example.com',
|
|
186
|
-
role: 'Editor',
|
|
187
|
-
status: 'Active',
|
|
188
|
-
department: 'IT',
|
|
189
|
-
lastLogin: '2026-03-30',
|
|
190
|
-
},
|
|
191
|
-
]
|
|
192
|
-
|
|
193
|
-
const sortRows = (rows: typeof allRows, key: string | undefined, direction: 'asc' | 'desc') => {
|
|
194
|
-
if (!key) return rows
|
|
195
|
-
return [...rows].sort((a, b) => {
|
|
196
|
-
const aVal = String(a[key as keyof typeof a] ?? '')
|
|
197
|
-
const bVal = String(b[key as keyof typeof b] ?? '')
|
|
198
|
-
const result = aVal.localeCompare(bVal, undefined, { numeric: true, sensitivity: 'base' })
|
|
199
|
-
return direction === 'asc' ? result : -result
|
|
200
|
-
})
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
export const Default: Story = {
|
|
204
|
-
args: { columns, rows: allRows },
|
|
205
|
-
render: (args) => ({
|
|
206
|
-
components: { Table },
|
|
207
|
-
setup() {
|
|
208
|
-
const sortKey = ref<string | undefined>(undefined)
|
|
209
|
-
const sortDirection = ref<'asc' | 'desc'>('asc')
|
|
210
|
-
const rows = computed(() =>
|
|
211
|
-
sortRows(args.rows as typeof allRows, sortKey.value, sortDirection.value),
|
|
212
|
-
)
|
|
213
|
-
const onSort = (key: string, direction: 'asc' | 'desc') => {
|
|
214
|
-
sortKey.value = key
|
|
215
|
-
sortDirection.value = direction
|
|
216
|
-
}
|
|
217
|
-
return { args, rows, sortKey, sortDirection, onSort }
|
|
218
|
-
},
|
|
219
|
-
template: `<Table :columns="args.columns" :rows="rows" :sort-key="sortKey" :sort-direction="sortDirection" @sort="onSort" />`,
|
|
220
|
-
}),
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
export const WithSelection: Story = {
|
|
224
|
-
args: { columns, rows: allRows, selectable: true },
|
|
225
|
-
render: (args) => ({
|
|
226
|
-
components: { Table },
|
|
227
|
-
setup() {
|
|
228
|
-
const sortKey = ref<string | undefined>(undefined)
|
|
229
|
-
const sortDirection = ref<'asc' | 'desc'>('asc')
|
|
230
|
-
const selected = ref<number[]>([])
|
|
231
|
-
const rows = computed(() =>
|
|
232
|
-
sortRows(args.rows as typeof allRows, sortKey.value, sortDirection.value),
|
|
233
|
-
)
|
|
234
|
-
const onSort = (key: string, direction: 'asc' | 'desc') => {
|
|
235
|
-
sortKey.value = key
|
|
236
|
-
sortDirection.value = direction
|
|
237
|
-
}
|
|
238
|
-
return { args, rows, sortKey, sortDirection, onSort, selected }
|
|
239
|
-
},
|
|
240
|
-
template: `<Table :columns="args.columns" :rows="rows" :sort-key="sortKey" :sort-direction="sortDirection" :selectable="args.selectable" v-model="selected" @sort="onSort" />`,
|
|
241
|
-
}),
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export const WithSlots: Story = {
|
|
245
|
-
args: { columns, rows: allRows },
|
|
246
|
-
render: (args) => ({
|
|
247
|
-
components: { Table },
|
|
248
|
-
setup() {
|
|
249
|
-
const sortKey = ref<string | undefined>(undefined)
|
|
250
|
-
const sortDirection = ref<'asc' | 'desc'>('asc')
|
|
251
|
-
const rows = computed(() =>
|
|
252
|
-
sortRows(args.rows as typeof allRows, sortKey.value, sortDirection.value),
|
|
253
|
-
)
|
|
254
|
-
const onSort = (key: string, direction: 'asc' | 'desc') => {
|
|
255
|
-
sortKey.value = key
|
|
256
|
-
sortDirection.value = direction
|
|
257
|
-
}
|
|
258
|
-
return { args, rows, sortKey, sortDirection, onSort }
|
|
259
|
-
},
|
|
260
|
-
template: `
|
|
261
|
-
<Table :columns="args.columns" :rows="rows" :sort-key="sortKey" :sort-direction="sortDirection" @sort="onSort">
|
|
262
|
-
<template #cell-name="{ value, row }">
|
|
263
|
-
<div class="flex flex-col">
|
|
264
|
-
<span class="font-medium">{{ value }}</span>
|
|
265
|
-
<span class="text-xs text-slate-400">{{ row.email }}</span>
|
|
266
|
-
</div>
|
|
267
|
-
</template>
|
|
268
|
-
<template #cell-status="{ value }">
|
|
269
|
-
<span
|
|
270
|
-
class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium"
|
|
271
|
-
:class="value === 'Active' ? 'bg-green-100 text-green-700' : 'bg-slate-100 text-slate-500'"
|
|
272
|
-
>
|
|
273
|
-
{{ value }}
|
|
274
|
-
</span>
|
|
275
|
-
</template>
|
|
276
|
-
</Table>
|
|
277
|
-
`,
|
|
278
|
-
}),
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
export const Empty: Story = {
|
|
282
|
-
args: { columns, rows: [] },
|
|
283
|
-
}
|