@pequity/squirrel 8.3.3 → 8.3.5
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/dist/cjs/index.js +6 -5
- package/dist/cjs/p-checkbox.js +10 -3
- package/dist/es/index.js +6 -5
- package/dist/es/p-checkbox.js +10 -3
- package/dist/squirrel.css +1 -1
- package/package.json +4 -4
- package/squirrel/components/p-checkbox/p-checkbox.spec.js +16 -1
- package/squirrel/components/p-checkbox/p-checkbox.vue +14 -2
- package/squirrel/components/p-file-upload/p-file-upload.spec.js +61 -4
- package/squirrel/components/p-file-upload/p-file-upload.vue +5 -1
package/dist/cjs/index.js
CHANGED
|
@@ -166,7 +166,9 @@ const _sfc_main$4 = /* @__PURE__ */ vue.defineComponent({
|
|
|
166
166
|
const file = filesToUpload[i];
|
|
167
167
|
const fileName = file.name || file.url;
|
|
168
168
|
if (res.length + files.value.length >= props.maxNumberOfFiles) {
|
|
169
|
-
|
|
169
|
+
if (!(props.multiple && props.maxNumberOfFiles === 1)) {
|
|
170
|
+
toast.error(`You can only upload a maximum of ${props.maxNumberOfFiles} ${fileWord.value}.`);
|
|
171
|
+
}
|
|
170
172
|
break;
|
|
171
173
|
}
|
|
172
174
|
if (!fileName) {
|
|
@@ -870,7 +872,7 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
|
|
|
870
872
|
ref: (el) => updateThsRefs(el, i),
|
|
871
873
|
key: col.id,
|
|
872
874
|
"data-col-id": col.id
|
|
873
|
-
}, col.thAttrs, {
|
|
875
|
+
}, { ref_for: true }, col.thAttrs, {
|
|
874
876
|
style: col.style,
|
|
875
877
|
class: "bg-surface"
|
|
876
878
|
}), [
|
|
@@ -886,9 +888,8 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
|
|
|
886
888
|
"show-filter-icon": col.filterable || col.sortable,
|
|
887
889
|
"tooltip-text": col.tooltip,
|
|
888
890
|
class: [{ "pl-2": i === 1 && _ctx.isFirstColFixed, "pr-2": i === _ctx.cols.length && _ctx.isLastColFixed }, "grow"],
|
|
889
|
-
"text-color": headerCellTextColor(col)
|
|
890
|
-
|
|
891
|
-
}, col.headerCellAttrs, {
|
|
891
|
+
"text-color": headerCellTextColor(col)
|
|
892
|
+
}, { ref_for: true }, col.headerCellAttrs, {
|
|
892
893
|
onClickFilterIcon: ($event) => _ctx.$emit("click-filter-icon", $event, col)
|
|
893
894
|
}), null, 16, ["text", "filter-active", "show-filter-icon", "tooltip-text", "class", "text-color", "onClickFilterIcon"])
|
|
894
895
|
]),
|
package/dist/cjs/p-checkbox.js
CHANGED
|
@@ -32,15 +32,22 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
|
32
32
|
const style = vue.computed(() => {
|
|
33
33
|
return allAttrs.style;
|
|
34
34
|
});
|
|
35
|
+
const isDisabled = vue.computed(() => {
|
|
36
|
+
return "disabled" in allAttrs && allAttrs.disabled !== false;
|
|
37
|
+
});
|
|
35
38
|
return (_ctx, _cache) => {
|
|
36
39
|
return vue.openBlock(), vue.createElementBlock("label", {
|
|
37
|
-
class: vue.normalizeClass(["inline-flex items-center", [
|
|
40
|
+
class: vue.normalizeClass(["inline-flex items-center", [
|
|
41
|
+
{ hidden: _ctx.$attrs.hidden },
|
|
42
|
+
_ctx.$attrs.class,
|
|
43
|
+
{ "cursor-not-allowed opacity-50": isDisabled.value, "cursor-pointer": !isDisabled.value }
|
|
44
|
+
]]),
|
|
38
45
|
style: vue.normalizeStyle(style.value)
|
|
39
46
|
}, [
|
|
40
47
|
vue.renderSlot(_ctx.$slots, "label-before", {}, void 0, true),
|
|
41
48
|
vue.createElementVNode("input", vue.mergeProps({
|
|
42
49
|
type: "checkbox",
|
|
43
|
-
class: "h-4 w-4 shrink-0 appearance-none rounded border border-p-gray-30 bg-surface duration-100 ease-in-out checked:border-none checked:bg-primary
|
|
50
|
+
class: "h-4 w-4 shrink-0 appearance-none rounded border border-p-gray-30 bg-surface duration-100 ease-in-out checked:border-none checked:bg-primary"
|
|
44
51
|
}, attrs.value, {
|
|
45
52
|
checked: __props.modelValue,
|
|
46
53
|
onChange: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("update:modelValue", $event.target.checked))
|
|
@@ -52,5 +59,5 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
|
52
59
|
};
|
|
53
60
|
}
|
|
54
61
|
});
|
|
55
|
-
const pCheckbox = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
62
|
+
const pCheckbox = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main, [["__scopeId", "data-v-b394a2f0"]]);
|
|
56
63
|
module.exports = pCheckbox;
|
package/dist/es/index.js
CHANGED
|
@@ -166,7 +166,9 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|
|
166
166
|
const file = filesToUpload[i2];
|
|
167
167
|
const fileName = file.name || file.url;
|
|
168
168
|
if (res.length + files.value.length >= props.maxNumberOfFiles) {
|
|
169
|
-
|
|
169
|
+
if (!(props.multiple && props.maxNumberOfFiles === 1)) {
|
|
170
|
+
toast.error(`You can only upload a maximum of ${props.maxNumberOfFiles} ${fileWord.value}.`);
|
|
171
|
+
}
|
|
170
172
|
break;
|
|
171
173
|
}
|
|
172
174
|
if (!fileName) {
|
|
@@ -870,7 +872,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
|
870
872
|
ref: (el) => updateThsRefs(el, i2),
|
|
871
873
|
key: col.id,
|
|
872
874
|
"data-col-id": col.id
|
|
873
|
-
}, col.thAttrs, {
|
|
875
|
+
}, { ref_for: true }, col.thAttrs, {
|
|
874
876
|
style: col.style,
|
|
875
877
|
class: "bg-surface"
|
|
876
878
|
}), [
|
|
@@ -886,9 +888,8 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
|
886
888
|
"show-filter-icon": col.filterable || col.sortable,
|
|
887
889
|
"tooltip-text": col.tooltip,
|
|
888
890
|
class: [{ "pl-2": i2 === 1 && _ctx.isFirstColFixed, "pr-2": i2 === _ctx.cols.length && _ctx.isLastColFixed }, "grow"],
|
|
889
|
-
"text-color": headerCellTextColor(col)
|
|
890
|
-
|
|
891
|
-
}, col.headerCellAttrs, {
|
|
891
|
+
"text-color": headerCellTextColor(col)
|
|
892
|
+
}, { ref_for: true }, col.headerCellAttrs, {
|
|
892
893
|
onClickFilterIcon: ($event) => _ctx.$emit("click-filter-icon", $event, col)
|
|
893
894
|
}), null, 16, ["text", "filter-active", "show-filter-icon", "tooltip-text", "class", "text-color", "onClickFilterIcon"])
|
|
894
895
|
]),
|
package/dist/es/p-checkbox.js
CHANGED
|
@@ -31,15 +31,22 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
31
31
|
const style = computed(() => {
|
|
32
32
|
return allAttrs.style;
|
|
33
33
|
});
|
|
34
|
+
const isDisabled = computed(() => {
|
|
35
|
+
return "disabled" in allAttrs && allAttrs.disabled !== false;
|
|
36
|
+
});
|
|
34
37
|
return (_ctx, _cache) => {
|
|
35
38
|
return openBlock(), createElementBlock("label", {
|
|
36
|
-
class: normalizeClass(["inline-flex items-center", [
|
|
39
|
+
class: normalizeClass(["inline-flex items-center", [
|
|
40
|
+
{ hidden: _ctx.$attrs.hidden },
|
|
41
|
+
_ctx.$attrs.class,
|
|
42
|
+
{ "cursor-not-allowed opacity-50": isDisabled.value, "cursor-pointer": !isDisabled.value }
|
|
43
|
+
]]),
|
|
37
44
|
style: normalizeStyle(style.value)
|
|
38
45
|
}, [
|
|
39
46
|
renderSlot(_ctx.$slots, "label-before", {}, void 0, true),
|
|
40
47
|
createElementVNode("input", mergeProps({
|
|
41
48
|
type: "checkbox",
|
|
42
|
-
class: "h-4 w-4 shrink-0 appearance-none rounded border border-p-gray-30 bg-surface duration-100 ease-in-out checked:border-none checked:bg-primary
|
|
49
|
+
class: "h-4 w-4 shrink-0 appearance-none rounded border border-p-gray-30 bg-surface duration-100 ease-in-out checked:border-none checked:bg-primary"
|
|
43
50
|
}, attrs.value, {
|
|
44
51
|
checked: __props.modelValue,
|
|
45
52
|
onChange: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("update:modelValue", $event.target.checked))
|
|
@@ -51,7 +58,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
51
58
|
};
|
|
52
59
|
}
|
|
53
60
|
});
|
|
54
|
-
const pCheckbox = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
61
|
+
const pCheckbox = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-b394a2f0"]]);
|
|
55
62
|
export {
|
|
56
63
|
pCheckbox as default
|
|
57
64
|
};
|
package/dist/squirrel.css
CHANGED
|
@@ -191,7 +191,7 @@ div[id^=popper_].dropdown .v-popper__inner .dropdown-menu .dropdown-divider {
|
|
|
191
191
|
--tw-content: "";
|
|
192
192
|
content: var(--tw-content);
|
|
193
193
|
}
|
|
194
|
-
input[type='checkbox'][data-v-
|
|
194
|
+
input[type='checkbox'][data-v-b394a2f0]:checked {
|
|
195
195
|
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3E%3C/svg%3E");
|
|
196
196
|
}
|
|
197
197
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pequity/squirrel",
|
|
3
3
|
"description": "Squirrel component library",
|
|
4
|
-
"version": "8.3.
|
|
4
|
+
"version": "8.3.5",
|
|
5
5
|
"packageManager": "pnpm@10.6.4",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"@types/node": "^22.15.21",
|
|
72
72
|
"@vitejs/plugin-vue": "^5.2.4",
|
|
73
73
|
"@vitest/coverage-v8": "^3.1.4",
|
|
74
|
-
"@vue/compiler-sfc": "3.5.
|
|
74
|
+
"@vue/compiler-sfc": "3.5.15",
|
|
75
75
|
"@vue/test-utils": "^2.4.6",
|
|
76
76
|
"@vuepic/vue-datepicker": "11.0.2",
|
|
77
77
|
"autoprefixer": "^10.4.21",
|
|
@@ -91,14 +91,14 @@
|
|
|
91
91
|
"resolve-tspaths": "^0.8.23",
|
|
92
92
|
"rimraf": "^6.0.1",
|
|
93
93
|
"sass": "^1.89.0",
|
|
94
|
-
"semantic-release": "^24.2.
|
|
94
|
+
"semantic-release": "^24.2.5",
|
|
95
95
|
"storybook": "^8.6.14",
|
|
96
96
|
"svgo": "^3.3.2",
|
|
97
97
|
"tailwindcss": "^3.4.17",
|
|
98
98
|
"typescript": "5.8.3",
|
|
99
99
|
"vite": "^6.3.5",
|
|
100
100
|
"vitest": "^3.1.4",
|
|
101
|
-
"vue": "3.5.
|
|
101
|
+
"vue": "3.5.15",
|
|
102
102
|
"vue-currency-input": "3.2.1",
|
|
103
103
|
"vue-router": "4.5.1",
|
|
104
104
|
"vue-toastification": "2.0.0-rc.5",
|
|
@@ -14,7 +14,6 @@ const checkboxClasses = [
|
|
|
14
14
|
'ease-in-out',
|
|
15
15
|
'checked:border-none',
|
|
16
16
|
'checked:bg-primary',
|
|
17
|
-
'disabled:opacity-50',
|
|
18
17
|
];
|
|
19
18
|
|
|
20
19
|
describe('PCheckbox.vue', () => {
|
|
@@ -39,4 +38,20 @@ describe('PCheckbox.vue', () => {
|
|
|
39
38
|
expect(input.classes()).toEqual(checkboxClasses);
|
|
40
39
|
expect(input.attributes().disabled).toBeDefined();
|
|
41
40
|
});
|
|
41
|
+
|
|
42
|
+
it('applies correct styling to label based on disabled state', async () => {
|
|
43
|
+
const enabledWrapper = createWrapperFor(PCheckbox, { props: { checked: true } });
|
|
44
|
+
const disabledWrapper = createWrapperFor(PCheckbox, { props: { checked: true, disabled: true } });
|
|
45
|
+
|
|
46
|
+
const enabledLabel = await enabledWrapper.find('label');
|
|
47
|
+
const disabledLabel = await disabledWrapper.find('label');
|
|
48
|
+
|
|
49
|
+
expect(enabledLabel.classes()).toContain('cursor-pointer');
|
|
50
|
+
expect(enabledLabel.classes()).not.toContain('cursor-not-allowed');
|
|
51
|
+
expect(enabledLabel.classes()).not.toContain('opacity-50');
|
|
52
|
+
|
|
53
|
+
expect(disabledLabel.classes()).toContain('cursor-not-allowed');
|
|
54
|
+
expect(disabledLabel.classes()).toContain('opacity-50');
|
|
55
|
+
expect(disabledLabel.classes()).not.toContain('cursor-pointer');
|
|
56
|
+
});
|
|
42
57
|
});
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<label
|
|
2
|
+
<label
|
|
3
|
+
class="inline-flex items-center"
|
|
4
|
+
:class="[
|
|
5
|
+
{ hidden: $attrs.hidden },
|
|
6
|
+
$attrs.class,
|
|
7
|
+
{ 'cursor-not-allowed opacity-50': isDisabled, 'cursor-pointer': !isDisabled },
|
|
8
|
+
]"
|
|
9
|
+
:style="style"
|
|
10
|
+
>
|
|
3
11
|
<slot name="label-before"></slot>
|
|
4
12
|
<input
|
|
5
13
|
type="checkbox"
|
|
6
|
-
class="h-4 w-4 shrink-0 appearance-none rounded border border-p-gray-30 bg-surface duration-100 ease-in-out checked:border-none checked:bg-primary
|
|
14
|
+
class="h-4 w-4 shrink-0 appearance-none rounded border border-p-gray-30 bg-surface duration-100 ease-in-out checked:border-none checked:bg-primary"
|
|
7
15
|
v-bind="attrs"
|
|
8
16
|
:checked="modelValue"
|
|
9
17
|
@change="$emit('update:modelValue', ($event.target as HTMLInputElement).checked)"
|
|
@@ -48,6 +56,10 @@ const attrs = computed(() => {
|
|
|
48
56
|
const style = computed(() => {
|
|
49
57
|
return allAttrs.style as StyleValue;
|
|
50
58
|
});
|
|
59
|
+
|
|
60
|
+
const isDisabled = computed(() => {
|
|
61
|
+
return 'disabled' in allAttrs && allAttrs.disabled !== false;
|
|
62
|
+
});
|
|
51
63
|
</script>
|
|
52
64
|
|
|
53
65
|
<style lang="css" scoped>
|
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
import PFileUpload from '@squirrel/components/p-file-upload/p-file-upload.vue';
|
|
2
|
+
import { expect } from '@storybook/test';
|
|
2
3
|
import { createWrapperFor } from '@tests/vitest.helpers';
|
|
4
|
+
import { vi } from 'vitest';
|
|
5
|
+
|
|
6
|
+
// Mocking the toastification library
|
|
7
|
+
const toastError = vi.fn();
|
|
8
|
+
|
|
9
|
+
vi.mock('vue-toastification', () => {
|
|
10
|
+
return {
|
|
11
|
+
useToast: () => {
|
|
12
|
+
return {
|
|
13
|
+
error: toastError,
|
|
14
|
+
};
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
});
|
|
3
18
|
|
|
4
|
-
const createFile = () => {
|
|
5
|
-
const file = new File([
|
|
19
|
+
const createFile = (fileName = 'filename') => {
|
|
20
|
+
const file = new File([fileName], `${fileName}.txt`, {
|
|
6
21
|
type: 'text/plain',
|
|
7
|
-
name:
|
|
8
|
-
url:
|
|
22
|
+
name: `${fileName}.txt`,
|
|
23
|
+
url: `https://www.pequity.com/${fileName}.txt`,
|
|
9
24
|
});
|
|
10
25
|
|
|
11
26
|
return file;
|
|
@@ -131,4 +146,46 @@ describe('PFileUpload.vue', () => {
|
|
|
131
146
|
|
|
132
147
|
expect(wrapper.findAll('div.truncate').length).toBe(3);
|
|
133
148
|
});
|
|
149
|
+
|
|
150
|
+
it('shows a toast when maxNumberOfFiles is exceeded', async () => {
|
|
151
|
+
const file1 = createFile('file1');
|
|
152
|
+
const file2 = createFile('file2');
|
|
153
|
+
|
|
154
|
+
const wrapper = createWrapperFor({
|
|
155
|
+
components: { PFileUpload },
|
|
156
|
+
data() {
|
|
157
|
+
return {
|
|
158
|
+
files: [file1, file2],
|
|
159
|
+
};
|
|
160
|
+
},
|
|
161
|
+
template: `
|
|
162
|
+
<PFileUpload v-model="files" :multiple="true" :max-number-of-files="2" />
|
|
163
|
+
`,
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
expect(wrapper.find('div[title="file1.txt"]').exists()).toBe(true);
|
|
167
|
+
expect(wrapper.find('div[title="file2.txt"]').exists()).toBe(true);
|
|
168
|
+
|
|
169
|
+
expect(toastError).toHaveBeenCalledWith('You can only upload a maximum of 2 files.');
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('does not show a toast when multiple is true and maxNumberOfFiles is 1', async () => {
|
|
173
|
+
const file1 = createFile('file1');
|
|
174
|
+
|
|
175
|
+
const wrapper = createWrapperFor({
|
|
176
|
+
components: { PFileUpload },
|
|
177
|
+
data() {
|
|
178
|
+
return {
|
|
179
|
+
files: [file1],
|
|
180
|
+
};
|
|
181
|
+
},
|
|
182
|
+
template: `
|
|
183
|
+
<PFileUpload v-model="files" :multiple="true" :max-number-of-files="1" />
|
|
184
|
+
`,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
expect(wrapper.find('div[title="file1.txt"]').exists()).toBe(true);
|
|
188
|
+
|
|
189
|
+
expect(toastError).not.toHaveBeenCalled();
|
|
190
|
+
});
|
|
134
191
|
});
|
|
@@ -166,7 +166,11 @@ const validateFiles = (filesToUpload: FileUploadFile[]) => {
|
|
|
166
166
|
|
|
167
167
|
// Bail if we reached the max number of files
|
|
168
168
|
if (res.length + files.value.length >= props.maxNumberOfFiles) {
|
|
169
|
-
toast
|
|
169
|
+
// Show a toast - except for the contradictory config (multiple: true with maxNumberOfFiles: 1)
|
|
170
|
+
if (!(props.multiple && props.maxNumberOfFiles === 1)) {
|
|
171
|
+
toast.error(`You can only upload a maximum of ${props.maxNumberOfFiles} ${fileWord.value}.`);
|
|
172
|
+
}
|
|
173
|
+
|
|
170
174
|
break;
|
|
171
175
|
}
|
|
172
176
|
|