@pequity/squirrel 3.0.2 → 3.1.0

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.
@@ -12,20 +12,23 @@ const _hoisted_2 = {
12
12
  key: 0,
13
13
  class: "invisible fixed"
14
14
  };
15
+ const textDivClass = `overflow-hidden whitespace-nowrap px-4 pt-1 h-8 text-center text-sm font-semibold text-p-purple-60`;
15
16
  const _sfc_main = /* @__PURE__ */ vue.defineComponent({
16
17
  ...{
17
18
  name: "PLoading"
18
19
  },
19
20
  __name: "p-loading",
20
21
  setup(__props) {
21
- const { show, content } = usePLoading.usePLoading();
22
- const widthReference = vue.ref(null);
22
+ const { show, content, props: componentProps } = usePLoading.usePLoading();
23
+ const dimsReference = vue.ref(null);
23
24
  const width = vue.ref(0);
25
+ const height = vue.ref(0);
24
26
  vue.watch(
25
27
  () => vue.toValue(content),
26
28
  () => {
27
- if (widthReference.value) {
28
- width.value = widthReference.value.offsetWidth;
29
+ if (dimsReference.value) {
30
+ width.value = dimsReference.value.offsetWidth;
31
+ height.value = dimsReference.value.offsetHeight;
29
32
  }
30
33
  },
31
34
  { flush: "post" }
@@ -44,12 +47,21 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
44
47
  default: vue.withCtx(() => [
45
48
  vue.unref(show) ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
46
49
  vue.createElementVNode("div", {
47
- style: vue.normalizeStyle({ width: `${width.value}px` }),
48
- class: "h-8 overflow-hidden whitespace-nowrap rounded-b border-x border-b border-p-gray-30 bg-p-blue-10 px-4 pt-2 text-center text-sm font-semibold leading-none text-p-purple-60 shadow-sm transition-all duration-500"
50
+ style: vue.normalizeStyle({ width: `${width.value}px`, height: `${height.value}px` }),
51
+ class: "overflow-hidden rounded-b border-x border-b border-p-gray-30 bg-p-blue-10 shadow-sm transition-all duration-300"
49
52
  }, [
50
- isComponent(vue.unref(content)) ? (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(vue.unref(content)), { key: 0 })) : (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 1 }, [
51
- vue.createTextVNode(vue.toDisplayString(vue.unref(content)), 1)
52
- ], 64))
53
+ vue.createVNode(vue.Transition, {
54
+ "enter-from-class": "opacity-0",
55
+ "enter-active-class": "transition duration-500"
56
+ }, {
57
+ default: vue.withCtx(() => [
58
+ isComponent(vue.unref(content)) ? (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(vue.unref(content)), vue.normalizeProps(vue.mergeProps({ key: 0 }, vue.unref(componentProps))), null, 16)) : (vue.openBlock(), vue.createElementBlock("div", {
59
+ key: 1,
60
+ class: vue.normalizeClass(textDivClass)
61
+ }, vue.toDisplayString(vue.unref(content)), 1))
62
+ ]),
63
+ _: 1
64
+ })
53
65
  ], 4)
54
66
  ])) : vue.createCommentVNode("", true)
55
67
  ]),
@@ -57,18 +69,18 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
57
69
  }),
58
70
  vue.unref(content) ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2, [
59
71
  vue.createElementVNode("div", {
60
- ref_key: "widthReference",
61
- ref: widthReference,
62
- class: "inline-flex px-4"
72
+ ref_key: "dimsReference",
73
+ ref: dimsReference
63
74
  }, [
64
- isComponent(vue.unref(content)) ? (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(vue.unref(content)), { key: 0 })) : (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 1 }, [
65
- vue.createTextVNode(vue.toDisplayString(vue.unref(content)), 1)
66
- ], 64))
75
+ isComponent(vue.unref(content)) ? (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(vue.unref(content)), vue.normalizeProps(vue.mergeProps({ key: 0 }, vue.unref(componentProps))), null, 16)) : (vue.openBlock(), vue.createElementBlock("div", {
76
+ key: 1,
77
+ class: vue.normalizeClass(textDivClass)
78
+ }, vue.toDisplayString(vue.unref(content)), 1))
67
79
  ], 512)
