@dcrackel/hematournamentui 1.0.708 → 1.0.710

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 (38) hide show
  1. package/README.md +148 -106
  2. package/dist/HemaTournamentUI-lib.es.js +6678 -6196
  3. package/dist/HemaTournamentUI-lib.umd.js +27 -27
  4. package/dist/hematournamentui-tailwind.css +16 -6
  5. package/package.json +1 -1
  6. package/src/stories/Atoms/Input/BaseInput.test.js +97 -85
  7. package/src/stories/Atoms/Input/BaseInput.vue +149 -150
  8. package/src/stories/Organisms/ComplexInputs/ImageCropper/ImageCropper.stories.js +31 -20
  9. package/src/stories/Organisms/ComplexInputs/ImageCropper/ImageCropper.test.js +109 -0
  10. package/src/stories/Organisms/ComplexInputs/ImageCropper/ImageCropper.vue +192 -133
  11. package/src/stories/Organisms/Wizards/EditEventWizard/BasicEventInfo/BasicEventInfo.stories.js +48 -41
  12. package/src/stories/Organisms/Wizards/EditEventWizard/BasicEventInfo/BasicEventInfo.vue +227 -206
  13. package/src/stories/Organisms/Wizards/EditEventWizard/DirectElimination/DirectElimination.vue +226 -225
  14. package/src/stories/Organisms/Wizards/EditEventWizard/DirectEliminationPromotion/DirectEliminationPromotion.vue +204 -204
  15. package/src/stories/Organisms/Wizards/EditEventWizard/EditEventWizard.stories.js +133 -91
  16. package/src/stories/Organisms/Wizards/EditEventWizard/EditEventWizard.test.js +191 -0
  17. package/src/stories/Organisms/Wizards/EditEventWizard/EditEventWizard.vue +366 -309
  18. package/src/stories/Organisms/Wizards/EditEventWizard/EventCustomization/EventCustomization.vue +172 -171
  19. package/src/stories/Organisms/Wizards/EditEventWizard/PoolConfiguration/PoolConfiguration.vue +216 -215
  20. package/src/stories/Organisms/Wizards/EditEventWizard/PriceFields.test.js +79 -0
  21. package/src/stories/Templates/EventManagement/EditEventInfo/EditEventInfo.stories.js +93 -52
  22. package/src/stories/Templates/EventManagement/EditEventInfo/EditEventInfo.vue +91 -75
  23. package/src/stories/Templates/PersonManagement/Admin/Administration/Administration.stories.js +14 -0
  24. package/src/stories/Templates/PersonManagement/Admin/Administration/Administration.test.js +39 -0
  25. package/src/stories/Templates/PersonManagement/Admin/Administration/Administration.vue +13 -3
  26. package/src/stories/Templates/PersonManagement/Basic/BasicEdit.vue +170 -172
  27. package/src/stories/Templates/PersonManagement/PersonManagement.stories.js +156 -103
  28. package/src/stories/Templates/PersonManagement/PersonManagement.test.js +329 -0
  29. package/src/stories/Templates/PersonManagement/PersonManagement.vue +329 -213
  30. package/src/stories/Templates/PersonManagement/PersonManagementDraft.js +42 -0
  31. package/src/stories/Templates/TournamentManagement/TournamentManagement.stories.js +84 -83
  32. package/src/stories/Templates/TournamentManagement/TournamentManagement.test.js +89 -0
  33. package/src/stories/Templates/TournamentManagement/TournamentManagement.vue +363 -360
  34. package/src/stories/Templates/TournamentManagement/TournamentPageOne/TournamentPageOne.stories.js +116 -113
  35. package/src/stories/Templates/TournamentManagement/TournamentPageOne/TournamentPageOne.vue +292 -280
  36. package/src/stories/Util/Validations/PersonManagementValidations.js +45 -29
  37. package/src/stories/Util/Validations/PriceValidation.js +6 -0
  38. package/src/stories/Util/Validations/TournamentFieldsValidations.js +4 -0
