vite-plugin-vue-devtools 1.0.0-beta.2 → 1.0.0-beta.4

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.
Files changed (45) hide show
  1. package/README.md +6 -0
  2. package/dist/client/assets/{Icon.vue_vue_type_script_setup_true_lang-5b8e75b9.js → Icon.vue_vue_type_script_setup_true_lang-4a8fe583.js} +1 -1
  3. package/dist/client/assets/{IconButton.vue_vue_type_script_setup_true_lang-1af9c374.js → IconButton.vue_vue_type_script_setup_true_lang-7533112d.js} +2 -2
  4. package/dist/client/assets/{IconTitle.vue_vue_type_script_setup_true_lang-4fc5b6ac.js → IconTitle.vue_vue_type_script_setup_true_lang-bdc080e4.js} +1 -1
  5. package/dist/client/assets/{IframeView.vue_vue_type_script_setup_true_lang-297e573e.js → IframeView.vue_vue_type_script_setup_true_lang-77dbdc62.js} +1 -1
  6. package/dist/client/assets/{PanelGrids-15f9a979.js → PanelGrids-3cdf73ad.js} +1 -1
  7. package/dist/client/assets/{SectionBlock-22f38034.js → SectionBlock-0fb75671.js} +3 -3
  8. package/dist/client/assets/{StateFields.vue_vue_type_script_setup_true_lang-eaba3733.js → StateFields.vue_vue_type_script_setup_true_lang-65d71ce4.js} +4 -4
  9. package/dist/client/assets/{Switch.vue_vue_type_script_setup_true_lang-a9a3bfb2.js → Switch.vue_vue_type_script_setup_true_lang-3983cd12.js} +2 -2
  10. package/dist/client/assets/{TextInput.vue_vue_type_script_setup_true_lang-9ca4104f.js → TextInput.vue_vue_type_script_setup_true_lang-40607e18.js} +2 -2
  11. package/dist/client/assets/{__eyedropper-e3f5ba7f.js → __eyedropper-ba9a76be.js} +4 -4
  12. package/dist/client/assets/{_commonjsHelpers-d60b99f1.js → _commonjsHelpers-7e83dbf2.js} +1 -4
  13. package/dist/client/assets/{assets-cef4559f.js → assets-1c2e5083.js} +94 -42
  14. package/dist/client/assets/{component-docs-9c6b3cc7.js → component-docs-57fca81e.js} +4 -4
  15. package/dist/client/assets/{components-50e17a38.js → components-b8f121d9.js} +8 -8
  16. package/dist/client/assets/{data-1539e705.js → data-4774a5dd.js} +2 -2
  17. package/dist/client/assets/{dayjs.min-3c1187ae.js → dayjs.min-ff0bd3aa.js} +1 -1
  18. package/dist/client/assets/{documentations-795a4925.js → documentations-f47e8527.js} +2 -2
  19. package/dist/client/assets/{graph-f6be4c87.js → graph-128136c1.js} +4 -4
  20. package/dist/client/assets/{index-ef144caa.js → index-5266a399.js} +1 -1
  21. package/dist/client/assets/{index-55dde797.js → index-6b2b8b6a.js} +19 -15
  22. package/dist/client/assets/index-f4f0a93b.css +480 -0
  23. package/dist/client/assets/{inspect-02ab40c2.js → inspect-d185c0d8.js} +2 -2
  24. package/dist/client/assets/{npm-729d97d0.js → npm-760dcb8c.js} +9 -8
  25. package/dist/client/assets/{overview-6ed55b17.js → overview-8f06d8d8.js} +4 -4
  26. package/dist/client/assets/{pages-2efdff81.js → pages-2ad456d4.js} +5 -5
  27. package/dist/client/assets/{pinia-99843507.js → pinia-1f4baab5.js} +6 -6
  28. package/dist/client/assets/rerender-trace-a8d6a8df.css +14 -0
  29. package/dist/client/assets/{rerender-trace-a1fc81e7.js → rerender-trace-e2a70cde.js} +102 -37
  30. package/dist/client/assets/{routes-56bbe197.js → routes-cc654c70.js} +7 -7
  31. package/dist/client/assets/{settings-6ac3fbc1.js → settings-0c6c179d.js} +7 -7
  32. package/dist/client/assets/{splitpanes.es-ca653775.js → splitpanes.es-16f3d333.js} +1 -1
  33. package/dist/client/assets/{timeline-d5f5f884.js → timeline-252da334.js} +9 -9
  34. package/dist/client/index.html +2 -2
  35. package/dist/vite.cjs +16 -10
  36. package/dist/vite.d.ts +5 -0
  37. package/dist/vite.mjs +15 -9
  38. package/package.json +5 -5
  39. package/src/views/ComponentInspector.vue +1 -0
  40. package/src/views/Main.vue +7 -1
  41. package/src/views/RerenderIndicator.vue +37 -0
  42. package/src/views/composables.ts +43 -1
  43. package/src/views/utils.ts +13 -0
  44. package/dist/client/assets/index-b16c49d4.css +0 -475
  45. package/dist/client/assets/rerender-trace-6c5229c1.css +0 -14
