@dcrackel/hematournamentui 1.0.7 → 1.0.20

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 (106) hide show
  1. package/.storybook/preview-head.html +3 -1
  2. package/dist/HemaTouranmentUI-lib.es.js +26609 -480
  3. package/dist/HemaTouranmentUI-lib.umd.js +183 -1
  4. package/dist/style.css +9 -0
  5. package/package/.eslintrc.js +18 -0
  6. package/package/.gitattributes +2 -0
  7. package/package/.prettierignore +1 -0
  8. package/package/.storybook/main.js +18 -0
  9. package/package/.storybook/mockRoutes.js +9 -0
  10. package/package/.storybook/preview-head.html +1 -0
  11. package/package/.storybook/preview.js +17 -0
  12. package/package/LICENSE +21 -0
  13. package/package/README.md +83 -0
  14. package/package/index.html +12 -0
  15. package/package/package.json +49 -0
  16. package/package/postcss.config.js +6 -0
  17. package/package/prettier.config.js +10 -0
  18. package/package/src/assets/default-tournament.png +0 -0
  19. package/package/src/index.js +15 -0
  20. package/package/src/main.js +2 -0
  21. package/package/src/mocks/fileMock.js +1 -0
  22. package/package/src/mocks/tournamentMock.js +34 -0
  23. package/package/src/stories/Configure.mdx +320 -0
  24. package/package/tailwind/output.css +1072 -0
  25. package/package/tailwind/tailwind.css +4 -0
  26. package/package/tailwind.config.js +25 -0
  27. package/package/vite.config.js +23 -0
  28. package/package.json +9 -2
  29. package/src/assets/select-tournament.png +0 -0
  30. package/src/index.js +20 -11
  31. package/src/stories/Atoms/Icon/BaseIcon.stories.js +54 -0
  32. package/src/stories/Atoms/Icon/BaseIcon.vue +47 -0
  33. package/src/stories/Atoms/Input/BaseInput.stories.js +28 -0
  34. package/src/stories/Atoms/Input/BaseInput.test.js +87 -0
  35. package/src/stories/Atoms/Input/BaseInput.vue +73 -0
  36. package/src/stories/Atoms/RadioGroup/BaseRadioGroup.stories.js +31 -0
  37. package/src/stories/Atoms/RadioGroup/BaseRadioGroup.vue +49 -0
  38. package/src/stories/Atoms/Tag/BaseTag.stories.js +29 -0
  39. package/src/stories/Atoms/Tag/BaseTag.test.js +42 -0
  40. package/src/stories/Atoms/Tag/BaseTag.vue +57 -0
  41. package/src/stories/Atoms/Text/BaseText.stories.js +77 -0
  42. package/src/stories/Atoms/Text/BaseText.test.js +172 -0
  43. package/src/stories/Atoms/Text/BaseText.vue +170 -0
  44. package/src/stories/Molecules/Breadcrumb/Admin/Breadcrumb.stories.js +41 -0
  45. package/src/stories/Molecules/Breadcrumb/Admin/Breadcrumb.vue +31 -0
  46. package/src/stories/Molecules/Button/BaseButton.stories.js +76 -0
  47. package/src/stories/Molecules/Button/BaseButton.test.js +147 -0
  48. package/src/stories/Molecules/Button/BaseButton.vue +125 -0
  49. package/src/stories/Molecules/Cards/Detail/TournamentCardDetail.stories.js +33 -0
  50. package/src/stories/Molecules/Cards/Detail/TournamentCardDetail.vue +38 -0
  51. package/src/stories/Molecules/Cards/Header/TournamentCardHeader.stories.js +48 -0
  52. package/src/stories/Molecules/Cards/Header/TournamentCardHeader.vue +40 -0
  53. package/src/stories/Molecules/Filters/FilterAndSortBar/FilterAndSortBar.stories.js +36 -0
  54. package/src/stories/Molecules/Filters/FilterAndSortBar/FilterAndSortBar.vue +49 -0
  55. package/src/stories/Molecules/Filters/FilterUpcomingPast/FilterUpcomingPast.stories.js +32 -0
  56. package/src/stories/Molecules/Filters/FilterUpcomingPast/FilterUpcomingPast.vue +46 -0
  57. package/src/stories/Organisms/AddressAutocomplete/AddressAutocomplete.stories.js +25 -0
  58. package/src/stories/Organisms/AddressAutocomplete/AddressAutocomplete.vue +51 -0
  59. package/src/stories/Organisms/DatePicker/DatePicker.stories.js +25 -0
  60. package/src/stories/Organisms/DatePicker/DatePicker.vue +62 -0
  61. package/src/stories/Organisms/DropDown/DropDownMenu.stories.js +34 -0
  62. package/src/stories/Organisms/DropDown/DropDownMenu.vue +51 -0
  63. package/src/stories/Organisms/Grid/GridContainer.stories.js +47 -0
  64. package/src/stories/Organisms/Grid/GridContainer.vue +108 -0
  65. package/src/stories/Organisms/ImageCropper/ImageCropper.stories.js +28 -0
  66. package/src/stories/Organisms/ImageCropper/ImageCropper.vue +86 -0
  67. package/src/stories/Organisms/TextBoxEditor/TextBoxEditor.stories.js +28 -0
  68. package/src/stories/Organisms/TextBoxEditor/TextBoxEditor.vue +97 -0
  69. package/src/stories/Organisms/TournamentCard/TournamentCard.stories.js +37 -0
  70. package/src/stories/Organisms/TournamentCard/TournamentCard.vue +35 -0
  71. package/src/stories/Templates/Forms/AddTournamentPageOne/AddTournamentPageOne.stories.js +25 -0
  72. package/src/stories/Templates/Forms/AddTournamentPageOne/AddTournamentPageOne.vue +136 -0
  73. package/src/stories/Templates/Menu/Admin/AdminLeftMenu.stories.js +28 -0
  74. package/src/stories/Templates/Menu/Admin/AdminLeftMenu.vue +57 -0
  75. package/tailwind/output.css +147 -7
  76. package/tailwind.config.js +28 -3
  77. /package/{src → package/src}/stories/Base/Button/BaseButton.stories.js +0 -0
  78. /package/{src → package/src}/stories/Base/Button/BaseButton.test.js +0 -0
  79. /package/{src → package/src}/stories/Base/Button/BaseButton.vue +0 -0
  80. /package/{src → package/src}/stories/Base/Input/BaseInput.stories.js +0 -0
  81. /package/{src → package/src}/stories/Base/Input/BaseInput.test.js +0 -0
  82. /package/{src → package/src}/stories/Base/Input/BaseInput.vue +0 -0
  83. /package/{src → package/src}/stories/Base/Tag/BaseTag.stories.js +0 -0
  84. /package/{src → package/src}/stories/Base/Tag/BaseTag.test.js +0 -0
  85. /package/{src → package/src}/stories/Base/Tag/BaseTag.vue +0 -0
  86. /package/{src → package/src}/stories/Base/Text/BaseText.stories.js +0 -0
  87. /package/{src → package/src}/stories/Base/Text/BaseText.test.js +0 -0
  88. /package/{src → package/src}/stories/Base/Text/BaseText.vue +0 -0
  89. /package/{src → package/src}/stories/Breadcrumb/Admin/Breadcrumb.stories.js +0 -0
  90. /package/{src → package/src}/stories/Breadcrumb/Admin/Breadcrumb.vue +0 -0
  91. /package/{src → package/src}/stories/Cards/TournamentCard/Detail/TournamentCardDetail.stories.js +0 -0
  92. /package/{src → package/src}/stories/Cards/TournamentCard/Detail/TournamentCardDetail.vue +0 -0
  93. /package/{src → package/src}/stories/Cards/TournamentCard/Header/TournamentCardHeader.stories.js +0 -0
  94. /package/{src → package/src}/stories/Cards/TournamentCard/Header/TournamentCardHeader.vue +0 -0
  95. /package/{src → package/src}/stories/Cards/TournamentCard/TournamentCard.stories.js +0 -0
  96. /package/{src → package/src}/stories/Cards/TournamentCard/TournamentCard.vue +0 -0
  97. /package/{src → package/src}/stories/Containers/Grid/GridContainer.stories.js +0 -0
  98. /package/{src → package/src}/stories/Containers/Grid/GridContainer.vue +0 -0
  99. /package/{src → package/src}/stories/Filters/FilterAndSortBar/FilterAndSortBar.stories.js +0 -0
  100. /package/{src → package/src}/stories/Filters/FilterAndSortBar/FilterAndSortBar.vue +0 -0
  101. /package/{src → package/src}/stories/Filters/FilterUpcomingPast/FilterUpcomingPast.stories.js +0 -0
  102. /package/{src → package/src}/stories/Filters/FilterUpcomingPast/FilterUpcomingPast.vue +0 -0
  103. /package/{src → package/src}/stories/Menu/Admin/AdminLeftMenu.stories.js +0 -0
  104. /package/{src → package/src}/stories/Menu/Admin/AdminLeftMenu.vue +0 -0
  105. /package/{src → package/src}/stories/Menu/DropDown/DropDownMenu.stories.js +0 -0
  106. /package/{src → package/src}/stories/Menu/DropDown/DropDownMenu.vue +0 -0
