@tanstack/router-devtools 1.22.5 → 1.22.6
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/dist/cjs/Explorer.cjs +1 -1
- package/dist/cjs/Explorer.cjs.map +1 -1
- package/dist/cjs/Explorer.d.cts +4 -4
- package/dist/cjs/devtools.cjs +37 -35
- package/dist/cjs/devtools.cjs.map +1 -1
- package/dist/cjs/devtools.d.cts +1 -2
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +4 -4
- package/dist/esm/Explorer.d.ts +4 -4
- package/dist/esm/Explorer.js +1 -1
- package/dist/esm/Explorer.js.map +1 -1
- package/dist/esm/devtools.d.ts +1 -2
- package/dist/esm/devtools.js +37 -35
- package/dist/esm/devtools.js.map +1 -1
- package/dist/esm/utils.d.ts +4 -4
- package/dist/esm/utils.js.map +1 -1
- package/package.json +3 -2
- package/src/Explorer.tsx +8 -8
- package/src/devtools.tsx +46 -45
- package/src/useMediaQuery.ts +2 -0
- package/src/utils.ts +12 -7
package/dist/cjs/utils.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import React from 'react'\nimport { AnyRootRoute
|
|
1
|
+
{"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import React from 'react'\nimport { useTheme } from './theme'\nimport useMediaQuery from './useMediaQuery'\nimport type {\n AnyRootRoute,\n AnyRoute,\n AnyRouteMatch,\n} from '@tanstack/react-router'\n\nimport type { Theme } from './theme'\n\nexport const isServer = typeof window === 'undefined'\n\ntype StyledComponent<T> = T extends 'button'\n ? React.DetailedHTMLProps<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n HTMLButtonElement\n >\n : T extends 'input'\n ? React.DetailedHTMLProps<\n React.InputHTMLAttributes<HTMLInputElement>,\n HTMLInputElement\n >\n : T extends 'select'\n ? React.DetailedHTMLProps<\n React.SelectHTMLAttributes<HTMLSelectElement>,\n HTMLSelectElement\n >\n : T extends keyof HTMLElementTagNameMap\n ? React.HTMLAttributes<HTMLElementTagNameMap[T]>\n : never\n\nexport function getStatusColor(match: AnyRouteMatch) {\n return match.status === 'success' && match.isFetching\n ? 'blue'\n : match.status === 'pending'\n ? 'yellow'\n : match.status === 'error'\n ? 'red'\n : match.status === 'success'\n ? 'green'\n : 'gray'\n}\n\nexport function getRouteStatusColor(\n matches: Array<AnyRouteMatch>,\n route: AnyRoute | AnyRootRoute,\n) {\n const found = matches.find((d) => d.routeId === route.id)\n if (!found) return 'gray'\n return getStatusColor(found)\n}\n\ntype Styles =\n | React.CSSProperties\n | ((props: Record<string, any>, theme: Theme) => React.CSSProperties)\n\nexport function styled<T extends keyof HTMLElementTagNameMap>(\n type: T,\n newStyles: Styles,\n queries: Record<string, Styles> = {},\n) {\n return React.forwardRef<HTMLElementTagNameMap[T], StyledComponent<T>>(\n ({ style, ...rest }, ref) => {\n const theme = useTheme()\n\n const mediaStyles = Object.entries(queries).reduce(\n (current, [key, value]) => {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useMediaQuery(key)\n ? {\n ...current,\n ...(typeof value === 'function' ? value(rest, theme) : value),\n }\n : current\n },\n {},\n )\n\n return React.createElement(type, {\n ...rest,\n style: {\n ...(typeof newStyles === 'function'\n ? newStyles(rest, theme)\n : newStyles),\n ...style,\n ...mediaStyles,\n },\n ref,\n })\n },\n )\n}\n\nexport function useIsMounted() {\n const mountedRef = React.useRef(false)\n const isMounted = React.useCallback(() => mountedRef.current, [])\n\n React[isServer ? 'useEffect' : 'useLayoutEffect'](() => {\n mountedRef.current = true\n return () => {\n mountedRef.current = false\n }\n }, [])\n\n return isMounted\n}\n\n/**\n * Displays a string regardless the type of the data\n * @param {unknown} value Value to be stringified\n */\nexport const displayValue = (value: unknown) => {\n const name = Object.getOwnPropertyNames(Object(value))\n const newValue = typeof value === 'bigint' ? `${value.toString()}n` : value\n try {\n return JSON.stringify(newValue, name)\n } catch (e) {\n return `unable to stringify`\n }\n}\n\n/**\n * This hook is a safe useState version which schedules state updates in microtasks\n * to prevent updating a component state while React is rendering different components\n * or when the component is not mounted anymore.\n */\nexport function useSafeState<T>(initialState: T): [T, (value: T) => void] {\n const isMounted = useIsMounted()\n const [state, setState] = React.useState(initialState)\n\n const safeSetState = React.useCallback(\n (value: T) => {\n scheduleMicrotask(() => {\n if (isMounted()) {\n setState(value)\n }\n })\n },\n [isMounted],\n )\n\n return [state, safeSetState]\n}\n\n/**\n * Schedules a microtask.\n * This can be useful to schedule state updates after rendering.\n */\nfunction scheduleMicrotask(callback: () => void) {\n Promise.resolve()\n .then(callback)\n .catch((error) =>\n setTimeout(() => {\n throw error\n }),\n )\n}\n\nexport function multiSortBy<T>(\n arr: Array<T>,\n accessors: Array<(item: T) => any> = [(d) => d],\n): Array<T> {\n return arr\n .map((d, i) => [d, i] as const)\n .sort(([a, ai], [b, bi]) => {\n for (const accessor of accessors) {\n const ao = accessor(a)\n const bo = accessor(b)\n\n if (typeof ao === 'undefined') {\n if (typeof bo === 'undefined') {\n continue\n }\n return 1\n }\n\n if (ao === bo) {\n continue\n }\n\n return ao > bo ? 1 : -1\n }\n\n return ai - bi\n })\n .map(([d]) => d)\n}\n"],"names":[],"mappings":";;;AAWa,MAAA,WAAW,OAAO,WAAW;AAqBnC,SAAS,eAAe,OAAsB;AACnD,SAAO,MAAM,WAAW,aAAa,MAAM,aACvC,SACA,MAAM,WAAW,YACf,WACA,MAAM,WAAW,UACf,QACA,MAAM,WAAW,YACf,UACA;AACZ;AAEgB,SAAA,oBACd,SACA,OACA;AACM,QAAA,QAAQ,QAAQ,KAAK,CAAC,MAAM,EAAE,YAAY,MAAM,EAAE;AACxD,MAAI,CAAC;AAAc,WAAA;AACnB,SAAO,eAAe,KAAK;AAC7B;AA2CO,SAAS,eAAe;AACvB,QAAA,aAAa,MAAM,OAAO,KAAK;AACrC,QAAM,YAAY,MAAM,YAAY,MAAM,WAAW,SAAS,CAAA,CAAE;AAEhE,QAAM,WAAW,cAAc,iBAAiB,EAAE,MAAM;AACtD,eAAW,UAAU;AACrB,WAAO,MAAM;AACX,iBAAW,UAAU;AAAA,IAAA;AAAA,EAEzB,GAAG,CAAE,CAAA;AAEE,SAAA;AACT;AAMa,MAAA,eAAe,CAAC,UAAmB;AAC9C,QAAM,OAAO,OAAO,oBAAoB,OAAO,KAAK,CAAC;AAC/C,QAAA,WAAW,OAAO,UAAU,WAAW,GAAG,MAAM,SAAU,CAAA,MAAM;AAClE,MAAA;AACK,WAAA,KAAK,UAAU,UAAU,IAAI;AAAA,WAC7B,GAAG;AACH,WAAA;AAAA,EACT;AACF;AAOO,SAAS,aAAgB,cAA0C;AACxE,QAAM,YAAY;AAClB,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAS,YAAY;AAErD,QAAM,eAAe,MAAM;AAAA,IACzB,CAAC,UAAa;AACZ,wBAAkB,MAAM;AACtB,YAAI,aAAa;AACf,mBAAS,KAAK;AAAA,QAChB;AAAA,MAAA,CACD;AAAA,IACH;AAAA,IACA,CAAC,SAAS;AAAA,EAAA;AAGL,SAAA,CAAC,OAAO,YAAY;AAC7B;AAMA,SAAS,kBAAkB,UAAsB;AAC/C,UAAQ,QAAQ,EACb,KAAK,QAAQ,EACb;AAAA,IAAM,CAAC,UACN,WAAW,MAAM;AACT,YAAA;AAAA,IAAA,CACP;AAAA,EAAA;AAEP;AAEO,SAAS,YACd,KACA,YAAqC,CAAC,CAAC,MAAM,CAAC,GACpC;AACV,SAAO,IACJ,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAU,EAC7B,KAAK,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,MAAM;AAC1B,eAAW,YAAY,WAAW;AAC1B,YAAA,KAAK,SAAS,CAAC;AACf,YAAA,KAAK,SAAS,CAAC;AAEjB,UAAA,OAAO,OAAO,aAAa;AACzB,YAAA,OAAO,OAAO,aAAa;AAC7B;AAAA,QACF;AACO,eAAA;AAAA,MACT;AAEA,UAAI,OAAO,IAAI;AACb;AAAA,MACF;AAEO,aAAA,KAAK,KAAK,IAAI;AAAA,IACvB;AAEA,WAAO,KAAK;AAAA,EACb,CAAA,EACA,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;AACnB;;;;;;;;"}
|
package/dist/cjs/utils.d.cts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { AnyRootRoute, AnyRoute, AnyRouteMatch } from '@tanstack/react-router';
|
|
3
|
-
import { Theme } from './theme.cjs';
|
|
2
|
+
import type { AnyRootRoute, AnyRoute, AnyRouteMatch } from '@tanstack/react-router';
|
|
3
|
+
import type { Theme } from './theme.cjs';
|
|
4
4
|
export declare const isServer: boolean;
|
|
5
5
|
type StyledComponent<T> = T extends 'button' ? React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> : T extends 'input' ? React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement> : T extends 'select' ? React.DetailedHTMLProps<React.SelectHTMLAttributes<HTMLSelectElement>, HTMLSelectElement> : T extends keyof HTMLElementTagNameMap ? React.HTMLAttributes<HTMLElementTagNameMap[T]> : never;
|
|
6
6
|
export declare function getStatusColor(match: AnyRouteMatch): "blue" | "yellow" | "red" | "green" | "gray";
|
|
7
|
-
export declare function getRouteStatusColor(matches: AnyRouteMatch
|
|
7
|
+
export declare function getRouteStatusColor(matches: Array<AnyRouteMatch>, route: AnyRoute | AnyRootRoute): "blue" | "yellow" | "red" | "green" | "gray";
|
|
8
8
|
type Styles = React.CSSProperties | ((props: Record<string, any>, theme: Theme) => React.CSSProperties);
|
|
9
9
|
export declare function styled<T extends keyof HTMLElementTagNameMap>(type: T, newStyles: Styles, queries?: Record<string, Styles>): React.ForwardRefExoticComponent<React.PropsWithoutRef<StyledComponent<T>> & React.RefAttributes<HTMLElementTagNameMap[T]>>;
|
|
10
10
|
export declare function useIsMounted(): () => boolean;
|
|
@@ -19,5 +19,5 @@ export declare const displayValue: (value: unknown) => string;
|
|
|
19
19
|
* or when the component is not mounted anymore.
|
|
20
20
|
*/
|
|
21
21
|
export declare function useSafeState<T>(initialState: T): [T, (value: T) => void];
|
|
22
|
-
export declare function multiSortBy<T>(arr: T
|
|
22
|
+
export declare function multiSortBy<T>(arr: Array<T>, accessors?: Array<(item: T) => any>): Array<T>;
|
|
23
23
|
export {};
|
package/dist/esm/Explorer.d.ts
CHANGED
|
@@ -11,14 +11,14 @@ type RendererProps = {
|
|
|
11
11
|
handleEntry: HandleEntryFn;
|
|
12
12
|
label?: React.ReactNode;
|
|
13
13
|
value: unknown;
|
|
14
|
-
subEntries: Entry
|
|
15
|
-
subEntryPages: Entry
|
|
14
|
+
subEntries: Array<Entry>;
|
|
15
|
+
subEntryPages: Array<Array<Entry>>;
|
|
16
16
|
type: string;
|
|
17
17
|
expanded: boolean;
|
|
18
18
|
toggleExpanded: () => void;
|
|
19
19
|
pageSize: number;
|
|
20
20
|
renderer?: Renderer;
|
|
21
|
-
filterSubEntries?: (subEntries: Property
|
|
21
|
+
filterSubEntries?: (subEntries: Array<Property>) => Array<Property>;
|
|
22
22
|
};
|
|
23
23
|
/**
|
|
24
24
|
* Chunk elements in the array by size
|
|
@@ -29,7 +29,7 @@ type RendererProps = {
|
|
|
29
29
|
* @example
|
|
30
30
|
* chunkArray(['a','b', 'c', 'd', 'e'], 2) // returns [['a','b'], ['c', 'd'], ['e']]
|
|
31
31
|
*/
|
|
32
|
-
export declare function chunkArray<T>(array: T
|
|
32
|
+
export declare function chunkArray<T>(array: Array<T>, size: number): Array<Array<T>>;
|
|
33
33
|
type Renderer = (props: RendererProps) => React.ReactNode;
|
|
34
34
|
export declare const DefaultRenderer: Renderer;
|
|
35
35
|
type HandleEntryFn = (entry: Entry) => React.ReactNode;
|
package/dist/esm/Explorer.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { clsx } from "clsx";
|
|
4
|
+
import { css } from "goober";
|
|
4
5
|
import { tokens } from "./tokens.js";
|
|
5
6
|
import { displayValue } from "./utils.js";
|
|
6
|
-
import { css } from "goober";
|
|
7
7
|
const Expander = ({ expanded, style = {} }) => /* @__PURE__ */ jsx("span", { className: getStyles().expander, children: /* @__PURE__ */ jsx(
|
|
8
8
|
"svg",
|
|
9
9
|
{
|
package/dist/esm/Explorer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Explorer.js","sources":["../../src/Explorer.tsx"],"sourcesContent":["import * as React from 'react'\nimport { clsx as cx } from 'clsx'\nimport { tokens } from './tokens'\nimport { displayValue, styled } from './utils'\nimport { css } from 'goober'\n\ntype ExpanderProps = {\n expanded: boolean\n style?: React.CSSProperties\n}\n\nexport const Expander = ({ expanded, style = {} }: ExpanderProps) => (\n <span className={getStyles().expander}>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n className={cx(getStyles().expanderIcon(expanded))}\n >\n <path\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n d=\"M9 18l6-6-6-6\"\n ></path>\n </svg>\n </span>\n)\n\ntype Entry = {\n label: string\n}\n\ntype RendererProps = {\n handleEntry: HandleEntryFn\n label?: React.ReactNode\n value: unknown\n subEntries: Entry[]\n subEntryPages: Entry[][]\n type: string\n expanded: boolean\n toggleExpanded: () => void\n pageSize: number\n renderer?: Renderer\n filterSubEntries?: (subEntries: Property[]) => Property[]\n}\n\n/**\n * Chunk elements in the array by size\n *\n * when the array cannot be chunked evenly by size, the last chunk will be\n * filled with the remaining elements\n *\n * @example\n * chunkArray(['a','b', 'c', 'd', 'e'], 2) // returns [['a','b'], ['c', 'd'], ['e']]\n */\nexport function chunkArray<T>(array: T[], size: number): T[][] {\n if (size < 1) return []\n let i = 0\n const result: T[][] = []\n while (i < array.length) {\n result.push(array.slice(i, i + size))\n i = i + size\n }\n return result\n}\n\ntype Renderer = (props: RendererProps) => React.ReactNode\n\nexport const DefaultRenderer: Renderer = ({\n handleEntry,\n label,\n value,\n subEntries = [],\n subEntryPages = [],\n type,\n expanded = false,\n toggleExpanded,\n pageSize,\n renderer,\n}) => {\n const [expandedPages, setExpandedPages] = React.useState<number[]>([])\n const [valueSnapshot, setValueSnapshot] = React.useState(undefined)\n\n const refreshValueSnapshot = () => {\n setValueSnapshot((value as () => any)())\n }\n\n return (\n <div className={getStyles().entry}>\n {subEntryPages.length ? (\n <>\n <button\n className={getStyles().expandButton}\n onClick={() => toggleExpanded()}\n >\n <Expander expanded={expanded} />\n {label}\n <span className={getStyles().info}>\n {String(type).toLowerCase() === 'iterable' ? '(Iterable) ' : ''}\n {subEntries.length} {subEntries.length > 1 ? `items` : `item`}\n </span>\n </button>\n {expanded ? (\n subEntryPages.length === 1 ? (\n <div className={getStyles().subEntries}>\n {subEntries.map((entry, index) => handleEntry(entry))}\n </div>\n ) : (\n <div className={getStyles().subEntries}>\n {subEntryPages.map((entries, index) => {\n return (\n <div key={index}>\n <div className={getStyles().entry}>\n <button\n className={cx(getStyles().labelButton, 'labelButton')}\n onClick={() =>\n setExpandedPages((old) =>\n old.includes(index)\n ? old.filter((d) => d !== index)\n : [...old, index],\n )\n }\n >\n <Expander expanded={expandedPages.includes(index)} />{' '}\n [{index * pageSize} ...{' '}\n {index * pageSize + pageSize - 1}]\n </button>\n {expandedPages.includes(index) ? (\n <div className={getStyles().subEntries}>\n {entries.map((entry) => handleEntry(entry))}\n </div>\n ) : null}\n </div>\n </div>\n )\n })}\n </div>\n )\n ) : null}\n </>\n ) : type === 'function' ? (\n <>\n <Explorer\n renderer={renderer}\n label={\n <button\n onClick={refreshValueSnapshot}\n className={getStyles().refreshValueBtn}\n >\n <span>{label}</span> 🔄{' '}\n </button>\n }\n value={valueSnapshot}\n defaultExpanded={{}}\n />\n </>\n ) : (\n <>\n <span>{label}:</span>{' '}\n <span className={getStyles().value}>{displayValue(value)}</span>\n </>\n )}\n </div>\n )\n}\n\ntype HandleEntryFn = (entry: Entry) => React.ReactNode\n\ntype ExplorerProps = Partial<RendererProps> & {\n renderer?: Renderer\n defaultExpanded?: true | Record<string, boolean>\n}\n\ntype Property = {\n defaultExpanded?: boolean | Record<string, boolean>\n label: string\n value: unknown\n}\n\nfunction isIterable(x: any): x is Iterable<unknown> {\n return Symbol.iterator in x\n}\n\nexport default function Explorer({\n value,\n defaultExpanded,\n renderer = DefaultRenderer,\n pageSize = 100,\n filterSubEntries,\n ...rest\n}: ExplorerProps) {\n const [expanded, setExpanded] = React.useState(Boolean(defaultExpanded))\n const toggleExpanded = React.useCallback(() => setExpanded((old) => !old), [])\n\n let type: string = typeof value\n let subEntries: Property[] = []\n\n const makeProperty = (sub: { label: string; value: unknown }): Property => {\n const subDefaultExpanded =\n defaultExpanded === true\n ? { [sub.label]: true }\n : defaultExpanded?.[sub.label]\n return {\n ...sub,\n defaultExpanded: subDefaultExpanded,\n }\n }\n\n if (Array.isArray(value)) {\n type = 'array'\n subEntries = value.map((d, i) =>\n makeProperty({\n label: i.toString(),\n value: d,\n }),\n )\n } else if (\n value !== null &&\n typeof value === 'object' &&\n isIterable(value) &&\n typeof value[Symbol.iterator] === 'function'\n ) {\n type = 'Iterable'\n subEntries = Array.from(value, (val, i) =>\n makeProperty({\n label: i.toString(),\n value: val,\n }),\n )\n } else if (typeof value === 'object' && value !== null) {\n type = 'object'\n subEntries = Object.entries(value).map(([key, val]) =>\n makeProperty({\n label: key,\n value: val,\n }),\n )\n }\n\n subEntries = filterSubEntries ? filterSubEntries(subEntries) : subEntries\n\n const subEntryPages = chunkArray(subEntries, pageSize)\n\n return renderer({\n handleEntry: (entry) => (\n <Explorer\n key={entry.label}\n value={value}\n renderer={renderer}\n filterSubEntries={filterSubEntries}\n {...rest}\n {...entry}\n />\n ),\n type,\n subEntries,\n subEntryPages,\n value,\n expanded,\n toggleExpanded,\n pageSize,\n ...rest,\n })\n}\n\nconst stylesFactory = () => {\n const { colors, font, size, alpha, shadow, border } = tokens\n const { fontFamily, lineHeight, size: fontSize } = font\n\n return {\n entry: css`\n font-family: ${fontFamily.mono};\n font-size: ${fontSize.xs};\n line-height: ${lineHeight.sm};\n outline: none;\n word-break: break-word;\n `,\n labelButton: css`\n cursor: pointer;\n color: inherit;\n font: inherit;\n outline: inherit;\n background: transparent;\n border: none;\n padding: 0;\n `,\n expander: css`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: ${size[3]};\n height: ${size[3]};\n padding-left: 3px;\n box-sizing: content-box;\n `,\n expanderIcon: (expanded: boolean) => {\n if (expanded) {\n return css`\n transform: rotate(90deg);\n transition: transform 0.1s ease;\n `\n }\n return css`\n transform: rotate(0deg);\n transition: transform 0.1s ease;\n `\n },\n expandButton: css`\n display: flex;\n gap: ${size[1]};\n align-items: center;\n cursor: pointer;\n color: inherit;\n font: inherit;\n outline: inherit;\n background: transparent;\n border: none;\n padding: 0;\n `,\n value: css`\n color: ${colors.purple[400]};\n `,\n subEntries: css`\n margin-left: ${size[2]};\n padding-left: ${size[2]};\n border-left: 2px solid ${colors.darkGray[400]};\n `,\n info: css`\n color: ${colors.gray[500]};\n font-size: ${fontSize['2xs']};\n padding-left: ${size[1]};\n `,\n refreshValueBtn: css`\n appearance: none;\n border: 0;\n cursor: pointer;\n background: transparent;\n color: inherit;\n padding: 0;\n font-family: ${fontFamily.mono};\n font-size: ${fontSize.xs};\n `,\n }\n}\n\nlet _styles: ReturnType<typeof stylesFactory> | null = null\n\nfunction getStyles() {\n if (_styles) return _styles\n _styles = stylesFactory()\n\n return _styles\n}\n"],"names":["cx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Explorer.js","sources":["../../src/Explorer.tsx"],"sourcesContent":["import * as React from 'react'\nimport { clsx as cx } from 'clsx'\nimport { css } from 'goober'\nimport { tokens } from './tokens'\nimport { displayValue, styled } from './utils'\n\ntype ExpanderProps = {\n expanded: boolean\n style?: React.CSSProperties\n}\n\nexport const Expander = ({ expanded, style = {} }: ExpanderProps) => (\n <span className={getStyles().expander}>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n className={cx(getStyles().expanderIcon(expanded))}\n >\n <path\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n d=\"M9 18l6-6-6-6\"\n ></path>\n </svg>\n </span>\n)\n\ntype Entry = {\n label: string\n}\n\ntype RendererProps = {\n handleEntry: HandleEntryFn\n label?: React.ReactNode\n value: unknown\n subEntries: Array<Entry>\n subEntryPages: Array<Array<Entry>>\n type: string\n expanded: boolean\n toggleExpanded: () => void\n pageSize: number\n renderer?: Renderer\n filterSubEntries?: (subEntries: Array<Property>) => Array<Property>\n}\n\n/**\n * Chunk elements in the array by size\n *\n * when the array cannot be chunked evenly by size, the last chunk will be\n * filled with the remaining elements\n *\n * @example\n * chunkArray(['a','b', 'c', 'd', 'e'], 2) // returns [['a','b'], ['c', 'd'], ['e']]\n */\nexport function chunkArray<T>(array: Array<T>, size: number): Array<Array<T>> {\n if (size < 1) return []\n let i = 0\n const result: Array<Array<T>> = []\n while (i < array.length) {\n result.push(array.slice(i, i + size))\n i = i + size\n }\n return result\n}\n\ntype Renderer = (props: RendererProps) => React.ReactNode\n\nexport const DefaultRenderer: Renderer = ({\n handleEntry,\n label,\n value,\n subEntries = [],\n subEntryPages = [],\n type,\n expanded = false,\n toggleExpanded,\n pageSize,\n renderer,\n}) => {\n const [expandedPages, setExpandedPages] = React.useState<Array<number>>([])\n const [valueSnapshot, setValueSnapshot] = React.useState(undefined)\n\n const refreshValueSnapshot = () => {\n setValueSnapshot((value as () => any)())\n }\n\n return (\n <div className={getStyles().entry}>\n {subEntryPages.length ? (\n <>\n <button\n className={getStyles().expandButton}\n onClick={() => toggleExpanded()}\n >\n <Expander expanded={expanded} />\n {label}\n <span className={getStyles().info}>\n {String(type).toLowerCase() === 'iterable' ? '(Iterable) ' : ''}\n {subEntries.length} {subEntries.length > 1 ? `items` : `item`}\n </span>\n </button>\n {expanded ? (\n subEntryPages.length === 1 ? (\n <div className={getStyles().subEntries}>\n {subEntries.map((entry, index) => handleEntry(entry))}\n </div>\n ) : (\n <div className={getStyles().subEntries}>\n {subEntryPages.map((entries, index) => {\n return (\n <div key={index}>\n <div className={getStyles().entry}>\n <button\n className={cx(getStyles().labelButton, 'labelButton')}\n onClick={() =>\n setExpandedPages((old) =>\n old.includes(index)\n ? old.filter((d) => d !== index)\n : [...old, index],\n )\n }\n >\n <Expander expanded={expandedPages.includes(index)} />{' '}\n [{index * pageSize} ...{' '}\n {index * pageSize + pageSize - 1}]\n </button>\n {expandedPages.includes(index) ? (\n <div className={getStyles().subEntries}>\n {entries.map((entry) => handleEntry(entry))}\n </div>\n ) : null}\n </div>\n </div>\n )\n })}\n </div>\n )\n ) : null}\n </>\n ) : type === 'function' ? (\n <>\n <Explorer\n renderer={renderer}\n label={\n <button\n onClick={refreshValueSnapshot}\n className={getStyles().refreshValueBtn}\n >\n <span>{label}</span> 🔄{' '}\n </button>\n }\n value={valueSnapshot}\n defaultExpanded={{}}\n />\n </>\n ) : (\n <>\n <span>{label}:</span>{' '}\n <span className={getStyles().value}>{displayValue(value)}</span>\n </>\n )}\n </div>\n )\n}\n\ntype HandleEntryFn = (entry: Entry) => React.ReactNode\n\ntype ExplorerProps = Partial<RendererProps> & {\n renderer?: Renderer\n defaultExpanded?: true | Record<string, boolean>\n}\n\ntype Property = {\n defaultExpanded?: boolean | Record<string, boolean>\n label: string\n value: unknown\n}\n\nfunction isIterable(x: any): x is Iterable<unknown> {\n return Symbol.iterator in x\n}\n\nexport default function Explorer({\n value,\n defaultExpanded,\n renderer = DefaultRenderer,\n pageSize = 100,\n filterSubEntries,\n ...rest\n}: ExplorerProps) {\n const [expanded, setExpanded] = React.useState(Boolean(defaultExpanded))\n const toggleExpanded = React.useCallback(() => setExpanded((old) => !old), [])\n\n let type: string = typeof value\n let subEntries: Array<Property> = []\n\n const makeProperty = (sub: { label: string; value: unknown }): Property => {\n const subDefaultExpanded =\n defaultExpanded === true\n ? { [sub.label]: true }\n : defaultExpanded?.[sub.label]\n return {\n ...sub,\n defaultExpanded: subDefaultExpanded,\n }\n }\n\n if (Array.isArray(value)) {\n type = 'array'\n subEntries = value.map((d, i) =>\n makeProperty({\n label: i.toString(),\n value: d,\n }),\n )\n } else if (\n value !== null &&\n typeof value === 'object' &&\n isIterable(value) &&\n typeof value[Symbol.iterator] === 'function'\n ) {\n type = 'Iterable'\n subEntries = Array.from(value, (val, i) =>\n makeProperty({\n label: i.toString(),\n value: val,\n }),\n )\n } else if (typeof value === 'object' && value !== null) {\n type = 'object'\n subEntries = Object.entries(value).map(([key, val]) =>\n makeProperty({\n label: key,\n value: val,\n }),\n )\n }\n\n subEntries = filterSubEntries ? filterSubEntries(subEntries) : subEntries\n\n const subEntryPages = chunkArray(subEntries, pageSize)\n\n return renderer({\n handleEntry: (entry) => (\n <Explorer\n key={entry.label}\n value={value}\n renderer={renderer}\n filterSubEntries={filterSubEntries}\n {...rest}\n {...entry}\n />\n ),\n type,\n subEntries,\n subEntryPages,\n value,\n expanded,\n toggleExpanded,\n pageSize,\n ...rest,\n })\n}\n\nconst stylesFactory = () => {\n const { colors, font, size, alpha, shadow, border } = tokens\n const { fontFamily, lineHeight, size: fontSize } = font\n\n return {\n entry: css`\n font-family: ${fontFamily.mono};\n font-size: ${fontSize.xs};\n line-height: ${lineHeight.sm};\n outline: none;\n word-break: break-word;\n `,\n labelButton: css`\n cursor: pointer;\n color: inherit;\n font: inherit;\n outline: inherit;\n background: transparent;\n border: none;\n padding: 0;\n `,\n expander: css`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: ${size[3]};\n height: ${size[3]};\n padding-left: 3px;\n box-sizing: content-box;\n `,\n expanderIcon: (expanded: boolean) => {\n if (expanded) {\n return css`\n transform: rotate(90deg);\n transition: transform 0.1s ease;\n `\n }\n return css`\n transform: rotate(0deg);\n transition: transform 0.1s ease;\n `\n },\n expandButton: css`\n display: flex;\n gap: ${size[1]};\n align-items: center;\n cursor: pointer;\n color: inherit;\n font: inherit;\n outline: inherit;\n background: transparent;\n border: none;\n padding: 0;\n `,\n value: css`\n color: ${colors.purple[400]};\n `,\n subEntries: css`\n margin-left: ${size[2]};\n padding-left: ${size[2]};\n border-left: 2px solid ${colors.darkGray[400]};\n `,\n info: css`\n color: ${colors.gray[500]};\n font-size: ${fontSize['2xs']};\n padding-left: ${size[1]};\n `,\n refreshValueBtn: css`\n appearance: none;\n border: 0;\n cursor: pointer;\n background: transparent;\n color: inherit;\n padding: 0;\n font-family: ${fontFamily.mono};\n font-size: ${fontSize.xs};\n `,\n }\n}\n\nlet _styles: ReturnType<typeof stylesFactory> | null = null\n\nfunction getStyles() {\n if (_styles) return _styles\n _styles = stylesFactory()\n\n return _styles\n}\n"],"names":["cx"],"mappings":"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"}
|
package/dist/esm/devtools.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { AnyRouter } from '@tanstack/react-router';
|
|
3
|
-
export type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
|
2
|
+
import type { AnyRouter } from '@tanstack/react-router';
|
|
4
3
|
interface DevtoolsOptions {
|
|
5
4
|
/**
|
|
6
5
|
* Set this true if you want the dev tools to default to being open
|
package/dist/esm/devtools.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import React__default from "react";
|
|
3
3
|
import { useRouter, useRouterState, invariant, rootRouteId, trimPath } from "@tanstack/react-router";
|
|
4
|
-
import useLocalStorage from "./useLocalStorage.js";
|
|
5
|
-
import { useSafeState, useIsMounted, multiSortBy, getStatusColor, getRouteStatusColor } from "./utils.js";
|
|
6
4
|
import { css } from "goober";
|
|
7
5
|
import { clsx } from "clsx";
|
|
6
|
+
import useLocalStorage from "./useLocalStorage.js";
|
|
7
|
+
import { useSafeState, useIsMounted, multiSortBy, getStatusColor, getRouteStatusColor } from "./utils.js";
|
|
8
8
|
import Explorer from "./Explorer.js";
|
|
9
9
|
import { tokens } from "./tokens.js";
|
|
10
10
|
import { TanStackLogo } from "./logo.js";
|
|
@@ -34,7 +34,7 @@ function TanStackRouterDevtools({
|
|
|
34
34
|
containerElement: Container = "footer",
|
|
35
35
|
router
|
|
36
36
|
}) {
|
|
37
|
-
const [rootEl, setRootEl] = React__default.useState(
|
|
37
|
+
const [rootEl, setRootEl] = React__default.useState();
|
|
38
38
|
const panelRef = React__default.useRef(null);
|
|
39
39
|
const [isOpen, setIsOpen] = useLocalStorage(
|
|
40
40
|
"tanstackRouterDevtoolsOpen",
|
|
@@ -57,7 +57,7 @@ function TanStackRouterDevtools({
|
|
|
57
57
|
};
|
|
58
58
|
const run = (moveEvent) => {
|
|
59
59
|
const delta = dragInfo.pageY - moveEvent.pageY;
|
|
60
|
-
const newHeight =
|
|
60
|
+
const newHeight = dragInfo.originalHeight + delta;
|
|
61
61
|
setDevtoolsHeight(newHeight);
|
|
62
62
|
if (newHeight < 70) {
|
|
63
63
|
setIsOpen(false);
|
|
@@ -100,7 +100,7 @@ function TanStackRouterDevtools({
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
return;
|
|
103
|
-
}, [isResolvedOpen]);
|
|
103
|
+
}, [isResolvedOpen, rootEl == null ? void 0 : rootEl.parentElement]);
|
|
104
104
|
React__default.useEffect(() => {
|
|
105
105
|
if (rootEl) {
|
|
106
106
|
const el = rootEl;
|
|
@@ -276,7 +276,7 @@ function RouteComp({
|
|
|
276
276
|
] });
|
|
277
277
|
}
|
|
278
278
|
const BaseTanStackRouterDevtoolsPanel = React__default.forwardRef(function BaseTanStackRouterDevtoolsPanel2(props, ref) {
|
|
279
|
-
var _a
|
|
279
|
+
var _a;
|
|
280
280
|
const {
|
|
281
281
|
isOpen = true,
|
|
282
282
|
setIsOpen,
|
|
@@ -291,11 +291,6 @@ const BaseTanStackRouterDevtoolsPanel = React__default.forwardRef(function BaseT
|
|
|
291
291
|
const routerState = useRouterState({
|
|
292
292
|
router
|
|
293
293
|
});
|
|
294
|
-
const matches = [
|
|
295
|
-
...routerState.pendingMatches ?? [],
|
|
296
|
-
...routerState.matches,
|
|
297
|
-
...routerState.cachedMatches
|
|
298
|
-
];
|
|
299
294
|
invariant(
|
|
300
295
|
router,
|
|
301
296
|
"No router was found for the TanStack Router Devtools. Please place the devtools in the <RouterProvider> component tree or pass the router instance to the devtools manually."
|
|
@@ -308,11 +303,20 @@ const BaseTanStackRouterDevtoolsPanel = React__default.forwardRef(function BaseT
|
|
|
308
303
|
"tanstackRouterDevtoolsActiveRouteId",
|
|
309
304
|
""
|
|
310
305
|
);
|
|
311
|
-
const activeMatch = React__default.useMemo(
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
306
|
+
const activeMatch = React__default.useMemo(() => {
|
|
307
|
+
const matches = [
|
|
308
|
+
...routerState.pendingMatches ?? [],
|
|
309
|
+
...routerState.matches,
|
|
310
|
+
...routerState.cachedMatches
|
|
311
|
+
];
|
|
312
|
+
return matches.find((d) => d.routeId === activeId || d.id === activeId);
|
|
313
|
+
}, [
|
|
314
|
+
activeId,
|
|
315
|
+
routerState.cachedMatches,
|
|
316
|
+
routerState.matches,
|
|
317
|
+
routerState.pendingMatches
|
|
318
|
+
]);
|
|
319
|
+
const hasSearch = Object.keys(routerState.location.search).length;
|
|
316
320
|
const explorerState = {
|
|
317
321
|
...router,
|
|
318
322
|
state: router.state
|
|
@@ -503,7 +507,7 @@ const BaseTanStackRouterDevtoolsPanel = React__default.forwardRef(function BaseT
|
|
|
503
507
|
);
|
|
504
508
|
}) }) })
|
|
505
509
|
] }),
|
|
506
|
-
|
|
510
|
+
routerState.cachedMatches.length ? /* @__PURE__ */ jsxs("div", { className: getStyles().cachedMatchesContainer, children: [
|
|
507
511
|
/* @__PURE__ */ jsxs("div", { className: getStyles().detailsHeader, children: [
|
|
508
512
|
/* @__PURE__ */ jsx("div", { children: "Cached Matches" }),
|
|
509
513
|
/* @__PURE__ */ jsx("div", { className: getStyles().detailsHeaderInfo, children: "age / staleTime / gcTime" })
|
|
@@ -553,15 +557,13 @@ const BaseTanStackRouterDevtoolsPanel = React__default.forwardRef(function BaseT
|
|
|
553
557
|
] }),
|
|
554
558
|
/* @__PURE__ */ jsxs("div", { className: getStyles().matchDetailsInfoLabel, children: [
|
|
555
559
|
/* @__PURE__ */ jsx("div", { children: "State:" }),
|
|
556
|
-
/* @__PURE__ */ jsx("div", { className: getStyles().matchDetailsInfo, children: ((
|
|
560
|
+
/* @__PURE__ */ jsx("div", { className: getStyles().matchDetailsInfo, children: ((_a = routerState.pendingMatches) == null ? void 0 : _a.find(
|
|
557
561
|
(d) => d.id === activeMatch.id
|
|
558
|
-
)) ? "Pending" :
|
|
562
|
+
)) ? "Pending" : routerState.matches.find((d) => d.id === activeMatch.id) ? "Active" : "Cached" })
|
|
559
563
|
] }),
|
|
560
564
|
/* @__PURE__ */ jsxs("div", { className: getStyles().matchDetailsInfoLabel, children: [
|
|
561
565
|
/* @__PURE__ */ jsx("div", { children: "Last Updated:" }),
|
|
562
|
-
/* @__PURE__ */ jsx("div", { className: getStyles().matchDetailsInfo, children: activeMatch.updatedAt ? new Date(
|
|
563
|
-
activeMatch.updatedAt
|
|
564
|
-
).toLocaleTimeString() : "N/A" })
|
|
566
|
+
/* @__PURE__ */ jsx("div", { className: getStyles().matchDetailsInfo, children: activeMatch.updatedAt ? new Date(activeMatch.updatedAt).toLocaleTimeString() : "N/A" })
|
|
565
567
|
] })
|
|
566
568
|
] }) }),
|
|
567
569
|
activeMatch.loaderData ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -583,13 +585,14 @@ const BaseTanStackRouterDevtoolsPanel = React__default.forwardRef(function BaseT
|
|
|
583
585
|
/* @__PURE__ */ jsx("div", { className: getStyles().detailsContent, children: /* @__PURE__ */ jsx(
|
|
584
586
|
Explorer,
|
|
585
587
|
{
|
|
586
|
-
value: routerState.location.search
|
|
587
|
-
defaultExpanded: Object.keys(
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
588
|
+
value: routerState.location.search,
|
|
589
|
+
defaultExpanded: Object.keys(routerState.location.search).reduce(
|
|
590
|
+
(obj, next) => {
|
|
591
|
+
obj[next] = {};
|
|
592
|
+
return obj;
|
|
593
|
+
},
|
|
594
|
+
{}
|
|
595
|
+
)
|
|
593
596
|
}
|
|
594
597
|
) })
|
|
595
598
|
] }) : null
|
|
@@ -612,15 +615,15 @@ function AgeTicker({
|
|
|
612
615
|
return () => {
|
|
613
616
|
clearInterval(interval);
|
|
614
617
|
};
|
|
615
|
-
}, []);
|
|
618
|
+
}, [rerender]);
|
|
616
619
|
if (!match) {
|
|
617
620
|
return null;
|
|
618
621
|
}
|
|
619
|
-
const route = router.looseRoutesById[match
|
|
622
|
+
const route = router.looseRoutesById[match.routeId];
|
|
620
623
|
if (!route.options.loader) {
|
|
621
624
|
return null;
|
|
622
625
|
}
|
|
623
|
-
const age = Date.now() -
|
|
626
|
+
const age = Date.now() - match.updatedAt;
|
|
624
627
|
const staleTime = route.options.staleTime ?? router.options.defaultStaleTime ?? 0;
|
|
625
628
|
const gcTime = route.options.gcTime ?? router.options.defaultGcTime ?? 30 * 60 * 1e3;
|
|
626
629
|
return /* @__PURE__ */ jsxs("div", { className: clsx(getStyles().ageTicker(age > staleTime)), children: [
|
|
@@ -841,10 +844,9 @@ const stylesFactory = () => {
|
|
|
841
844
|
classes.push(inactiveStyles);
|
|
842
845
|
}
|
|
843
846
|
if (showBorder) {
|
|
844
|
-
|
|
847
|
+
classes.push(css`
|
|
845
848
|
border-right: 1px solid ${tokens.colors.gray[500]};
|
|
846
|
-
|
|
847
|
-
classes.push(border2);
|
|
849
|
+
`);
|
|
848
850
|
}
|
|
849
851
|
return classes;
|
|
850
852
|
},
|