@pequity/squirrel 8.4.3 → 8.4.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/README.md +2 -1
- package/dist/cjs/chunks/p-alert.js +3 -0
- package/dist/cjs/chunks/p-avatar.js +16 -0
- package/dist/cjs/chunks/p-btn.js +3 -0
- package/dist/cjs/chunks/p-card.js +4 -0
- package/dist/cjs/chunks/p-dropdown-select.js +34 -0
- package/dist/cjs/chunks/p-input-number.js +32 -0
- package/dist/cjs/chunks/p-input-percent.js +13 -2
- package/dist/cjs/chunks/p-input.js +28 -0
- package/dist/cjs/chunks/p-pagination-info.js +9 -5
- package/dist/cjs/chunks/p-pagination.js +23 -13
- package/dist/cjs/chunks/p-select-btn.js +2 -1
- package/dist/cjs/chunks/p-select.js +33 -0
- package/dist/cjs/chunks/p-table-loader.js +20 -0
- package/dist/cjs/chunks/p-tabs.js +12 -0
- package/dist/cjs/chunks/p-textarea.js +20 -0
- package/dist/cjs/index.js +40 -3
- package/dist/cjs/p-checkbox.js +8 -1
- package/dist/cjs/p-chips.js +17 -1
- package/dist/cjs/p-close-btn.js +6 -1
- package/dist/cjs/p-drawer.js +90 -2
- package/dist/cjs/p-dropdown.js +2 -1
- package/dist/cjs/p-icon.js +3 -2
- package/dist/cjs/p-input-search.js +13 -1
- package/dist/cjs/p-loading.js +1 -1
- package/dist/cjs/p-modal.js +82 -2
- package/dist/cjs/p-select-pill.js +36 -2
- package/dist/cjs/p-skeleton-loader.js +17 -1
- package/dist/cjs/p-table-filter-icon.js +4 -1
- package/dist/cjs/p-table-header-cell.js +29 -0
- package/dist/cjs/p-table-td.js +1 -1
- package/dist/cjs/p-toggle.js +22 -1
- package/dist/es/chunks/p-alert.js +3 -0
- package/dist/es/chunks/p-avatar.js +16 -0
- package/dist/es/chunks/p-btn.js +3 -0
- package/dist/es/chunks/p-card.js +4 -0
- package/dist/es/chunks/p-dropdown-select.js +34 -0
- package/dist/es/chunks/p-input-number.js +32 -0
- package/dist/es/chunks/p-input-percent.js +13 -2
- package/dist/es/chunks/p-input.js +28 -0
- package/dist/es/chunks/p-pagination-info.js +9 -5
- package/dist/es/chunks/p-pagination.js +24 -14
- package/dist/es/chunks/p-select-btn.js +2 -1
- package/dist/es/chunks/p-select.js +33 -0
- package/dist/es/chunks/p-table-loader.js +20 -0
- package/dist/es/chunks/p-tabs.js +12 -0
- package/dist/es/chunks/p-textarea.js +20 -0
- package/dist/es/index.js +40 -3
- package/dist/es/p-checkbox.js +8 -1
- package/dist/es/p-chips.js +17 -1
- package/dist/es/p-close-btn.js +6 -1
- package/dist/es/p-drawer.js +90 -2
- package/dist/es/p-dropdown.js +2 -1
- package/dist/es/p-icon.js +3 -2
- package/dist/es/p-input-search.js +13 -1
- package/dist/es/p-loading.js +1 -1
- package/dist/es/p-modal.js +82 -2
- package/dist/es/p-select-pill.js +36 -2
- package/dist/es/p-skeleton-loader.js +17 -1
- package/dist/es/p-table-filter-icon.js +4 -1
- package/dist/es/p-table-header-cell.js +29 -0
- package/dist/es/p-table-td.js +1 -1
- package/dist/es/p-toggle.js +22 -1
- package/dist/squirrel/components/p-action-bar/p-action-bar.vue.d.ts +15 -3
- package/dist/squirrel/components/p-alert/p-alert.vue.d.ts +17 -4
- package/dist/squirrel/components/p-avatar/p-avatar.vue.d.ts +36 -1
- package/dist/squirrel/components/p-btn/p-btn.vue.d.ts +21 -5
- package/dist/squirrel/components/p-card/p-card.vue.d.ts +21 -8
- package/dist/squirrel/components/p-checkbox/p-checkbox.vue.d.ts +26 -8
- package/dist/squirrel/components/p-chips/p-chips.vue.d.ts +24 -0
- package/dist/squirrel/components/p-close-btn/p-close-btn.vue.d.ts +14 -1
- package/dist/squirrel/components/p-date-picker/p-date-picker.vue.d.ts +17 -1
- package/dist/squirrel/components/p-drawer/p-drawer.vue.d.ts +144 -6
- package/dist/squirrel/components/p-dropdown/p-dropdown.vue.d.ts +11 -2
- package/dist/squirrel/components/p-dropdown-select/p-dropdown-select.vue.d.ts +70 -2
- package/dist/squirrel/components/p-file-upload/p-file-upload.vue.d.ts +71 -7
- package/dist/squirrel/components/p-icon/p-icon.types.d.ts +3 -2
- package/dist/squirrel/components/p-icon/p-icon.vue.d.ts +5 -1
- package/dist/squirrel/components/p-info-icon/p-info-icon.vue.d.ts +12 -5
- package/dist/squirrel/components/p-inline-date-picker/p-inline-date-picker.vue.d.ts +28 -8
- package/dist/squirrel/components/p-input/p-input.vue.d.ts +74 -9
- package/dist/squirrel/components/p-input-number/p-input-number.vue.d.ts +83 -12
- package/dist/squirrel/components/p-input-percent/p-input-percent.vue.d.ts +23 -3
- package/dist/squirrel/components/p-input-search/p-input-search.vue.d.ts +25 -1
- package/dist/squirrel/components/p-link/p-link.vue.d.ts +1 -1
- package/dist/squirrel/components/p-loading/p-loading.vue.d.ts +1 -1
- package/dist/squirrel/components/p-modal/p-modal.vue.d.ts +186 -16
- package/dist/squirrel/components/p-pagination/p-pagination.vue.d.ts +23 -13
- package/dist/squirrel/components/p-pagination-info/p-pagination-info.vue.d.ts +17 -9
- package/dist/squirrel/components/p-progress-bar/p-progress-bar.vue.d.ts +21 -1
- package/dist/squirrel/components/p-ring-loader/p-ring-loader.vue.d.ts +11 -1
- package/dist/squirrel/components/p-select/p-select.vue.d.ts +77 -7
- package/dist/squirrel/components/p-select-btn/p-select-btn.vue.d.ts +68 -11
- package/dist/squirrel/components/p-select-list/p-select-list.vue.d.ts +2 -2
- package/dist/squirrel/components/p-select-pill/p-select-pill.vue.d.ts +72 -2
- package/dist/squirrel/components/p-skeleton-loader/p-skeleton-loader.vue.d.ts +40 -0
- package/dist/squirrel/components/p-steps/p-steps.vue.d.ts +13 -1
- package/dist/squirrel/components/p-table/p-table.vue.d.ts +32 -0
- package/dist/squirrel/components/p-table-header-cell/p-table-filter-icon.vue.d.ts +7 -1
- package/dist/squirrel/components/p-table-header-cell/p-table-header-cell.vue.d.ts +59 -4
- package/dist/squirrel/components/p-table-loader/p-table-loader.vue.d.ts +41 -1
- package/dist/squirrel/components/p-table-sort/p-table-sort.vue.d.ts +13 -3
- package/dist/squirrel/components/p-table-td/p-table-td.vue.d.ts +13 -1
- package/dist/squirrel/components/p-tabs/p-tabs.vue.d.ts +34 -3
- package/dist/squirrel/components/p-tabs-pills/p-tabs-pills.vue.d.ts +23 -1
- package/dist/squirrel/components/p-textarea/p-textarea.vue.d.ts +53 -9
- package/dist/squirrel/components/p-toggle/p-toggle.vue.d.ts +51 -4
- package/dist/squirrel.css +68 -68
- package/package.json +20 -21
- package/squirrel/components/p-action-bar/p-action-bar.stories.js +5 -5
- package/squirrel/components/p-action-bar/p-action-bar.vue +30 -3
- package/squirrel/components/p-alert/p-alert.vue +24 -0
- package/squirrel/components/p-avatar/p-avatar.vue +28 -0
- package/squirrel/components/p-btn/p-btn.vue +35 -0
- package/squirrel/components/p-card/p-card.vue +24 -1
- package/squirrel/components/p-checkbox/p-checkbox.vue +23 -1
- package/squirrel/components/p-chips/p-chips.vue +24 -0
- package/squirrel/components/p-close-btn/p-close-btn.vue +15 -0
- package/squirrel/components/p-date-picker/p-date-picker.vue +23 -1
- package/squirrel/components/p-drawer/p-drawer.vue +95 -0
- package/squirrel/components/p-dropdown/p-dropdown.vue +12 -1
- package/squirrel/components/p-dropdown-select/p-dropdown-select.vue +41 -0
- package/squirrel/components/p-file-upload/p-file-upload.vue +58 -3
- package/squirrel/components/p-icon/p-icon.types.ts +3 -2
- package/squirrel/components/p-icon/p-icon.vue +16 -0
- package/squirrel/components/p-info-icon/p-info-icon.vue +19 -0
- package/squirrel/components/p-inline-date-picker/p-inline-date-picker.vue +32 -0
- package/squirrel/components/p-input/p-input.vue +61 -1
- package/squirrel/components/p-input-number/p-input-number.vue +78 -1
- package/squirrel/components/p-input-percent/p-input-percent.vue +27 -3
- package/squirrel/components/p-input-search/p-input-search.vue +30 -2
- package/squirrel/components/p-link/p-link.vue +13 -0
- package/squirrel/components/p-loading/p-loading.vue +9 -2
- package/squirrel/components/p-modal/p-modal.vue +138 -2
- package/squirrel/components/p-pagination/p-pagination.vue +28 -8
- package/squirrel/components/p-pagination-info/p-pagination-info.vue +16 -4
- package/squirrel/components/p-progress-bar/p-progress-bar.vue +31 -4
- package/squirrel/components/p-ring-loader/p-ring-loader.vue +17 -0
- package/squirrel/components/p-select/p-select.vue +50 -1
- package/squirrel/components/p-select-btn/p-select-btn.vue +90 -2
- package/squirrel/components/p-select-list/p-select-list.vue +7 -0
- package/squirrel/components/p-select-pill/p-select-pill.vue +52 -2
- package/squirrel/components/p-skeleton-loader/p-skeleton-loader.vue +24 -0
- package/squirrel/components/p-steps/p-steps.vue +25 -0
- package/squirrel/components/p-table/p-table.vue +39 -0
- package/squirrel/components/p-table-header-cell/p-table-filter-icon.vue +9 -0
- package/squirrel/components/p-table-header-cell/p-table-header-cell.vue +36 -0
- package/squirrel/components/p-table-loader/p-table-loader.vue +28 -0
- package/squirrel/components/p-table-sort/p-table-sort.vue +19 -1
- package/squirrel/components/p-table-td/p-table-td.vue +20 -0
- package/squirrel/components/p-tabs/p-tabs.stories.js +2 -2
- package/squirrel/components/p-tabs/p-tabs.vue +33 -1
- package/squirrel/components/p-tabs-pills/p-tabs-pills.vue +33 -0
- package/squirrel/components/p-textarea/p-textarea.vue +43 -1
- package/squirrel/components/p-toggle/p-toggle.vue +44 -1
- package/squirrel/assets/pagination-left-icon.svg +0 -5
- package/squirrel/assets/pagination-right-icon.svg +0 -5
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
</div>
|
|
11
11
|
<div class="relative w-full">
|
|
12
12
|
<div v-if="!!$slots.prefix || prefixString">
|
|
13
|
+
<!-- Slot for custom prefix content - overrides the prefixString prop -->
|
|
13
14
|
<slot name="prefix">
|
|
14
15
|
<div
|
|
15
16
|
:class="[{ 'absolute left-3 flex items-center': prefixString }, prefixString ? prefixClasses[size] : '']"
|
|
@@ -53,30 +54,82 @@ const prefixClasses: Record<Size, string> = {
|
|
|
53
54
|
lg: 'text-lg h-12 left-5',
|
|
54
55
|
};
|
|
55
56
|
|
|
57
|
+
/**
|
|
58
|
+
* A specialized input component for numeric values with currency formatting.
|
|
59
|
+
* Provides number-only input with configurable currency display, precision, and formatting options.
|
|
60
|
+
* Supports custom labels, error states, tooltips, and prefix content.
|
|
61
|
+
* Uses vue-currency-input for robust number handling and formatting.
|
|
62
|
+
*/
|
|
56
63
|
defineOptions({
|
|
57
64
|
name: 'PInputNumber',
|
|
58
65
|
inheritAttrs: false,
|
|
59
66
|
});
|
|
60
67
|
|
|
61
|
-
const emit = defineEmits
|
|
68
|
+
const emit = defineEmits<{
|
|
69
|
+
/**
|
|
70
|
+
* Emitted when the numeric value changes.
|
|
71
|
+
* @param {number | null} value - The new numeric value
|
|
72
|
+
*/
|
|
73
|
+
'update:modelValue': [value: number | null];
|
|
74
|
+
/**
|
|
75
|
+
* Emitted when the value changes (includes the new value).
|
|
76
|
+
* @param {number | null} value - The new numeric value
|
|
77
|
+
*/
|
|
78
|
+
change: [value: number | null];
|
|
79
|
+
}>();
|
|
80
|
+
|
|
81
|
+
defineSlots<{
|
|
82
|
+
/**
|
|
83
|
+
* Custom label content - overrides the label prop.
|
|
84
|
+
* @param {string} label - The label text
|
|
85
|
+
* @param {string} label-classes - CSS classes for the label
|
|
86
|
+
*/
|
|
87
|
+
label?: (props: { label: string; labelClasses: string }) => unknown;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Custom prefix content - overrides the prefixString prop.
|
|
91
|
+
* Use this slot for custom prefix content instead of the prefixString prop.
|
|
92
|
+
*/
|
|
93
|
+
prefix?: () => unknown;
|
|
94
|
+
}>();
|
|
62
95
|
|
|
63
96
|
const props = defineProps({
|
|
97
|
+
/**
|
|
98
|
+
* The current numeric value of the input (v-model).
|
|
99
|
+
* Supports two-way binding for form inputs.
|
|
100
|
+
*/
|
|
64
101
|
modelValue: {
|
|
65
102
|
type: [Number, String] as PropType<number | string | null | undefined>,
|
|
66
103
|
default: null,
|
|
67
104
|
},
|
|
105
|
+
/**
|
|
106
|
+
* Text label for the input field.
|
|
107
|
+
* If not provided, you can use the label slot instead.
|
|
108
|
+
*/
|
|
68
109
|
label: {
|
|
69
110
|
type: String,
|
|
70
111
|
default: '',
|
|
71
112
|
},
|
|
113
|
+
/**
|
|
114
|
+
* Error message to display below the input.
|
|
115
|
+
* When provided, the input will show error styling.
|
|
116
|
+
*/
|
|
72
117
|
errorMsg: {
|
|
73
118
|
type: String,
|
|
74
119
|
default: '',
|
|
75
120
|
},
|
|
121
|
+
/**
|
|
122
|
+
* Whether the input is required.
|
|
123
|
+
* Adds required attribute and visual indicator.
|
|
124
|
+
*/
|
|
76
125
|
required: {
|
|
77
126
|
type: Boolean,
|
|
78
127
|
default: false,
|
|
79
128
|
},
|
|
129
|
+
/**
|
|
130
|
+
* The size of the input - affects padding, font size, and spacing.
|
|
131
|
+
* Valid values: 'sm', 'md', 'lg'
|
|
132
|
+
*/
|
|
80
133
|
size: {
|
|
81
134
|
type: String as PropType<Size>,
|
|
82
135
|
default: 'md',
|
|
@@ -84,14 +137,26 @@ const props = defineProps({
|
|
|
84
137
|
return SIZES.includes(value);
|
|
85
138
|
},
|
|
86
139
|
},
|
|
140
|
+
/**
|
|
141
|
+
* Whether to select all text when the input receives focus.
|
|
142
|
+
* Provides better UX for number input fields.
|
|
143
|
+
*/
|
|
87
144
|
selectOnClick: {
|
|
88
145
|
type: Boolean,
|
|
89
146
|
default: true,
|
|
90
147
|
},
|
|
148
|
+
/**
|
|
149
|
+
* Text for the info tooltip displayed next to the label.
|
|
150
|
+
* Uses PInfoIcon component for consistent tooltip styling.
|
|
151
|
+
*/
|
|
91
152
|
tooltipText: {
|
|
92
153
|
type: String,
|
|
93
154
|
default: '',
|
|
94
155
|
},
|
|
156
|
+
/**
|
|
157
|
+
* String to display as prefix in the input field.
|
|
158
|
+
* Can be overridden by the prefix slot for custom content.
|
|
159
|
+
*/
|
|
95
160
|
prefixString: {
|
|
96
161
|
type: String,
|
|
97
162
|
default: '',
|
|
@@ -155,9 +220,21 @@ const style = computed(() => {
|
|
|
155
220
|
return attrs.style as StyleValue;
|
|
156
221
|
});
|
|
157
222
|
|
|
223
|
+
/**
|
|
224
|
+
* Handles focus event on the input field.
|
|
225
|
+
* Selects all text if selectOnClick is enabled.
|
|
226
|
+
* @param {void} - No parameters
|
|
227
|
+
* @returns {void}
|
|
228
|
+
*/
|
|
158
229
|
const focus = () => {
|
|
159
230
|
props.selectOnClick && inputRef.value.select();
|
|
160
231
|
};
|
|
161
232
|
|
|
233
|
+
/**
|
|
234
|
+
* Programmatically sets the numeric value of the input.
|
|
235
|
+
* Useful for external control of the input value.
|
|
236
|
+
* @param {number | null} value - The numeric value to set
|
|
237
|
+
* @returns {void}
|
|
238
|
+
*/
|
|
162
239
|
defineExpose({ setValue });
|
|
163
240
|
</script>
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
<script setup lang="ts">
|
|
12
12
|
import { type Size } from '@squirrel/components/p-btn/p-btn.types';
|
|
13
13
|
import PInputNumber from '@squirrel/components/p-input-number/p-input-number.vue';
|
|
14
|
+
import { toNumberOrNull } from '@squirrel/utils/number';
|
|
14
15
|
import { isNumber } from 'lodash-es';
|
|
15
16
|
import { computed, type PropType } from 'vue';
|
|
16
17
|
|
|
@@ -20,25 +21,48 @@ const prefixClasses: Record<Size, string> = {
|
|
|
20
21
|
lg: 'text-lg h-12 left-5',
|
|
21
22
|
};
|
|
22
23
|
|
|
24
|
+
/**
|
|
25
|
+
* A percentage input component that wraps PInputNumber with automatic decimal conversion.
|
|
26
|
+
* Displays values as percentages (multiplied by 100) while storing the actual decimal value.
|
|
27
|
+
* Provides a consistent interface for percentage inputs with proper formatting and validation.
|
|
28
|
+
*
|
|
29
|
+
* @displayName PInputPercent
|
|
30
|
+
*/
|
|
23
31
|
defineOptions({
|
|
24
32
|
name: 'PInputPercent',
|
|
25
33
|
});
|
|
26
34
|
|
|
27
35
|
const props = defineProps({
|
|
36
|
+
/**
|
|
37
|
+
* The current value (v-model).
|
|
38
|
+
* Stored as a decimal (0.5 = 50%) but displayed as a percentage.
|
|
39
|
+
* Supports two-way binding for form inputs.
|
|
40
|
+
*/
|
|
28
41
|
modelValue: {
|
|
29
42
|
type: [Number, String] as PropType<number | string | null | undefined>,
|
|
30
43
|
default: null,
|
|
31
44
|
},
|
|
45
|
+
/**
|
|
46
|
+
* The size of the input field.
|
|
47
|
+
* Valid values: 'sm', 'md', 'lg'
|
|
48
|
+
* @values sm, md, lg
|
|
49
|
+
*/
|
|
32
50
|
size: {
|
|
33
51
|
type: String as PropType<Size>,
|
|
34
52
|
default: 'md',
|
|
35
53
|
},
|
|
36
54
|
});
|
|
37
55
|
|
|
38
|
-
const emit = defineEmits
|
|
56
|
+
const emit = defineEmits<{
|
|
57
|
+
/**
|
|
58
|
+
* Emitted when the percentage value changes.
|
|
59
|
+
* @param {number | null} value - The new decimal value
|
|
60
|
+
*/
|
|
61
|
+
'update:modelValue': [value: number | null];
|
|
62
|
+
}>();
|
|
39
63
|
|
|
40
64
|
const convertedValue = computed({
|
|
41
|
-
get: () => (isNumber(props.modelValue) ? props.modelValue * 100 : props.modelValue),
|
|
42
|
-
set: (nV) => emit('update:modelValue', isNumber(nV) ? nV / 100 : nV),
|
|
65
|
+
get: () => (isNumber(props.modelValue) ? props.modelValue * 100 : toNumberOrNull(props.modelValue)),
|
|
66
|
+
set: (nV) => emit('update:modelValue', isNumber(nV) ? nV / 100 : toNumberOrNull(nV)),
|
|
43
67
|
});
|
|
44
68
|
</script>
|
|
@@ -40,23 +40,47 @@ import PIcon from '@squirrel/components/p-icon/p-icon.vue';
|
|
|
40
40
|
import PInput from '@squirrel/components/p-input/p-input.vue';
|
|
41
41
|
import { type PropType, ref, useTemplateRef, watch } from 'vue';
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
/**
|
|
44
|
+
* A search input component that provides a specialized input field for search functionality.
|
|
45
|
+
* Features include a search icon prefix, optional enter key icon, clear button,
|
|
46
|
+
* and automatic focus management. Built on top of PInput with search-specific styling
|
|
47
|
+
* and behavior.
|
|
48
|
+
*
|
|
49
|
+
* @displayName PInputSearch
|
|
50
|
+
*/
|
|
45
51
|
defineOptions({
|
|
46
52
|
name: 'PInputSearch',
|
|
47
53
|
inheritAttrs: false,
|
|
48
54
|
});
|
|
49
55
|
|
|
56
|
+
type PInputInstance = InstanceType<typeof PInput>;
|
|
57
|
+
|
|
50
58
|
const emit = defineEmits<{
|
|
59
|
+
/**
|
|
60
|
+
* Emitted when the search query value changes.
|
|
61
|
+
* @param {string} value - The new search query
|
|
62
|
+
*/
|
|
51
63
|
'update:modelValue': [value: string];
|
|
64
|
+
/**
|
|
65
|
+
* Emitted when the enter key is pressed.
|
|
66
|
+
* @param {string} value - The current search query
|
|
67
|
+
*/
|
|
52
68
|
enter: [value: string];
|
|
53
69
|
}>();
|
|
54
70
|
|
|
55
71
|
const props = defineProps({
|
|
72
|
+
/**
|
|
73
|
+
* The search query value (v-model).
|
|
74
|
+
* Controls the input field content and visibility of the clear button.
|
|
75
|
+
*/
|
|
56
76
|
modelValue: {
|
|
57
77
|
type: String,
|
|
58
78
|
default: '',
|
|
59
79
|
},
|
|
80
|
+
/**
|
|
81
|
+
* The size of the search input.
|
|
82
|
+
* Affects the overall dimensions and icon positioning.
|
|
83
|
+
*/
|
|
60
84
|
size: {
|
|
61
85
|
type: String as PropType<Size>,
|
|
62
86
|
default: 'md',
|
|
@@ -64,6 +88,10 @@ const props = defineProps({
|
|
|
64
88
|
return SIZES.includes(value);
|
|
65
89
|
},
|
|
66
90
|
},
|
|
91
|
+
/**
|
|
92
|
+
* Whether to show the enter key icon when the input is focused.
|
|
93
|
+
* Provides visual feedback that pressing enter will trigger a search.
|
|
94
|
+
*/
|
|
67
95
|
showEnterIcon: {
|
|
68
96
|
type: Boolean,
|
|
69
97
|
default: false,
|
|
@@ -12,9 +12,22 @@ import { isExternalLink } from '@squirrel/utils/link';
|
|
|
12
12
|
import { sanitizeUrl } from '@squirrel/utils/sanitization';
|
|
13
13
|
import { RouterLink, type RouterLinkProps } from 'vue-router';
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* A link component that intelligently handles both internal and external links.
|
|
17
|
+
* Automatically detects external URLs and renders them as anchor tags with
|
|
18
|
+
* proper security attributes, while internal links use Vue Router's RouterLink.
|
|
19
|
+
* Supports all RouterLink props for internal navigation.
|
|
20
|
+
*
|
|
21
|
+
* @displayName PLink
|
|
22
|
+
*/
|
|
15
23
|
defineOptions({
|
|
16
24
|
name: 'PLink',
|
|
17
25
|
});
|
|
18
26
|
|
|
27
|
+
/**
|
|
28
|
+
* All props from Vue Router's RouterLink component are supported.
|
|
29
|
+
* The component automatically handles external vs internal link detection
|
|
30
|
+
* and applies appropriate rendering and security measures.
|
|
31
|
+
*/
|
|
19
32
|
defineProps<RouterLinkProps>();
|
|
20
33
|
</script>
|
|
@@ -33,12 +33,19 @@ import { usePLoading } from '@squirrel/components/p-loading/usePLoading';
|
|
|
33
33
|
import { isComponent } from '@squirrel/utils/component';
|
|
34
34
|
import { onBeforeUnmount, ref, toValue, watch } from 'vue';
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
/**
|
|
37
|
+
* A loading component that displays a loading rectangle at the top center of the screen.
|
|
38
|
+
* Shows a customizable content area with smooth animations and dynamic sizing.
|
|
39
|
+
* Supports both text content and component content with automatic dimension calculation.
|
|
40
|
+
*
|
|
41
|
+
* @displayName PLoading
|
|
42
|
+
*/
|
|
38
43
|
defineOptions({
|
|
39
44
|
name: 'PLoading',
|
|
40
45
|
});
|
|
41
46
|
|
|
47
|
+
const textDivClass = `flex h-8 justify-center gap-x-1.5 overflow-hidden whitespace-nowrap px-6 pt-1 text-sm font-semibold text-p-purple-60`;
|
|
48
|
+
|
|
42
49
|
const { show, content, props: componentProps, loadingHide } = usePLoading();
|
|
43
50
|
const dimsReference = ref<HTMLElement | null>(null);
|
|
44
51
|
const width = ref(0);
|
|
@@ -90,99 +90,235 @@ const FOCUSABLE_ELEMENTS =
|
|
|
90
90
|
'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
91
91
|
let animatingZIndex = 0;
|
|
92
92
|
|
|
93
|
+
/**
|
|
94
|
+
* A modal dialog component with advanced features like animations, focus management, and accessibility.
|
|
95
|
+
* Provides a teleported modal interface with backdrop, customizable styling, and lifecycle events.
|
|
96
|
+
* Supports both controlled and uncontrolled modes with proper keyboard navigation.
|
|
97
|
+
*
|
|
98
|
+
* @displayName PModal
|
|
99
|
+
*/
|
|
93
100
|
defineOptions({
|
|
94
101
|
name: 'PModal',
|
|
95
102
|
});
|
|
96
103
|
|
|
104
|
+
defineSlots<{
|
|
105
|
+
/**
|
|
106
|
+
* Default content slot for the modal body.
|
|
107
|
+
*/
|
|
108
|
+
default?: () => unknown;
|
|
109
|
+
/**
|
|
110
|
+
* Custom title wrapper content.
|
|
111
|
+
*/
|
|
112
|
+
'title-wrapper'?: () => unknown;
|
|
113
|
+
/**
|
|
114
|
+
* Custom content wrapper.
|
|
115
|
+
*/
|
|
116
|
+
'content-wrapper'?: () => unknown;
|
|
117
|
+
/**
|
|
118
|
+
* Custom footer content.
|
|
119
|
+
*/
|
|
120
|
+
footer?: () => unknown;
|
|
121
|
+
/**
|
|
122
|
+
* Custom footer wrapper.
|
|
123
|
+
*/
|
|
124
|
+
'footer-wrapper'?: () => unknown;
|
|
125
|
+
}>();
|
|
126
|
+
|
|
97
127
|
const emit = defineEmits<{
|
|
128
|
+
/**
|
|
129
|
+
* Emitted before the modal starts opening.
|
|
130
|
+
*/
|
|
98
131
|
'before-open': [];
|
|
132
|
+
/**
|
|
133
|
+
* Emitted when the modal is opening (animation in progress).
|
|
134
|
+
*/
|
|
99
135
|
opening: [];
|
|
136
|
+
/**
|
|
137
|
+
* Emitted when the modal has finished opening.
|
|
138
|
+
*/
|
|
100
139
|
opened: [];
|
|
140
|
+
/**
|
|
141
|
+
* Emitted before the modal starts closing.
|
|
142
|
+
*/
|
|
101
143
|
'before-close': [];
|
|
144
|
+
/**
|
|
145
|
+
* Emitted when the modal is closing (animation in progress).
|
|
146
|
+
*/
|
|
102
147
|
closing: [];
|
|
148
|
+
/**
|
|
149
|
+
* Emitted when the modal has finished closing.
|
|
150
|
+
*/
|
|
103
151
|
closed: [];
|
|
104
|
-
|
|
105
|
-
|
|
152
|
+
/**
|
|
153
|
+
* Emitted when the modal visibility changes (v-model).
|
|
154
|
+
* @param {boolean} value - The new visibility state
|
|
155
|
+
*/
|
|
156
|
+
'update:modelValue': [value: boolean];
|
|
157
|
+
/**
|
|
158
|
+
* Emitted when the backdrop is clicked.
|
|
159
|
+
* @param {MouseEvent} event - The click event
|
|
160
|
+
*/
|
|
161
|
+
'click:overlay': [event: MouseEvent];
|
|
106
162
|
}>();
|
|
107
163
|
|
|
108
164
|
const props = defineProps({
|
|
165
|
+
/**
|
|
166
|
+
* Unique name for the modal when using the modal service.
|
|
167
|
+
* Used for programmatic control of the modal.
|
|
168
|
+
*/
|
|
109
169
|
name: {
|
|
110
170
|
type: String,
|
|
111
171
|
default: '',
|
|
112
172
|
},
|
|
173
|
+
/**
|
|
174
|
+
* Title displayed in the modal header.
|
|
175
|
+
* Used for accessibility and visual identification.
|
|
176
|
+
*/
|
|
113
177
|
title: {
|
|
114
178
|
type: String,
|
|
115
179
|
default: '',
|
|
116
180
|
},
|
|
181
|
+
/**
|
|
182
|
+
* Base z-index for the modal.
|
|
183
|
+
* Higher values ensure the modal appears above other content.
|
|
184
|
+
*/
|
|
117
185
|
baseZindex: {
|
|
118
186
|
type: Number,
|
|
119
187
|
default: 1051,
|
|
120
188
|
},
|
|
189
|
+
/**
|
|
190
|
+
* CSS classes for the backdrop element.
|
|
191
|
+
* Controls the appearance of the modal overlay.
|
|
192
|
+
*/
|
|
121
193
|
bgClass: {
|
|
122
194
|
type: [String, Object, Array] as PropType<StyleValue>,
|
|
123
195
|
default: 'fixed bottom-0 left-0 right-0 top-0 bg-black/20',
|
|
124
196
|
},
|
|
197
|
+
/**
|
|
198
|
+
* CSS classes for the modal wrapper element.
|
|
199
|
+
* Controls the positioning and layout of the modal container.
|
|
200
|
+
*/
|
|
125
201
|
wrapperClass: {
|
|
126
202
|
type: [String, Object, Array] as PropType<StyleValue>,
|
|
127
203
|
default:
|
|
128
204
|
'fixed bottom-0 left-0 right-0 top-0 flex flex-col items-center justify-center overflow-y-auto overflow-x-hidden outline-none',
|
|
129
205
|
},
|
|
206
|
+
/**
|
|
207
|
+
* Base CSS classes for the modal content.
|
|
208
|
+
* Controls the appearance of the modal dialog itself.
|
|
209
|
+
*/
|
|
130
210
|
modalBaseClass: {
|
|
131
211
|
type: [String, Object, Array] as PropType<StyleValue>,
|
|
132
212
|
default: 'pm relative flex flex-col rounded-2xl pb-6 cursor-default bg-surface shadow-xl',
|
|
133
213
|
},
|
|
214
|
+
/**
|
|
215
|
+
* Additional CSS classes for the modal content.
|
|
216
|
+
* Merged with modalBaseClass for custom styling.
|
|
217
|
+
*/
|
|
134
218
|
modalClass: {
|
|
135
219
|
type: [String, Object, Array] as PropType<StyleValue>,
|
|
136
220
|
default: '',
|
|
137
221
|
},
|
|
222
|
+
/**
|
|
223
|
+
* Inline styles for the modal content.
|
|
224
|
+
* Applied directly to the modal element.
|
|
225
|
+
*/
|
|
138
226
|
modalStyle: {
|
|
139
227
|
type: [String, Object, Array] as PropType<StyleValue>,
|
|
140
228
|
default: '',
|
|
141
229
|
},
|
|
230
|
+
/**
|
|
231
|
+
* CSS class for the modal entrance animation.
|
|
232
|
+
* Controls how the modal appears.
|
|
233
|
+
*/
|
|
142
234
|
inClass: {
|
|
143
235
|
type: String,
|
|
144
236
|
default: 'slideInTop',
|
|
145
237
|
},
|
|
238
|
+
/**
|
|
239
|
+
* CSS class for the modal exit animation.
|
|
240
|
+
* Controls how the modal disappears.
|
|
241
|
+
*/
|
|
146
242
|
outClass: {
|
|
147
243
|
type: String,
|
|
148
244
|
default: 'slideOutTop',
|
|
149
245
|
},
|
|
246
|
+
/**
|
|
247
|
+
* CSS class for the backdrop entrance animation.
|
|
248
|
+
* Controls how the backdrop appears.
|
|
249
|
+
*/
|
|
150
250
|
bgInClass: {
|
|
151
251
|
type: String,
|
|
152
252
|
default: 'fadeIn',
|
|
153
253
|
},
|
|
254
|
+
/**
|
|
255
|
+
* CSS class for the backdrop exit animation.
|
|
256
|
+
* Controls how the backdrop disappears.
|
|
257
|
+
*/
|
|
154
258
|
bgOutClass: {
|
|
155
259
|
type: String,
|
|
156
260
|
default: 'fadeOut',
|
|
157
261
|
},
|
|
262
|
+
/**
|
|
263
|
+
* Target element to append the modal to.
|
|
264
|
+
* Usually 'body' for proper z-index stacking.
|
|
265
|
+
*/
|
|
158
266
|
appendTo: {
|
|
159
267
|
type: String,
|
|
160
268
|
default: 'body',
|
|
161
269
|
},
|
|
270
|
+
/**
|
|
271
|
+
* Whether the modal should be mounted immediately.
|
|
272
|
+
* Useful for modals that are always present in the DOM.
|
|
273
|
+
*/
|
|
162
274
|
live: {
|
|
163
275
|
type: Boolean,
|
|
164
276
|
default: false,
|
|
165
277
|
},
|
|
278
|
+
/**
|
|
279
|
+
* Whether the modal can be closed by user interaction.
|
|
280
|
+
* Controls close button visibility and backdrop click behavior.
|
|
281
|
+
*/
|
|
166
282
|
enableClose: {
|
|
167
283
|
type: Boolean,
|
|
168
284
|
default: true,
|
|
169
285
|
},
|
|
286
|
+
/**
|
|
287
|
+
* Controls the visibility of the modal (v-model).
|
|
288
|
+
* Supports two-way binding for modal state.
|
|
289
|
+
*/
|
|
170
290
|
modelValue: {
|
|
171
291
|
type: Boolean,
|
|
172
292
|
default: false,
|
|
173
293
|
},
|
|
294
|
+
/**
|
|
295
|
+
* Accessibility label for the close button.
|
|
296
|
+
* Used by screen readers for better accessibility.
|
|
297
|
+
*/
|
|
174
298
|
closeLabel: {
|
|
175
299
|
type: String,
|
|
176
300
|
default: 'Close',
|
|
177
301
|
},
|
|
302
|
+
/**
|
|
303
|
+
* Whether the modal content is disabled.
|
|
304
|
+
* Prevents user interaction with modal content.
|
|
305
|
+
*/
|
|
178
306
|
disabled: {
|
|
179
307
|
type: Boolean,
|
|
180
308
|
default: false,
|
|
181
309
|
},
|
|
310
|
+
/**
|
|
311
|
+
* Error message to display in the modal.
|
|
312
|
+
* Shows an error alert above the modal content.
|
|
313
|
+
*/
|
|
182
314
|
errorMsg: {
|
|
183
315
|
type: String,
|
|
184
316
|
default: '',
|
|
185
317
|
},
|
|
318
|
+
/**
|
|
319
|
+
* Maximum width of the modal.
|
|
320
|
+
* Controls the responsive behavior of the modal.
|
|
321
|
+
*/
|
|
186
322
|
maxWidth: {
|
|
187
323
|
type: String,
|
|
188
324
|
default: '500px',
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
aria-label="go to the previous page"
|
|
7
7
|
@click="setPage(Number(modelValue) - 1)"
|
|
8
8
|
>
|
|
9
|
-
<
|
|
9
|
+
<PIcon icon="chevron-left" width="24px" />
|
|
10
10
|
</div>
|
|
11
11
|
<div v-for="(page, index) in pages" :key="index" @click="setPage(Number(page))">
|
|
12
12
|
<div class="flex">
|
|
@@ -25,51 +25,71 @@
|
|
|
25
25
|
aria-label="go to the next page"
|
|
26
26
|
@click="setPage(Number(modelValue) + 1)"
|
|
27
27
|
>
|
|
28
|
-
<
|
|
28
|
+
<PIcon icon="chevron-right" width="24px" />
|
|
29
29
|
</div>
|
|
30
30
|
</div>
|
|
31
31
|
</template>
|
|
32
32
|
|
|
33
33
|
<script setup lang="ts">
|
|
34
|
+
import PIcon from '@squirrel/components/p-icon/p-icon.vue';
|
|
34
35
|
import PSkeletonLoader from '@squirrel/components/p-skeleton-loader/p-skeleton-loader.vue';
|
|
35
36
|
import { createPagingRange } from '@squirrel/utils/pagination';
|
|
36
37
|
import { computed, type PropType } from 'vue';
|
|
37
38
|
|
|
39
|
+
/**
|
|
40
|
+
* A pagination component that displays page numbers with navigation controls.
|
|
41
|
+
* Provides a complete pagination interface with previous/next buttons, page numbers,
|
|
42
|
+
* loading states, and ellipsis for large page ranges.
|
|
43
|
+
* Supports customizable page sizes and offset ranges for optimal display.
|
|
44
|
+
*
|
|
45
|
+
* @displayName PPagination
|
|
46
|
+
*/
|
|
38
47
|
defineOptions({ name: 'PPagination' });
|
|
39
48
|
|
|
40
|
-
const emit = defineEmits
|
|
49
|
+
const emit = defineEmits<{
|
|
50
|
+
/**
|
|
51
|
+
* Emitted when the current page changes.
|
|
52
|
+
* @param {number} value - The new page number
|
|
53
|
+
*/
|
|
54
|
+
'update:modelValue': [value: number];
|
|
55
|
+
}>();
|
|
41
56
|
|
|
42
57
|
const props = defineProps({
|
|
43
58
|
/**
|
|
44
|
-
* The current page.
|
|
59
|
+
* The current page number (v-model).
|
|
60
|
+
* Controls which page is visually active and navigable.
|
|
45
61
|
*/
|
|
46
62
|
modelValue: {
|
|
47
63
|
type: Number as PropType<number | null>,
|
|
48
64
|
default: null,
|
|
49
65
|
},
|
|
50
66
|
/**
|
|
51
|
-
* The amount of
|
|
67
|
+
* The total amount of items to paginate through.
|
|
68
|
+
* Used to calculate the total number of pages.
|
|
52
69
|
*/
|
|
53
70
|
count: {
|
|
54
71
|
type: Number,
|
|
55
72
|
default: 0,
|
|
56
73
|
},
|
|
57
74
|
/**
|
|
58
|
-
* The
|
|
75
|
+
* The number of items to display per page.
|
|
76
|
+
* Used to calculate the total number of pages.
|
|
59
77
|
*/
|
|
60
78
|
pageSize: {
|
|
61
79
|
type: Number,
|
|
62
80
|
default: 10,
|
|
63
81
|
},
|
|
64
82
|
/**
|
|
65
|
-
* The
|
|
83
|
+
* The number of pages to show before and after the current page.
|
|
84
|
+
* Controls the range of page numbers displayed around the current page.
|
|
66
85
|
*/
|
|
67
86
|
pageOffset: {
|
|
68
87
|
type: Number,
|
|
69
88
|
default: 2,
|
|
70
89
|
},
|
|
71
90
|
/**
|
|
72
|
-
* Whether the pagination is loading.
|
|
91
|
+
* Whether the pagination is in a loading state.
|
|
92
|
+
* When true, shows a skeleton loader instead of the pagination controls.
|
|
73
93
|
*/
|
|
74
94
|
loading: {
|
|
75
95
|
type: Boolean,
|
|
@@ -10,32 +10,44 @@
|
|
|
10
10
|
import PSkeletonLoader from '@squirrel/components/p-skeleton-loader/p-skeleton-loader.vue';
|
|
11
11
|
import { computed } from 'vue';
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* A pagination info component that displays current page information and result counts.
|
|
15
|
+
* Shows the range of items being displayed (e.g., "Showing 1 to 10 of 100 results")
|
|
16
|
+
* and provides a customizable slot for when no results are found.
|
|
17
|
+
* Includes loading state with skeleton loader.
|
|
18
|
+
*
|
|
19
|
+
* @displayName PPaginationInfo
|
|
20
|
+
*/
|
|
13
21
|
defineOptions({ name: 'PPaginationInfo' });
|
|
14
22
|
|
|
15
23
|
const props = defineProps({
|
|
16
24
|
/**
|
|
17
|
-
* The current page.
|
|
25
|
+
* The current page number (1-based).
|
|
26
|
+
* Used to calculate the starting item number in the display range.
|
|
18
27
|
*/
|
|
19
28
|
currentPage: {
|
|
20
29
|
type: Number,
|
|
21
30
|
default: 0,
|
|
22
31
|
},
|
|
23
32
|
/**
|
|
24
|
-
* The
|
|
33
|
+
* The total number of items across all pages.
|
|
34
|
+
* Used to calculate the total count and ending item number.
|
|
25
35
|
*/
|
|
26
36
|
count: {
|
|
27
37
|
type: Number,
|
|
28
38
|
default: 0,
|
|
29
39
|
},
|
|
30
40
|
/**
|
|
31
|
-
* The
|
|
41
|
+
* The number of items displayed per page.
|
|
42
|
+
* Used to calculate the `from` and `to` limits for the current page.
|
|
32
43
|
*/
|
|
33
44
|
pageSize: {
|
|
34
45
|
type: Number,
|
|
35
46
|
default: 0,
|
|
36
47
|
},
|
|
37
48
|
/**
|
|
38
|
-
* Whether the pagination is loading.
|
|
49
|
+
* Whether the pagination data is loading.
|
|
50
|
+
* When true, shows a skeleton loader instead of the info text.
|
|
39
51
|
*/
|
|
40
52
|
loading: {
|
|
41
53
|
type: Boolean,
|