68
80
  ])) : vue.createCommentVNode("", true)
69
81
  ], 64);
70
82
  };
71
83
  }
72
84
  });
73
- const pLoading = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main, [["__scopeId", "data-v-8c0c66ab"]]);
85
+ const pLoading = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main, [["__scopeId", "data-v-6f528d56"]]);
74
86
  module.exports = pLoading;
@@ -8,6 +8,10 @@ const content = vue.computed(() => {
8
8
  var _a;
9
9
  return (_a = loadingItems.value[loadingItems.value.length - 1]) == null ? void 0 : _a.content;
10
10
  });
11
+ const props = vue.computed(() => {
12
+ var _a;
13
+ return (_a = loadingItems.value[loadingItems.value.length - 1]) == null ? void 0 : _a.props;
14
+ });
11
15
  let timer;
12
16
  const usePLoading = (options) => {
13
17
  const { delay } = { delay: 200, ...options };
@@ -25,11 +29,19 @@ const usePLoading = (options) => {
25
29
  }
26
30
  loadingItems.value.push({
27
31
  id: loadingItem.id,
28
- content: loadingItem.content && typeof loadingItem.content === "object" ? vue.markRaw(loadingItem.content) : loadingItem.content || LOADING_TEXT
32
+ content: loadingItem.content && typeof loadingItem.content === "object" ? vue.markRaw(loadingItem.content) : loadingItem.content || LOADING_TEXT,
33
+ props: loadingItem.props
29
34
  });
30
35
  };
31
36
  const loadingHide = (id) => {
32
- loadingItems.value = id && typeof id === "string" ? loadingItems.value.filter((item) => item.id !== id) : [];
37
+ if (id && typeof id === "string") {
38
+ const index = loadingItems.value.findIndex((item) => item.id === id);
39
+ if (index !== -1) {
40
+ loadingItems.value.splice(index, 1);
41
+ }
42
+ } else {
43
+ loadingItems.value = [];
44
+ }
33
45
  if (loadingItems.value.length === 0) {
34
46
  show.value = false;
35
47
  }
@@ -42,6 +54,6 @@ const usePLoading = (options) => {
42
54
  clearTimeout(timer);
43
55
  });
44
56
  }
45
- return { show, content, loadingShow, loadingHide };
57
+ return { show, content, props, loadingShow, loadingHide };
46
58
  };
47
59
  exports.usePLoading = usePLoading;
@@ -1,4 +1,4 @@
1
- import { defineComponent, ref, watch, toValue, openBlock, createElementBlock, Fragment, createVNode, Transition, withCtx, unref, createElementVNode, normalizeStyle, createBlock, resolveDynamicComponent, createTextVNode, toDisplayString, createCommentVNode } from "vue";
1
+ import { defineComponent, ref, watch, toValue, openBlock, createElementBlock, Fragment, createVNode, Transition, withCtx, unref, createElementVNode, normalizeStyle, createBlock, resolveDynamicComponent, normalizeProps, mergeProps, normalizeClass, toDisplayString, createCommentVNode } from "vue";
2
2
  import { usePLoading } from "./usePLoading.js";
3
3
  import { _ as _export_sfc } from "./chunks/_plugin-vue_export-helper.js";
