@davidbirchall/core 1.0.8 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/Button/types.d.ts +4 -0
  2. package/dist/Calendar/types.d.ts +22 -0
  3. package/{src/components/Card/types.ts → dist/Card/types.d.ts} +1 -1
  4. package/dist/Checkbox/types.d.ts +7 -0
  5. package/dist/DataTable/types.d.ts +11 -0
  6. package/dist/Dropdown/types.d.ts +13 -0
  7. package/dist/EmptyState/types.d.ts +8 -0
  8. package/dist/ErrorSummary/types.d.ts +4 -0
  9. package/dist/Heading/types.d.ts +6 -0
  10. package/dist/Input/types.d.ts +11 -0
  11. package/dist/Select/types.d.ts +15 -0
  12. package/dist/StatCard/types.d.ts +12 -0
  13. package/dist/Tag/types.d.ts +4 -0
  14. package/dist/TextArea/types.d.ts +11 -0
  15. package/dist/core.css +1 -0
  16. package/dist/core.js +24 -0
  17. package/dist/core.js.map +1 -0
  18. package/dist/core.umd.cjs +2 -0
  19. package/dist/core.umd.cjs.map +1 -0
  20. package/dist/index.d.ts +2 -0
  21. package/dist/package.json +27 -0
  22. package/package.json +4 -1
  23. package/.storybook/main.ts +0 -18
  24. package/.storybook/preview.ts +0 -14
  25. package/src/components/Badge/Badge.stories.ts +0 -147
  26. package/src/components/Badge/Badge.test.ts +0 -57
  27. package/src/components/Badge/Badge.vue +0 -79
  28. package/src/components/Button/Button.stories.ts +0 -80
  29. package/src/components/Button/Button.test.ts +0 -145
  30. package/src/components/Button/Button.vue +0 -108
  31. package/src/components/Button/types.ts +0 -4
  32. package/src/components/Calendar/Calendar.stories.ts +0 -261
  33. package/src/components/Calendar/Calendar.test.ts +0 -119
  34. package/src/components/Calendar/Calendar.vue +0 -528
  35. package/src/components/Calendar/types.ts +0 -20
  36. package/src/components/Card/Card.stories.ts +0 -88
  37. package/src/components/Card/Card.test.ts +0 -173
  38. package/src/components/Card/Card.vue +0 -59
  39. package/src/components/Checkbox/Checkbox.stories.ts +0 -126
  40. package/src/components/Checkbox/Checkbox.test.ts +0 -155
  41. package/src/components/Checkbox/Checkbox.vue +0 -121
  42. package/src/components/Checkbox/types.ts +0 -7
  43. package/src/components/DataTable/DataTable.stories.ts +0 -156
  44. package/src/components/DataTable/DataTable.test.ts +0 -185
  45. package/src/components/DataTable/DataTable.vue +0 -177
  46. package/src/components/DataTable/types.ts +0 -12
  47. package/src/components/DatePicker/DatePicker.stories.ts +0 -172
  48. package/src/components/DatePicker/DatePicker.test.ts +0 -87
  49. package/src/components/DatePicker/DatePicker.vue +0 -302
  50. package/src/components/Dropdown/Dropdown.stories.ts +0 -231
  51. package/src/components/Dropdown/Dropdown.vue +0 -314
  52. package/src/components/Dropdown/types.ts +0 -14
  53. package/src/components/EmptyState/EmptyState.stories.ts +0 -189
  54. package/src/components/EmptyState/EmptyState.vue +0 -215
  55. package/src/components/EmptyState/types.ts +0 -8
  56. package/src/components/ErrorSummary/ErrorSummary.vue +0 -78
  57. package/src/components/ErrorSummary/types.ts +0 -4
  58. package/src/components/FormGroup/FormGroup.stories.ts +0 -264
  59. package/src/components/FormGroup/FormGroup.test.ts +0 -63
  60. package/src/components/FormGroup/FormGroup.vue +0 -58
  61. package/src/components/Heading/Heading.stories.ts +0 -121
  62. package/src/components/Heading/Heading.test.ts +0 -184
  63. package/src/components/Heading/Heading.vue +0 -95
  64. package/src/components/Heading/types.ts +0 -6
  65. package/src/components/Input/Input.stories.ts +0 -172
  66. package/src/components/Input/Input.test.ts +0 -213
  67. package/src/components/Input/Input.vue +0 -121
  68. package/src/components/Input/types.ts +0 -11
  69. package/src/components/Modal/Modal.stories.ts +0 -341
  70. package/src/components/Modal/Modal.test.ts +0 -99
  71. package/src/components/Modal/Modal.vue +0 -278
  72. package/src/components/ProgressBar/ProgressBar.stories.ts +0 -313
  73. package/src/components/ProgressBar/ProgressBar.test.ts +0 -98
  74. package/src/components/ProgressBar/ProgressBar.vue +0 -117
  75. package/src/components/Select/Select.stories.ts +0 -177
  76. package/src/components/Select/Select.test.ts +0 -225
  77. package/src/components/Select/Select.vue +0 -147
  78. package/src/components/Select/types.ts +0 -16
  79. package/src/components/StatCard/StatCard.stories.ts +0 -274
  80. package/src/components/StatCard/StatCard.vue +0 -226
  81. package/src/components/StatCard/types.ts +0 -12
  82. package/src/components/Tag/Tag.stories.ts +0 -78
  83. package/src/components/Tag/Tag.test.ts +0 -50
  84. package/src/components/Tag/Tag.vue +0 -71
  85. package/src/components/Tag/types.ts +0 -4
  86. package/src/components/TextArea/TextArea.stories.ts +0 -171
  87. package/src/components/TextArea/TextArea.test.ts +0 -202
  88. package/src/components/TextArea/TextArea.vue +0 -122
  89. package/src/components/TextArea/types.ts +0 -11
  90. package/src/components/index.ts +0 -5
  91. package/src/test/setup.ts +0 -1
  92. package/src/vite-env.d.ts +0 -6
  93. package/tsconfig.json +0 -29
  94. package/vite.config.ts +0 -33
  95. package/vitest.config.ts +0 -28