@@ -1,12 +1,12 @@
1
- import { _ as _sfc_main$2 } from './StateFields.vue_vue_type_script_setup_true_lang-eaba3733.js';
2
- import { _ as __unplugin_components_0 } from './PanelGrids-15f9a979.js';
3
- import { p as pushScopeId, a as popScopeId, n as nextTick, o as openBlock, c as createBlock, w as withScopeId, m as markRaw, s as shallowReactive, r as resolveComponent, b as resolveDirective, d as withDirectives, e as createElementBlock, f as renderSlot, g as createCommentVNode, h as withCtx, F as Fragment, i as renderList, j as resolveDynamicComponent, k as mergeProps, t as toHandlers, l as normalizeStyle, q as normalizeClass, u as createVNode, v as defineComponent, x as createBaseVNode, y as toDisplayString, z as unref, _ as __unplugin_components_7, A as timelineLayer, B as activeTimelineEvents, C as activeTimelineEventIndex, D as toggleTimelineEventIndex, E as timelineEventDetails, G as activeLayerId, H as toggleTimelineLayer } from './index-55dde797.js';
4
- import { d as dayjs } from './dayjs.min-3c1187ae.js';
5
- import { g, M } from './splitpanes.es-ca653775.js';
6
- import './Icon.vue_vue_type_script_setup_true_lang-5b8e75b9.js';
7
- import './index-ef144caa.js';
8
- import './IconButton.vue_vue_type_script_setup_true_lang-1af9c374.js';
9
- import './_commonjsHelpers-d60b99f1.js';
1
+ import { _ as _sfc_main$2 } from './StateFields.vue_vue_type_script_setup_true_lang-65d71ce4.js';
2
+ import { _ as __unplugin_components_0 } from './PanelGrids-3cdf73ad.js';
3
+ import { p as pushScopeId, a as popScopeId, n as nextTick, o as openBlock, c as createBlock, w as withScopeId, m as markRaw, s as shallowReactive, r as resolveComponent, b as resolveDirective, d as withDirectives, e as createElementBlock, f as renderSlot, g as createCommentVNode, h as withCtx, F as Fragment, i as renderList, j as resolveDynamicComponent, k as mergeProps, t as toHandlers, l as normalizeStyle, q as normalizeClass, u as createVNode, v as defineComponent, x as createBaseVNode, y as toDisplayString, z as unref, _ as __unplugin_components_7, A as timelineLayer, B as activeTimelineEvents, C as activeTimelineEventIndex, D as toggleTimelineEventIndex, E as timelineEventDetails, G as activeLayerId, H as toggleTimelineLayer } from './index-6b2b8b6a.js';
4
+ import { d as dayjs } from './dayjs.min-ff0bd3aa.js';
5
+ import { g, M } from './splitpanes.es-16f3d333.js';
6
+ import './Icon.vue_vue_type_script_setup_true_lang-4a8fe583.js';
7
+ import './index-5266a399.js';
8
+ import './IconButton.vue_vue_type_script_setup_true_lang-7533112d.js';
9
+ import './_commonjsHelpers-7e83dbf2.js';
10
10
 