4
4
  const _hoisted_1 = {
@@ -11,20 +11,23 @@ const _hoisted_2 = {
11
11
  key: 0,
12
12
  class: "invisible fixed"
13
13
  };
14
+ const textDivClass = `overflow-hidden whitespace-nowrap px-4 pt-1 h-8 text-center text-sm font-semibold text-p-purple-60`;
14
15
  const _sfc_main = /* @__PURE__ */ defineComponent({
15
16
  ...{
16
17
  name: "PLoading"
17
18
  },
18
19
  __name: "p-loading",
19
20
  setup(__props) {
20
- const { show, content } = usePLoading();
21
- const widthReference = ref(null);
21
+ const { show, content, props: componentProps } = usePLoading();
22
+ const dimsReference = ref(null);
22
23
  const width = ref(0);
24
+ const height = ref(0);
23
25
  watch(
24
26
  () => toValue(content),
25
27
  () => {
26
- if (widthReference.value) {
27
- width.value = widthReference.value.offsetWidth;
28
+ if (dimsReference.value) {
29
+ width.value = dimsReference.value.offsetWidth;
30
+ height.value = dimsReference.value.offsetHeight;
28
31
  }
29
32
  },
30
33
  { flush: "post" }
@@ -43,12 +46,21 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
43
46
  default: withCtx(() => [
44
47
  unref(show) ? (openBlock(), createElementBlock("div", _hoisted_1, [
45
48
  createElementVNode("div", {
46
- style: normalizeStyle({ width: `${width.value}px` }),
47
- class: "h-8 overflow-hidden whitespace-nowrap rounded-b border-x border-b border-p-gray-30 bg-p-blue-10 px-4 pt-2 text-center text-sm font-semibold leading-none text-p-purple-60 shadow-sm transition-all duration-500"
49
+ style: normalizeStyle({ width: `${width.value}px`, height: `${height.value}px` }),
50
+ class: "overflow-hidden rounded-b border-x border-b border-p-gray-30 bg-p-blue-10 shadow-sm transition-all duration-300"
48
51
  }, [
49
- isComponent(unref(content)) ? (openBlock(), createBlock(resolveDynamicComponent(unref(content)), { key: 0 })) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
50
- createTextVNode(toDisplayString(unref(content)), 1)
51
- ], 64))
52
+ createVNode(Transition, {
53
+ "enter-from-class": "opacity-0",
54
+ "enter-active-class": "transition duration-500"
55
+ }, {
56
+ default: withCtx(() => [
57
+ isComponent(unref(content)) ? (openBlock(), createBlock(resolveDynamicComponent(unref(content)), normalizeProps(mergeProps({ key: 0 }, unref(componentProps))), null, 16)) : (openBlock(), createElementBlock("div", {
58
+ key: 1,
59
+ class: normalizeClass(textDivClass)
60
+ }, toDisplayString(unref(content)), 1))
61
+ ]),
62
+ _: 1
63
+ })
52
64
  ], 4)
53
65
  ])) : createCommentVNode("", true)
54
66
  ]),
@@ -56,20 +68,20 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
56
68
  }),
57
69
  unref(content) ? (openBlock(), createElementBlock("div", _hoisted_2, [
58
70
  createElementVNode("div", {
59
- ref_key: "widthReference",
60
- ref: widthReference,
61
- class: "inline-flex px-4"
71
+ ref_key: "dimsReference",
72
+ ref: dimsReference
62
73
  }, [
63
- isComponent(unref(content)) ? (openBlock(), createBlock(resolveDynamicComponent(unref(content)), { key: 0 })) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
64
- createTextVNode(toDisplayString(unref(content)), 1)
65
- ], 64))
74
+ isComponent(unref(content)) ? (openBlock(), createBlock(resolveDynamicComponent(unref(content)), normalizeProps(mergeProps({ key: 0 }, unref(componentProps))), null, 16)) : (openBlock(), createElementBlock("div", {
75
+ key: 1,
76
+ class: normalizeClass(textDivClass)
77
+ }, toDisplayString(unref(content)), 1))
66
78
  ], 512)
67
79
  ])) : createCommentVNode("", true)
68
80
  ], 64);
69
81
  };
70
82
  }
71
83
  });
72
- const pLoading = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-8c0c66ab"]]);
84
+ const pLoading = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-6f528d56"]]);
73
85
  export {
74
86
  pLoading as default
75
87
  };
@@ -6,6 +6,10 @@ const content = computed(() => {
6
6
  var _a;
7
7
  return (_a = loadingItems.value[loadingItems.value.length - 1]) == null ? void 0 : _a.content;
8
8
  });
9
+ const props = computed(() => {
10
+ var _a;
11
+ return (_a = loadingItems.value[loadingItems.value.length - 1]) == null ? void 0 : _a.props;
12
+ });
9
13
  let timer;
