@dcrackel/hematournamentui 1.0.712 → 1.0.714
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierignore +7 -7
- package/.storybook/main.js +3 -1
- package/README.md +42 -0
- package/dist/HemaTournamentUI-lib.es.js +6856 -6243
- package/dist/HemaTournamentUI-lib.umd.js +27 -27
- package/dist/hematournamentui-tailwind.css +79 -9
- package/package.json +96 -96
- package/prettier.config.js +16 -16
- package/src/index.js +43 -42
- package/src/main.js +1 -1
- package/src/mocks/getDEBouts-TableOf128.js +37 -37
- package/src/mocks/getDEBouts-TableOf64.js +35 -35
- package/src/stories/Atoms/Input/BaseInput.test.js +97 -97
- package/src/stories/Atoms/Input/BaseInput.vue +149 -149
- package/src/stories/Molecules/Indicators/MissingHemaRatingsId/MissingHemaRatingsId.stories.js +23 -23
- package/src/stories/Molecules/Indicators/MissingHemaRatingsId/MissingHemaRatingsId.vue +35 -35
- package/src/stories/Molecules/Indicators/RegistrationStatus/RegistrationStatus.vue +30 -30
- package/src/stories/Molecules/Menus/HoverActions/HoverActions.test.js +138 -0
- package/src/stories/Molecules/Menus/HoverActions/HoverActions.vue +212 -0
- package/src/stories/Molecules/Modals/BracketDirectorsModal/BracketDirectorsModal.stories.js +49 -0
- package/src/stories/Molecules/Modals/BracketDirectorsModal/BracketDirectorsModal.test.js +129 -0
- package/src/stories/Molecules/Modals/BracketDirectorsModal/BracketDirectorsModal.vue +165 -0
- package/src/stories/Molecules/Modals/DirectorModal/DirectorModal.stories.js +6 -0
- package/src/stories/Molecules/Modals/DirectorModal/DirectorModal.test.js +18 -18
- package/src/stories/Molecules/Modals/DirectorModal/DirectorModal.vue +1 -1
- package/src/stories/Organisms/Cards/BoutCard/BoutCard.vue +5 -1
- package/src/stories/Organisms/Cards/BoutCard/Variants/BoutCardActive/BoutCardActive.vue +19 -10
- package/src/stories/Organisms/Cards/BoutCard/Variants/BoutCardInactive/BoutCardInactive.vue +11 -7
- package/src/stories/Organisms/Cards/BracketDirectorAssignmentCard/BracketDirectorAssignmentCard.stories.js +42 -33
- package/src/stories/Organisms/Cards/BracketDirectorAssignmentCard/BracketDirectorAssignmentCard.test.js +76 -45
- package/src/stories/Organisms/Cards/BracketDirectorAssignmentCard/BracketDirectorAssignmentCard.vue +122 -103
- package/src/stories/Organisms/Cards/Director/DirectorCard.test.js +82 -0
- package/src/stories/Organisms/Cards/Director/DirectorCard.vue +32 -51
- package/src/stories/Organisms/Cards/EditBout/EditBout.test.js +51 -51
- package/src/stories/Organisms/Cards/EventCard/EventCard.test.js +106 -106
- package/src/stories/Organisms/Cards/FencerCard/FencerCard.vue +298 -298
- package/src/stories/Organisms/Cards/TableauBoutCard/TableauBoutCard.stories.js +77 -60
- package/src/stories/Organisms/Cards/TableauBoutCard/TableauBoutCard.test.js +144 -143
- package/src/stories/Organisms/Cards/TableauBoutCard/TableauBoutCard.vue +289 -256
- package/src/stories/Organisms/Cards/TableauFencerCard/TableauFencerCard.stories.js +69 -69
- package/src/stories/Organisms/Cards/TableauFencerCard/TableauFencerCard.vue +80 -80
- package/src/stories/Organisms/Cards/WaitlistFencerCard/WaitlistFencerCard.vue +153 -153
- package/src/stories/Organisms/ComplexInputs/DropDown/DropDownMenu.vue +4 -0
- package/src/stories/Organisms/ComplexInputs/ImageCropper/ImageCropper.stories.js +31 -31
- package/src/stories/Organisms/ComplexInputs/ImageCropper/ImageCropper.test.js +109 -109
- package/src/stories/Organisms/ComplexInputs/ImageCropper/ImageCropper.vue +192 -192
- package/src/stories/Organisms/Containers/Tableau/Tableau.stories.js +1 -0
- package/src/stories/Organisms/Containers/Tableau/Tableau.test.js +247 -204
- package/src/stories/Organisms/Containers/Tableau/Tableau.vue +89 -15
- package/src/stories/Organisms/Containers/Tableau/components/BracketDirectorAssignmentPanel.test.js +51 -29
- package/src/stories/Organisms/Containers/Tableau/components/BracketDirectorAssignmentPanel.vue +63 -46
- package/src/stories/Organisms/Containers/Tableau/components/TableauSvgOverlay.test.js +21 -21
- package/src/stories/Organisms/Containers/Tableau/components/TableauSvgOverlay.vue +39 -39
- package/src/stories/Organisms/Containers/Tableau/layout/TableauLayoutEngine.js +145 -145
- package/src/stories/Organisms/Containers/Tableau/layout/TableauLayoutEngine.test.js +64 -64
- package/src/stories/Organisms/Containers/Tableau/plannedAssignments.js +36 -57
- package/src/stories/Organisms/Containers/Tableau/plannedAssignments.test.js +101 -65
- package/src/stories/Organisms/Containers/TableauColumn/TableauColumn.vue +14 -1
- package/src/stories/Organisms/Wizards/EditEventWizard/BasicEventInfo/BasicEventInfo.stories.js +52 -52
- package/src/stories/Organisms/Wizards/EditEventWizard/BasicEventInfo/BasicEventInfo.vue +10 -3
- package/src/stories/Organisms/Wizards/EditEventWizard/DirectElimination/DirectElimination.vue +226 -226
- package/src/stories/Organisms/Wizards/EditEventWizard/DirectEliminationPromotion/DirectEliminationPromotion.vue +204 -204
- package/src/stories/Organisms/Wizards/EditEventWizard/EditEventWizard.stories.js +137 -137
- package/src/stories/Organisms/Wizards/EditEventWizard/EventCustomization/EventCustomization.vue +172 -172
- package/src/stories/Organisms/Wizards/EditEventWizard/PoolConfiguration/PoolConfiguration.vue +216 -216
- package/src/stories/Organisms/Wizards/EditEventWizard/PriceFields.test.js +79 -79
- package/src/stories/Organisms/Wizards/EditEventWizard/RuleSerialization.test.js +29 -29
- package/src/stories/Organisms/Wizards/EditEventWizard/WeaponSelection.test.js +138 -0
- package/src/stories/Templates/EventManagement/Bracket/Bracket.stories.js +149 -9
- package/src/stories/Templates/EventManagement/Bracket/Bracket.test.js +54 -2
- package/src/stories/Templates/EventManagement/Bracket/Bracket.vue +77 -8
- package/src/stories/Templates/EventManagement/Bracket/BracketDirectorAssignment.test.js +242 -0
- package/src/stories/Templates/EventManagement/Bracket/BracketMobile.test.js +131 -0
- package/src/stories/Templates/EventManagement/Bracket/BracketPlannedSuggestions.js +50 -39
- package/src/stories/Templates/EventManagement/Bracket/BracketStories.test.js +201 -0
- package/src/stories/Templates/EventManagement/Bracket/BracketStoryAssignments.js +93 -0
- package/src/stories/Templates/EventManagement/Bracket/BracketStoryAssignments.test.js +152 -0
- package/src/stories/Templates/EventManagement/Bracket/BracketStoryHarness.js +39 -39
- package/src/stories/Templates/EventManagement/Bracket/BracketStoryHarness.test.js +79 -79
- package/src/stories/Templates/EventManagement/EditEventInfo/EditEventInfo.stories.js +93 -93
- package/src/stories/Templates/EventManagement/EditEventInfo/EditEventInfo.vue +91 -91
- package/src/stories/Templates/EventManagement/PoolLive/PoolLive.test.js +121 -121
- package/src/stories/Templates/Menus/EditEventsTopMenu/EditEventsTopMenu.stories.js +9 -2
- package/src/stories/Templates/Menus/EditEventsTopMenu/EditEventsTopMenu.vue +5 -4
- package/src/stories/Templates/PersonManagement/Admin/Administration/Administration.stories.js +81 -81
- package/src/stories/Templates/PersonManagement/Admin/Administration/Administration.test.js +39 -39
- package/src/stories/Templates/PersonManagement/Admin/Administration/Administration.vue +101 -101
- package/src/stories/Templates/PersonManagement/Admin/FencerAdmin/FencerAdmin.stories.js +71 -71
- package/src/stories/Templates/PersonManagement/Admin/FencerAdmin/FencerAdmin.vue +86 -86
- package/src/stories/Templates/PersonManagement/Admin/MergeAccounts/MergeAccounts.stories.js +86 -86
- package/src/stories/Templates/PersonManagement/Admin/MergeAccounts/MergeAccounts.vue +247 -247
- package/src/stories/Templates/PersonManagement/Basic/BasicEdit.vue +170 -170
- package/src/stories/Templates/PersonManagement/PersonManagement.stories.js +156 -156
- package/src/stories/Templates/PersonManagement/PersonManagement.test.js +329 -329
- package/src/stories/Templates/PersonManagement/PersonManagement.vue +329 -329
- package/src/stories/Templates/PersonManagement/PersonManagementDraft.js +42 -42
- package/src/stories/Templates/TournamentManagement/TournamentManagement.stories.js +84 -84
- package/src/stories/Templates/TournamentManagement/TournamentManagement.test.js +114 -114
- package/src/stories/Templates/TournamentManagement/TournamentManagement.vue +363 -363
- package/src/stories/Templates/TournamentManagement/TournamentPageOne/TournamentPageOne.stories.js +116 -116
- package/src/stories/Templates/TournamentManagement/TournamentPageOne/TournamentPageOne.vue +307 -307
- package/src/stories/Util/Validations/PersonManagementValidations.js +45 -45
- package/src/stories/Util/Validations/PriceValidation.js +6 -6
- package/src/stories/Util/boutDirectorAssignment.js +46 -0
- package/src/stories/Util/bracketDirectors.js +86 -0
- package/src/stories/Util/registrationStatus.js +11 -11
- package/src/stories/Util/tabs.js +19 -47
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
import historicalSixtySevenFencerBracket from './getDEBouts-67Fencers.js';
|
|
2
|
-
|
|
3
|
-
const FIRST_TABLE_OF_64_BOUT_ID = 65;
|
|
4
|
-
|
|
5
|
-
const roundLabelRules = [
|
|
6
|
-
{ matches: boutId => boutId >= 65 && boutId <= 96, label: 'Table of 64' },
|
|
7
|
-
{ matches: boutId => boutId >= 97 && boutId <= 112, label: 'Table of 32' },
|
|
8
|
-
{ matches: boutId => boutId >= 113 && boutId <= 120, label: 'Table of 16' },
|
|
9
|
-
{ matches: boutId => boutId >= 121 && boutId <= 124, label: 'Table of 8' },
|
|
10
|
-
{ matches: boutId => boutId >= 125 && boutId <= 126, label: 'Semifinal' },
|
|
11
|
-
{ matches: boutId => boutId === 127, label: 'Final' }
|
|
12
|
-
];
|
|
13
|
-
|
|
14
|
-
const isTableOf64Bout = bout => Number(bout.DEBoutId) >= FIRST_TABLE_OF_64_BOUT_ID;
|
|
15
|
-
|
|
16
|
-
const getCurrentRoundLabel = bout => {
|
|
17
|
-
const boutId = Number(bout.DEBoutId);
|
|
18
|
-
return roundLabelRules.find(rule => rule.matches(boutId))?.label || bout.RoundLabel;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const normalizeTableOf64Bout = bout => ({
|
|
22
|
-
...bout,
|
|
23
|
-
RoundLabel: getCurrentRoundLabel(bout)
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
const [historicalPool, ...otherPools] = historicalSixtySevenFencerBracket.pools;
|
|
27
|
-
const tableOf64Bouts = historicalPool.Bouts.filter(isTableOf64Bout).map(normalizeTableOf64Bout);
|
|
28
|
-
|
|
29
|
-
const getDEBoutsTableOf64 = {
|
|
30
|
-
...historicalSixtySevenFencerBracket,
|
|
31
|
-
message: 'Current Table of 64 fixture retrieved',
|
|
32
|
-
pools: [{ ...historicalPool, Bouts: tableOf64Bouts }, ...otherPools]
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export default getDEBoutsTableOf64;
|
|
1
|
+
import historicalSixtySevenFencerBracket from './getDEBouts-67Fencers.js';
|
|
2
|
+
|
|
3
|
+
const FIRST_TABLE_OF_64_BOUT_ID = 65;
|
|
4
|
+
|
|
5
|
+
const roundLabelRules = [
|
|
6
|
+
{ matches: boutId => boutId >= 65 && boutId <= 96, label: 'Table of 64' },
|
|
7
|
+
{ matches: boutId => boutId >= 97 && boutId <= 112, label: 'Table of 32' },
|
|
8
|
+
{ matches: boutId => boutId >= 113 && boutId <= 120, label: 'Table of 16' },
|
|
9
|
+
{ matches: boutId => boutId >= 121 && boutId <= 124, label: 'Table of 8' },
|
|
10
|
+
{ matches: boutId => boutId >= 125 && boutId <= 126, label: 'Semifinal' },
|
|
11
|
+
{ matches: boutId => boutId === 127, label: 'Final' }
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
const isTableOf64Bout = bout => Number(bout.DEBoutId) >= FIRST_TABLE_OF_64_BOUT_ID;
|
|
15
|
+
|
|
16
|
+
const getCurrentRoundLabel = bout => {
|
|
17
|
+
const boutId = Number(bout.DEBoutId);
|
|
18
|
+
return roundLabelRules.find(rule => rule.matches(boutId))?.label || bout.RoundLabel;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const normalizeTableOf64Bout = bout => ({
|
|
22
|
+
...bout,
|
|
23
|
+
RoundLabel: getCurrentRoundLabel(bout)
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const [historicalPool, ...otherPools] = historicalSixtySevenFencerBracket.pools;
|
|
27
|
+
const tableOf64Bouts = historicalPool.Bouts.filter(isTableOf64Bout).map(normalizeTableOf64Bout);
|
|
28
|
+
|
|
29
|
+
const getDEBoutsTableOf64 = {
|
|
30
|
+
...historicalSixtySevenFencerBracket,
|
|
31
|
+
message: 'Current Table of 64 fixture retrieved',
|
|
32
|
+
pools: [{ ...historicalPool, Bouts: tableOf64Bouts }, ...otherPools]
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default getDEBoutsTableOf64;
|
|
@@ -1,97 +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 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
|
+
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,149 +1,149 @@
|
|
|
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
|
+
<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>
|
package/src/stories/Molecules/Indicators/MissingHemaRatingsId/MissingHemaRatingsId.stories.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import MissingHemaRatingsId from './MissingHemaRatingsId.vue';
|
|
2
|
-
|
|
3
|
-
export default {
|
|
4
|
-
title: 'Molecules/Indicators/MissingHemaRatingsId',
|
|
5
|
-
component: MissingHemaRatingsId,
|
|
6
|
-
tags: ['autodocs'],
|
|
7
|
-
args: { person: { HemaRatingsId: null } },
|
|
8
|
-
argTypes: {
|
|
9
|
-
person: { control: 'object' }
|
|
10
|
-
}
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export const MissingId = {
|
|
14
|
-
args: { person: { HemaRatingsId: null } }
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export const UnratedWithId = {
|
|
18
|
-
args: { person: { HemaRatingsId: 10255, HEMARatings: [] } }
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const IdFromRating = {
|
|
22
|
-
args: { person: { HEMARatings: [{ HemaRatingId: 10255, Rating: 1708.8 }] } }
|
|
23
|
-
};
|
|
1
|
+
import MissingHemaRatingsId from './MissingHemaRatingsId.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Molecules/Indicators/MissingHemaRatingsId',
|
|
5
|
+
component: MissingHemaRatingsId,
|
|
6
|
+
tags: ['autodocs'],
|
|
7
|
+
args: { person: { HemaRatingsId: null } },
|
|
8
|
+
argTypes: {
|
|
9
|
+
person: { control: 'object' }
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const MissingId = {
|
|
14
|
+
args: { person: { HemaRatingsId: null } }
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const UnratedWithId = {
|
|
18
|
+
args: { person: { HemaRatingsId: 10255, HEMARatings: [] } }
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const IdFromRating = {
|
|
22
|
+
args: { person: { HEMARatings: [{ HemaRatingId: 10255, Rating: 1708.8 }] } }
|
|
23
|
+
};
|