11
11
  function getInternetExplorerVersion() {
12
12
  var ua = window.navigator.userAgent;
@@ -5,8 +5,8 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <link rel="icon" href="/favicon.svg" type="image/svg+xml">
7
7
  <title>Vue DevTools</title>
8
- <script type="module" crossorigin src="./assets/index-55dde797.js"></script>
9
- <link rel="stylesheet" href="./assets/index-b16c49d4.css">
8
+ <script type="module" crossorigin src="./assets/index-6b2b8b6a.js"></script>
9
+ <link rel="stylesheet" href="./assets/index-f4f0a93b.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="app"></div>
package/dist/vite.cjs CHANGED
@@ -16,10 +16,10 @@ const require$$0$3 = require('stream');
16
16
  const require$$2 = require('events');
17
17
  const require$$0$4 = require('fs');
18
18
  const fs$1$1 = require('node:fs');
19
+ const process$2 = require('node:process');
19
20
  const require$$0$7 = require('readline');
20
21
  const node_buffer = require('node:buffer');
21
22
  const childProcess = require('node:child_process');
22
- const process$2 = require('node:process');
23
23
  const require$$0$2$1 = require('child_process');
24
24
  const os$1$1 = require('node:os');
25
25
  const require$$0$3$1 = require('assert');
@@ -42,9 +42,9 @@ const require$$0__default$3 = /*#__PURE__*/_interopDefaultCompat(require$$0$3);
42
42
  const require$$2__default = /*#__PURE__*/_interopDefaultCompat(require$$2);
43
43
  const require$$0__default$4 = /*#__PURE__*/_interopDefaultCompat(require$$0$4);
44
44
  const fs$1__default = /*#__PURE__*/_interopDefaultCompat(fs$1$1);
45
+ const process$2__default = /*#__PURE__*/_interopDefaultCompat(process$2);
45
46
  const require$$0$7__default = /*#__PURE__*/_interopDefaultCompat(require$$0$7);
46
47
  const childProcess__default = /*#__PURE__*/_interopDefaultCompat(childProcess);
47
- const process$2__default = /*#__PURE__*/_interopDefaultCompat(process$2);
48
48
  const require$$0$2__default = /*#__PURE__*/_interopDefaultCompat(require$$0$2$1);
49
49
  const os$1__default = /*#__PURE__*/_interopDefaultCompat(os$1$1);
50
50
  const require$$0$3__default = /*#__PURE__*/_interopDefaultCompat(require$$0$3$1);
@@ -6646,6 +6646,8 @@ var settings = {};
6646
6646
  if (this.stats) {
6647
6647
  this.objectMode = true;
6648
6648
  }
6649
+ // Remove the cast to the array in the next major (#404).
6650
+ this.ignore = [].concat(this.ignore);
6649
6651
  }