10
14
  const usePLoading = (options) => {
11
15
  const { delay } = { delay: 200, ...options };
@@ -23,11 +27,19 @@ const usePLoading = (options) => {
23
27
  }
24
28
  loadingItems.value.push({
25
29
  id: loadingItem.id,
26
- content: loadingItem.content && typeof loadingItem.content === "object" ? markRaw(loadingItem.content) : loadingItem.content || LOADING_TEXT
30
+ content: loadingItem.content && typeof loadingItem.content === "object" ? markRaw(loadingItem.content) : loadingItem.content || LOADING_TEXT,
31
+ props: loadingItem.props
27
32
  });
28
33
  };
29
34
  const loadingHide = (id) => {
30
- loadingItems.value = id && typeof id === "string" ? loadingItems.value.filter((item) => item.id !== id) : [];
35
+ if (id && typeof id === "string") {
36
+ const index = loadingItems.value.findIndex((item) => item.id === id);
37
+ if (index !== -1) {
38
+ loadingItems.value.splice(index, 1);
39
+ }
40
+ } else {
41
+ loadingItems.value = [];
42
+ }
31
43
  if (loadingItems.value.length === 0) {
32
44
  show.value = false;
33
45
  }
@@ -40,7 +52,7 @@ const usePLoading = (options) => {
40
52
  clearTimeout(timer);
41
53
  });
42
54
  }
43
- return { show, content, loadingShow, loadingHide };
55
+ return { show, content, props, loadingShow, loadingHide };
44
56
  };