@@ -1,156 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/vue3'
2
- import DataTable from './DataTable.vue'
3
- import type { DataTableColumn } from './types'
4
-
5
- const meta = {
6
- title: 'Components/DataTable',
7
- component: DataTable,
8
- tags: ['autodocs'],
9
- argTypes: {
10
- hoverable: {
11
- control: 'boolean',
12
- description: 'Enable hover effect on rows'
13
- },
14
- emptyText: {
15
- control: 'text',
16
- description: 'Text to display when no data is available'
17
- }
18
- },
19
- args: {
20
- hoverable: true,
21
- emptyText: 'No data available'
22
- }
23
- } satisfies Meta<typeof DataTable>
24
-
25
- export default meta
26
- type Story = StoryObj<typeof meta>
27
-
28
- const sampleColumns: DataTableColumn[] = [
29
- { key: 'id', label: 'ID', sortable: true },
30
- { key: 'name', label: 'Name', sortable: true },
31
- { key: 'email', label: 'Email', sortable: true },
32
- { key: 'role', label: 'Role', sortable: false }
33
- ]
34
-
35
- const sampleData = [
36
- { id: 1, name: 'John Doe', email: 'john@example.com', role: 'Admin' },
37
- { id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'User' },
38
- { id: 3, name: 'Bob Johnson', email: 'bob@example.com', role: 'Editor' },
39
- { id: 4, name: 'Alice Williams', email: 'alice@example.com', role: 'User' },
40
- { id: 5, name: 'Charlie Brown', email: 'charlie@example.com', role: 'Admin' }
41
- ]
42
-
43
- export const Basic: Story = {
44
- args: {
45
- columns: sampleColumns,
46
- data: sampleData
47
- }
48
- }
49
-
50
- export const Empty: Story = {
51
- args: {
52
- columns: sampleColumns,
53
- data: []
54
- }
55
- }
56
-
57
- export const CustomEmptyText: Story = {
58
- args: {
59
- columns: sampleColumns,
60
- data: [],
61
- emptyText: 'No users found'
62
- }
63
- }
64
-
65
- export const NoHover: Story = {
66
- args: {
67
- columns: sampleColumns,
68
- data: sampleData,
69
- hoverable: false
70
- }
71
- }
72
-
73
- export const ProductTable: Story = {
74
- args: {
75
- columns: [
76
- { key: 'product', label: 'Product', sortable: true },
77
- { key: 'category', label: 'Category', sortable: true },
78
- { key: 'price', label: 'Price', sortable: true },
79
- { key: 'stock', label: 'Stock', sortable: true },
80
- { key: 'status', label: 'Status', sortable: false }
81
- ],
82
- data: [
83
- { product: 'Laptop', category: 'Electronics', price: 999, stock: 45, status: 'In Stock' },
84
- { product: 'Mouse', category: 'Accessories', price: 25, stock: 120, status: 'In Stock' },
85
- { product: 'Keyboard', category: 'Accessories', price: 75, stock: 0, status: 'Out of Stock' },
86
- { product: 'Monitor', category: 'Electronics', price: 350, stock: 23, status: 'In Stock' },
87
- { product: 'Webcam', category: 'Electronics', price: 89, stock: 8, status: 'Low Stock' }
88
- ]
89
- }
90
- }
91
-
92
- export const WithCustomSlots: Story = {
93
- args: {
94
- columns: [
95
- { key: 'name', label: 'Name', sortable: true },
96
- { key: 'status', label: 'Status', sortable: false },
97
- { key: 'actions', label: 'Actions', sortable: false }
98
- ],
99
- data: [
100
- { name: 'John Doe', status: 'active', actions: '' },
101
- { name: 'Jane Smith', status: 'inactive', actions: '' },
102
- { name: 'Bob Johnson', status: 'active', actions: '' }
103
- ]
104
- },
105
- render: (args: any) => ({
106
- components: { DataTable },
107
- setup() {
108
- return { args }
109
- },
110
- template: `
111
- <DataTable v-bind="args">
112
- <template #cell-status="{ value }">
113
- <span :style="{
114
- color: value === 'active' ? '#10b981' : '#ef4444',
115
- fontWeight: 600
116
- }">
117
- {{ value.toUpperCase() }}
118
- </span>
119
- </template>
120
- <template #cell-actions>
121
- <button style="
122
- padding: 0.25rem 0.75rem;
123
- background: #3b82f6;
124
- color: white;
125
- border: none;
126
- border-radius: 0.25rem;
127
- cursor: pointer;
128
- ">
129
- Edit
130
- </button>
131
- </template>
132
- </DataTable>
133
- `
134
- })
135
- }
136
-
137
- export const LargeDataset: Story = {
138
- args: {
139
- columns: [
140
- { key: 'id', label: 'ID', sortable: true },
141
- { key: 'firstName', label: 'First Name', sortable: true },
142
- { key: 'lastName', label: 'Last Name', sortable: true },
143
- { key: 'email', label: 'Email', sortable: true },
144
- { key: 'department', label: 'Department', sortable: true },
145
- { key: 'salary', label: 'Salary', sortable: true }
146
- ],
147
- data: Array.from({ length: 50 }, (_, i) => ({
148
- id: i + 1,
149
- firstName: ['John', 'Jane', 'Bob', 'Alice', 'Charlie'][i % 5],
150
- lastName: ['Doe', 'Smith', 'Johnson', 'Williams', 'Brown'][i % 5],
151
- email: `user${i + 1}@example.com`,
152
- department: ['Engineering', 'Marketing', 'Sales', 'HR', 'Finance'][i % 5],
153
- salary: 50000 + (i * 1000)
154
- }))
155
- }
156
- }
@@ -1,185 +0,0 @@
1
- import { describe, it, expect } from 'vitest'
2
- import { render, screen } from '@testing-library/vue'
3
- import userEvent from '@testing-library/user-event'
4
- import DataTable from './DataTable.vue'
5
- import type { DataTableColumn } from './types'
6
-
7
- describe('DataTable', () => {
8
- const columns: DataTableColumn[] = [
9
- { key: 'name', label: 'Name', sortable: true },
10
- { key: 'age', label: 'Age', sortable: true },
11
- { key: 'email', label: 'Email' }
12
- ]
13
-
14
- const data = [
15
- { name: 'John Doe', age: 30, email: 'john@example.com' },
16
- { name: 'Jane Smith', age: 25, email: 'jane@example.com' },
17
- { name: 'Bob Johnson', age: 35, email: 'bob@example.com' }
18
- ]
19
-
20
- describe('rendering', () => {
21
- it('renders table headers', () => {
22
- render(DataTable, {
23
- props: {
24
- columns,
25
- data
26
- }
27
- })
28
-
29
- expect(screen.getByText('Name')).toBeInTheDocument()
30
- expect(screen.getByText('Age')).toBeInTheDocument()
31
- expect(screen.getByText('Email')).toBeInTheDocument()
32
- })
33
-
34
- it('renders table data', () => {
35
- render(DataTable, {
36
- props: {
37
- columns,
38
- data
39
- }
40
- })
41
-
42
- expect(screen.getByText('John Doe')).toBeInTheDocument()
43
- expect(screen.getByText('30')).toBeInTheDocument()
44
- expect(screen.getByText('john@example.com')).toBeInTheDocument()
45
- })
46
-
47
- it('renders all rows', () => {
48
- const { container } = render(DataTable, {
49
- props: {
50
- columns,
51
- data
52
- }
53
- })
54
-
55
- const rows = container.querySelectorAll('tbody tr')
56
- expect(rows).toHaveLength(3)
57
- })
58
-
59
- it('shows empty text when no data', () => {
60
- render(DataTable, {
61
- props: {
62
- columns,
63
- data: []
64
- }
65
- })
66
-
67
- expect(screen.getByText('No data available')).toBeInTheDocument()
68
- })
69
-
70
- it('shows custom empty text', () => {
71
- render(DataTable, {
72
- props: {
73
- columns,
74
- data: [],
75
- emptyText: 'Custom empty message'
76
- }
77
- })
78
-
79
- expect(screen.getByText('Custom empty message')).toBeInTheDocument()
80
- })
81
- })
82
-
83
- describe('sorting', () => {
84
- it('sorts data in ascending order when clicking sortable column', async () => {
85
- const user = userEvent.setup()
86
- const { container } = render(DataTable, {
87
- props: {
88
- columns,
89
- data
90
- }
91
- })
92
-
93
- const nameHeader = screen.getByText('Name').closest('th')
94
- await user.click(nameHeader!)
95
-
96
- const cells = container.querySelectorAll('tbody td:first-child')
97
- expect(cells[0]).toHaveTextContent('Bob Johnson')
98
- expect(cells[1]).toHaveTextContent('Jane Smith')
99
- expect(cells[2]).toHaveTextContent('John Doe')
100
- })
101
-
102
- it('sorts data in descending order when clicking sortable column twice', async () => {
103
- const user = userEvent.setup()
104
- const { container } = render(DataTable, {
105
- props: {
106
- columns,
107
- data
108
- }
109
- })
110
-
111
- const nameHeader = screen.getByText('Name').closest('th')
112
- await user.click(nameHeader!)
113
- await user.click(nameHeader!)
114
-
115
- const cells = container.querySelectorAll('tbody td:first-child')
116
- expect(cells[0]).toHaveTextContent('John Doe')
117
- expect(cells[1]).toHaveTextContent('Jane Smith')
118
- expect(cells[2]).toHaveTextContent('Bob Johnson')
119
- })
120
-
121
- it('sorts numeric columns correctly', async () => {
122
- const user = userEvent.setup()
123
- const { container } = render(DataTable, {
124
- props: {
125
- columns,
126
- data
127
- }
128
- })
129
-
130
- const ageHeader = screen.getByText('Age').closest('th')
131
- await user.click(ageHeader!)
132
-
133
- const cells = container.querySelectorAll('tbody td:nth-child(2)')
134
- expect(cells[0]).toHaveTextContent('25')
135
- expect(cells[1]).toHaveTextContent('30')
136
- expect(cells[2]).toHaveTextContent('35')
137
- })
138
-
139
- it('does not sort non-sortable columns', async () => {
140
- const user = userEvent.setup()
141
- const { container } = render(DataTable, {
142
- props: {
143
- columns,
144
- data
145
- }
146
- })
147
-
148
- const emailHeader = screen.getByText('Email').closest('th')
149
- await user.click(emailHeader!)
150
-
151
- // Data should remain in original order
152
- const cells = container.querySelectorAll('tbody td:first-child')
153
- expect(cells[0]).toHaveTextContent('John Doe')
154
- expect(cells[1]).toHaveTextContent('Jane Smith')
155
- expect(cells[2]).toHaveTextContent('Bob Johnson')
156
- })
157
- })
158
-
159
- describe('hoverable', () => {
160
- it('applies hoverable class by default', () => {
161
- const { container } = render(DataTable, {
162
- props: {
163
- columns,
164
- data
165
- }
166
- })
167
-
168
- const firstRow = container.querySelector('tbody tr')
169
- expect(firstRow).toHaveClass('data-table__row--hoverable')
170
- })
171
-
172
- it('does not apply hoverable class when disabled', () => {
173
- const { container } = render(DataTable, {
174
- props: {
175
- columns,
176
- data,
177
- hoverable: false
178
- }
179
- })
180
-
181
- const firstRow = container.querySelector('tbody tr')
182
- expect(firstRow).not.toHaveClass('data-table__row--hoverable')
183
- })
184
- })
185
- })
@@ -1,177 +0,0 @@
1
- <template>
2
- <div class="data-table">
3
- <div class="data-table__wrapper">
4
- <table class="data-table__table">
5
- <thead class="data-table__head">
6
- <tr>
7
- <th
8
- v-for="column in columns"
9
- :key="column.key"
10
- class="data-table__header"
11
- :class="{ 'data-table__header--sortable': column.sortable }"
12
- @click="column.sortable ? handleSort(column.key) : undefined"
13
- >
14
- <div class="data-table__header-content">
15
- {{ column.label }}
16
- <span v-if="column.sortable" class="data-table__sort-icon">
17
- <span v-if="sortKey === column.key">
18
- {{ sortOrder === 'asc' ? '↑' : '↓' }}
19
- </span>
20
- <span v-else class="data-table__sort-icon--inactive">↕</span>
21
- </span>
22
- </div>
23
- </th>
24
- </tr>
25
- </thead>
26
- <tbody>
27
- <tr
28
- v-for="(row, index) in sortedData"
29
- :key="index"
30
- class="data-table__row"
31
- >
32
- <td
33
- v-for="column in columns"
34
- :key="column.key"
35
- class="data-table__cell"
36
- >
37
- <slot :name="`cell-${column.key}`" :row="row" :value="row[column.key]">
38
- {{ row[column.key] }}
39
- </slot>
40
- </td>
41
- </tr>
42
- <tr v-if="sortedData.length === 0">
43
- <td :colspan="columns.length" class="data-table__cell data-table__cell--empty">
44
- {{ emptyText }}
45
- </td>
46
- </tr>
47
- </tbody>
48
- </table>
49
- </div>
50
- </div>
51
- </template>
52
-
53
- <script setup lang="ts">
54
- import { ref, computed } from 'vue'
55
-
56
- export interface DataTableColumn {
57
- key: string
58
- label: string
59
- sortable?: boolean
60
- }
61
-
62
- export interface DataTableProps {
63
- columns: DataTableColumn[]
64
- data: Record<string, any>[]
65
- hoverable?: boolean
66
- emptyText?: string
67
- }
68
-
69
- const props = withDefaults(defineProps<DataTableProps>(), {
70
- hoverable: true,
71
- emptyText: 'No data available'
72
- })
73
-
74
- const sortKey = ref<string | null>(null)
75
- const sortOrder = ref<'asc' | 'desc'>('asc')
76
-
77
- const handleSort = (key: string) => {
78
- if (sortKey.value === key) {
79
- sortOrder.value = sortOrder.value === 'asc' ? 'desc' : 'asc'
80
- } else {
81
- sortKey.value = key
82
- sortOrder.value = 'asc'
83
- }
84
- }
85
-
86
- const sortedData = computed(() => {
87
- if (!sortKey.value) {
88
- return props.data
89
- }
90
-
91
- return [...props.data].sort((a, b) => {
92
- const aVal = a[sortKey.value!]
93
- const bVal = b[sortKey.value!]
94
-
95
- if (aVal === bVal) return 0
96
-
97
- let comparison = 0
98
- if (typeof aVal === 'number' && typeof bVal === 'number') {
99
- comparison = aVal - bVal
100
- } else {
101
- comparison = String(aVal).localeCompare(String(bVal))
102
- }
103
-
104
- return sortOrder.value === 'asc' ? comparison : -comparison
105
- })
106
- })
107
- </script>
108
-
109
- <style scoped>
110
- .data-table {
111
- width: 100%;
112
- }
113
-
114
- .data-table__wrapper {
115
- overflow-x: auto;
116
- }
117
-
118
- .data-table__table {
119
- min-width: 100%;
120
- border-collapse: collapse;
121
- }
122
-
123
- .data-table__head {
124
- background-color: #f9fafb;
125
- }
126
-
127
- .data-table__header {
128
- padding: 0.75rem 1.5rem;
129
- text-align: left;
130
- font-size: 0.75rem;
131
- font-weight: 500;
132
- color: #6b7280;
133
- text-transform: uppercase;
134
- letter-spacing: 0.05em;
135
- border-bottom: 1px solid #e5e7eb;
136
- }
137
-
138
- .data-table__header--sortable {
139
- cursor: pointer;
140
- user-select: none;
141
- }
142
-
143
- .data-table__header--sortable:hover {
144
- background-color: #f3f4f6;
145
- }
146
-
147
- .data-table__header-content {
148
- display: flex;
149
- align-items: center;
150
- gap: 0.5rem;
151
- }
152
-
153
- .data-table__sort-icon {
154
- font-size: 0.75rem;
155
- color: #6b7280;
156
- }
157
-
158
- .data-table__sort-icon--inactive {
159
- color: #d1d5db;
160
- }
161
-
162
- .data-table__row {
163
- border-bottom: 1px solid #e5e7eb;
164
- }
165
-
166
- .data-table__cell {
167
- padding: 1rem 1.5rem;
168
- font-size: 0.875rem;
169
- color: #6b7280;
170
- }
171
-
172
- .data-table__cell--empty {
173
- text-align: center;
174
- color: #9ca3af;
175
- font-style: italic;
176
- }
177
- </style>
@@ -1,12 +0,0 @@
1
- export interface DataTableColumn {
2
- key: string
3
- label: string
4
- sortable?: boolean
5
- }
6
-
7
- export interface DataTableProps {
8
- columns: DataTableColumn[]
9
- data: Record<string, any>[]
10
- hoverable?: boolean
11
- emptyText?: string
12
- }
@@ -1,172 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/vue3'
2
- import { ref } from 'vue'
3
- import DatePicker from './DatePicker.vue'
4
-
5
- const meta = {
6
- title: 'Components/DatePicker',
7
- component: DatePicker,
8
- tags: ['autodocs']
9
- } satisfies Meta<typeof DatePicker>
10
-
11
- export default meta
12
- type Story = StoryObj<typeof meta>
13
-
14
- export const Default: Story = {
15
- render: (args: any) => ({
16
- components: { DatePicker },
17
- setup() {
18
- const date = ref<string>('')
19
- return { args, date }
20
- },
21
- template: `
22
- <div>
23
- <DatePicker v-bind="args" v-model="date" />
24
- <div style="margin-top: 1rem; padding: 1rem; background: #f3f4f6; border-radius: 0.5rem;">
25
- Selected: {{ date || 'None' }}
26
- </div>
27
- </div>
28
- `
29
- })
30
- }
31
-
32
- export const WithValue: Story = {
33
- render: (args: any) => ({
34
- components: { DatePicker },
35
- setup() {
36
- const date = ref<string>('2026-03-15')
37
- return { args, date }
38
- },
39
- template: `
40
- <div>
41
- <DatePicker v-bind="args" v-model="date" />
42
- <div style="margin-top: 1rem; padding: 1rem; background: #f3f4f6; border-radius: 0.5rem;">
43
- Selected: {{ date }}
44
- </div>
45
- </div>
46
- `
47
- })
48
- }
49
-
50
- export const DateRange: Story = {
51
- render: (args: any) => ({
52
- components: { DatePicker },
53
- setup() {
54
- const dateRange = ref<{ start: string; end: string }>({ start: '', end: '' })
55
- return { args, dateRange }
56
- },
57
- template: `
58
- <div>
59
- <DatePicker v-bind="args" v-model="dateRange" mode="range" placeholder="Select date range" />
60
- <div style="margin-top: 1rem; padding: 1rem; background: #f3f4f6; border-radius: 0.5rem;">
61
- Start: {{ dateRange.start || 'Not set' }}<br />
62
- End: {{ dateRange.end || 'Not set' }}
63
- </div>
64
- </div>
65
- `
66
- })
67
- }
68
-
69
- export const WithMinMaxDates: Story = {
70
- render: (args: any) => ({
71
- components: { DatePicker },
72
- setup() {
73
- const date = ref<string>('')
74
- const today = new Date()
75
- const minDate = today.toISOString().split('T')[0]
76
- const maxDate = new Date(today.getFullYear(), today.getMonth() + 3, today.getDate()).toISOString().split('T')[0]
77
-
78
- return { args, date, minDate, maxDate }
79
- },
80
- template: `
81
- <div>
82
- <DatePicker
83
- v-bind="args"
84
- v-model="date"
85
- :min-date="minDate"
86
- :max-date="maxDate"
87
- placeholder="Future dates only"
88
- />
89
- <div style="margin-top: 1rem; padding: 1rem; background: #f3f4f6; border-radius: 0.5rem;">
90
- Selected: {{ date || 'None' }}<br />
91
- <small style="color: #6b7280;">Min: {{ minDate }} | Max: {{ maxDate }}</small>
92
- </div>
93
- </div>
94
- `
95
- })
96
- }
97
-
98
- export const FormExample: Story = {
99
- render: (args: any) => ({
100
- components: { DatePicker },
101
- setup() {
102
- const passportNumber = ref('')
103
- const expiryDate = ref<string>('')
104
-
105
- return { args, passportNumber, expiryDate }
106
- },
107
- template: `
108
- <div style="max-width: 400px;">
109
- <div style="margin-bottom: 1rem;">
110
- <label style="display: block; margin-bottom: 0.5rem; font-weight: 600;">Passport Number</label>
111
- <input
112
- v-model="passportNumber"
113
- type="text"
114
- placeholder="e.g., X12345678"
115
- style="width: 100%; padding: 0.5rem; border: 1px solid #d1d5db; border-radius: 0.375rem;"
116
- />
117
- </div>
118
-
119
- <div style="margin-bottom: 1rem;">
120
- <label style="display: block; margin-bottom: 0.5rem; font-weight: 600;">Expiry Date</label>
121
- <DatePicker
122
- v-bind="args"
123
- v-model="expiryDate"
124
- placeholder="Select expiry date"
125
- />
126
- </div>
127
-
128
- <div style="padding: 1rem; background: #f3f4f6; border-radius: 0.5rem;">
129
- <strong>Form Data:</strong><br />
130
- Passport: {{ passportNumber || 'Not entered' }}<br />
131
- Expiry: {{ expiryDate || 'Not selected' }}
132
- </div>
133
- </div>
134
- `
135
- })
136
- }
137
-
138
- export const LongFormat: Story = {
139
- render: (args: any) => ({
140
- components: { DatePicker },
141
- setup() {
142
- const date = ref<string>('2026-06-15')
143
- return { args, date }
144
- },
145
- template: `
146
- <div>
147
- <DatePicker v-bind="args" v-model="date" format="long" />
148
- <div style="margin-top: 1rem; padding: 1rem; background: #f3f4f6; border-radius: 0.5rem;">
149
- Selected: {{ date }}
150
- </div>
151
- </div>
152
- `
153
- })
154
- }
155
-
156
- export const Disabled: Story = {
157
- render: (args: any) => ({
158
- components: { DatePicker },
159
- setup() {
160
- const date = ref<string>('2026-02-07')
161
- return { args, date }
162
- },
163
- template: `
164
- <div>
165
- <DatePicker v-bind="args" v-model="date" disabled />
166
- <div style="margin-top: 1rem; padding: 1rem; background: #f3f4f6; border-radius: 0.5rem;">
167
- Selected: {{ date }}
168
- </div>
169
- </div>
170
- `
171
- })
172
- }