@@ -659,6 +659,9 @@
659
659
  .min-h-0 {
660
660
  min-height: calc(var(--spacing) * 0);
661
661
  }
662
+ .min-h-5 {
663
+ min-height: calc(var(--spacing) * 5);
664
+ }
662
665
  .min-h-16 {
663
666
  min-height: calc(var(--spacing) * 16);
664
667
  }
@@ -927,6 +930,9 @@
927
930
  .scrollbar-thin {
928
931
  scrollbar-width: thin;
929
932
  }
933
+ .list-disc {
934
+ list-style-type: disc;
935
+ }
930
936
  .appearance-none {
931
937
  appearance: none;
932
938
  }
@@ -1125,6 +1131,10 @@
1125
1131
  border-style: var(--tw-border-style);
1126
1132
  border-width: 1px;
1127
1133
  }
1134
+ .border-0 {
1135
+ border-style: var(--tw-border-style);
1136
+ border-width: 0px;
1137
+ }
1128
1138
  .border-2 {
1129
1139
  border-style: var(--tw-border-style);
1130
1140
  border-width: 2px;
@@ -1366,6 +1376,9 @@
1366
1376
  .object-cover {
1367
1377
  object-fit: cover;
1368
1378
  }
1379
+ .p-0 {
1380
+ padding: calc(var(--spacing) * 0);
1381
+ }
1369
1382
  .p-0\! {
1370
1383
  padding: calc(var(--spacing) * 0) !important;
1371
1384
  }
@@ -1510,6 +1523,9 @@
1510
1523
  .pl-4 {
1511
1524
  padding-left: calc(var(--spacing) * 4);
1512
1525
  }
1526
+ .pl-5 {
1527
+ padding-left: calc(var(--spacing) * 5);
1528
+ }
1513
1529
  .text-center {
1514
1530
  text-align: center;
1515
1531
  }
@@ -1851,12 +1867,6 @@
1851
1867
  -webkit-user-select: none;
1852
1868
  user-select: none;
1853
1869
  }