45
57
  export {
46
58
  usePLoading
@@ -6,10 +6,12 @@ type Content = string | Component;
6
6
  type LoadingItem = {
7
7
  id: string;
8
8
  content?: Content;
9
+ props?: Ref;
9
10
  };
10
11
  type UsePLoading = {
11
12
  show: Ref<boolean>;
12
13
  content: Content;
14
+ props: Ref;
13
15
  loadingShow: (loadingItem: LoadingItem) => void;
14
16
  loadingHide: (id: LoadingItem['id']) => void;
15
17
  };
package/dist/style.css CHANGED
@@ -381,12 +381,12 @@ from {
381
381
  to {
382
382
  opacity: 0;
383
383
  }
384
- }.fadeInDown[data-v-8c0c66ab] {
384
+ }.fadeInDown[data-v-6f528d56] {
385
385
  animation-duration: 0.4s;
386
386
  animation-fill-mode: both;
387
- animation-name: fadeInDown-8c0c66ab;
387
+ animation-name: fadeInDown-6f528d56;
388
388
  }
389
- @keyframes fadeInDown-8c0c66ab {
389
+ @keyframes fadeInDown-6f528d56 {
390
390
  0% {
391
391
  opacity: 0;
392
392
  transform: translate3d(0, -100%, 0);
@@ -396,12 +396,12 @@ to {
396
396
  transform: none;
397
397
  }
398
398
  }
399
- .fadeOutUp[data-v-8c0c66ab] {
399
+ .fadeOutUp[data-v-6f528d56] {
400
400
  animation-duration: 0.25s;
401
401
  animation-fill-mode: both;
402
- animation-name: fadeOutUp-8c0c66ab;
402
+ animation-name: fadeOutUp-6f528d56;
403
403
  }
404
- @keyframes fadeOutUp-8c0c66ab {
404
+ @keyframes fadeOutUp-6f528d56 {
405
405
  0% {
406
406
  opacity: 1;
407
407
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pequity/squirrel",
3
3
  "description": "Squirrel component library",
4
- "version": "3.0.2",
4
+ "version": "3.1.0",
5
5
  "packageManager": "pnpm@8.9.2",
6
6
  "type": "module",
7
7
  "scripts": {
@@ -82,11 +82,11 @@
82
82
  "@vue/vue3-jest": "^29.2.6",
83
83
  "autoprefixer": "^10.4.19",
84
84
  "babel-jest": "^29.7.0",
85
- "dayjs": "1.11.11",
85
+ "dayjs": "1.11.12",
86
86
  "eslint": "^8.57.0",
87
87
  "eslint-plugin-storybook": "^0.8.0",
88
88
  "floating-vue": "5.2.2",
89
- "glob": "^10.4.3",
89
+ "glob": "^10.4.5",
90
90
  "husky": "^9.1.1",
91
91
  "jest": "^29.7.0",
92
92
  "jest-environment-jsdom": "^29.7.0",
@@ -97,17 +97,17 @@
97
97
  "prettier": "^3.3.3",
98
98
  "prettier-plugin-tailwindcss": "^0.6.5",
99
99
  "resolve-tspaths": "^0.8.19",
100
- "rimraf": "^5.0.8",
100
+ "rimraf": "^5.0.9",
101
101
  "sass": "^1.77.8",
102
102
  "semantic-release": "^24.0.0",
103
103
  "storybook": "^8.2.5",
104
104
  "svgo": "^3.3.2",
105
105
  "tailwindcss": "^3.4.6",
106
106
  "ts-jest": "^29.2.3",
107
- "typescript": "5.5.3",
107
+ "typescript": "5.5.4",
108
108
  "v-calendar": "3.1.2",
109
109
  "vite": "^5.3.4",
110
- "vue": "3.4.32",
110
+ "vue": "3.4.33",
111
111
  "vue-currency-input": "3.1.0",
112
112
  "vue-router": "4.4.0",
113
113
  "vue-toastification": "2.0.0-rc.5",
@@ -1,6 +1,7 @@
1
1
  import PLoading from '@squirrel/components/p-loading/p-loading.vue';
2
2
  import PSkeletonLoader from '@squirrel/components/p-skeleton-loader/p-skeleton-loader.vue';
3
3
  import { createWrapperFor, waitNT } from '@tests/jest.helpers';
4
+ import { defineComponent, ref } from 'vue';
4
5
  import { usePLoading } from '@squirrel/components/p-loading/usePLoading';
5
6
 
6
7
  const createAppWrapper = () =>
@@ -218,4 +219,61 @@ describe('PLoading.vue', () => {
218
219
  });
219
220
  }).toThrowError('id is required');
220
221
  });
222
+
223
+ it(`accepts a component with reactive props as the content`, async () => {
224
+ const TestComponent = defineComponent({
225
+ name: 'TestComponent',
226
+ props: {
227
+ modelValue: {
228
+ type: Number,
229
+ required: true,
230
+ },
231
+ },
232
+ template: `<div>{{ modelValue }}</div>`,
233
+ });
234
+
235
+ const wrapper = createWrapperFor({
236
+ template: `
237
+ <button class="request-1-sec-component-props" @click="fireRequestComponentProps"></button>
238
+ <button class="update-props" @click="updateProps"></button>
239
+ `,
240
+ components: { TestComponent },
241
+ setup() {
242
+ const componentProps = ref({ modelValue: 0 });
243
+ const { loadingShow, loadingHide } = usePLoading();
244
+
245
+ const fireRequestComponentProps = async () => {
246
+ const id = `component-props`;
247
+ componentProps.value.modelValue = 10;
248
+ loadingShow({ id, content: TestComponent, props: componentProps });
249
+ await new Promise((resolve) => setTimeout(resolve, 1000));
250
+ loadingHide(id);
251
+ };
252
+
253
+ const updateProps = () => {
254
+ componentProps.value.modelValue = 20;
255
+ };
256
+
257
+ return { loadingShow, loadingHide, fireRequestComponentProps, updateProps };
258
+ },
259
+ });
260
+
261
+ await wrapper.find('.request-1-sec-component-props').trigger('click');
262
+
263
+ jest.advanceTimersByTime(300);
264
+ await waitNT(appWrapper.vm);
265
+ const testComponent = appWrapper.findComponent(TestComponent);
266
+ expect(appWrapper.find('[aria-busy]').exists()).toBe(true);
267
+ expect(testComponent.exists()).toBe(true);
268
+ expect(testComponent.props().modelValue).toBe(10);
269
+
270
+ jest.advanceTimersByTime(300);
271
+ await waitNT(appWrapper.vm);
272
+ await wrapper.find('.update-props').trigger('click');
273
+ expect(testComponent.props().modelValue).toBe(20);
274
+
275
+ jest.advanceTimersByTime(500);
276
+ await waitNT(appWrapper.vm);
277
+ expect(appWrapper.find('[aria-busy]').exists()).toBe(false);
278
+ });
221
279
  });
@@ -1,8 +1,20 @@
1
- import ComputationStatus from '@/playground/components/ComputationStatus.vue';
1
+ import ComputationStatus1 from '@/playground/components/ComputationStatus1.vue';
2
2
  import PBtn from '@squirrel/components/p-btn/p-btn.vue';
3
3
  import PLoading from '@squirrel/components/p-loading/p-loading.vue';
4
+ import { defineComponent, ref } from 'vue';
4
5
  import { usePLoading } from '@squirrel/components/p-loading/usePLoading';
5
6
 
7
+ const TestComponent = defineComponent({
8
+ name: 'TestComponent',
9
+ props: {
10
+ modelValue: {
11
+ type: String,
12
+ default: '',
13
+ },
14
+ },
15
+ template: `<div class="text-sm px-4 py-2 whitespace-nowrap">{{ modelValue }}</div>`,
16
+ });
17
+
6
18
  export default {
7
19
  title: 'Components/PLoading',
8
20
  component: PLoading,
@@ -87,7 +99,7 @@ export const WithComponentAsContent = {
87
99
 
88
100
  const fireRequestComponent = async (time) => {
89
101
  const id = `component-${time}`;
90
- loadingShow({ id, content: ComputationStatus });
102
+ loadingShow({ id, content: ComputationStatus1 });
91
103
  await new Promise((resolve) => setTimeout(resolve, time));
92
104
  loadingHide(id);
93
105
  };
@@ -107,3 +119,46 @@ export const WithComponentAsContent = {
107
119
  `,
108
120
  }),
109
121
  };
122
+
123
+ export const WithComponentWithPropsAsContent = {
124
+ render: (args) => ({
125
+ components: { PLoading, PBtn, TestComponent },
126
+ setup() {
127
+ const { loadingShow, loadingHide } = usePLoading();
128
+ const loading = ref(false);
129
+ const componentProps = ref({ modelValue: '' });
130
+
131
+ const fireRequestComponentProps = async () => {
132
+ const id = `component-props`;
133
+ componentProps.value = { modelValue: 'Loading, please wait' };
134
+
135
+ loading.value = true;
136
+ loadingShow({ id, content: TestComponent, props: componentProps });
137
+
138
+ await new Promise((resolve) => setTimeout(resolve, 1500));
139
+
140
+ componentProps.value = { modelValue: 'Still loading...' };
141
+
142
+ await new Promise((resolve) => setTimeout(resolve, 1500));
143
+
144
+ componentProps.value = { modelValue: 'Almost there!' };
145
+
146
+ await new Promise((resolve) => setTimeout(resolve, 1500));
147
+
148
+ loadingHide(id);
149
+ loading.value = false;
150
+ };
151
+
152
+ return { args, loadingShow, fireRequestComponentProps, loading };
153
+ },
154
+ template: `
155
+ <PLoading />
156
+ <div class="mt-10">
157
+ <div>Demo with a component with props as content</div>
158
+ <div class="flex gap-4 mt-2">
159
+ <PBtn @click="fireRequestComponentProps" :disabled="loading">Display loader</PBtn>
160
+ </div>
161
+ </div>
162
+ `,
163
+ }),
164
+ };
@@ -2,18 +2,20 @@
2
2
  <Transition name="pm-backdrop-transition" enter-active-class="fadeInDown" leave-active-class="fadeOutUp">
3
3
  <div v-if="show" class="fixed left-0 top-0 z-[120] flex w-full justify-center" aria-live="polite" aria-busy="true">
4
4
  <div
5
- :style="{ width: `${width}px` }"
6
- class="h-8 overflow-hidden whitespace-nowrap rounded-b border-x border-b border-p-gray-30 bg-p-blue-10 px-4 pt-2 text-center text-sm font-semibold leading-none text-p-purple-60 shadow-sm transition-all duration-500"
5
+ :style="{ width: `${width}px`, height: `${height}px` }"
6
+ class="overflow-hidden rounded-b border-x border-b border-p-gray-30 bg-p-blue-10 shadow-sm transition-all duration-300"
7
7
  >
8
- <Component :is="content" v-if="isComponent(content)" />
9
- <template v-else>{{ content }}</template>
8
+ <Transition enter-from-class="opacity-0" enter-active-class="transition duration-500">
9
+ <Component :is="content" v-if="isComponent(content)" v-bind="componentProps" />
10
+ <div v-else :class="textDivClass">{{ content }}</div>
11
+ </Transition>
10
12
  </div>
11
13
  </div>
12
14
  </Transition>
13
15
  <div v-if="content" class="invisible fixed">
14
- <div ref="widthReference" class="inline-flex px-4">
15
- <Component :is="content" v-if="isComponent(content)" />
16
- <template v-else>{{ content }}</template>
16
+ <div ref="dimsReference">
17
+ <Component :is="content" v-if="isComponent(content)" v-bind="componentProps" />
18
+ <div v-else :class="textDivClass">{{ content }}</div>
17
19
  </div>
18
20
  </div>
19
21
  </template>
@@ -22,19 +24,23 @@
22
24
  import { type Component, ref, toValue, watch } from 'vue';
23
25
  import { usePLoading } from '@squirrel/components/p-loading/usePLoading';
24
26
 
27
+ const textDivClass = `overflow-hidden whitespace-nowrap px-4 pt-1 h-8 text-center text-sm font-semibold text-p-purple-60`;
28
+
25
29
  defineOptions({
26
30
  name: 'PLoading',
27
31
  });
28
32
 
29
- const { show, content } = usePLoading();
30
- const widthReference = ref<HTMLElement | null>(null);
33
+ const { show, content, props: componentProps } = usePLoading();
34
+ const dimsReference = ref<HTMLElement | null>(null);
31
35
  const width = ref(0);
36
+ const height = ref(0);
32
37
 
33
38
  watch(
34
39
  () => toValue(content),
35
40
  () => {
36
- if (widthReference.value) {
37
- width.value = widthReference.value.offsetWidth;
41
+ if (dimsReference.value) {
42
+ width.value = dimsReference.value.offsetWidth;
43
+ height.value = dimsReference.value.offsetHeight;
38
44
  }
39
45
  },
40
46
  { flush: 'post' }
@@ -9,11 +9,13 @@ type Content = string | Component;
9
9
  type LoadingItem = {
10
10
  id: string;
11
11
  content?: Content;
12
+ props?: Ref;
12
13
  };
13
14
 
14
15
  type UsePLoading = {
15
16
  show: Ref<boolean>;
16
17
  content: Content;
18
+ props: Ref;
17
19
  loadingShow: (loadingItem: LoadingItem) => void;
18
20
  loadingHide: (id: LoadingItem['id']) => void;
19
21
  };
@@ -22,6 +24,7 @@ const LOADING_TEXT = 'Loading...';
22
24
  const show = ref(false);
23
25
  const loadingItems = ref<LoadingItem[]>([]);
24
26
  const content = computed(() => loadingItems.value[loadingItems.value.length - 1]?.content);
27
+ const props = computed(() => loadingItems.value[loadingItems.value.length - 1]?.props);
25
28
  let timer: ReturnType<typeof setTimeout>;
26
29
 
27
30
  export const usePLoading = (options?: Options): UsePLoading => {
@@ -47,11 +50,21 @@ export const usePLoading = (options?: Options): UsePLoading => {
47
50
  loadingItem.content && typeof loadingItem.content === 'object'
48
51
  ? markRaw(loadingItem.content)
49
52
  : loadingItem.content || LOADING_TEXT,
53
+ props: loadingItem.props,
50
54
  });
51
55
  };
52
56
 
53
57
  const loadingHide = (id?: LoadingItem['id']) => {
54
- loadingItems.value = id && typeof id === 'string' ? loadingItems.value.filter((item) => item.id !== id) : [];
58
+ if (id && typeof id === 'string') {
59
+ const index = loadingItems.value.findIndex((item) => item.id === id);
60
+
61
+ if (index !== -1) {
62
+ loadingItems.value.splice(index, 1);
63
+ }
64
+ } else {
65
+ loadingItems.value = [];
66
+ }
67
+
55
68
  if (loadingItems.value.length === 0) {
56
69
  show.value = false;
57
70
  }
@@ -66,5 +79,5 @@ export const usePLoading = (options?: Options): UsePLoading => {
66
79
  });
67
80
  }
68
81
 
69
- return { show, content, loadingShow, loadingHide };
82
+ return { show, content, props, loadingShow, loadingHide };
70
83
  };