@@ -0,0 +1,4 @@
1
+ @import 'tailwindcss/base';
2
+ @import 'tailwindcss/components';
3
+ @import 'tailwindcss/utilities';
4
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@200;400;500;600;700&display=swap');
@@ -0,0 +1,25 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+ export default {
3
+ content: [
4
+ "./index.html",
5
+ "./src/**/*.{vue,js,ts,jsx,tsx}",
6
+ ],
7
+ theme: {
8
+ extend: {
9
+ fontFamily: {
10
+ sans: ['Inter', 'system-ui', '-apple-system', 'BlinkMacSystemFont']
11
+ },
12
+ colors: {
13
+ primary: '#141B33',
14
+ primaryHighlight: '#52586C',
15
+ secondary: '#2B324B',
16
+ tertiary: '#F6FAFD',
17
+ quaternary: '#8991AC',
18
+ dropdownSelect: '#D5E4EE',
19
+ neutral: '#FFFFFF',
20
+ bright: '#A0B1EC'
21
+ }
22
+ },
23
+ },
24
+ plugins: [],
25
+ }
@@ -0,0 +1,23 @@
1
+ import { defineConfig } from 'vite'
2
+ import vue from '@vitejs/plugin-vue'
3
+ export default defineConfig({
4
+ plugins: [vue()],
5
+ test: {
6
+ environment: "happy-dom",
7
+ },
8
+ build: {
9
+ lib: {
10
+ entry: 'src/index.js', // this will be your entry point file where you export components
11
+ name: 'HemaTournamentUI', // this is the name of your library
12
+ fileName: (format) => `HemaTouranmentUI-lib.${format}.js`
13
+ },
14
+ rollupOptions: {
15
+ external: ['vue'], // add external dependencies here
16
+ output: {
17
+ globals: {
18
+ vue: 'Vue'
19
+ }
20
+ }
21
+ }
22
+ }
23
+ })
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dcrackel/hematournamentui",
3
3
  "private": false,
