@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,173 +0,0 @@
1
- import { describe, it, expect } from 'vitest'
2
- import { render, screen } from '@testing-library/vue'
3
- import Card from './Card.vue'
4
-
5
- describe('Card', () => {
6
- describe('rendering', () => {
7
- it('renders default slot content', () => {
8
- render(Card, {
9
- slots: {
10
- default: '<p>Card content</p>'
11
- }
12
- })
13
-
14
- expect(screen.getByText('Card content')).toBeInTheDocument()
15
- })
16
-
17
- it('renders header slot when provided', () => {
18
- const { container } = render(Card, {
19
- slots: {
20
- header: 'Card Header',
21
- default: 'Card content'
22
- }
23
- })
24
-
25
- const header = container.querySelector('.card__header')
26
- expect(header).toBeInTheDocument()
27
- expect(header).toHaveTextContent('Card Header')
28
- })
29
-
30
- it('does not render header section when slot is not provided', () => {
31
- const { container } = render(Card, {
32
- slots: {
33
- default: 'Card content'
34
- }
35
- })
36
-
37
- const header = container.querySelector('.card__header')
38
- expect(header).not.toBeInTheDocument()
39
- })
40
-
41
- it('renders footer slot when provided', () => {
42
- const { container } = render(Card, {
43
- slots: {
44
- default: 'Card content',
45
- footer: 'Card Footer'
46
- }
47
- })
48
-
49
- const footer = container.querySelector('.card__footer')
50
- expect(footer).toBeInTheDocument()
51
- expect(footer).toHaveTextContent('Card Footer')
52
- })
53
-
54
- it('does not render footer section when slot is not provided', () => {
55
- const { container } = render(Card, {
56
- slots: {
57
- default: 'Card content'
58
- }
59
- })
60
-
61
- const footer = container.querySelector('.card__footer')
62
- expect(footer).not.toBeInTheDocument()
63
- })
64
-
65
- it('renders all slots together', () => {
66
- const { container } = render(Card, {
67
- slots: {
68
- header: 'Header',
69
- default: 'Body',
70
- footer: 'Footer'
71
- }
72
- })
73
-
74
- expect(container.querySelector('.card__header')).toBeInTheDocument()
75
- expect(container.querySelector('.card__body')).toBeInTheDocument()
76
- expect(container.querySelector('.card__footer')).toBeInTheDocument()
77
- })
78
- })
79
-
80
- describe('hoverable prop', () => {
81
- it('does not apply hoverable class by default', () => {
82
- const { container } = render(Card, {
83
- slots: {
84
- default: 'Content'
85
- }
86
- })
87
-
88
- const card = container.querySelector('.card')
89
- expect(card).not.toHaveClass('card--hoverable')
90
- })
91
-
92
- it('applies hoverable class when prop is true', () => {
93
- const { container } = render(Card, {
94
- props: {
95
- hoverable: true
96
- },
97
- slots: {
98
- default: 'Content'
99
- }
100
- })
101
-
102
- const card = container.querySelector('.card')
103
- expect(card).toHaveClass('card--hoverable')
104
- })
105
-
106
- it('does not apply hoverable class when prop is false', () => {
107
- const { container } = render(Card, {
108
- props: {
109
- hoverable: false
110
- },
111
- slots: {
112
- default: 'Content'
113
- }
114
- })
115
-
116
- const card = container.querySelector('.card')
117
- expect(card).not.toHaveClass('card--hoverable')
118
- })
119
- })
120
-
121
- describe('styling', () => {
122
- it('always applies base card class', () => {
123
- const { container } = render(Card, {
124
- slots: {
125
- default: 'Content'
126
- }
127
- })
128
-
129
- const card = container.querySelector('.card')
130
- expect(card).toHaveClass('card')
131
- })
132
-
133
- it('maintains card structure with body wrapper', () => {
134
- const { container } = render(Card, {
135
- slots: {
136
- default: 'Test content'
137
- }
138
- })
139
-
140
- const body = container.querySelector('.card__body')
141
- expect(body).toBeInTheDocument()
142
- expect(body).toHaveTextContent('Test content')
143
- })
144
- })
145
-
146
- describe('complex content', () => {
147
- it('handles complex HTML in slots', () => {
148
- const { container } = render(Card, {
149
- slots: {
150
- header: '<h2>Title</h2>',
151
- default: '<div><p>Paragraph 1</p><p>Paragraph 2</p></div>',
152
- footer: '<button>Action</button>'
153
- }
154
- })
155
-
156
- expect(container.querySelector('.card__header h2')).toBeInTheDocument()
157
- expect(container.querySelectorAll('.card__body p')).toHaveLength(2)
158
- expect(screen.getByRole('button', { name: 'Action' })).toBeInTheDocument()
159
- })
160
-
161
- it('handles nested components in slots', () => {
162
- const { container } = render(Card, {
163
- slots: {
164
- default: '<div class="custom-content">Nested</div>'
165
- }
166
- })
167
-
168
- const customContent = container.querySelector('.custom-content')
169
- expect(customContent).toBeInTheDocument()
170
- expect(customContent).toHaveTextContent('Nested')
171
- })
172
- })
173
- })
@@ -1,59 +0,0 @@
1
- <template>
2
- <div :class="['card', { 'card--hoverable': hoverable }]">
3
- <div v-if="$slots.header" class="card__header">
4
- <slot name="header" />
5
- </div>
6
- <div class="card__body">
7
- <slot />
8
- </div>
9
- <div v-if="$slots.footer" class="card__footer">
10
- <slot name="footer" />
11
- </div>
12
- </div>
13
- </template>
14
-
15
- <script setup lang="ts">
16
- export interface CardProps {
17
- hoverable?: boolean
18
- }
19
-
20
- withDefaults(defineProps<CardProps>(), {
21
- hoverable: false
22
- })
23
- </script>
24
-
25
- <style scoped>
26
- .card {
27
- background: white;
28
- border: 1px solid #e5e7eb;
29
- border-radius: 0.5rem;
30
- overflow: hidden;
31
- }
32
-
33
- .card--hoverable {
34
- transition: all 0.2s ease-in-out;
35
- cursor: pointer;
36
- }
37
-
38
- .card--hoverable:hover {
39
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
40
- transform: translateY(-2px);
41
- }
42
-
43
- .card__header {
44
- padding: 1rem 1.5rem;
45
- border-bottom: 1px solid #e5e7eb;
46
- font-weight: 600;
47
- font-size: 1.125rem;
48
- }
49
-
50
- .card__body {
51
- padding: 1.5rem;
52
- }
53
-
54
- .card__footer {
55
- padding: 1rem 1.5rem;
56
- border-top: 1px solid #e5e7eb;
57
- background-color: #f9fafb;
58
- }
59
- </style>
@@ -1,126 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/vue3'
2
- import { ref } from 'vue'
3
- import Checkbox from './Checkbox.vue'
4
-
5
- const meta = {
6
- title: 'Form Fields/Checkbox',
7
- component: Checkbox,
8
- tags: ['autodocs'],
9
- argTypes: {
10
- modelValue: {
11
- control: 'boolean',
12
- description: 'Checked state'
13
- },
14
- label: {
15
- control: 'text',
16
- description: 'Label text'
17
- },
18
- disabled: {
19
- control: 'boolean',
20
- description: 'Disabled state'
21
- },
22
- required: {
23
- control: 'boolean',
24
- description: 'Required field'
25
- },
26
- error: {
27
- control: 'text',
28
- description: 'Error message'
29
- }
30
- },
31
- args: {
32
- modelValue: false,
33
- disabled: false,
34
- required: false
35
- }
36
- } satisfies Meta<typeof Checkbox>
37
-
38
- export default meta
39
- type Story = StoryObj<typeof meta>
40
-
41
- export const Default: Story = {
42
- args: {
43
- label: 'Accept terms and conditions'
44
- },
45
- render: (args: any) => ({
46
- components: { Checkbox },
47
- setup() {
48
- const checked = ref(args.modelValue ?? false)
49
- return { args, checked }
50
- },
51
- template: '<Checkbox v-bind="args" v-model="checked" />'
52
- })
53
- }
54
-
55
- export const Checked: Story = {
56
- args: {
57
- label: 'Subscribe to newsletter',
58
- modelValue: true
59
- },
60
- render: (args: any) => ({
61
- components: { Checkbox },
62
- setup() {
63
- const checked = ref(args.modelValue ?? false)
64
- return { args, checked }
65
- },
66
- template: '<Checkbox v-bind="args" v-model="checked" />'
67
- })
68
- }
69
-
70
- export const Disabled: Story = {
71
- args: {
72
- label: 'Disabled option',
73
- disabled: true
74
- },
75
- render: (args: any) => ({
76
- components: { Checkbox },
77
- setup() {
78
- const checked = ref(false)
79
- return { args, checked }
80
- },
81
- template: '<Checkbox v-bind="args" v-model="checked" />'
82
- })
83
- }
84
-
85
- export const DisabledChecked: Story = {
86
- args: {
87
- label: 'Disabled checked option',
88
- disabled: true,
89
- modelValue: true
90
- },
91
- render: (args: any) => ({
92
- components: { Checkbox },
93
- setup() {
94
- const checked = ref(args.modelValue ?? false)
95
- return { args, checked }
96
- },
97
- template: '<Checkbox v-bind="args" v-model="checked" />'
98
- })
99
- }
100
-
101
- export const WithError: Story = {
102
- args: {
103
- label: 'I agree to the terms',
104
- error: 'You must accept the terms to continue'
105
- },
106
- render: (args: any) => ({
107
- components: { Checkbox },
108
- setup() {
109
- const checked = ref(false)
110
- return { args, checked }
111
- },
112
- template: '<Checkbox v-bind="args" v-model="checked" />'
113
- })
114
- }
115
-
116
- export const WithoutLabel: Story = {
117
- args: {},
118
- render: (args: any) => ({
119
- components: { Checkbox },
120
- setup() {
121
- const checked = ref(false)
122
- return { args, checked }
123
- },
124
- template: '<Checkbox v-bind="args" v-model="checked" />'
125
- })
126
- }
@@ -1,155 +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 Checkbox from './Checkbox.vue'
5
-
6
- describe('Checkbox', () => {
7
- describe('rendering', () => {
8
- it('renders with label', () => {
9
- render(Checkbox, {
10
- props: {
11
- label: 'Accept terms'
12
- }
13
- })
14
-
15
- expect(screen.getByText('Accept terms')).toBeInTheDocument()
16
- })
17
-
18
- it('renders without label', () => {
19
- const { container } = render(Checkbox)
20
-
21
- expect(container.querySelector('.checkbox-text')).not.toBeInTheDocument()
22
- })
23
-
24
- it('renders error message', () => {
25
- render(Checkbox, {
26
- props: {
27
- error: 'This field is required'
28
- }
29
- })
30
-
31
- expect(screen.getByText('This field is required')).toBeInTheDocument()
32
- })
33
-
34
- it('applies disabled class when disabled', () => {
35
- render(Checkbox, {
36
- props: {
37
- label: 'Disabled',
38
- disabled: true
39
- }
40
- })
41
-
42
- const label = screen.getByText('Disabled').closest('.checkbox-label')
43
- expect(label).toHaveClass('checkbox-label--disabled')
44
- })
45
- })
46
-
47
- describe('checked state', () => {
48
- it('is unchecked by default', () => {
49
- render(Checkbox, {
50
- props: {
51
- label: 'Checkbox'
52
- }
53
- })
54
-
55
- const checkbox = screen.getByRole('checkbox')
56
- expect(checkbox).not.toBeChecked()
57
- })
58
-
59
- it('renders as checked when modelValue is true', () => {
60
- render(Checkbox, {
61
- props: {
62
- label: 'Checkbox',
63
- modelValue: true
64
- }
65
- })
66
-
67
- const checkbox = screen.getByRole('checkbox')
68
- expect(checkbox).toBeChecked()
69
- })
70
-
71
- it('can be toggled', async () => {
72
- const user = userEvent.setup()
73
- const { emitted } = render(Checkbox, {
74
- props: {
75
- label: 'Toggle me'
76
- }
77
- })
78
-
79
- const checkbox = screen.getByRole('checkbox')
80
- await user.click(checkbox)
81
-
82
- expect(emitted()['update:modelValue']).toBeTruthy()
83
- expect(emitted()['update:modelValue'][0]).toEqual([true])
84
- })
85
- })
86
-
87
- describe('disabled state', () => {
88
- it('disables the checkbox when disabled prop is true', () => {
89
- render(Checkbox, {
90
- props: {
91
- label: 'Disabled',
92
- disabled: true
93
- }
94
- })
95
-
96
- const checkbox = screen.getByRole('checkbox')
97
- expect(checkbox).toBeDisabled()
98
- })
99
-
100
- it('does not emit events when disabled', async () => {
101
- const user = userEvent.setup()
102
- const { emitted } = render(Checkbox, {
103
- props: {
104
- label: 'Disabled',
105
- disabled: true
106
- }
107
- })
108
-
109
- const checkbox = screen.getByRole('checkbox')
110
- await user.click(checkbox)
111
-
112
- expect(emitted()['update:modelValue']).toBeFalsy()
113
- })
114
- })
115
-
116
- describe('required attribute', () => {
117
- it('sets required attribute when required prop is true', () => {
118
- render(Checkbox, {
119
- props: {
120
- label: 'Required',
121
- required: true
122
- }
123
- })
124
-
125
- const checkbox = screen.getByRole('checkbox')
126
- expect(checkbox).toBeRequired()
127
- })
128
-
129
- it('does not set required attribute by default', () => {
130
- render(Checkbox, {
131
- props: {
132
- label: 'Optional'
133
- }
134
- })
135
-
136
- const checkbox = screen.getByRole('checkbox')
137
- expect(checkbox).not.toBeRequired()
138
- })
139
- })
140
-
141
- describe('accessibility', () => {
142
- it('associates label with checkbox', () => {
143
- render(Checkbox, {
144
- props: {
145
- label: 'Accept terms'
146
- }
147
- })
148
-
149
- const checkbox = screen.getByRole('checkbox')
150
- const label = screen.getByText('Accept terms')
151
-
152
- expect(checkbox.closest('label')).toContainElement(label)
153
- })
154
- })
155
- })
@@ -1,121 +0,0 @@
1
- <template>
2
- <div class="checkbox-wrapper">
3
- <label :class="['checkbox-label', { 'checkbox-label--disabled': disabled }]">
4
- <input
5
- type="checkbox"
6
- class="checkbox-input"
7
- :checked="modelValue"
8
- :disabled="disabled"
9
- :required="required"
10
- @change="handleChange"
11
- />
12
- <span class="checkbox-box"></span>
13
- <span v-if="label" class="checkbox-text">{{ label }}</span>
14
- </label>
15
- <span v-if="error" class="checkbox-error">{{ error }}</span>
16
- </div>
17
- </template>
18
-
19
- <script setup lang="ts">
20
-
21
- export interface CheckboxProps {
22
- modelValue?: boolean
23
- label?: string
24
- disabled?: boolean
25
- required?: boolean
26
- error?: string
27
- }
28
-
29
- withDefaults(defineProps<CheckboxProps>(), {
30
- modelValue: false,
31
- disabled: false,
32
- required: false
33
- })
34
-
35
- const emit = defineEmits<{
36
- 'update:modelValue': [value: boolean]
37
- }>()
38
-
39
- const handleChange = (event: Event) => {
40
- const target = event.target as HTMLInputElement
41
- emit('update:modelValue', target.checked)
42
- }
43
- </script>
44
-
45
- <style scoped>
46
- .checkbox-wrapper {
47
- display: flex;
48
- flex-direction: column;
49
- gap: 0.25rem;
50
- }
51
-
52
- .checkbox-label {
53
- display: inline-flex;
54
- align-items: center;
55
- gap: 0.5rem;
56
- cursor: pointer;
57
- position: relative;
58
- }
59
-
60
- .checkbox-label--disabled {
61
- cursor: not-allowed;
62
- opacity: 0.6;
63
- }
64
-
65
- .checkbox-input {
66
- position: absolute;
67
- opacity: 0;
68
- width: 0;
69
- height: 0;
70
- }
71
-
72
- .checkbox-box {
73
- width: 1.25rem;
74
- height: 1.25rem;
75
- border: 2px solid #d1d5db;
76
- border-radius: 0.25rem;
77
- display: flex;
78
- align-items: center;
79
- justify-content: center;
80
- transition: all 0.2s ease-in-out;
81
- background: white;
82
- flex-shrink: 0;
83
- }
84
-
85
- .checkbox-input:checked + .checkbox-box {
86
- background: #3b82f6;
87
- border-color: #3b82f6;
88
- }
89
-
90
- .checkbox-input:checked + .checkbox-box::after {
91
- content: '';
92
- width: 0.375rem;
93
- height: 0.75rem;
94
- border: solid white;
95
- border-width: 0 2px 2px 0;
96
- transform: rotate(45deg);
97
- margin-bottom: 0.125rem;
98
- }
99
-
100
- .checkbox-input:focus + .checkbox-box {
101
- outline: 2px solid #3b82f6;
102
- outline-offset: 2px;
103
- }
104
-
105
- .checkbox-input:disabled + .checkbox-box {
106
- background: #f3f4f6;
107
- cursor: not-allowed;
108
- }
109
-
110
- .checkbox-text {
111
- font-size: 0.875rem;
112
- color: #374151;
113
- user-select: none;
114
- }
115
-
116
- .checkbox-error {
117
- font-size: 0.75rem;
118
- color: #ef4444;
119
- margin-left: 1.75rem;
120
- }
121
- </style>
@@ -1,7 +0,0 @@
1
- export interface CheckboxProps {
2
- modelValue?: boolean
3
- label?: string
4
- disabled?: boolean
5
- required?: boolean
6
- error?: string
7
- }