1854
- .placeholder\:text-xs {
1855
- &::placeholder {
1856
- font-size: var(--text-xs);
1857
- line-height: var(--tw-leading, var(--text-xs--line-height));
1858
- }
1859
- }
1860
1870
  .last\:border-b-0 {
1861
1871
  &:last-child {
1862
1872
  border-bottom-style: var(--tw-border-style);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dcrackel/hematournamentui",
3
3
  "private": false,
4
- "version": "1.0.708",
4
+ "version": "1.0.710",
5
5
  "type": "module",
6
6
  "main": "dist/HemaTournamentUI-lib.umd.js",
7
7
  "module": "dist/HemaTournamentUI-lib.es.js",
@@ -1,85 +1,97 @@
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
- it('renders with default props', () => {
7
- const wrapper = mount(BaseInput);
8
- const inputElement = wrapper.find('input');
9
-
10
- expect(inputElement.attributes('placeholder')).toBe('');
11
- expect(wrapper.vm.internalValue).toBe('');
12
- });
13
-
14
- it('initializes with the correct value prop', () => {
15
- const initialValue = 'Hello, World!';
16
- const wrapper = mount(BaseInput, {
17
- props: {
18
- value: initialValue
19
- }
20
- });
21
-
22
- expect(wrapper.vm.internalValue).toBe(initialValue);
23
- });
24
-
25
- it('updates internalValue when value prop changes', async () => {
26
- const wrapper = mount(BaseInput);
27
- await wrapper.setProps({ value: 'New Value' });
28
-
29
- expect(wrapper.vm.internalValue).toBe('New Value');
30
- });
31
-
32
- it('emits update:value with a delay upon input', async () => {
33
- const wrapper = mount(BaseInput);
34
- const inputElement = wrapper.find('input');
35
-
36
- await inputElement.setValue('Test Input');
37
-
38
- // TODO: Handle timer-related functionality with vitest
39
- await new Promise(resolve => setTimeout(resolve, 350));
40
-
41
- expect(wrapper.emitted('update:value')).toBeTruthy();
42
- expect(wrapper.emitted('update:value')[0]).toEqual(['Test Input']);
43
- });
44
-
45
- it('applies formInput styles when type is formInput', () => {
46
- const wrapper = mount(BaseInput, {
47
- props: {
48
- type: 'formInput',
49
- invalid: false
50
- }
51
- });
52
- const inputElement = wrapper.find('input');
53
- expect(inputElement.classes()).toContain('border');
54
- expect(inputElement.classes()).toContain('rounded-lg');
55
- expect(inputElement.classes()).toContain('text-secondary');
56
- expect(inputElement.classes()).toContain('placeholder:text-xs');
57
- expect(inputElement.classes()).toContain('text-sm');
58
- expect(inputElement.classes()).toContain('p-2');
59
- expect(inputElement.classes()).toContain('w-full');
60
- expect(inputElement.classes()).toContain('border-dropdownSelect');
61
- });
62
-
63
- it('applies border-alarm class when invalid is true', () => {
64
- const wrapper = mount(BaseInput, {
65
- props: {
66
- type: 'formInput',
67
- invalid: true
68
- }
69
- });
70
- const inputElement = wrapper.find('input');
71
- expect(inputElement.classes()).toContain('border-alarm');
72
- });
73
-
74
- it('does not apply border-alarm class when invalid is false', () => {
75
- const wrapper = mount(BaseInput, {
76
- props: {
77
- type: 'formInput',
78
- invalid: false
79
- }
80
- });
81
- const inputElement = wrapper.find('input');
82
- expect(inputElement.classes()).not.toContain('border-alarm');
83
- expect(inputElement.classes()).toContain('border-dropdownSelect');
84
- });
85
- });
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
+ it('renders with default props', () => {
7
+ const wrapper = mount(BaseInput);
8
+ const inputElement = wrapper.find('input');
9
+
10
+ expect(inputElement.attributes('placeholder')).toBe('');
11
+ expect(wrapper.vm.internalValue).toBe('');
12
+ });
13
+
14
+ it('initializes with the correct value prop', () => {
15
+ const initialValue = 'Hello, World!';
16
+ const wrapper = mount(BaseInput, {
17
+ props: {
18
+ value: initialValue
19
+ }
20
+ });
21
+
22
+ expect(wrapper.vm.internalValue).toBe(initialValue);
23
+ });
24
+
25
+ it('updates internalValue when value prop changes', async () => {
26
+ const wrapper = mount(BaseInput);
27
+ await wrapper.setProps({ value: 'New Value' });
28
+
29
+ expect(wrapper.vm.internalValue).toBe('New Value');
30
+ });
31
+
32
+ it('emits the latest value synchronously before the next action', () => {
33
+ const wrapper = mount(BaseInput);
34
+ const inputElement = wrapper.find('input');
35
+
36
+ inputElement.element.value = 'Test Input';
37
+ inputElement.element.dispatchEvent(new Event('input', { bubbles: true }));
38
+ expect(wrapper.emitted('update:value')).toEqual([['Test Input']]);
39
+ });
40
+
41
+ it('applies input border styles when addBorder is enabled', () => {
42
+ const wrapper = mount(BaseInput, {
43
+ props: {
44
+ addBorder: true,
45
+ invalid: false
46
+ }
47
+ });
48
+ const inputElement = wrapper.find('input');
49
+ expect(inputElement.classes()).toContain('border');
50
+ expect(inputElement.classes()).toContain('rounded-lg');
51
+ expect(inputElement.classes()).toContain('text-quinary');
52
+ expect(inputElement.classes()).toContain('text-sm');
53
+ expect(inputElement.classes()).toContain('p-2');
54
+ expect(inputElement.classes()).toContain('w-full');
55
+ expect(inputElement.classes()).toContain('border-dropdownSelect');
56
+ });
57
+
58
+ it('applies border-alarm class when invalid is true', () => {
59
+ const wrapper = mount(BaseInput, {
60
+ props: {
61
+ addBorder: true,
62
+ invalid: true
63
+ }
64
+ });
65
+ const inputElement = wrapper.find('input');
66
+ expect(inputElement.classes()).toContain('border-alarm');
67
+ });
68
+
69
+ it('does not apply border-alarm class when invalid is false', () => {
70
+ const wrapper = mount(BaseInput, {
71
+ props: {
72
+ addBorder: true,
73
+ invalid: false
74
+ }
75
+ });
76
+ const inputElement = wrapper.find('input');
77
+ expect(inputElement.classes()).not.toContain('border-alarm');
78
+ expect(inputElement.classes()).toContain('border-dropdownSelect');
79
+ });
80
+
81
+ it('delivers a cleared value before the input is unmounted', () => {
82
+ const wrapper = mount(BaseInput, { props: { value: '123', inputType: 'number' } });
83
+ const input = wrapper.find('input');
84
+ input.element.value = '';
85
+ input.element.dispatchEvent(new Event('input', { bubbles: true }));
86
+ expect(wrapper.emitted('update:value')).toEqual([['']]);
87
+ wrapper.unmount();
88
+ });
89
+
90
+ it('does not emit edits while disabled', () => {
91
+ const wrapper = mount(BaseInput, { props: { disabled: true, value: 'original' } });
92
+ const input = wrapper.find('input');
93
+ input.element.value = 'changed';
94
+ input.element.dispatchEvent(new Event('input', { bubbles: true }));
95
+ expect(wrapper.emitted('update:value')).toBeUndefined();
96
+ });
97
+ });
@@ -1,150 +1,149 @@
1
- <template>
2
- <div :class="iconName ? '' : ''">
3
- <input
4
- ref="input"
5
- v-model="internalValue"
6
- :class="baseClasses"
7
- :placeholder="placeholder"
8
- :type="inputType"
9
- :disabled="disabled"
10
- @input="onInput"
11
- @focus="onFocus"
12
- @blur="onBlur"
13
- />
14
- </div>
15
- </template>
16
-
17
- <script>
18
- const sizeClasses = {
19
- xs: ' text-xs',
20
- sm: ' text-sm',
21
- md: ' text-md',
22
- lg: ' text-lg',
23
- xl: ' text-xl',
24
- '2xl': ' text-2xl',
25
- '3xl': ' text-3xl',
26
- '4xl': ' text-4xl',
27
- '5xl': ' text-5xl'
28
- };
29
-
30
- export default {
31
- name: 'BaseInput',
32
- emits: ['update:value'],
33
- props: {
34
- placeholder: {
35
- type: [String, Number],
36
- default: ''
37
- },
38
- value: {
39
- type: [String, Number],
40
- default: ''
41
- },
42
- inputType: {
43
- type: String,
44
- default: 'text'
45
- },
46
- invalid: {
47
- type: Boolean,
48
- default: false
49
- },
50
- addBorder: {
51
- type: Boolean,
52
- default: false
53
- },
54
- iconName: {
55
- type: String,
56
- default: ''
57
- },
58
- disabled: {
59
- type: Boolean,
60
- default: false
61
- },
62
- iconStyle: {
63
- type: String,
64
- default: 'fa-solid',
65
- validator: value => ['fa-solid', 'fa-regular', 'fa-light', 'fa-thing'].includes(value)
66
- },
67
- size: {
68
- type: String,
69
- default: 'sm',
70
- validator: value => ['', ' ', 'xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl'].includes(value)
71
- },
72
- centerInput: {
73
- type: Boolean,
74
- default: false
75
- },
76
- iconColor: {
77
- type: String,
78
- default: 'primary',
79
- validator: value =>
80
- ['neutral', 'primary', 'secondary', 'tertiary', 'quaternary', 'quinary', 'bright', 'white', 'alarm'].includes(
81
- value
82
- )
83
- },
84
- allowPercent: {
85
- type: Boolean,
86
- default: false
87
- }
88
- },
89
- data() {
90
- return {
91
- internalValue: this.value,
92
- currentPlaceholder: this.placeholder,
93
- timeout: null
94
- };
95
- },
96
- computed: {
97
- baseClasses() {
98
- let classes = 'appearance-none focus:outline-none w-full text-sm rounded-lg text-quinary';
99
- if (this.addBorder) {
100
- classes += this.invalid ? ' border border-alarm p-2' : ' border border-dropdownSelect p-2';
101
- }
102
-
103
- if (this.centerInput) classes += ' text-center';
104
-
105
- classes += sizeClasses[this.size] || '';
106
-
107
- return classes;
108
- }
109
- },
110
- watch: {
111
- value(newValue) {
112
- this.internalValue = newValue;
113
- }
114
- },
115
- methods: {
116
- onInput(event) {
117
- let sanitizedValue = event.target.value;
118
-
119
- if (this.inputType === 'number') {
120
- sanitizedValue = sanitizedValue.replace(/\D/g, '');
121
- }
122
- if (this.inputType === 'text') {
123
- this.allowPercent
124
- ? (sanitizedValue = sanitizedValue.replace(/[\\'"=*<>|#$^(){}\[\]]/g, ''))
125
- : (sanitizedValue = sanitizedValue.replace(/[\\'"=*<>|#$%^(){}\[\]]/g, ''));
126
- }
127
-
128
- this.internalValue = sanitizedValue;
129
-
130
- clearTimeout(this.timeout);
131
- this.timeout = setTimeout(() => {
132
- this.$emit('update:value', this.internalValue);
133
- }, 300);
134
- },
135
- onFocus() {
136
- this.currentPlaceholder = '';
137
- },
138
- onBlur() {
139
- if (!this.internalValue) {
140
- this.currentPlaceholder = this.placeholder;
141
- }
142
- },
143
- focus() {
144
- if (this.$refs.input) {
145
- this.$refs.input.focus();
146
- }
147
- }
148
- }
149
- };
150
- </script>
1
+ <template>
2
+ <div :class="iconName ? '' : ''">
3
+ <input
4
+ ref="input"
5
+ :value="internalValue"
6
+ :class="baseClasses"
7
+ :placeholder="placeholder"
8
+ :type="inputType"
9
+ :disabled="disabled"
10
+ :aria-invalid="invalid"
11
+ @input="onInput"
12
+ @focus="onFocus"
13
+ @blur="onBlur"
14
+ />
15
+ </div>
16
+ </template>
17
+
18
+ <script>
19
+ const sizeClasses = {
20
+ xs: ' text-xs',
21
+ sm: ' text-sm',
22
+ md: ' text-md',
23
+ lg: ' text-lg',
24
+ xl: ' text-xl',
25
+ '2xl': ' text-2xl',
26
+ '3xl': ' text-3xl',
27
+ '4xl': ' text-4xl',
28
+ '5xl': ' text-5xl'
29
+ };
30
+
31
+ export default {
32
+ name: 'BaseInput',
33
+ emits: ['update:value'],
34
+ props: {
35
+ placeholder: {
36
+ type: [String, Number],
37
+ default: ''
38
+ },
39
+ value: {
40
+ type: [String, Number],
41
+ default: ''
42
+ },
43
+ inputType: {
44
+ type: String,
45
+ default: 'text'
46
+ },
47
+ invalid: {
48
+ type: Boolean,
49
+ default: false
50
+ },
51
+ addBorder: {
52
+ type: Boolean,
53
+ default: false
54
+ },
55
+ iconName: {
56
+ type: String,
57
+ default: ''
58
+ },
59
+ disabled: {
60
+ type: Boolean,
61
+ default: false
62
+ },
63
+ iconStyle: {
64
+ type: String,
65
+ default: 'fa-solid',
66
+ validator: value => ['fa-solid', 'fa-regular', 'fa-light', 'fa-thing'].includes(value)
67
+ },
68
+ size: {
69
+ type: String,
70
+ default: 'sm',
71
+ validator: value => ['', ' ', 'xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl'].includes(value)
72
+ },
73
+ centerInput: {
74
+ type: Boolean,
75
+ default: false
76
+ },
77
+ iconColor: {
78
+ type: String,
79
+ default: 'primary',
80
+ validator: value =>
81
+ ['neutral', 'primary', 'secondary', 'tertiary', 'quaternary', 'quinary', 'bright', 'white', 'alarm'].includes(
82
+ value
83
+ )
84
+ },
85
+ allowPercent: {
86
+ type: Boolean,
87
+ default: false
88
+ }
89
+ },
90
+ data() {
91
+ return {
92
+ internalValue: this.value,
93
+ currentPlaceholder: this.placeholder
94
+ };
95
+ },
96
+ computed: {
97
+ baseClasses() {
98
+ let classes = 'appearance-none focus:outline-none w-full text-sm rounded-lg text-quinary';
99
+ if (this.addBorder) {
100
+ classes += this.invalid ? ' border border-alarm p-2' : ' border border-dropdownSelect p-2';
101
+ }
102
+
103
+ if (this.centerInput) classes += ' text-center';
104
+
105
+ classes += sizeClasses[this.size] || '';
106
+
107
+ return classes;
108
+ }
109
+ },
110
+ watch: {
111
+ value(newValue) {
112
+ this.internalValue = newValue;
113
+ }
114
+ },
115
+ methods: {
116
+ onInput(event) {
117
+ if (this.disabled) return;
118
+ const input = event.target;
119
+ let sanitizedValue = input.value;
120
+
121
+ if (this.inputType === 'number') {
122
+ sanitizedValue = sanitizedValue.replace(/\D/g, '');
123
+ }
124
+ if (this.inputType === 'text') {
125
+ this.allowPercent
126
+ ? (sanitizedValue = sanitizedValue.replace(/[\\'"=*<>|#$^(){}\[\]]/g, ''))
127
+ : (sanitizedValue = sanitizedValue.replace(/[\\'"=*<>|#$%^(){}\[\]]/g, ''));
128
+ }
129
+
130
+ this.internalValue = sanitizedValue;
131
+ input.value = sanitizedValue;
132
+ this.$emit('update:value', sanitizedValue);
133
+ },
134
+ onFocus() {
135
+ this.currentPlaceholder = '';
136
+ },
137
+ onBlur() {
138
+ if (!this.internalValue) {
139
+ this.currentPlaceholder = this.placeholder;
140
+ }
141
+ },
142
+ focus() {
143
+ if (this.$refs.input) {
144
+ this.$refs.input.focus();
145
+ }
146
+ }
147
+ }
148
+ };
149
+ </script>
@@ -1,20 +1,31 @@
1
- import GenericImageCropper from './ImageCropper.vue';
2
-
3
- export default {
4
- title: 'Organisms/ComplexInputs/ImageCropper',
5
- component: GenericImageCropper,
6
- tags: ['autodocs'],
7
- args: {},
8
- argTypes: {
9
- personID: {
10
- control: 'number',
11
- description: 'The ID of the person for the image cropper'
12
- }
13
- }
14
- };
15
-
16
- export const Default = {
17
- args: {
18
- personID: 1
19
- }
20
- };
1
+ import GenericImageCropper from './ImageCropper.vue';
2
+
3
+ export default {
4
+ title: 'Organisms/ComplexInputs/ImageCropper',
5
+ component: GenericImageCropper,
6
+ tags: ['autodocs'],
7
+ args: { urlToImage: '', isProfile: true, disabled: false },
8
+ argTypes: {
9
+ urlToImage: { control: 'text' },
10
+ uploadImageName: { control: 'text' },
11
+ uploadServer: { control: 'text' },
12
+ imageServer: { control: 'text' },
13
+ isProfile: { control: 'boolean' },
14
+ disabled: { control: 'boolean' },
15
+ 'update:url': { action: 'update:url' },
16
+ 'update:uploading': { action: 'update:uploading' },
17
+ 'error:load': { action: 'error:load' },
18
+ 'error:upload': { action: 'error:upload' }
19
+ }
20
+ };
21
+
22
+ export const Default = {
23
+ args: {
24
+ urlToImage: '',
25
+ isProfile: true
26
+ }
27
+ };
28
+
29
+ export const Disabled = {
30
+ args: { urlToImage: '', isProfile: true, disabled: true }
31
+ };