@pequity/squirrel 5.4.8 → 5.4.10
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/README.md +1 -1
- package/dist/cjs/chunks/p-date-picker.js +143 -85
- package/dist/cjs/chunks/p-inline-date-picker.js +117 -67
- package/dist/es/chunks/p-date-picker.js +144 -86
- package/dist/es/chunks/p-inline-date-picker.js +118 -68
- package/dist/squirrel/components/p-date-picker/p-date-picker.vue.d.ts +27 -31
- package/dist/squirrel/components/p-drawer/p-drawer.vue.d.ts +2 -2
- package/dist/squirrel/components/p-dropdown-select/p-dropdown-select.vue.d.ts +1 -1
- package/dist/squirrel/components/p-inline-date-picker/p-inline-date-picker.vue.d.ts +46 -0
- package/dist/squirrel/components/p-modal/p-modal.vue.d.ts +3 -3
- package/dist/style.css +37 -928
- package/package.json +7 -9
- package/squirrel/assets/squirrel.css +45 -6
- package/squirrel/components/p-date-picker/p-date-picker.spec.js +292 -0
- package/squirrel/components/p-date-picker/p-date-picker.stories.js +2 -2
- package/squirrel/components/p-date-picker/p-date-picker.vue +45 -90
- package/squirrel/components/p-inline-date-picker/p-inline-date-picker.spec.js +21 -45
- package/squirrel/components/p-inline-date-picker/p-inline-date-picker.stories.js +2 -2
- package/squirrel/components/p-inline-date-picker/p-inline-date-picker.vue +16 -85
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import PInlineDatePicker from '@squirrel/components/p-inline-date-picker/p-inline-date-picker.vue';
|
|
2
2
|
import { createWrapperFor } from '@tests/vitest.helpers';
|
|
3
|
-
import { DatePicker } from 'v-calendar';
|
|
4
3
|
|
|
5
4
|
const createWrapper = (props) => {
|
|
6
5
|
return createWrapperFor(PInlineDatePicker, {
|
|
7
6
|
props,
|
|
8
7
|
global: {
|
|
9
8
|
stubs: {
|
|
10
|
-
|
|
11
|
-
name: 'DatePicker',
|
|
12
|
-
template: '<div class="date-picker-stub"></div>',
|
|
13
|
-
props: ['modelValue', 'selectAttribute', 'minDate', 'maxDate', 'masks', 'timezone', 'style'],
|
|
14
|
-
},
|
|
9
|
+
VueDatePicker: true,
|
|
15
10
|
},
|
|
16
11
|
},
|
|
17
12
|
});
|
|
@@ -21,15 +16,13 @@ describe('PInlineDatePicker.vue', () => {
|
|
|
21
16
|
it('renders a datepicker', () => {
|
|
22
17
|
const wrapper = createWrapper();
|
|
23
18
|
|
|
24
|
-
const datePicker = wrapper.findComponent(
|
|
19
|
+
const datePicker = wrapper.findComponent({ name: 'VueDatePicker' });
|
|
25
20
|
|
|
26
21
|
expect(datePicker.props()).toMatchObject({
|
|
27
|
-
modelValue:
|
|
28
|
-
selectAttribute: { highlight: { class: 'bg-primary', contentClass: 'text-white' } },
|
|
22
|
+
modelValue: '',
|
|
29
23
|
minDate: null,
|
|
30
24
|
maxDate: null,
|
|
31
|
-
|
|
32
|
-
timezone: '',
|
|
25
|
+
timezone: null,
|
|
33
26
|
});
|
|
34
27
|
|
|
35
28
|
expect(wrapper.find('label').exists()).toBe(false);
|
|
@@ -44,9 +37,9 @@ describe('PInlineDatePicker.vue', () => {
|
|
|
44
37
|
timezone: 'UTC',
|
|
45
38
|
});
|
|
46
39
|
|
|
47
|
-
const datePicker = wrapper.findComponent(
|
|
40
|
+
const datePicker = wrapper.findComponent({ name: 'VueDatePicker' });
|
|
48
41
|
|
|
49
|
-
expect(datePicker.props().modelValue).
|
|
42
|
+
expect(datePicker.props().modelValue).toBe('2024-05-19');
|
|
50
43
|
expect(datePicker.props().minDate).toEqual(new Date('2024-05-01'));
|
|
51
44
|
expect(datePicker.props().maxDate).toEqual(new Date('2024-05-31'));
|
|
52
45
|
expect(datePicker.props().timezone).toBe('UTC');
|
|
@@ -78,8 +71,9 @@ describe('PInlineDatePicker.vue', () => {
|
|
|
78
71
|
|
|
79
72
|
expect(wrapper.props().required).toBe(true);
|
|
80
73
|
});
|
|
74
|
+
|
|
81
75
|
it('passes listeners to the datepicker', () => {
|
|
82
|
-
// Since
|
|
76
|
+
// Since VueDatePicker emits are not defined on PInlineDatePicker we need to Spy on console.warn and mock the implementation to suppress the warning:
|
|
83
77
|
// [Vue warn]: Component emitted event "update:view" but it is neither declared in the emits option nor as an "onUpdate:view" prop.
|
|
84
78
|
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
85
79
|
|
|
@@ -100,7 +94,7 @@ describe('PInlineDatePicker.vue', () => {
|
|
|
100
94
|
},
|
|
101
95
|
});
|
|
102
96
|
|
|
103
|
-
const datePicker = wrapper.findComponent(
|
|
97
|
+
const datePicker = wrapper.findComponent({ name: 'VueDatePicker' });
|
|
104
98
|
|
|
105
99
|
datePicker.vm.$emit('update:view');
|
|
106
100
|
|
|
@@ -112,12 +106,16 @@ describe('PInlineDatePicker.vue', () => {
|
|
|
112
106
|
it('sets the disabled state correctly', () => {
|
|
113
107
|
const wrapper = createWrapper({ label: 'test datepicker', disabled: true });
|
|
114
108
|
|
|
115
|
-
const
|
|
109
|
+
const datePicker = wrapper.findComponent({ name: 'VueDatePicker' });
|
|
116
110
|
|
|
117
|
-
expect(
|
|
111
|
+
expect(datePicker.props().disabled).toBe(true);
|
|
118
112
|
});
|
|
119
113
|
|
|
120
|
-
it(
|
|
114
|
+
it('updates the value bound with v-model', async () => {
|
|
115
|
+
// Since VueDatePicker emits are not defined on PInlineDatePicker we need to Spy on console.warn and mock the implementation to suppress the warning:
|
|
116
|
+
// [Vue warn]: Component emitted event "update:modelValue" but it is neither declared in the emits option nor as an "onUpdate:view" prop.
|
|
117
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
118
|
+
|
|
121
119
|
const wrapper = createWrapperFor({
|
|
122
120
|
template: `<PInlineDatePicker v-model="dateStrVal" />`,
|
|
123
121
|
components: { PInlineDatePicker },
|
|
@@ -128,25 +126,13 @@ describe('PInlineDatePicker.vue', () => {
|
|
|
128
126
|
},
|
|
129
127
|
});
|
|
130
128
|
|
|
131
|
-
const datePicker = wrapper.findComponent(
|
|
129
|
+
const datePicker = wrapper.findComponent({ name: 'VueDatePicker' });
|
|
132
130
|
|
|
133
|
-
datePicker.vm.$emit('
|
|
131
|
+
datePicker.vm.$emit('update:modelValue', '2024-09-02');
|
|
134
132
|
|
|
135
133
|
expect(wrapper.vm.dateStrVal).toBe('2024-09-02');
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
it(`updates the datepicker value when modelValue is changed`, async () => {
|
|
139
|
-
const wrapper = createWrapper({ modelValue: '2024-09-01' });
|
|
140
|
-
|
|
141
|
-
const datePicker = wrapper.findComponent(DatePicker);
|
|
142
|
-
datePicker.vm.move = vi.fn();
|
|
143
|
-
|
|
144
|
-
expect(datePicker.props().modelValue).toEqual(new Date('2024-09-01'));
|
|
145
|
-
|
|
146
|
-
await wrapper.setProps({ modelValue: '2024-09-02' });
|
|
147
134
|
|
|
148
|
-
|
|
149
|
-
expect(datePicker.props().modelValue).toEqual(new Date('2024-09-02'));
|
|
135
|
+
warnSpy.mockRestore();
|
|
150
136
|
});
|
|
151
137
|
|
|
152
138
|
it('sets the error state correctly', () => {
|
|
@@ -155,20 +141,10 @@ describe('PInlineDatePicker.vue', () => {
|
|
|
155
141
|
errorMsg: 'datepicker has error',
|
|
156
142
|
});
|
|
157
143
|
|
|
158
|
-
expect(wrapper.attributes()['data-has-error']).toBeDefined();
|
|
159
|
-
const datePickerDiv = wrapper.find('.vc-container');
|
|
160
|
-
|
|
161
|
-
expect(datePickerDiv.element.style.border).toBe('1px solid #f0453c');
|
|
162
144
|
const errorDiv = wrapper.find('div.text-xs.text-on-error.mt-1');
|
|
145
|
+
|
|
146
|
+
expect(wrapper.attributes()['data-has-error']).toBeDefined();
|
|
163
147
|
expect(errorDiv.isVisible()).toBe(true);
|
|
164
148
|
expect(errorDiv.text()).toBe('datepicker has error');
|
|
165
149
|
});
|
|
166
|
-
|
|
167
|
-
it('emits null when date is invalid', async () => {
|
|
168
|
-
const wrapper = createWrapper({ label: 'test datepicker', modelValue: 'not a date' });
|
|
169
|
-
|
|
170
|
-
await wrapper.vm.$nextTick();
|
|
171
|
-
|
|
172
|
-
expect(wrapper.emitted()['update:modelValue'][0][0]).toBe(null);
|
|
173
|
-
});
|
|
174
150
|
});
|
|
@@ -22,8 +22,8 @@ export default {
|
|
|
22
22
|
docs: {
|
|
23
23
|
description: {
|
|
24
24
|
component: `Allows users to select a date by choosing a date from the calendar.
|
|
25
|
-
This component uses
|
|
26
|
-
So please take a look also there at their extensive [documentation](https://
|
|
25
|
+
This component uses \`VueDatePicker\` from [@vuepic/vue-datepicker](https://vue3datepicker.com) internally.
|
|
26
|
+
So please take a look also there at their extensive [documentation](https://vue3datepicker.com/).`,
|
|
27
27
|
},
|
|
28
28
|
},
|
|
29
29
|
},
|
|
@@ -5,123 +5,54 @@
|
|
|
5
5
|
{{ label }}
|
|
6
6
|
</label>
|
|
7
7
|
</slot>
|
|
8
|
-
<
|
|
9
|
-
ref="datepickerRef"
|
|
10
|
-
:class="{ 'pointer-events-none opacity-70': $attrs.disabled }"
|
|
11
|
-
:model-value="innerValue"
|
|
12
|
-
:select-attribute="selectAttribute"
|
|
13
|
-
:min-date="minDate || null"
|
|
14
|
-
:max-date="maxDate || null"
|
|
15
|
-
:masks="masks"
|
|
16
|
-
:style="styleDatepicker"
|
|
17
|
-
:timezone="timezone"
|
|
18
|
-
v-bind="listeners"
|
|
19
|
-
@dayclick="dayclick"
|
|
20
|
-
/>
|
|
8
|
+
<VueDatePicker v-model="model" v-bind="datePickerProps" />
|
|
21
9
|
<div v-show="errorMsg" :class="errorMsgClasses">{{ errorMsg }}</div>
|
|
22
10
|
</div>
|
|
23
11
|
</template>
|
|
24
12
|
|
|
25
13
|
<script setup lang="ts">
|
|
26
14
|
import { useInputClasses } from '@squirrel/composables/useInputClasses';
|
|
27
|
-
import
|
|
28
|
-
import {
|
|
29
|
-
import { type AttributeConfig } from 'v-calendar/dist/types/src/utils/attribute.d';
|
|
30
|
-
import { computed, ref, type StyleValue, useAttrs, watch } from 'vue';
|
|
15
|
+
import VueDatePicker, { type VueDatePickerProps } from '@vuepic/vue-datepicker';
|
|
16
|
+
import { computed, type StyleValue, useAttrs } from 'vue';
|
|
31
17
|
|
|
32
18
|
defineOptions({
|
|
33
19
|
name: 'PInlineDatePicker',
|
|
34
20
|
inheritAttrs: false,
|
|
35
21
|
});
|
|
36
22
|
|
|
37
|
-
const selectAttribute: AttributeConfig = {
|
|
38
|
-
highlight: { class: 'bg-primary', contentClass: 'text-white' },
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const DEFAULT_MASKS = {
|
|
42
|
-
// The mask for the input
|
|
43
|
-
input: 'DD-MMM-YYYY',
|
|
44
|
-
// The mask for the model value
|
|
45
|
-
data: 'YYYY-MM-DD',
|
|
46
|
-
};
|
|
47
|
-
|
|
48
23
|
type Props = {
|
|
49
|
-
modelValue?: string | null;
|
|
50
24
|
label?: string;
|
|
51
25
|
errorMsg?: string;
|
|
52
26
|
required?: boolean;
|
|
53
|
-
|
|
54
|
-
maxDate?: Date | null;
|
|
55
|
-
timezone?: string;
|
|
56
|
-
};
|
|
27
|
+
} & VueDatePickerProps;
|
|
57
28
|
|
|
58
29
|
const props = withDefaults(defineProps<Props>(), {
|
|
59
|
-
modelValue: '',
|
|
60
30
|
label: '',
|
|
61
31
|
errorMsg: '',
|
|
62
32
|
required: false,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
33
|
+
inline: true,
|
|
34
|
+
autoApply: true,
|
|
35
|
+
enableTimePicker: false,
|
|
36
|
+
modelType: 'yyyy-MM-dd',
|
|
37
|
+
hideOffsetDates: true,
|
|
38
|
+
weekStart: 0,
|
|
66
39
|
});
|
|
67
40
|
|
|
68
|
-
const
|
|
69
|
-
'update:modelValue': [value: string | null];
|
|
70
|
-
}>();
|
|
41
|
+
const model = defineModel<Date | string | null>({ default: '' });
|
|
71
42
|
|
|
72
43
|
// Data
|
|
73
|
-
const { labelClasses, errorMsgClasses } = useInputClasses(props);
|
|
74
44
|
const attrs = useAttrs();
|
|
75
|
-
|
|
76
|
-
const innerValue = ref<Date | null>(null);
|
|
77
|
-
const datepickerRef = ref<InstanceType<typeof DatePicker> | null>(null);
|
|
45
|
+
const { labelClasses, errorMsgClasses } = useInputClasses(props);
|
|
78
46
|
|
|
79
47
|
// Computed
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
}
|
|
48
|
+
const datePickerProps = computed(() => {
|
|
49
|
+
const { modelValue: _, ...propsWithoutModelValue } = props;
|
|
50
|
+
const { class: classes, style, ...attrsWithoutClassAndStyle } = attrs;
|
|
83
51
|
|
|
84
|
-
|
|
85
|
-
return Object.keys(attrs).reduce((acc, curr) => {
|
|
86
|
-
if (curr.startsWith('on')) {
|
|
87
|
-
return { ...acc, [curr]: attrs[curr] };
|
|
88
|
-
} else {
|
|
89
|
-
return acc;
|
|
90
|
-
}
|
|
91
|
-
}, {});
|
|
52
|
+
return { ...propsWithoutModelValue, ...attrsWithoutClassAndStyle };
|
|
92
53
|
});
|
|
93
54
|
|
|
94
55
|
const style = computed(() => {
|
|
95
56
|
return attrs.style as StyleValue;
|
|
96
57
|
});
|
|
97
|
-
|
|
98
|
-
const styleDatepicker = computed(() => {
|
|
99
|
-
return props.errorMsg ? { border: '1px solid #f0453c' } : {};
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
// Methods
|
|
103
|
-
const dayclick = (e: { id: string }) => {
|
|
104
|
-
emit('update:modelValue', e.id);
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
// Watch
|
|
108
|
-
watch(
|
|
109
|
-
() => props.modelValue,
|
|
110
|
-
async (nV) => {
|
|
111
|
-
const date = dayjs(nV, masks.value.data).toDate();
|
|
112
|
-
|
|
113
|
-
if (nV && date.toString() === 'Invalid Date') {
|
|
114
|
-
emit('update:modelValue', null);
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
innerValue.value = nV ? dayjs(nV, masks.value.data).toDate() : null;
|
|
119
|
-
const datepicker = datepickerRef.value as { move: (val: unknown) => void };
|
|
120
|
-
|
|
121
|
-
if (datepicker && typeof datepicker.move === 'function' && innerValue.value) {
|
|
122
|
-
await datepicker.move(innerValue.value);
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
{ immediate: true }
|
|
126
|
-
);
|
|
127
58
|
</script>
|