6650
6652
  _getValue(option, value) {
6651
6653
  return option === undefined ? value : option;
@@ -8035,8 +8037,8 @@ async function findUp(name, options = {}) {
8035
8037
  return matches[0];
8036
8038
  }
8037
8039
 
8038
- process.env.NI_CONFIG_FILE;
8039
- const home = process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME;
8040
+ process$2__default.env.NI_CONFIG_FILE;
8041
+ const home = process$2__default.platform === "win32" ? process$2__default.env.USERPROFILE : process$2__default.env.HOME;
8040
8042
  path$3__default.join(home || "~/", ".nirc");
8041
8043
 
8042
8044
  var crossSpawn$1 = {exports: {}};
@@ -13634,8 +13636,8 @@ async function detect({ autoInstall, programmatic, cwd } = {}) {
13634
13636
  if (!autoInstall) {
13635
13637
  console.warn(`[ni] Detected ${agent} but it doesn't seem to be installed.
13636
13638
  `);
13637
- if (process.env.CI)
13638
- process.exit(1);
13639
+ if (process$2__default.env.CI)
13640
+ process$2__default.exit(1);
13639
13641
  const link = terminalLink(agent, INSTALL_PAGE[agent]);
13640
13642
  const { tryInstall } = await prompts$1({
13641
13643
  name: "tryInstall",
@@ -13643,7 +13645,7 @@ async function detect({ autoInstall, programmatic, cwd } = {}) {
13643
13645
  message: `Would you like to globally install ${link}?`
13644
13646
  });
13645
13647
  if (!tryInstall)
13646
- process.exit(1);
13648
+ process$2__default.exit(1);
13647
13649
  }
13648
13650
  await execaCommand(`npm i -g ${agent}${version ? `@${version}` : ""}`, { stdio: "inherit", cwd });
13649
13651
  }
@@ -13663,7 +13665,8 @@ function getCommand(agent, command, args = []) {
13663
13665
  return c(args);
13664
13666
  if (!c)
13665
13667
  throw new UnsupportedCommand({ agent, command });
13666
- return c.replace("{0}", args.join(" ")).trim();
13668
+ const quote = (arg) => !arg.startsWith("--") && arg.includes(" ") ? JSON.stringify(arg) : arg;
13669
+ return c.replace("{0}", args.map(quote).join(" ")).trim();
13667
13670
  }
13668
13671
  const parseNi = (agent, args, ctx) => {
13669
13672
  if (agent === "bun")
@@ -13754,7 +13757,8 @@ function getVueDevtoolsPath() {
13754
13757
  }
13755
13758
  const defaultOptions = {
13756
13759
  appendTo: "",
13757
- analyze: compiler.analyzeOptionsDefault
13760
+ analyze: compiler.analyzeOptionsDefault,
13761
+ openInEditorHost: false
13758
13762
  };
13759
13763
  function mergeOptions(options) {
13760
13764
  return Object.assign({}, defaultOptions, options);
@@ -13865,7 +13869,9 @@ import 'virtual:vue-devtools-path:app.js'`;
13865
13869
  inspect,
13866
13870
  VueInspector__default({
13867
13871
  toggleComboKey: "",
13868
- toggleButtonVisibility: "never"
13872
+ toggleButtonVisibility: "never",
13873
+ openInEditorHost: pluginOptions.openInEditorHost,
13874
+ ...pluginOptions.appendTo ? { appendTo: pluginOptions.appendTo } : {}
13869
13875
  })
13870
13876
  ];
13871
13877
  }
package/dist/vite.d.ts CHANGED
@@ -18,6 +18,11 @@ interface VitePluginVueDevToolsOptions {
18
18
  * }
19
19
  */
20
20
  analyze?: Partial<AnalyzeOptions>;
21
+ /**
22
+ * Customize openInEditor host (e.g. http://localhost:3000)
23
+ * @default false
24
+ */
25
+ openInEditorHost?: string | false;
21
26
  }
22
27
  declare function VitePluginVueDevTools(options?: VitePluginVueDevToolsOptions): PluginOption;
23
28
 
package/dist/vite.mjs CHANGED
@@ -14,10 +14,10 @@ import require$$0$3 from 'stream';
14
14
  import require$$2 from 'events';
15
15
  import require$$0$4 from 'fs';
16
16
  import fs$1$1, { promises, createWriteStream, createReadStream } from 'node:fs';
17
+ import process$2 from 'node:process';
17
18
  import require$$0$7 from 'readline';
18
19
  import { Buffer as Buffer$1 } from 'node:buffer';
19
20
  import childProcess, { ChildProcess } from 'node:child_process';
20
- import process$2 from 'node:process';
21
21
  import require$$0$2$1 from 'child_process';
22
22
  import os$1$1, { constants as constants$5 } from 'node:os';
23
23
  import require$$0$3$1 from 'assert';
@@ -6620,6 +6620,8 @@ var settings = {};
6620
6620
  if (this.stats) {
6621
6621
  this.objectMode = true;
6622
6622
  }
6623
+ // Remove the cast to the array in the next major (#404).
6624
+ this.ignore = [].concat(this.ignore);
6623
6625
  }
6624
6626
  _getValue(option, value) {
6625
6627
  return option === undefined ? value : option;
@@ -8009,8 +8011,8 @@ async function findUp(name, options = {}) {
8009
8011
  return matches[0];
8010
8012
  }
8011
8013
 
8012
- process.env.NI_CONFIG_FILE;
8013
- const home = process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME;
8014
+ process$2.env.NI_CONFIG_FILE;
8015
+ const home = process$2.platform === "win32" ? process$2.env.USERPROFILE : process$2.env.HOME;
8014
8016
  path$3$1.join(home || "~/", ".nirc");
8015
8017
 
8016
8018
  var crossSpawn$1 = {exports: {}};
@@ -13608,8 +13610,8 @@ async function detect({ autoInstall, programmatic, cwd } = {}) {
13608
13610
  if (!autoInstall) {
13609
13611
  console.warn(`[ni] Detected ${agent} but it doesn't seem to be installed.
13610
13612
  `);
13611
- if (process.env.CI)
13612
- process.exit(1);
13613
+ if (process$2.env.CI)
13614
+ process$2.exit(1);
13613
13615
  const link = terminalLink(agent, INSTALL_PAGE[agent]);
13614
13616
  const { tryInstall } = await prompts$1({
13615
13617
  name: "tryInstall",
@@ -13617,7 +13619,7 @@ async function detect({ autoInstall, programmatic, cwd } = {}) {
13617
13619
  message: `Would you like to globally install ${link}?`
13618
13620
  });
13619
13621
  if (!tryInstall)
13620
- process.exit(1);
13622
+ process$2.exit(1);
13621
13623
  }
13622
13624
  await execaCommand(`npm i -g ${agent}${version ? `@${version}` : ""}`, { stdio: "inherit", cwd });
13623
13625
  }
@@ -13637,7 +13639,8 @@ function getCommand(agent, command, args = []) {
13637
13639
  return c(args);
13638
13640
  if (!c)
13639
13641
  throw new UnsupportedCommand({ agent, command });
13640
- return c.replace("{0}", args.join(" ")).trim();
13642
+ const quote = (arg) => !arg.startsWith("--") && arg.includes(" ") ? JSON.stringify(arg) : arg;
13643
+ return c.replace("{0}", args.map(quote).join(" ")).trim();
13641
13644
  }
13642
13645
  const parseNi = (agent, args, ctx) => {
13643
13646
  if (agent === "bun")
@@ -13728,7 +13731,8 @@ function getVueDevtoolsPath() {
13728
13731
  }
13729
13732
  const defaultOptions = {
13730
13733
  appendTo: "",
13731
- analyze: analyzeOptionsDefault
13734
+ analyze: analyzeOptionsDefault,
13735
+ openInEditorHost: false
13732
13736
  };
13733
13737
  function mergeOptions(options) {
13734
13738
  return Object.assign({}, defaultOptions, options);
@@ -13839,7 +13843,9 @@ import 'virtual:vue-devtools-path:app.js'`;
13839
13843
  inspect,
13840
13844
  VueInspector({
13841
13845
  toggleComboKey: "",
13842
- toggleButtonVisibility: "never"
13846
+ toggleButtonVisibility: "never",
13847
+ openInEditorHost: pluginOptions.openInEditorHost,
13848
+ ...pluginOptions.appendTo ? { appendTo: pluginOptions.appendTo } : {}
13843
13849
  })
13844
13850
  ];
13845
13851
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vite-plugin-vue-devtools",
3
3
  "type": "module",
4
- "version": "1.0.0-beta.2",
4
+ "version": "1.0.0-beta.4",
5
5
  "description": "A vite plugin for Vue DevTools",
6
6
  "author": "webfansplz",
7
7
  "license": "MIT",
@@ -52,12 +52,12 @@
52
52
  "execa": "^7.1.1",
53
53
  "sirv": "^2.0.3",
54
54
  "vite-plugin-inspect": "^0.7.33",
55
- "vite-plugin-vue-inspector": "^3.4.2",
56
- "@vite-plugin-vue-devtools/core": "1.0.0-beta.2"
55
+ "vite-plugin-vue-inspector": "^3.5.0",
56
+ "@vite-plugin-vue-devtools/core": "1.0.0-beta.4"
57
57
  },
58
58
  "devDependencies": {
59
- "@types/node": "^20.4.2",
60
- "fast-glob": "^3.3.0",
59
+ "@types/node": "^20.4.4",
60
+ "fast-glob": "^3.3.1",
61
61
  "image-meta": "^0.1.1",
62
62
  "pathe": "^1.1.1"
63
63
  },
@@ -28,6 +28,7 @@ const inspectorCardStyle = computed(() => ({ top: props.bounds.top < 35 ? 0 : '-
28
28
  <span class="vue-devtools-component-inspector-card" :style="inspectorCardStyle">
29
29
  &lt;{{ name }}&gt;
30
30
  <i>{{ Math.round(bounds.width * 100) / 100 }} x {{ Math.round(bounds.height * 100) / 100 }}</i>
31
+ <slot name="header-extra" />
31
32
  </span>
32
33
  </div>
33
34
  </template>
@@ -6,8 +6,9 @@ import vueDevToolsOptions from 'virtual:vue-devtools-options'
6
6
  import { DevToolsHooks, collectDevToolsHookBuffer } from '@vite-plugin-vue-devtools/core'
7
7
  import Frame from './FrameBox.vue'
8
8
  import ComponentInspector from './ComponentInspector.vue'
9
- import { useHighlightComponent, useIframe, useInspector, usePanelVisible, usePiPMode, usePosition } from './composables'
9
+ import { useHighlightComponent, useIframe, useInspector, usePanelVisible, usePiPMode, usePosition, useRerenderHighlight } from './composables'
10
10
  import { checkIsSafari, useColorScheme, usePreferredColorScheme, warn } from './utils'
11
+ import RerenderIndicator from './RerenderIndicator.vue'
11
12
 
12
13
  const props = defineProps({
13
14
  hook: {
@@ -79,6 +80,7 @@ const { iframe, getIframe } = useIframe(clientUrl, async () => {
79
80
  // Picture-in-Picture mode
80
81
  const { popup } = usePiPMode(getIframe, hook)
81
82
  const { overlayVisible, name: componentName, bounds, highlight, unHighlight } = useHighlightComponent()
83
+ const { updateRerenderHighlightInfo } = useRerenderHighlight()
82
84
 
83
85
  async function setupClient(iframe: HTMLIFrameElement) {
84
86
  const injection: any = iframe?.contentWindow?.__VUE_DEVTOOLS_VIEW__
@@ -124,6 +126,9 @@ async function setupClient(iframe: HTMLIFrameElement) {
124
126
  }, 2000)
125
127
  },
126
128
  },
129
+ rerenderHighlight: {
130
+ updateInfo: updateRerenderHighlightInfo,
131
+ },
127
132
  })
128
133
  }
129
134
 
@@ -284,6 +289,7 @@ collectHookBuffer()
284
289
  </div>
285
290
  <!-- component inspector -->
286
291
  <ComponentInspector v-if="overlayVisible" :bounds="bounds" :name="componentName" />
292
+ <RerenderIndicator />
287
293
  </template>
288
294
 
289
295
  <style scoped>
@@ -0,0 +1,37 @@
1
+ <script setup lang="ts">
2
+ import ComponentInspector from './ComponentInspector.vue'
3
+ import { useRerenderHighlight } from './composables'
4
+
5
+ const { rerenderHighlightMap } = useRerenderHighlight()
6
+
7
+ const colors = [
8
+ ['#ff5555', 50],
9
+ ['#fff888', 20],
10
+ ] as const
11
+
12
+ function getColors(times: number) {
13
+ const [color] = colors.find(([_, t]) => times >= t) || '#fff'
14
+ return color as string
15
+ }
16
+ </script>
17
+
18
+ <template>
19
+ <template v-for="[uid, { bound, rerenderCount, name }] in rerenderHighlightMap.entries()" :key="uid">
20
+ <ComponentInspector
21
+ :bounds="bound"
22
+ :name="name"
23
+ >
24
+ <template #header-extra>
25
+ <span
26
+ v-if="rerenderCount"
27
+ >
28
+ (Rerender Count: <span
29
+ :style="{
30
+ color: getColors(rerenderCount),
31
+ }"
32
+ >{{ rerenderCount + 1 }})</span>
33
+ </span>
34
+ </template>
35
+ </ComponentInspector>
36
+ </template>
37
+ </template>
@@ -1,6 +1,6 @@
1
1
  import { computed, onMounted, reactive, ref, shallowRef, watchEffect } from 'vue'
2
2
  import type { CSSProperties, Ref } from 'vue'
3
- import { clamp, useObjectStorage, useScreenSafeArea, useWindowEventListener, warn } from './utils'
3
+ import { clamp, createDebounceFn, useObjectStorage, useScreenSafeArea, useWindowEventListener, warn } from './utils'
4
4
 
5
5
  interface DevToolsFrameState {
6
6
  width: number
@@ -474,3 +474,45 @@ export function useHighlightComponent() {
474
474
  unHighlight,
475
475
  }
476
476
  }
477
+
478
+ // use rerender highlight
479
+
480
+ interface RerenderHighlightData {
481
+ name: string
482
+ rerenderCount: number
483
+ bound: {
484
+ width: number
485
+ height: number
486
+ left: number
487
+ top: number
488
+ }
489
+ debounceFn: () => void
490
+ }
491
+
492
+ const rerenderHighlightMap = ref<Map</* component instance uid */string, RerenderHighlightData>>(new Map())
493
+
494
+ function updateRerenderHighlightInfo(uid: string, name: string, bound: RerenderHighlightData['bound']) {
495
+ const data = rerenderHighlightMap.value.get(uid)
496
+ if (!data) {
497
+ const debounceFn = createDebounceFn(() => {
498
+ rerenderHighlightMap.value.delete(uid)
499
+ }, 3000)
500
+ rerenderHighlightMap.value.set(uid, {
501
+ rerenderCount: 0,
502
+ bound,
503
+ debounceFn,
504
+ name,
505
+ })
506
+ debounceFn()
507
+ return
508
+ }
509
+ data.rerenderCount += 1
510
+ data.debounceFn()
511
+ }
512
+
513
+ export function useRerenderHighlight() {
514
+ return {
515
+ rerenderHighlightMap,
516
+ updateRerenderHighlightInfo,
517
+ }
518
+ }
@@ -226,3 +226,16 @@ export function usePreferredColorScheme() {
226
226
 
227
227
  return computed(() => isDark.value ? 'dark' : 'light')
228
228
  }
229
+
230
+ export function createDebounceFn<const P, T>(fn: (this: T, ...args: P[]) => void, delay = 100) {
231
+ let timer: any | null = null
232
+ return function (this: T, ...args: P[]) {
233
+ if (timer)
234
+ clearTimeout(timer)
235
+
236
+ timer = setTimeout(() => {
237
+ fn.apply(this, args)
238
+ timer = null
239
+ }, delay)
240
+ }
241
+ }