@pequity/squirrel 8.3.1 → 8.3.2
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 +69 -18
- package/dist/cjs/p-steps.js +0 -2
- package/dist/es/chunks/p-dropdown-select.js +2 -2
- package/dist/es/index.js +102 -51
- package/dist/es/p-dropdown-select.js +1 -1
- package/dist/es/p-steps.js +1 -4
- package/dist/squirrel/components/index.d.ts +2 -1
- package/dist/squirrel/components/p-steps/p-steps.types.d.ts +5 -0
- package/dist/squirrel/components/p-steps/p-steps.vue.d.ts +14 -15
- package/dist/squirrel.css +74 -74
- package/package.json +5 -5
- package/squirrel/components/index.ts +2 -0
- package/squirrel/components/p-steps/__snapshots__/{p-steps.spec.js.snap → p-steps.spec.ts.snap} +5 -5
- package/squirrel/components/p-steps/p-steps.spec.ts +203 -0
- package/squirrel/components/p-steps/p-steps.stories.js +32 -4
- package/squirrel/components/p-steps/p-steps.types.ts +5 -0
- package/squirrel/components/p-steps/p-steps.vue +30 -21
- package/dist/cjs/chunks/p-steps.js +0 -55
- package/dist/es/chunks/p-steps.js +0 -56
- package/squirrel/components/p-steps/p-steps.spec.js +0 -126
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="flex items-center gap-2">
|
|
3
|
-
<template v-for="(step,
|
|
4
|
-
<div
|
|
5
|
-
|
|
3
|
+
<template v-for="(step, i) in steps" :key="step.value">
|
|
4
|
+
<div
|
|
5
|
+
class="text-nowrap rounded-full border px-4 py-1 text-sm font-semibold"
|
|
6
|
+
:class="[stepClasses(step, i), { 'cursor-pointer': clickable && !step.disabled }]"
|
|
7
|
+
@click="emit('click:step', step, i)"
|
|
8
|
+
>
|
|
9
|
+
{{ step.text || startCase(String(step.value)) }}
|
|
6
10
|
</div>
|
|
7
|
-
<div v-if="
|
|
11
|
+
<div v-if="i < steps.length - 1" class="flex items-center">
|
|
8
12
|
<PIcon
|
|
9
13
|
icon="material-symbols:arrow-right-alt-rounded"
|
|
10
|
-
:class="[
|
|
14
|
+
:class="[activeStepIndex <= i ? 'text-p-gray-30' : 'text-p-blue-50']"
|
|
11
15
|
/>
|
|
12
16
|
</div>
|
|
13
17
|
</template>
|
|
14
18
|
</div>
|
|
15
19
|
</template>
|
|
16
20
|
|
|
17
|
-
<script setup lang="ts"
|
|
21
|
+
<script setup lang="ts">
|
|
18
22
|
import PIcon from '@squirrel/components/p-icon/p-icon.vue';
|
|
23
|
+
import type { StepItem } from '@squirrel/components/p-steps/p-steps.types';
|
|
19
24
|
import { startCase } from 'lodash-es';
|
|
20
25
|
import { computed } from 'vue';
|
|
21
26
|
|
|
@@ -24,28 +29,32 @@ defineOptions({
|
|
|
24
29
|
});
|
|
25
30
|
|
|
26
31
|
type Props = {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
activeStep?: StepItem['value'];
|
|
33
|
+
steps?: readonly StepItem[];
|
|
34
|
+
clickable?: boolean;
|
|
30
35
|
};
|
|
31
36
|
|
|
32
|
-
const props = defineProps<Props>()
|
|
37
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
38
|
+
activeStep: null,
|
|
39
|
+
steps: () => [],
|
|
40
|
+
clickable: false,
|
|
41
|
+
});
|
|
33
42
|
|
|
34
|
-
const
|
|
43
|
+
const emit = defineEmits<{
|
|
44
|
+
'click:step': [step: StepItem, index: number];
|
|
45
|
+
}>();
|
|
35
46
|
|
|
36
|
-
const
|
|
37
|
-
if (step === props.currentStep) {
|
|
38
|
-
return 'border border-p-blue-50 bg-p-blue-50 text-surface';
|
|
39
|
-
}
|
|
47
|
+
const activeStepIndex = computed(() => props.steps.findIndex((s) => s.value === props.activeStep));
|
|
40
48
|
|
|
41
|
-
|
|
42
|
-
|
|
49
|
+
const stepClasses = (step: StepItem, stepIndex: number) => {
|
|
50
|
+
if (step.value === props.activeStep) {
|
|
51
|
+
return 'border-p-blue-50 bg-p-blue-50 text-surface';
|
|
43
52
|
}
|
|
44
53
|
|
|
45
|
-
|
|
46
|
-
|
|
54
|
+
if (activeStepIndex.value < stepIndex) {
|
|
55
|
+
return 'border-p-gray-30 text-p-gray-30';
|
|
56
|
+
}
|
|
47
57
|
|
|
48
|
-
|
|
49
|
-
return props.stepTitleMap?.[step] || startCase(step);
|
|
58
|
+
return 'border-p-blue-50 text-p-blue-50';
|
|
50
59
|
};
|
|
51
60
|
</script>
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
const vue = require("vue");
|
|
3
|
-
const pIcon_vue_vue_type_script_setup_true_lang = require("./p-icon.js");
|
|
4
|
-
const lodashEs = require("lodash-es");
|
|
5
|
-
const _hoisted_1 = { class: "flex items-center gap-2" };
|
|
6
|
-
const _hoisted_2 = {
|
|
7
|
-
key: 0,
|
|
8
|
-
class: "flex items-center"
|
|
9
|
-
};
|
|
10
|
-
const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
11
|
-
...{
|
|
12
|
-
name: "PSteps"
|
|
13
|
-
},
|
|
14
|
-
__name: "p-steps",
|
|
15
|
-
props: {
|
|
16
|
-
steps: {},
|
|
17
|
-
currentStep: {},
|
|
18
|
-
stepTitleMap: {}
|
|
19
|
-
},
|
|
20
|
-
setup(__props) {
|
|
21
|
-
const props = __props;
|
|
22
|
-
const currentStepIndex = vue.computed(() => props.steps.findIndex((s) => s === props.currentStep));
|
|
23
|
-
const stepClasses = (step, stepIndex) => {
|
|
24
|
-
if (step === props.currentStep) {
|
|
25
|
-
return "border border-p-blue-50 bg-p-blue-50 text-surface";
|
|
26
|
-
}
|
|
27
|
-
if (currentStepIndex.value < stepIndex) {
|
|
28
|
-
return "border border-p-gray-30 text-p-gray-30";
|
|
29
|
-
}
|
|
30
|
-
return "border border-p-blue-50 text-p-blue-50";
|
|
31
|
-
};
|
|
32
|
-
const stepTitle = (step) => {
|
|
33
|
-
var _a;
|
|
34
|
-
return ((_a = props.stepTitleMap) == null ? void 0 : _a[step]) || lodashEs.startCase(step);
|
|
35
|
-
};
|
|
36
|
-
return (_ctx, _cache) => {
|
|
37
|
-
return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
|
|
38
|
-
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(_ctx.steps, (step, idx) => {
|
|
39
|
-
return vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: step }, [
|
|
40
|
-
vue.createElementVNode("div", {
|
|
41
|
-
class: vue.normalizeClass(["text-nowrap rounded-full border px-4 py-1 text-sm font-semibold", stepClasses(step, idx)])
|
|
42
|
-
}, vue.toDisplayString(stepTitle(step)), 3),
|
|
43
|
-
idx < _ctx.steps.length - 1 ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2, [
|
|
44
|
-
vue.createVNode(pIcon_vue_vue_type_script_setup_true_lang._sfc_main, {
|
|
45
|
-
icon: "material-symbols:arrow-right-alt-rounded",
|
|
46
|
-
class: vue.normalizeClass([currentStepIndex.value <= idx ? "text-p-gray-30" : "text-p-blue-50"])
|
|
47
|
-
}, null, 8, ["class"])
|
|
48
|
-
])) : vue.createCommentVNode("", true)
|
|
49
|
-
], 64);
|
|
50
|
-
}), 128))
|
|
51
|
-
]);
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
exports._sfc_main = _sfc_main;
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { defineComponent, computed, createElementBlock, openBlock, Fragment, renderList, createElementVNode, createCommentVNode, normalizeClass, toDisplayString, createVNode } from "vue";
|
|
2
|
-
import { _ as _sfc_main$1 } from "./p-icon.js";
|
|
3
|
-
import { startCase } from "lodash-es";
|
|
4
|
-
const _hoisted_1 = { class: "flex items-center gap-2" };
|
|
5
|
-
const _hoisted_2 = {
|
|
6
|
-
key: 0,
|
|
7
|
-
class: "flex items-center"
|
|
8
|
-
};
|
|
9
|
-
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
10
|
-
...{
|
|
11
|
-
name: "PSteps"
|
|
12
|
-
},
|
|
13
|
-
__name: "p-steps",
|
|
14
|
-
props: {
|
|
15
|
-
steps: {},
|
|
16
|
-
currentStep: {},
|
|
17
|
-
stepTitleMap: {}
|
|
18
|
-
},
|
|
19
|
-
setup(__props) {
|
|
20
|
-
const props = __props;
|
|
21
|
-
const currentStepIndex = computed(() => props.steps.findIndex((s) => s === props.currentStep));
|
|
22
|
-
const stepClasses = (step, stepIndex) => {
|
|
23
|
-
if (step === props.currentStep) {
|
|
24
|
-
return "border border-p-blue-50 bg-p-blue-50 text-surface";
|
|
25
|
-
}
|
|
26
|
-
if (currentStepIndex.value < stepIndex) {
|
|
27
|
-
return "border border-p-gray-30 text-p-gray-30";
|
|
28
|
-
}
|
|
29
|
-
return "border border-p-blue-50 text-p-blue-50";
|
|
30
|
-
};
|
|
31
|
-
const stepTitle = (step) => {
|
|
32
|
-
var _a;
|
|
33
|
-
return ((_a = props.stepTitleMap) == null ? void 0 : _a[step]) || startCase(step);
|
|
34
|
-
};
|
|
35
|
-
return (_ctx, _cache) => {
|
|
36
|
-
return openBlock(), createElementBlock("div", _hoisted_1, [
|
|
37
|
-
(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.steps, (step, idx) => {
|
|
38
|
-
return openBlock(), createElementBlock(Fragment, { key: step }, [
|
|
39
|
-
createElementVNode("div", {
|
|
40
|
-
class: normalizeClass(["text-nowrap rounded-full border px-4 py-1 text-sm font-semibold", stepClasses(step, idx)])
|
|
41
|
-
}, toDisplayString(stepTitle(step)), 3),
|
|
42
|
-
idx < _ctx.steps.length - 1 ? (openBlock(), createElementBlock("div", _hoisted_2, [
|
|
43
|
-
createVNode(_sfc_main$1, {
|
|
44
|
-
icon: "material-symbols:arrow-right-alt-rounded",
|
|
45
|
-
class: normalizeClass([currentStepIndex.value <= idx ? "text-p-gray-30" : "text-p-blue-50"])
|
|
46
|
-
}, null, 8, ["class"])
|
|
47
|
-
])) : createCommentVNode("", true)
|
|
48
|
-
], 64);
|
|
49
|
-
}), 128))
|
|
50
|
-
]);
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
export {
|
|
55
|
-
_sfc_main as _
|
|
56
|
-
};
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import PSteps from '@squirrel/components/p-steps/p-steps.vue';
|
|
2
|
-
import { createWrapperFor } from '@tests/vitest.helpers';
|
|
3
|
-
|
|
4
|
-
describe('PSteps.vue', () => {
|
|
5
|
-
it('renders correctly', () => {
|
|
6
|
-
const wrapper = createWrapperFor(PSteps, {
|
|
7
|
-
props: {
|
|
8
|
-
steps: ['first', 'second', 'third'],
|
|
9
|
-
currentStep: 'second',
|
|
10
|
-
stepTitleMap: {},
|
|
11
|
-
},
|
|
12
|
-
});
|
|
13
|
-
expect(wrapper.html()).toMatchSnapshot();
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('renders the correct number of steps', () => {
|
|
17
|
-
const steps = ['first', 'second', 'third'];
|
|
18
|
-
const wrapper = createWrapperFor(PSteps, {
|
|
19
|
-
props: {
|
|
20
|
-
steps,
|
|
21
|
-
currentStep: 'second',
|
|
22
|
-
stepTitleMap: {},
|
|
23
|
-
},
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
const stepElements = wrapper.findAll('.rounded-full.border');
|
|
27
|
-
expect(stepElements.length).toBe(steps.length);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('applies correct classes for current step', () => {
|
|
31
|
-
const wrapper = createWrapperFor(PSteps, {
|
|
32
|
-
props: {
|
|
33
|
-
steps: ['first', 'second', 'third'],
|
|
34
|
-
currentStep: 'second',
|
|
35
|
-
stepTitleMap: {},
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
const stepElements = wrapper.findAll('.rounded-full.border');
|
|
40
|
-
|
|
41
|
-
// First step should be completed (blue text)
|
|
42
|
-
expect(stepElements[0].classes()).toContain('text-nowrap');
|
|
43
|
-
expect(stepElements[0].classes()).toContain('text-p-blue-50');
|
|
44
|
-
expect(stepElements[0].classes()).toContain('border-p-blue-50');
|
|
45
|
-
|
|
46
|
-
// Second step should be current (blue background)
|
|
47
|
-
expect(stepElements[1].classes()).toContain('text-nowrap');
|
|
48
|
-
expect(stepElements[1].classes()).toContain('bg-p-blue-50');
|
|
49
|
-
expect(stepElements[1].classes()).toContain('text-surface');
|
|
50
|
-
expect(stepElements[1].classes()).toContain('border-p-blue-50');
|
|
51
|
-
|
|
52
|
-
// Third step should be upcoming (gray)
|
|
53
|
-
expect(stepElements[2].classes()).toContain('text-nowrap');
|
|
54
|
-
expect(stepElements[2].classes()).toContain('text-p-gray-30');
|
|
55
|
-
expect(stepElements[2].classes()).toContain('border-p-gray-30');
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('displays step titles from stepTitleMap when provided', () => {
|
|
59
|
-
const wrapper = createWrapperFor(PSteps, {
|
|
60
|
-
props: {
|
|
61
|
-
steps: ['step1', 'step2', 'step3'],
|
|
62
|
-
currentStep: 'step2',
|
|
63
|
-
stepTitleMap: {
|
|
64
|
-
step1: 'Custom Step 1',
|
|
65
|
-
step2: 'Custom Step 2',
|
|
66
|
-
step3: 'Custom Step 3',
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
const stepElements = wrapper.findAll('.rounded-full.border');
|
|
72
|
-
expect(stepElements[0].text()).toBe('Custom Step 1');
|
|
73
|
-
expect(stepElements[1].text()).toBe('Custom Step 2');
|
|
74
|
-
expect(stepElements[2].text()).toBe('Custom Step 3');
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('uses startCase for step titles when stepTitleMap entry is not provided', () => {
|
|
78
|
-
const wrapper = createWrapperFor(PSteps, {
|
|
79
|
-
props: {
|
|
80
|
-
steps: ['firstStep', 'secondStep', 'thirdStep'],
|
|
81
|
-
currentStep: 'secondStep',
|
|
82
|
-
stepTitleMap: {
|
|
83
|
-
secondStep: 'Custom Second',
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
const stepElements = wrapper.findAll('.rounded-full.border');
|
|
89
|
-
expect(stepElements[0].text()).toBe('First Step'); // startCase applied
|
|
90
|
-
expect(stepElements[1].text()).toBe('Custom Second'); // from map
|
|
91
|
-
expect(stepElements[2].text()).toBe('Third Step'); // startCase applied
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it('renders the correct number of arrows between steps', () => {
|
|
95
|
-
const wrapper = createWrapperFor(PSteps, {
|
|
96
|
-
props: {
|
|
97
|
-
steps: ['first', 'second', 'third', 'fourth'],
|
|
98
|
-
currentStep: 'second',
|
|
99
|
-
stepTitleMap: {},
|
|
100
|
-
},
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
// There should be 3 arrows for 4 steps
|
|
104
|
-
const arrowElements = wrapper.findAll('[icon="material-symbols:arrow-right-alt-rounded"]');
|
|
105
|
-
expect(arrowElements.length).toBe(3);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it('applies the correct classes to arrows based on current step', () => {
|
|
109
|
-
const wrapper = createWrapperFor(PSteps, {
|
|
110
|
-
props: {
|
|
111
|
-
steps: ['first', 'second', 'third', 'fourth'],
|
|
112
|
-
currentStep: 'second',
|
|
113
|
-
stepTitleMap: {},
|
|
114
|
-
},
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
const arrowElements = wrapper.findAll('[icon="material-symbols:arrow-right-alt-rounded"]');
|
|
118
|
-
|
|
119
|
-
// Arrow between first and second step should be colored
|
|
120
|
-
expect(arrowElements[0].classes()).toContain('text-p-blue-50');
|
|
121
|
-
|
|
122
|
-
// Arrow after current step should be gray
|
|
123
|
-
expect(arrowElements[1].classes()).toContain('text-p-gray-30');
|
|
124
|
-
expect(arrowElements[2].classes()).toContain('text-p-gray-30');
|
|
125
|
-
});
|
|
126
|
-
});
|