@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 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/react-pacer)
107
- > - [**Preact Pacer**](https://tanstack.com/pacer/latest/docs/framework/preact/preact-pacer)
108
- > - [**Solid Pacer**](https://tanstack.com/pacer/latest/docs/framework/solid/solid-pacer)
109
- > - [**Angular Pacer**](https://tanstack.com/pacer/latest/docs/framework/angular/angular-pacer)
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/components/StateHeader.tsx
1095
- 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`);
1096
- dayjs.extend(relativeTime);
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 completedExecutions = entry.type.toLowerCase().includes("async") ? Number(state.settleCount) || 0 : Number(state.executionCount) || 0;
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 totalItemsProcessed = Number(state.totalItemsProcessed) || 0;
1102
- if (totalItemsProcessed === 0) return 0;
1103
- return Math.round((totalItemsProcessed - completedExecutions) / totalItemsProcessed * 100);
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
- //#region src/core.d.ts
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 { PacerDevtoolsCore, type PacerDevtoolsInit };
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-BwHXH_1Y.js"));
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 { PacerDevtoolsCore, type PacerDevtoolsInit };
6
+ export type { PacerDevtoolsInit };
@@ -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-BwHXH_1Y.js"));
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-BXAd-LGS.js"));
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-BXAd-LGS.js"));
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.4.0",
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": ">=18"
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.6.0",
75
- "@tanstack/devtools-utils": "^0.6.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.21",
78
+ "dayjs": "^1.11.23",
80
79
  "goober": "^2.1.19",
81
- "solid-js": "^1.9.14"
80
+ "solid-js": "^1.9.15"
82
81
  },
83
82
  "devDependencies": {
84
83
  "rolldown-plugin-solid": "^0.2.1",
85
- "tsdown": "^0.22.14",
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
- }