4
- "version": "1.0.7",
4
+ "version": "1.0.20",
5
5
  "type": "module",
6
6
  "main": "dist/HemaTouranmentUI-lib.umd.js",
7
7
  "module": "dist/HemaTouranmentUI-lib.es.js",
@@ -20,10 +20,17 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "@storybook/addon-actions": "^7.4.5",
23
+ "@tiptap/extension-bold": "^2.1.11",
24
+ "@tiptap/starter-kit": "^2.1.11",
25
+ "@tiptap/vue-3": "^2.1.11",
26
+ "@vuepic/vue-datepicker": "^7.1.0",
23
27
  "concurrently": "^8.2.1",
28
+ "cropperjs": "^1.6.1",
24
29
  "font-awesome": "^4.7.0",
25
30
  "happy-dom": "^12.8.0",
26
- "vue": "^3.3.4"
31
+ "vue": "^3.3.4",
32
+ "vue-avatar-cropper": "^6.0.9",
33
+ "vue-google-autocomplete": "^1.1.4"
27
34
  },
28
35
  "devDependencies": {
29
36
  "@storybook/addon-docs": "^7.4.5",
Binary file
package/src/index.js CHANGED
@@ -1,15 +1,24 @@
1
- export { default as BaseInput } from './stories/Base/Input/BaseInput.vue';
2
- export { default as BaseButton } from './stories/Base/Button/BaseButton.vue';
3
- export { default as BaseTag } from './stories/Base/Tag/BaseTag.vue';
4
- export { default as BaseText } from './stories/Base/Text/BaseText.vue';
1
+ export { default as BaseIcon } from './stories/Atoms/Icon/BaseIcon.vue';
2
+ export { default as BaseInput } from './stories/Atoms/Input/BaseInput.vue';
3
+ export { default as BaseRaioGroup } from './stories/Atoms/RadioGroup/BaseRadioGroup.vue';
4
+ export { default as BaseTag } from './stories/Atoms/Tag/BaseTag.vue';
5
+ export { default as BaseText } from './stories/Atoms/Text/BaseText.vue';
5
6
 
6
- export { default as TournamentCard } from './stories/Cards/TournamentCard/TournamentCard.vue';
7
- export { default as TournamentCardDetails } from './stories/Cards/TournamentCard/Detail/TournamentCardDetail.vue';
8
- export { default as TournamentCardHeader } from './stories/Cards/TournamentCard/Header/TournamentCardHeader.vue';
7
+ export { default as Breadcrumb } from './stories/Molecules/Breadcrumb/Admin/Breadcrumb.vue';
8
+ export { default as BaseButton } from './stories/Molecules/Button/BaseButton.vue';
9
+ export { default as TournamentCardDetails } from './stories/Molecules/Cards/Detail/TournamentCardDetail.vue';
10
+ export { default as TournamentCardHeader } from './stories/Molecules/Cards/Header/TournamentCardHeader.vue';
11
+ export { default as FilterAndSortBar } from './stories/Molecules/Filters/FilterAndSortBar/FilterAndSortBar.vue';
12
+ export { default as FilterUpcomingPast } from './stories/Molecules/Filters/FilterUpcomingPast/FilterUpcomingPast.vue';
9
13
 
10
- export { default as GridContainer } from './stories/Containers/Grid/GridContainer.vue';
14
+ export { default as AddressAutocomplete } from './stories/Organisms/AddressAutocomplete/AddressAutocomplete.vue';
15
+ export { default as DatePicker } from './stories/Organisms/DatePicker/DatePicker.vue';
16
+ export { default as DropDown } from './stories/Organisms/DropDown/DropDownMenu.vue';
17
+ export { default as ImageCropper } from './stories/Organisms/ImageCropper/ImageCropper.vue';
18
+ export { default as TextBoxEditor } from './stories/Organisms/TextBoxEditor/TextBoxEditor.vue';
19
+ export { default as TournamentCard } from './stories/Organisms/TournamentCard/TournamentCard.vue';
11
20
 
12
- export { default as FilterAndSortBar } from './stories/Filters/FilterAndSortBar/FilterAndSortBar.vue';
13
- export { default as AdminLeftMenu } from './stories/Menu/Admin/AdminLeftMenu.vue';
14
- export { default as DropDownMenu } from './stories/Menu/DropDown/DropDownMenu.vue';
21
+ export { default as AddTournamentPageOne } from './stories/Templates/Forms/AddTournamentPageOne/AddTournamentPageOne.vue';
22
+ // export { default as AddTournamentPageTwo } from './stories/Templates/Forms/AddTournamentPageTwo/AddTournamentPageTwo.vue';
23
+ export { default as AdminLeftMenu } from './stories/Templates/Menu/Admin/AdminLeftMenu.vue';
15
24
 
@@ -0,0 +1,54 @@
1
+ import BaseIcon from './BaseIcon.vue';
2
+
3
+ export default {
4
+ title: 'Atoms/BaseIcon',
5
+ component: BaseIcon,
6
+ tags: ['autodocs'],
7
+ argTypes: {
8
+ iconName: {
9
+ control: {
10
+ type: 'text',
11
+ defaultValue: 'fa-check'
12
+ }
13
+ },
14
+ style: {
15
+ control: {
16
+ type: 'select'
17
+ },
18
+ options: ['fa-solid', 'fa-regular', 'fa-solid', 'fa-light', 'fa-thing'],
19
+ defaultValue: 'solid'
20
+ },
21
+ size: {
22
+ control: {
23
+ type: 'select'
24
+ },
25
+ options: ['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl'],
26
+ defaultValue: 'sm'
27
+ },
28
+ color: {
29
+ control: {
30
+ type: 'text'
31
+ },
32
+ options: ['primary', 'secondary', 'tertiary', 'neutral', 'bright'],
33
+ defaultValue: 'primary'
34
+ }
35
+ }
36
+ };
37
+
38
+ export const BasicPrimary = {
39
+ args: {
40
+ iconName: 'fa-face-smile',
41
+ size: 'sm',
42
+ color: 'primary',
43
+ style: 'fa-solid'
44
+ }
45
+ };
46
+
47
+ export const RegularAndBright = {
48
+ args: {
49
+ iconName: 'fa-face-smile',
50
+ size: 'lg',
51
+ color: 'bright',
52
+ style: 'fa-regular'
53
+ }
54
+ };
@@ -0,0 +1,47 @@
1
+ <template>
2
+ <i :class="computedIconClass"></i>
3
+ </template>
4
+
5
+ <script>
6
+
7
+ export default {
8
+ name: 'BaseIcon',
9
+ props: {
10
+ iconName: {
11
+ type: String,
12
+ required: true
13
+ },
14
+ style: {
15
+ type: String,
16
+ default: 'fa-solid',
17
+ validator: function (value) {
18
+ return ['fa-solid', 'fa-regular', 'fa-solid', 'fa-light', 'fa-thing'].indexOf(value) !== -1;
19
+ },
20
+ },
21
+ size: {
22
+ type: String,
23
+ validator: function (value) {
24
+ return ['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl'].indexOf(value) !== -1;
25
+ },
26
+ default: 'sm'
27
+ },
28
+ color: {
29
+ type: String,
30
+ default: 'primary'
31
+ }
32
+ },
33
+ computed: {
34
+ computedIconClass() {
35
+ return [
36
+ this.style,
37
+ this.iconName,
38
+ `text-${this.size}`,
39
+ this.colorClass
40
+ ];
41
+ },
42
+ colorClass() {
43
+ return `text-${this.color}`;
44
+ }
45
+ }
46
+ };
47
+ </script>
@@ -0,0 +1,28 @@
1
+ import BaseInput from './BaseInput.vue';
2
+
3
+ export default {
4
+ title: 'Atoms/BaseInput',
5
+ component: BaseInput,
6
+ tags: ['autodocs'],
7
+ argTypes: {
8
+ placeholder: { control: 'text' },
9
+ value: { control: 'text' }
10
+ }
11
+ };
12
+
13
+ const Template = args => ({
14
+ components: { BaseInput },
15
+ props: Object.keys(args),
16
+ methods: {
17
+ onValueUpdate(newValue) {
18
+ console.log('Value updated:', newValue);
19
+ }
20
+ }
21
+ });
22
+
23
+ export const Default = {
24
+ args: {
25
+ placeholder: 'Enter text...',
26
+ value: ''
27
+ }
28
+ };
@@ -0,0 +1,87 @@
1
+ import BaseInput from './BaseInput.vue';
2
+ import { mount } from "@vue/test-utils";
3
+ import { describe, expect, test, it } from "vitest";
4
+
5
+ describe('BaseInput.vue', () => {
6
+
7
+ it('renders with default props', () => {
8
+ const wrapper = mount(BaseInput);
9
+ const inputElement = wrapper.find('input');
10
+
11
+ expect(inputElement.attributes('placeholder')).toBe('');
12
+ expect(wrapper.vm.internalValue).toBe('');
13
+ });
14
+
15
+ it('initializes with the correct value prop', () => {
16
+ const initialValue = 'Hello, World!';
17
+ const wrapper = mount(BaseInput, {
18
+ props: {
19
+ value: initialValue
20
+ }
21
+ });
22
+
23
+ expect(wrapper.vm.internalValue).toBe(initialValue);
24
+ });
25
+
26
+ it('updates internalValue when value prop changes', async () => {
27
+ const wrapper = mount(BaseInput);
28
+ await wrapper.setProps({ value: 'New Value' });
29
+
30
+ expect(wrapper.vm.internalValue).toBe('New Value');
31
+ });
32
+
33
+ it('emits update:value with a delay upon input', async () => {
34
+ const wrapper = mount(BaseInput);
35
+ const inputElement = wrapper.find('input');
36
+
37
+ await inputElement.setValue('Test Input');
38
+
39
+ // TODO: Handle timer-related functionality with vitest
40
+ await new Promise(resolve => setTimeout(resolve, 350));
41
+
42
+ expect(wrapper.emitted('update:value')).toBeTruthy();
43
+ expect(wrapper.emitted('update:value')[0]).toEqual(['Test Input']);
44
+ });
45
+
46
+ it('applies formInput styles when type is formInput', () => {
47
+ const wrapper = mount(BaseInput, {
48
+ props: {
49
+ type: 'formInput',
50
+ invalid: false
51
+ }
52
+ });
53
+ const inputElement = wrapper.find('input');
54
+ expect(inputElement.classes()).toContain('border');
55
+ expect(inputElement.classes()).toContain('rounded-lg');
56
+ expect(inputElement.classes()).toContain('text-secondary');
57
+ expect(inputElement.classes()).toContain('placeholder:text-xs');
58
+ expect(inputElement.classes()).toContain('text-sm');
59
+ expect(inputElement.classes()).toContain('p-2');
60
+ expect(inputElement.classes()).toContain('w-full');
61
+ expect(inputElement.classes()).toContain('border-dropdownSelect');
62
+ });
63
+
64
+ it('applies border-alarm class when invalid is true', () => {
65
+ const wrapper = mount(BaseInput, {
66
+ props: {
67
+ type: 'formInput',
68
+ invalid: true
69
+ }
70
+ });
71
+ const inputElement = wrapper.find('input');
72
+ expect(inputElement.classes()).toContain('border-alarm');
73
+ });
74
+
75
+ it('does not apply border-alarm class when invalid is false', () => {
76
+ const wrapper = mount(BaseInput, {
77
+ props: {
78
+ type: 'formInput',
79
+ invalid: false
80
+ }
81
+ });
82
+ const inputElement = wrapper.find('input');
83
+ expect(inputElement.classes()).not.toContain('border-alarm');
84
+ expect(inputElement.classes()).toContain('border-dropdownSelect');
85
+ });
86
+
87
+ });
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <input
3
+ :class="baseClasses"
4
+ :placeholder="placeholder"
5
+ v-model="internalValue"
6
+ @input="onInput"
7
+ />
8
+ </template>
9
+
10
+ <script>
11
+ import { ref, watch, computed } from 'vue';
12
+
13
+ export default {
14
+ name: 'BaseInput',
15
+ props: {
16
+ placeholder: {
17
+ type: String,
18
+ default: ''
19
+ },
20
+ value: {
21
+ type: String,
22
+ default: ''
23
+ },
24
+ type: {
25
+ type: String,
26
+ default: 'borderless',
27
+ validator: function (value) {
28
+ return ['formInput', 'borderless'].indexOf(value) !== -1;
29
+ }
30
+ },
31
+ invalid: {
32
+ type: Boolean,
33
+ default: false
34
+ }
35
+ },
36
+ setup(props, { emit }) {
37
+ const internalValue = ref(props.value);
38
+ const timeout = ref(null);
39
+
40
+ watch(() => props.value, newValue => {
41
+ internalValue.value = newValue;
42
+ });
43
+
44
+ const baseClasses = computed(() => {
45
+ let baseClasses = 'appearance-none focus:outline-none';
46
+
47
+ switch (props.type) {
48
+ case 'borderless':
49
+ baseClasses += ' w-full text-sm';
50
+ break;
51
+ case 'formInput':
52
+ baseClasses += ' border rounded-lg text-secondary placeholder:text-xs text-sm p-2 w-full';
53
+ props.invalid ? baseClasses += ' border-alarm' : baseClasses += ' border border-dropdownSelect';
54
+ break;
55
+ }
56
+ return baseClasses;
57
+ });
58
+
59
+ const onInput = () => {
60
+ clearTimeout(timeout.value);
61
+ timeout.value = setTimeout(() => {
62
+ emit('update:value', internalValue.value);
63
+ }, 300);
64
+ }
65
+
66
+ return {
67
+ internalValue,
68
+ baseClasses,
69
+ onInput
70
+ };
71
+ }
72
+ };
73
+ </script>
@@ -0,0 +1,31 @@
1
+ import BaseRadioGroup from './BaseRadioGroup.vue';
2
+
3
+ export default {
4
+ title: 'Atoms/BaseRadioGroup',
5
+ component: BaseRadioGroup,
6
+ tags: ['autodocs'],
7
+ argTypes: {
8
+ items: {
9
+ control: {
10
+ type: 'object',
11
+ },
12
+ }
13
+ },
14
+ };
15
+
16
+ const Template = (args) => ({
17
+ components: { BaseRadioGroup },
18
+ setup() {
19
+ return { args };
20
+ },
21
+ template: '<BaseRadioGroup v-bind="args" />',
22
+ });
23
+
24
+ export const Default = Template.bind({});
25
+ Default.args = {
26
+ items: [
27
+ { label: 'Option 1', value: 'opt1', description: 'Description for Item1' },
28
+ { label: 'Option 2', value: 'opt2', description: 'Description for Item2' },
29
+ { label: 'Option 2', value: 'opt2', description: 'Description for Item3' },
30
+ ]
31
+ };
@@ -0,0 +1,49 @@
1
+ <template>
2
+ <div class="text-xl" role="radiogroup">
3
+ <div
4
+ class="flex flex-row p-4 text-quaternary rounded-lg mb-2 shadow border hover:bg-tertiary"
5
+ v-for="(item, index) in items"
6
+ :key="index"
7
+ :class="[selectedIndex === index ? ' bg-tertiary' : ' bg-white', invalid ? ' border-alarm' : ' border-dropdownSelect']"
8
+ @click="selectItem(index)"
9
+ role="radio"
10
+ :aria-checked="selectedIndex === index ? 'true' : 'false'"
11
+ tabindex="0"
12
+ @keydown.enter.prevent="selectItem(index)"
13
+ >
14
+ <i :class="[selectedIndex === index ? 'fa-circle-dot text-quaternary ' : 'fa-circle ' ]" class="fa-regular pr-4 pt-2" ></i>
15
+ <div class="flex flex-col">
16
+ <p :class="[selectedIndex === index ? 'text-quaternary ' : '' ]" class="font-bold text-sm">{{ item.label }}</p>
17
+ <p :class="[selectedIndex === index ? 'text-quaternary ' : '' ]" class="text-sm">{{ item.description }}</p>
18
+ </div>
19
+ </div>
20
+ </div>
21
+ </template>
22
+
23
+ <script>
24
+ export default {
25
+ name: 'BaseRadioGroup',
26
+ props: {
27
+ invalid: {
28
+ type: Boolean,
29
+ default: false,
30
+ },
31
+ items: {
32
+ type: Array,
33
+ required: true,
34
+ },
35
+ },
36
+ data() {
37
+ return {
38
+ selectedIndex: null,
39
+ };
40
+ },
41
+ methods: {
42
+ selectItem(index) {
43
+ this.selectedIndex = index;
44
+ this.$emit('update:value', this.items[index].value);
45
+ },
46
+ },
47
+ };
48
+ </script>
49
+
@@ -0,0 +1,29 @@
1
+ import BaseTag from './BaseTag.vue';
2
+
3
+ export default {
4
+ title: 'Atoms/BaseTag',
5
+ component: BaseTag,
6
+ tags: ['autodocs'],
7
+ argTypes: {
8
+ label: {
9
+ control: {
10
+ type: 'text',
11
+ defaultValue: 'Default Label'
12
+ }
13
+ },
14
+ backgroundColor: {
15
+ control: {
16
+ type: 'select'
17
+ },
18
+ options: ['primary', 'secondary', 'tertiary', 'neutral', 'bright'],
19
+ defaultValue: 'primary'
20
+ }
21
+ }
22
+ };
23
+
24
+ export const Basic = {
25
+ args: {
26
+ label: 'default tag',
27
+ backgroundColor: 'primary'
28
+ }
29
+ };
@@ -0,0 +1,42 @@
1
+ import BaseTag from './BaseTag.vue';
2
+ import { mount } from "@vue/test-utils";
3
+ import { describe, expect, test, it } from "vitest";
4
+
5
+ describe('base-tag.vue', () => {
6
+
7
+ it('renders with default classes and primary background color', () => {
8
+ const wrapper = mount(BaseTag, {
9
+ props: { label: 'Test Tag' }
10
+ });
11
+ const tagElement = wrapper.find('div');
12
+
13
+ expect(tagElement.classes()).toContain('cursor-pointer');
14
+ expect(tagElement.classes()).toContain('bg-primary');
15
+ expect(tagElement.text()).toBe('Test Tag');
16
+ });
17
+
18
+ it('renders with specified background color classes', () => {
19
+ const backgrounds = ['primary', 'secondary', 'tertiary', 'neutral', 'bright'];
20
+
21
+ backgrounds.forEach(async (bg) => {
22
+ const wrapper = mount(BaseTag, {
23
+ props: { label: 'Test Tag', backgroundColor: bg }
24
+ });
25
+ const tagElement = wrapper.find('div');
26
+
27
+ expect(tagElement.classes()).toContain(`bg-${bg}`);
28
+ });
29
+ });
30
+
31
+ it('renders with primary background color for unknown values', () => {
32
+ const wrapper = mount(BaseTag, {
33
+ props: { label: 'Test Tag', backgroundColor: 'unknown' }
34
+ });
35
+ const tagElement = wrapper.find('div');
36
+
37
+ expect(tagElement.classes()).toContain('bg-primary');
38
+ });
39
+
40
+
41
+
42
+ });
@@ -0,0 +1,57 @@
1
+ <template>
2
+ <div :class="classes">{{ label }}</div>
3
+ </template>
4
+
5
+ <script>
6
+ import { computed, reactive } from 'vue';
7
+
8
+ export default {
9
+ name: 'base-tag',
10
+
11
+ props: {
12
+ label: {
13
+ type: String,
14
+ required: true
15
+ },
16
+ backgroundColor: {
17
+ type: String,
18
+ validator: function (value) {
19
+ return ['primary', 'secondary', 'tertiary', 'neutral', 'bright'].indexOf(value) !== -1;
20
+ }
21
+ }
22
+ },
23
+
24
+ setup(props) {
25
+ props = reactive(props);
26
+
27
+ return {
28
+ classes: computed(() => {
29
+ let baseClasses = 'cursor-pointer inline-block py-1 px-3 my-2 ml-3 text-xs font-normal rounded-full text-neutral';
30
+
31
+ switch (props.backgroundColor) {
32
+ case 'primary':
33
+ baseClasses += ' bg-primary';
34
+ break;
35
+ case 'secondary':
36
+ baseClasses += ' bg-secondary';
37
+ break;
38
+ case 'tertiary':
39
+ baseClasses += ' bg-tertiary';
40
+ break;
41
+ case 'neutral':
42
+ baseClasses += ' bg-neutral';
43
+ break;
44
+ case 'bright':
45
+ baseClasses += ' bg-bright';
46
+ break;
47
+ default:
48
+ baseClasses += ' bg-primary';
49
+ break;
50
+ }
51
+
52
+ return baseClasses;
53
+ })
54
+ };
55
+ }
56
+ };
57
+ </script>