@tanstack/pacer-devtools 1.4.0 → 1.5.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.
- package/README.md +4 -4
- package/dist/{components-BwHXH_1Y.js → components-BwcTEJfm.js} +15 -7
- package/dist/{components-BXAd-LGS.js → components-D6zc5Wjw.js} +24 -16
- package/dist/index.d.ts +6 -3
- package/dist/index.js +1 -1
- package/dist/production/index.d.ts +2 -2
- package/dist/production/index.js +1 -1
- package/dist/production/server.js +1 -1
- package/dist/server.js +1 -1
- package/package.json +10 -10
- package/src/PacerContextProvider.tsx +0 -172
- package/src/components/ActionButtons.tsx +0 -170
- package/src/components/DetailsPanel.tsx +0 -62
- package/src/components/Shell.tsx +0 -176
- package/src/components/StateHeader.tsx +0 -139
- package/src/components/UtilList.tsx +0 -62
- package/src/components/UtilStateJsonTree.tsx +0 -25
- package/src/components/index.tsx +0 -19
- package/src/components/util-groups.ts +0 -54
- package/src/core.tsx +0 -9
- package/src/index.ts +0 -10
- package/src/production.ts +0 -5
- package/src/styles/tokens.ts +0 -305
- package/src/styles/use-styles.ts +0 -385
- package/src/utils/read-pacer-store-state.ts +0 -33
package/README.md
CHANGED
|
@@ -103,10 +103,10 @@ A lightweight timing and scheduling library for debouncing, throttling, rate lim
|
|
|
103
103
|
> [!NOTE]
|
|
104
104
|
> You may know **TanStack Pacer** by our adapter names, too!
|
|
105
105
|
>
|
|
106
|
-
> - [**React Pacer**](https://tanstack.com/pacer/latest/docs/framework/react
|
|
107
|
-
> - [**Preact Pacer**](https://tanstack.com/pacer/latest/docs/framework/preact
|
|
108
|
-
> - [**Solid Pacer**](https://tanstack.com/pacer/latest/docs/framework/solid
|
|
109
|
-
> - [**Angular Pacer**](https://tanstack.com/pacer/latest/docs/framework/angular
|
|
106
|
+
> - [**React Pacer**](https://tanstack.com/pacer/latest/docs/framework/react)
|
|
107
|
+
> - [**Preact Pacer**](https://tanstack.com/pacer/latest/docs/framework/preact)
|
|
108
|
+
> - [**Solid Pacer**](https://tanstack.com/pacer/latest/docs/framework/solid)
|
|
109
|
+
> - [**Angular Pacer**](https://tanstack.com/pacer/latest/docs/framework/angular)
|
|
110
110
|
> - Svelte Pacer - needs a contributor!
|
|
111
111
|
> - Vue Pacer - needs a contributor!
|
|
112
112
|
|
|
@@ -1091,16 +1091,20 @@ function ActionButtons(props) {
|
|
|
1091
1091
|
}
|
|
1092
1092
|
delegateEvents(["mousedown"]);
|
|
1093
1093
|
//#endregion
|
|
1094
|
-
//#region src/
|
|
1095
|
-
|
|
1096
|
-
|
|
1094
|
+
//#region src/utils/reduction-from-state.ts
|
|
1095
|
+
/**
|
|
1096
|
+
* Calculates the percentage of requests saved by a Pacer utility.
|
|
1097
|
+
* Async batch totals include both successful and failed items because both
|
|
1098
|
+
* outcomes contribute to the completed execution count.
|
|
1099
|
+
*/
|
|
1097
1100
|
function reductionFromState(entry, state) {
|
|
1098
1101
|
if (!state) return 0;
|
|
1099
|
-
const
|
|
1102
|
+
const isAsync = entry.type.toLowerCase().includes("async");
|
|
1103
|
+
const completedExecutions = isAsync ? Number(state.settleCount ?? state.settledCount) || 0 : Number(state.executionCount) || 0;
|
|
1100
1104
|
if (entry.type.toLowerCase().includes("batcher")) {
|
|
1101
|
-
const
|
|
1102
|
-
if (
|
|
1103
|
-
return Math.round((
|
|
1105
|
+
const totalItems = (Number(state.totalItemsProcessed) || 0) + (isAsync ? Number(state.totalItemsFailed) || 0 : 0);
|
|
1106
|
+
if (totalItems === 0) return 0;
|
|
1107
|
+
return Math.round((totalItems - completedExecutions) / totalItems * 100);
|
|
1104
1108
|
}
|
|
1105
1109
|
let requestCount = 0;
|
|
1106
1110
|
if (state.maybeExecuteCount !== void 0) requestCount = Number(state.maybeExecuteCount) || 0;
|
|
@@ -1110,6 +1114,10 @@ function reductionFromState(entry, state) {
|
|
|
1110
1114
|
const reduction = requestCount - completedExecutions;
|
|
1111
1115
|
return Math.round(reduction / requestCount * 100);
|
|
1112
1116
|
}
|
|
1117
|
+
//#endregion
|
|
1118
|
+
//#region src/components/StateHeader.tsx
|
|
1119
|
+
var _tmpl$$2 = /*#__PURE__*/ template(`<div><div></div><div style=display:flex;align-items:center;gap:16px><div><div>Key</div><div></div><div>Last Updated</div><div> (<!>)</div></div><div style=margin-left:auto;font-weight:bold>% reduction`);
|
|
1120
|
+
dayjs.extend(relativeTime);
|
|
1113
1121
|
function StateHeaderInner(props) {
|
|
1114
1122
|
const key = props.entry.instance.key;
|
|
1115
1123
|
const updatedAt = () => props.utilState().lastUpdatedByKey[key] ?? Date.now();
|
|
@@ -976,6 +976,30 @@ function ActionButtons(props) {
|
|
|
976
976
|
return ssr(_tmpl$2$2, ssrAttribute("class", escape(styles().actionsRow, true), false), hasPending() && ssr(_tmpl$3$1, ssrAttribute("class", escape(styles().actionButton, true), false), ssrAttribute("class", escape(styles().actionDotBlue, true), false), isPending() ? "Restore Pending" : "Trigger Pending"), hasFlush && ssr(_tmpl$4, ssrAttribute("class", escape(styles().actionButton, true), false), ssrAttribute("disabled", utilNameLower.includes("debouncer") && !isPending() || utilNameLower.includes("throttler") && !isPending() || utilNameLower.includes("batcher") && isEmptyFlag() || utilNameLower.includes("queuer") && isEmptyFlag(), true), ssrAttribute("class", escape(styles().actionDotGreen, true), false)), hasCancel && ssr(_tmpl$5, ssrAttribute("class", escape(styles().actionButton, true), false), ssrAttribute("disabled", utilNameLower.includes("debouncer") && !isPending() || utilNameLower.includes("throttler") && !isPending() || utilNameLower.includes("batcher") && isEmptyFlag() || utilNameLower.includes("queuer") && isEmptyFlag(), true), ssrAttribute("class", escape(styles().actionDotRed, true), false)), hasReset && ssr(_tmpl$6, ssrAttribute("class", escape(styles().actionButton, true), false), ssrAttribute("class", escape(styles().actionDotYellow, true), false)), hasClear && ssr(_tmpl$7, ssrAttribute("class", escape(styles().actionButton, true), false), ssrAttribute("disabled", utilNameLower.includes("batcher") && isEmptyFlag() || utilNameLower.includes("queuer") && isEmptyFlag(), true), ssrAttribute("class", escape(styles().actionDotOrange, true), false)), hasStartStop && ssr(_tmpl$3$1, ssrAttribute("class", escape(styles().actionButton, true), false), ssrAttribute("class", escape(styles().actionDotPurple, true), false), isRunning() ? "Stop" : "Start"));
|
|
977
977
|
}
|
|
978
978
|
//#endregion
|
|
979
|
+
//#region src/utils/reduction-from-state.ts
|
|
980
|
+
/**
|
|
981
|
+
* Calculates the percentage of requests saved by a Pacer utility.
|
|
982
|
+
* Async batch totals include both successful and failed items because both
|
|
983
|
+
* outcomes contribute to the completed execution count.
|
|
984
|
+
*/
|
|
985
|
+
function reductionFromState(entry, state) {
|
|
986
|
+
if (!state) return 0;
|
|
987
|
+
const isAsync = entry.type.toLowerCase().includes("async");
|
|
988
|
+
const completedExecutions = isAsync ? Number(state.settleCount ?? state.settledCount) || 0 : Number(state.executionCount) || 0;
|
|
989
|
+
if (entry.type.toLowerCase().includes("batcher")) {
|
|
990
|
+
const totalItems = (Number(state.totalItemsProcessed) || 0) + (isAsync ? Number(state.totalItemsFailed) || 0 : 0);
|
|
991
|
+
if (totalItems === 0) return 0;
|
|
992
|
+
return Math.round((totalItems - completedExecutions) / totalItems * 100);
|
|
993
|
+
}
|
|
994
|
+
let requestCount = 0;
|
|
995
|
+
if (state.maybeExecuteCount !== void 0) requestCount = Number(state.maybeExecuteCount) || 0;
|
|
996
|
+
else if (state.addItemCount !== void 0) requestCount = Number(state.addItemCount) || 0;
|
|
997
|
+
else return 0;
|
|
998
|
+
if (requestCount === 0) return 0;
|
|
999
|
+
const reduction = requestCount - completedExecutions;
|
|
1000
|
+
return Math.round(reduction / requestCount * 100);
|
|
1001
|
+
}
|
|
1002
|
+
//#endregion
|
|
979
1003
|
//#region src/components/StateHeader.tsx
|
|
980
1004
|
var _tmpl$$2 = [
|
|
981
1005
|
"<div",
|
|
@@ -996,22 +1020,6 @@ var _tmpl$$2 = [
|
|
|
996
1020
|
"% reduction</div></div></div>"
|
|
997
1021
|
];
|
|
998
1022
|
dayjs.extend(relativeTime);
|
|
999
|
-
function reductionFromState(entry, state) {
|
|
1000
|
-
if (!state) return 0;
|
|
1001
|
-
const completedExecutions = entry.type.toLowerCase().includes("async") ? Number(state.settleCount) || 0 : Number(state.executionCount) || 0;
|
|
1002
|
-
if (entry.type.toLowerCase().includes("batcher")) {
|
|
1003
|
-
const totalItemsProcessed = Number(state.totalItemsProcessed) || 0;
|
|
1004
|
-
if (totalItemsProcessed === 0) return 0;
|
|
1005
|
-
return Math.round((totalItemsProcessed - completedExecutions) / totalItemsProcessed * 100);
|
|
1006
|
-
}
|
|
1007
|
-
let requestCount = 0;
|
|
1008
|
-
if (state.maybeExecuteCount !== void 0) requestCount = Number(state.maybeExecuteCount) || 0;
|
|
1009
|
-
else if (state.addItemCount !== void 0) requestCount = Number(state.addItemCount) || 0;
|
|
1010
|
-
else return 0;
|
|
1011
|
-
if (requestCount === 0) return 0;
|
|
1012
|
-
const reduction = requestCount - completedExecutions;
|
|
1013
|
-
return Math.round(reduction / requestCount * 100);
|
|
1014
|
-
}
|
|
1015
1023
|
function StateHeaderInner(props) {
|
|
1016
1024
|
const key = props.entry.instance.key;
|
|
1017
1025
|
const updatedAt = () => props.utilState().lastUpdatedByKey[key] ?? Date.now();
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { ClassType } from "@tanstack/devtools-utils/solid";
|
|
2
|
-
|
|
2
|
+
declare namespace core_d_exports {
|
|
3
|
+
export { PacerDevtoolsCore$1 as PacerDevtoolsCore, PacerDevtoolsCoreNoOp, PacerDevtoolsInit };
|
|
4
|
+
}
|
|
3
5
|
interface PacerDevtoolsInit {}
|
|
4
6
|
declare const PacerDevtoolsCore$1: ClassType;
|
|
7
|
+
declare const PacerDevtoolsCoreNoOp: ClassType;
|
|
5
8
|
//#endregion
|
|
6
9
|
//#region src/index.d.ts
|
|
7
|
-
declare const PacerDevtoolsCore: typeof PacerDevtoolsCore$1;
|
|
10
|
+
export declare const PacerDevtoolsCore: typeof PacerDevtoolsCore$1;
|
|
8
11
|
//#endregion
|
|
9
|
-
export {
|
|
12
|
+
export type { PacerDevtoolsInit };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { constructCoreClass } from "@tanstack/devtools-utils/solid";
|
|
3
3
|
//#region src/core.tsx
|
|
4
|
-
const coreClasses = constructCoreClass(() => import("./components-
|
|
4
|
+
const coreClasses = constructCoreClass(() => import("./components-BwcTEJfm.js"));
|
|
5
5
|
const PacerDevtoolsCore$1 = coreClasses[0];
|
|
6
6
|
const PacerDevtoolsCoreNoOp = coreClasses[1];
|
|
7
7
|
//#endregion
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ClassType } from "@tanstack/devtools-utils/solid";
|
|
2
2
|
//#region src/core.d.ts
|
|
3
3
|
interface PacerDevtoolsInit {}
|
|
4
|
-
declare const PacerDevtoolsCore: ClassType;
|
|
4
|
+
export declare const PacerDevtoolsCore: ClassType;
|
|
5
5
|
//#endregion
|
|
6
|
-
export {
|
|
6
|
+
export type { PacerDevtoolsInit };
|
package/dist/production/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { constructCoreClass } from "@tanstack/devtools-utils/solid";
|
|
3
3
|
//#region src/core.tsx
|
|
4
|
-
const coreClasses = constructCoreClass(() => import("../components-
|
|
4
|
+
const coreClasses = constructCoreClass(() => import("../components-BwcTEJfm.js"));
|
|
5
5
|
const PacerDevtoolsCore = coreClasses[0];
|
|
6
6
|
coreClasses[1];
|
|
7
7
|
//#endregion
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { constructCoreClass } from "@tanstack/devtools-utils/solid";
|
|
3
3
|
//#region src/core.tsx
|
|
4
|
-
const coreClasses = constructCoreClass(() => import("../components-
|
|
4
|
+
const coreClasses = constructCoreClass(() => import("../components-D6zc5Wjw.js"));
|
|
5
5
|
const PacerDevtoolsCore = coreClasses[0];
|
|
6
6
|
coreClasses[1];
|
|
7
7
|
//#endregion
|
package/dist/server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { constructCoreClass } from "@tanstack/devtools-utils/solid";
|
|
3
3
|
//#region src/core.tsx
|
|
4
|
-
const coreClasses = constructCoreClass(() => import("./components-
|
|
4
|
+
const coreClasses = constructCoreClass(() => import("./components-D6zc5Wjw.js"));
|
|
5
5
|
const PacerDevtoolsCore$1 = coreClasses[0];
|
|
6
6
|
const PacerDevtoolsCoreNoOp = coreClasses[1];
|
|
7
7
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/pacer-devtools",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Devtools for Pacer.",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -61,28 +61,27 @@
|
|
|
61
61
|
},
|
|
62
62
|
"sideEffects": false,
|
|
63
63
|
"engines": {
|
|
64
|
-
"node": ">=
|
|
64
|
+
"node": ">=20"
|
|
65
65
|
},
|
|
66
66
|
"files": [
|
|
67
|
-
"dist
|
|
68
|
-
"src"
|
|
67
|
+
"dist"
|
|
69
68
|
],
|
|
70
69
|
"peerDependencies": {
|
|
71
70
|
"@tanstack/pacer": ">=0.16.4"
|
|
72
71
|
},
|
|
73
72
|
"dependencies": {
|
|
74
|
-
"@tanstack/devtools-ui": "0.
|
|
75
|
-
"@tanstack/devtools-utils": "^0.
|
|
73
|
+
"@tanstack/devtools-ui": "0.7.1",
|
|
74
|
+
"@tanstack/devtools-utils": "^0.7.0",
|
|
76
75
|
"@tanstack/solid-store": "^0.11.1",
|
|
77
76
|
"clsx": "^2.1.1",
|
|
78
77
|
"csstype": "^3.2.3",
|
|
79
|
-
"dayjs": "^1.11.
|
|
78
|
+
"dayjs": "^1.11.23",
|
|
80
79
|
"goober": "^2.1.19",
|
|
81
|
-
"solid-js": "^1.9.
|
|
80
|
+
"solid-js": "^1.9.15"
|
|
82
81
|
},
|
|
83
82
|
"devDependencies": {
|
|
84
83
|
"rolldown-plugin-solid": "^0.2.1",
|
|
85
|
-
"tsdown": "^0.
|
|
84
|
+
"tsdown": "^0.23.0",
|
|
86
85
|
"vite-plugin-solid": "^2.11.14"
|
|
87
86
|
},
|
|
88
87
|
"scripts": {
|
|
@@ -92,6 +91,7 @@
|
|
|
92
91
|
"test:lib": "vitest",
|
|
93
92
|
"test:lib:dev": "pnpm test:lib --watch",
|
|
94
93
|
"test:types": "tsc",
|
|
95
|
-
"build": "tsdown"
|
|
94
|
+
"build": "tsdown",
|
|
95
|
+
"test:build": "publint --strict && node ../../scripts/verify-package.ts"
|
|
96
96
|
}
|
|
97
97
|
}
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import { createStore, produce } from 'solid-js/store'
|
|
2
|
-
import { createContext, createEffect, onCleanup, useContext } from 'solid-js'
|
|
3
|
-
import {
|
|
4
|
-
getPacerDevtoolsInstance,
|
|
5
|
-
pacerEventClient,
|
|
6
|
-
} from '@tanstack/pacer/event-client'
|
|
7
|
-
import type {
|
|
8
|
-
AsyncBatcher,
|
|
9
|
-
AsyncDebouncer,
|
|
10
|
-
AsyncQueuer,
|
|
11
|
-
AsyncRateLimiter,
|
|
12
|
-
AsyncThrottler,
|
|
13
|
-
Batcher,
|
|
14
|
-
Debouncer,
|
|
15
|
-
PacerEventName,
|
|
16
|
-
Queuer,
|
|
17
|
-
RateLimiter,
|
|
18
|
-
Throttler,
|
|
19
|
-
} from '@tanstack/pacer'
|
|
20
|
-
|
|
21
|
-
interface PacerDevtoolsContextType {
|
|
22
|
-
asyncBatchers: Array<AsyncBatcher<any>>
|
|
23
|
-
asyncDebouncers: Array<AsyncDebouncer<any>>
|
|
24
|
-
asyncQueuers: Array<AsyncQueuer<any>>
|
|
25
|
-
asyncRateLimiters: Array<AsyncRateLimiter<any>>
|
|
26
|
-
asyncThrottlers: Array<AsyncThrottler<any>>
|
|
27
|
-
batchers: Array<Batcher<any>>
|
|
28
|
-
debouncers: Array<Debouncer<any>>
|
|
29
|
-
queuers: Array<Queuer<any>>
|
|
30
|
-
rateLimiters: Array<RateLimiter<any>>
|
|
31
|
-
throttlers: Array<Throttler<any>>
|
|
32
|
-
lastUpdatedByKey: Record<string, number>
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const initialPacerDevtoolsStore = {
|
|
36
|
-
asyncBatchers: [],
|
|
37
|
-
asyncDebouncers: [],
|
|
38
|
-
asyncQueuers: [],
|
|
39
|
-
asyncRateLimiters: [],
|
|
40
|
-
asyncThrottlers: [],
|
|
41
|
-
batchers: [],
|
|
42
|
-
debouncers: [],
|
|
43
|
-
queuers: [],
|
|
44
|
-
rateLimiters: [],
|
|
45
|
-
throttlers: [],
|
|
46
|
-
lastUpdatedByKey: {},
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const PacerDevtoolsContext = createContext<
|
|
50
|
-
[
|
|
51
|
-
PacerDevtoolsContextType,
|
|
52
|
-
(newState: Partial<PacerDevtoolsContextType>) => void,
|
|
53
|
-
]
|
|
54
|
-
>([initialPacerDevtoolsStore, () => {}])
|
|
55
|
-
|
|
56
|
-
type UtilListKey = Exclude<keyof PacerDevtoolsContextType, 'lastUpdatedByKey'>
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Match TanStack Form devtools: subscribe with {@link pacerEventClient.on} per
|
|
60
|
-
* event suffix so the same `pacer:${suffix}` channel the library emits on is
|
|
61
|
-
* observed. `onAllPluginEvents` only sees `tanstack-devtools-global`, which is
|
|
62
|
-
* not always relayed the same way by the shell.
|
|
63
|
-
*
|
|
64
|
-
* `d-*` suffixes are used when the devtools panel pushes state back (see
|
|
65
|
-
* ActionButtons); those must update the panel store too.
|
|
66
|
-
*/
|
|
67
|
-
const PACER_DEVTOOLS_UTIL_EVENTS: Array<{
|
|
68
|
-
listKey: UtilListKey
|
|
69
|
-
suffixes: ReadonlyArray<PacerEventName>
|
|
70
|
-
}> = [
|
|
71
|
-
{
|
|
72
|
-
listKey: 'asyncBatchers',
|
|
73
|
-
suffixes: ['AsyncBatcher', 'd-AsyncBatcher'],
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
listKey: 'asyncDebouncers',
|
|
77
|
-
suffixes: ['AsyncDebouncer', 'd-AsyncDebouncer'],
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
listKey: 'asyncQueuers',
|
|
81
|
-
suffixes: ['AsyncQueuer', 'd-AsyncQueuer'],
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
listKey: 'asyncRateLimiters',
|
|
85
|
-
suffixes: ['AsyncRateLimiter', 'd-AsyncRateLimiter'],
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
listKey: 'asyncThrottlers',
|
|
89
|
-
suffixes: ['AsyncThrottler', 'd-AsyncThrottler'],
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
listKey: 'batchers',
|
|
93
|
-
suffixes: ['Batcher', 'd-Batcher'],
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
listKey: 'debouncers',
|
|
97
|
-
suffixes: ['Debouncer', 'd-Debouncer'],
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
listKey: 'queuers',
|
|
101
|
-
suffixes: ['Queuer', 'd-Queuer'],
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
listKey: 'rateLimiters',
|
|
105
|
-
suffixes: ['RateLimiter', 'd-RateLimiter'],
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
listKey: 'throttlers',
|
|
109
|
-
suffixes: ['Throttler', 'd-Throttler'],
|
|
110
|
-
},
|
|
111
|
-
]
|
|
112
|
-
|
|
113
|
-
export function PacerContextProvider(props: { children: any }) {
|
|
114
|
-
const [store, setStore] = createStore<PacerDevtoolsContextType>(
|
|
115
|
-
initialPacerDevtoolsStore,
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
createEffect(() => {
|
|
119
|
-
const cleanups: Array<() => void> = []
|
|
120
|
-
|
|
121
|
-
for (const { listKey, suffixes } of PACER_DEVTOOLS_UTIL_EVENTS) {
|
|
122
|
-
for (const suffix of suffixes) {
|
|
123
|
-
cleanups.push(
|
|
124
|
-
pacerEventClient.on(suffix, (e) => {
|
|
125
|
-
const payload = e.payload
|
|
126
|
-
const key = payload.key
|
|
127
|
-
if (!key) return
|
|
128
|
-
|
|
129
|
-
const instance = getPacerDevtoolsInstance(key)
|
|
130
|
-
if (!instance || typeof instance !== 'object') return
|
|
131
|
-
|
|
132
|
-
setStore(
|
|
133
|
-
produce((draft) => {
|
|
134
|
-
const list = draft[listKey] as Array<{ key: string }>
|
|
135
|
-
const index = list.findIndex((item) => item.key === key)
|
|
136
|
-
const inst = instance as { key: string }
|
|
137
|
-
if (index !== -1) {
|
|
138
|
-
list[index] = inst as (typeof list)[number]
|
|
139
|
-
} else {
|
|
140
|
-
list.push(inst as (typeof list)[number])
|
|
141
|
-
}
|
|
142
|
-
draft.lastUpdatedByKey[key] = Date.now()
|
|
143
|
-
}),
|
|
144
|
-
)
|
|
145
|
-
}),
|
|
146
|
-
)
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
onCleanup(() => {
|
|
151
|
-
for (const cleanup of cleanups) {
|
|
152
|
-
cleanup()
|
|
153
|
-
}
|
|
154
|
-
})
|
|
155
|
-
})
|
|
156
|
-
return (
|
|
157
|
-
<PacerDevtoolsContext.Provider value={[store, setStore]}>
|
|
158
|
-
{props.children}
|
|
159
|
-
</PacerDevtoolsContext.Provider>
|
|
160
|
-
)
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const usePacerDevtoolsContext = () => {
|
|
164
|
-
const context = useContext(PacerDevtoolsContext)
|
|
165
|
-
|
|
166
|
-
return context
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
export const usePacerDevtoolsState = () => {
|
|
170
|
-
const [state] = usePacerDevtoolsContext()
|
|
171
|
-
return state
|
|
172
|
-
}
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import { emitChange } from '@tanstack/pacer'
|
|
2
|
-
import { shallow, useSelector } from '@tanstack/solid-store'
|
|
3
|
-
import { useStyles } from '../styles/use-styles'
|
|
4
|
-
import {
|
|
5
|
-
getPacerUtilStoreState,
|
|
6
|
-
isPacerUtilTanStackStore,
|
|
7
|
-
} from '../utils/read-pacer-store-state'
|
|
8
|
-
import type { PacerEventName } from '@tanstack/pacer'
|
|
9
|
-
|
|
10
|
-
type ActionButtonsProps = {
|
|
11
|
-
instance: any
|
|
12
|
-
utilName: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function ActionButtons(props: ActionButtonsProps) {
|
|
16
|
-
const styles = useStyles()
|
|
17
|
-
const utilInstance = props.instance
|
|
18
|
-
const store = utilInstance?.store
|
|
19
|
-
|
|
20
|
-
const stateAccessor = isPacerUtilTanStackStore(store)
|
|
21
|
-
? useSelector(
|
|
22
|
-
store as never,
|
|
23
|
-
(s: unknown) =>
|
|
24
|
-
s !== null && s !== undefined && typeof s === 'object'
|
|
25
|
-
? (s as Record<string, unknown>)
|
|
26
|
-
: {},
|
|
27
|
-
{ compare: shallow },
|
|
28
|
-
)
|
|
29
|
-
: () => getPacerUtilStoreState(utilInstance) as Record<string, unknown>
|
|
30
|
-
|
|
31
|
-
const getState = () => stateAccessor()
|
|
32
|
-
|
|
33
|
-
const hasPending = () => {
|
|
34
|
-
const u = getState()
|
|
35
|
-
return 'isPending' in u
|
|
36
|
-
}
|
|
37
|
-
const isPending = () => {
|
|
38
|
-
const u = getState()
|
|
39
|
-
return 'isPending' in u ? !!u.isPending : false
|
|
40
|
-
}
|
|
41
|
-
const isEmptyFlag = () => {
|
|
42
|
-
const u = getState()
|
|
43
|
-
return 'isEmpty' in u ? !!u.isEmpty : false
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const hasFlush = typeof utilInstance.flush === 'function'
|
|
47
|
-
const hasCancel = typeof utilInstance.cancel === 'function'
|
|
48
|
-
const hasReset = typeof utilInstance.reset === 'function'
|
|
49
|
-
const hasClear = typeof utilInstance.clear === 'function'
|
|
50
|
-
const hasStart = typeof utilInstance.start === 'function'
|
|
51
|
-
const hasStop = typeof utilInstance.stop === 'function'
|
|
52
|
-
const hasStartStop = hasStart && hasStop
|
|
53
|
-
|
|
54
|
-
const isRunning = () => {
|
|
55
|
-
const u = getState()
|
|
56
|
-
return 'isRunning' in u ? !!u.isRunning : true
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (!hasPending() && !hasFlush && !hasCancel && !hasReset && !hasClear) {
|
|
60
|
-
return (
|
|
61
|
-
<div class={styles().sectionEmpty}>
|
|
62
|
-
No actions available for this util
|
|
63
|
-
</div>
|
|
64
|
-
)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const emitName = `d-${props.utilName}` as PacerEventName
|
|
68
|
-
const utilNameLower = props.utilName.toLowerCase()
|
|
69
|
-
|
|
70
|
-
return (
|
|
71
|
-
<div class={styles().actionsRow}>
|
|
72
|
-
{hasPending() && (
|
|
73
|
-
<button
|
|
74
|
-
class={styles().actionButton}
|
|
75
|
-
onMouseDown={() => {
|
|
76
|
-
const next = !isPending()
|
|
77
|
-
utilInstance.store.setState((prev: any) => ({
|
|
78
|
-
...prev,
|
|
79
|
-
isPending: next,
|
|
80
|
-
}))
|
|
81
|
-
emitChange(emitName, utilInstance)
|
|
82
|
-
}}
|
|
83
|
-
>
|
|
84
|
-
<span class={styles().actionDotBlue} />
|
|
85
|
-
{isPending() ? 'Restore Pending' : 'Trigger Pending'}
|
|
86
|
-
</button>
|
|
87
|
-
)}
|
|
88
|
-
{hasFlush && (
|
|
89
|
-
<button
|
|
90
|
-
class={styles().actionButton}
|
|
91
|
-
onMouseDown={() => {
|
|
92
|
-
utilInstance.flush()
|
|
93
|
-
emitChange(emitName, utilInstance)
|
|
94
|
-
}}
|
|
95
|
-
disabled={
|
|
96
|
-
(utilNameLower.includes('debouncer') && !isPending()) ||
|
|
97
|
-
(utilNameLower.includes('throttler') && !isPending()) ||
|
|
98
|
-
(utilNameLower.includes('batcher') && isEmptyFlag()) ||
|
|
99
|
-
(utilNameLower.includes('queuer') && isEmptyFlag())
|
|
100
|
-
}
|
|
101
|
-
>
|
|
102
|
-
<span class={styles().actionDotGreen} />
|
|
103
|
-
Flush
|
|
104
|
-
</button>
|
|
105
|
-
)}
|
|
106
|
-
{hasCancel && (
|
|
107
|
-
<button
|
|
108
|
-
class={styles().actionButton}
|
|
109
|
-
onMouseDown={() => {
|
|
110
|
-
utilInstance.cancel()
|
|
111
|
-
emitChange(emitName, utilInstance)
|
|
112
|
-
}}
|
|
113
|
-
disabled={
|
|
114
|
-
(utilNameLower.includes('debouncer') && !isPending()) ||
|
|
115
|
-
(utilNameLower.includes('throttler') && !isPending()) ||
|
|
116
|
-
(utilNameLower.includes('batcher') && isEmptyFlag()) ||
|
|
117
|
-
(utilNameLower.includes('queuer') && isEmptyFlag())
|
|
118
|
-
}
|
|
119
|
-
>
|
|
120
|
-
<span class={styles().actionDotRed} />
|
|
121
|
-
Cancel
|
|
122
|
-
</button>
|
|
123
|
-
)}
|
|
124
|
-
{hasReset && (
|
|
125
|
-
<button
|
|
126
|
-
class={styles().actionButton}
|
|
127
|
-
onMouseDown={() => {
|
|
128
|
-
utilInstance.reset()
|
|
129
|
-
emitChange(emitName, utilInstance)
|
|
130
|
-
}}
|
|
131
|
-
>
|
|
132
|
-
<span class={styles().actionDotYellow} />
|
|
133
|
-
Reset
|
|
134
|
-
</button>
|
|
135
|
-
)}
|
|
136
|
-
{hasClear && (
|
|
137
|
-
<button
|
|
138
|
-
class={styles().actionButton}
|
|
139
|
-
onMouseDown={() => {
|
|
140
|
-
utilInstance.clear()
|
|
141
|
-
emitChange(emitName, utilInstance)
|
|
142
|
-
}}
|
|
143
|
-
disabled={
|
|
144
|
-
(utilNameLower.includes('batcher') && isEmptyFlag()) ||
|
|
145
|
-
(utilNameLower.includes('queuer') && isEmptyFlag())
|
|
146
|
-
}
|
|
147
|
-
>
|
|
148
|
-
<span class={styles().actionDotOrange} />
|
|
149
|
-
Clear
|
|
150
|
-
</button>
|
|
151
|
-
)}
|
|
152
|
-
{hasStartStop && (
|
|
153
|
-
<button
|
|
154
|
-
class={styles().actionButton}
|
|
155
|
-
onMouseDown={() => {
|
|
156
|
-
if (isRunning()) {
|
|
157
|
-
utilInstance.stop()
|
|
158
|
-
} else {
|
|
159
|
-
utilInstance.start()
|
|
160
|
-
}
|
|
161
|
-
emitChange(emitName, utilInstance)
|
|
162
|
-
}}
|
|
163
|
-
>
|
|
164
|
-
<span class={styles().actionDotPurple} />
|
|
165
|
-
{isRunning() ? 'Stop' : 'Start'}
|
|
166
|
-
</button>
|
|
167
|
-
)}
|
|
168
|
-
</div>
|
|
169
|
-
)
|
|
170
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { JsonTree } from '@tanstack/devtools-ui'
|
|
2
|
-
import { useStyles } from '../styles/use-styles'
|
|
3
|
-
import { ActionButtons } from './ActionButtons'
|
|
4
|
-
import { StateHeader } from './StateHeader'
|
|
5
|
-
import { UtilStateJsonTree } from './UtilStateJsonTree'
|
|
6
|
-
|
|
7
|
-
type DetailsPanelProps = {
|
|
8
|
-
selectedInstance: () => { instance: any; type: string } | null
|
|
9
|
-
utilState: () => { lastUpdatedByKey: Record<string, number> }
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function DetailsPanel(props: DetailsPanelProps) {
|
|
13
|
-
const styles = useStyles()
|
|
14
|
-
|
|
15
|
-
return (
|
|
16
|
-
<div class={styles().stateDetails}>
|
|
17
|
-
{(() => {
|
|
18
|
-
const entry = props.selectedInstance()
|
|
19
|
-
if (!entry) {
|
|
20
|
-
return (
|
|
21
|
-
<div class={styles().noSelection}>
|
|
22
|
-
Select a util from the left panel to view its state
|
|
23
|
-
</div>
|
|
24
|
-
)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return (
|
|
28
|
-
<>
|
|
29
|
-
<StateHeader
|
|
30
|
-
selectedInstance={props.selectedInstance}
|
|
31
|
-
utilState={props.utilState}
|
|
32
|
-
/>
|
|
33
|
-
|
|
34
|
-
<div class={styles().detailsGrid}>
|
|
35
|
-
<div class={styles().detailSection}>
|
|
36
|
-
<div class={styles().detailSectionHeader}>Actions</div>
|
|
37
|
-
<ActionButtons
|
|
38
|
-
instance={entry.instance}
|
|
39
|
-
utilName={entry.type}
|
|
40
|
-
/>
|
|
41
|
-
</div>
|
|
42
|
-
|
|
43
|
-
<div class={styles().detailSection}>
|
|
44
|
-
<div class={styles().detailSectionHeader}>State</div>
|
|
45
|
-
<div class={styles().stateContent}>
|
|
46
|
-
<UtilStateJsonTree instance={entry.instance} />
|
|
47
|
-
</div>
|
|
48
|
-
</div>
|
|
49
|
-
|
|
50
|
-
<div class={styles().detailSection}>
|
|
51
|
-
<div class={styles().detailSectionHeader}>Options</div>
|
|
52
|
-
<div class={styles().stateContent}>
|
|
53
|
-
<JsonTree value={entry.instance.options as unknown} />
|
|
54
|
-
</div>
|
|
55
|
-
</div>
|
|
56
|
-
</div>
|
|
57
|
-
</>
|
|
58
|
-
)
|
|
59
|
-
})()}
|
|
60
|
-
</div>
|
|
61
|
-
)
|
|
62
|
-
}
|