react-state-custom 1.0.22 → 1.0.24
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/.github/copilot-instructions.md +17 -2
- package/.github/workflows/deploy.yml +56 -0
- package/API_DOCUMENTATION.md +132 -3
- package/README.md +69 -1
- package/dist/dev-tool/DataViewComponent.d.ts +6 -0
- package/dist/dev-tool/DevTool.d.ts +5 -0
- package/dist/dev-tool/DevToolState.d.ts +9 -0
- package/dist/dev-tool/StateLabelRender.d.ts +2 -0
- package/dist/dev-tool/useHighlight.d.ts +11 -0
- package/dist/dev.d.ts +0 -1
- package/dist/examples/Playground.d.ts +1 -0
- package/dist/examples/cart/app.d.ts +1 -0
- package/dist/examples/cart/index.d.ts +3 -0
- package/dist/examples/cart/state.d.ts +23 -0
- package/dist/examples/cart/view.d.ts +4 -0
- package/dist/examples/counter/app.d.ts +1 -0
- package/dist/examples/counter/index.d.ts +2 -0
- package/dist/examples/counter/state.d.ts +6 -0
- package/dist/examples/counter/view.d.ts +2 -0
- package/dist/examples/form/app.d.ts +1 -0
- package/dist/examples/form/index.d.ts +3 -0
- package/dist/examples/form/state.d.ts +16 -0
- package/dist/examples/form/view.d.ts +4 -0
- package/dist/examples/timer/app.d.ts +1 -0
- package/dist/examples/timer/index.d.ts +2 -0
- package/dist/examples/timer/state.d.ts +11 -0
- package/dist/examples/timer/view.d.ts +4 -0
- package/dist/examples/todo/app.d.ts +1 -0
- package/dist/examples/todo/index.d.ts +3 -0
- package/dist/examples/todo/state.d.ts +17 -0
- package/dist/examples/todo/view.d.ts +4 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.es.js +297 -397
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/react-state-custom.css +1 -1
- package/dist/state-utils/ctx.d.ts +3 -2
- package/package.json +7 -2
- package/src/dev-tool/DataViewComponent.tsx +17 -0
- package/src/dev-tool/DevTool.css +134 -0
- package/src/{DevTool.tsx → dev-tool/DevTool.tsx} +3 -2
- package/src/dev-tool/DevToolState.tsx +78 -0
- package/src/dev-tool/StateLabelRender.tsx +38 -0
- package/src/dev-tool/useHighlight.tsx +56 -0
- package/src/dev.tsx +4 -11
- package/src/examples/Playground.tsx +180 -0
- package/src/examples/cart/app.tsx +16 -0
- package/src/examples/cart/index.ts +3 -0
- package/src/examples/cart/state.ts +67 -0
- package/src/examples/cart/view.tsx +62 -0
- package/src/examples/counter/app.tsx +14 -0
- package/src/examples/counter/index.ts +2 -0
- package/src/examples/counter/state.ts +22 -0
- package/src/examples/counter/state.tsx?raw +0 -0
- package/src/examples/counter/view.tsx +20 -0
- package/src/examples/form/app.tsx +16 -0
- package/src/examples/form/index.ts +3 -0
- package/src/examples/form/state.ts +58 -0
- package/src/examples/form/view.tsx +53 -0
- package/src/examples/timer/app.tsx +16 -0
- package/src/examples/timer/index.ts +2 -0
- package/src/examples/timer/state.ts +43 -0
- package/src/examples/timer/view.tsx +26 -0
- package/src/examples/todo/app.tsx +16 -0
- package/src/examples/todo/index.ts +3 -0
- package/src/examples/todo/state.ts +54 -0
- package/src/examples/todo/view.tsx +47 -0
- package/src/index.ts +2 -1
- package/src/state-utils/ctx.ts +36 -13
- package/src/vite-env.d.ts +6 -0
- package/tsconfig.json +12 -3
- package/vite.config.dev.ts +6 -1
- package/dist/DevTool.d.ts +0 -4
- package/dist/DevToolState.d.ts +0 -15
- package/dist/Test.d.ts +0 -1
- package/src/DevTool.css +0 -192
- package/src/DevToolState.tsx +0 -319
- package/src/Test.tsx +0 -97
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { createRootCtx, createAutoCtx } from '../../index'
|
|
2
|
+
import { useCallback, useEffect, useState } from 'react'
|
|
3
|
+
|
|
4
|
+
export const { useCtxState: useTimerCtx } = createAutoCtx(
|
|
5
|
+
createRootCtx(
|
|
6
|
+
"timer",
|
|
7
|
+
({ timerId }: { timerId: string }) => {
|
|
8
|
+
const [milliseconds, setMilliseconds] = useState(0)
|
|
9
|
+
const [isRunning, setIsRunning] = useState(false)
|
|
10
|
+
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (!isRunning) return
|
|
13
|
+
const interval = setInterval(() => {
|
|
14
|
+
setMilliseconds(ms => ms + 10)
|
|
15
|
+
}, 10)
|
|
16
|
+
return () => clearInterval(interval)
|
|
17
|
+
}, [isRunning])
|
|
18
|
+
|
|
19
|
+
const totalSeconds = Math.floor(milliseconds / 1000)
|
|
20
|
+
const minutes = Math.floor(totalSeconds / 60)
|
|
21
|
+
const seconds = totalSeconds % 60
|
|
22
|
+
const ms = Math.floor((milliseconds % 1000) / 10)
|
|
23
|
+
const formattedTime = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}.${ms.toString().padStart(2, '0')}`
|
|
24
|
+
|
|
25
|
+
const start = useCallback(() => setIsRunning(true), [])
|
|
26
|
+
const pause = useCallback(() => setIsRunning(false), [])
|
|
27
|
+
const reset = useCallback(() => {
|
|
28
|
+
setIsRunning(false)
|
|
29
|
+
setMilliseconds(0)
|
|
30
|
+
}, [])
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
timerId,
|
|
34
|
+
milliseconds,
|
|
35
|
+
isRunning,
|
|
36
|
+
formattedTime,
|
|
37
|
+
start,
|
|
38
|
+
pause,
|
|
39
|
+
reset,
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
)
|
|
43
|
+
)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useQuickSubscribe } from '../../index'
|
|
2
|
+
import { useTimerCtx } from './state'
|
|
3
|
+
|
|
4
|
+
export const TimerExample = ({ timerId = "main-timer" }: { timerId?: string }) => {
|
|
5
|
+
const { formattedTime, isRunning, start, pause, reset } =
|
|
6
|
+
useQuickSubscribe(useTimerCtx({ timerId }))
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<div style={{ padding: '1rem', border: '1px solid #ccc', marginBottom: '1rem' }}>
|
|
10
|
+
<h3>Timer ({timerId})</h3>
|
|
11
|
+
<div style={{ fontSize: '2rem', fontFamily: 'monospace', marginBottom: '1rem' }}>
|
|
12
|
+
{formattedTime}
|
|
13
|
+
</div>
|
|
14
|
+
<div style={{ display: 'flex', gap: '0.5rem' }}>
|
|
15
|
+
{!isRunning ? (
|
|
16
|
+
<button onClick={start}>Start</button>
|
|
17
|
+
) : (
|
|
18
|
+
<button onClick={pause}>Pause</button>
|
|
19
|
+
)}
|
|
20
|
+
<button onClick={reset}>Reset</button>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default TimerExample
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { TodoExample } from './view'
|
|
2
|
+
|
|
3
|
+
export default function App() {
|
|
4
|
+
return (
|
|
5
|
+
<>
|
|
6
|
+
{/* <AutoRootCtx/> */}
|
|
7
|
+
<TodoExample listId="main" />
|
|
8
|
+
<TodoExample listId="work" />
|
|
9
|
+
<p style={{ color: '#666', fontSize: '0.875rem' }}>
|
|
10
|
+
Multiple independent todo lists showing how contexts can be scoped by parameters (listId).
|
|
11
|
+
Each list maintains its own state.
|
|
12
|
+
</p>
|
|
13
|
+
{/* <DevToolContainer Component={DataView} /> */}
|
|
14
|
+
</>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { createRootCtx, createAutoCtx } from '../../index'
|
|
2
|
+
import { useCallback, useState } from 'react'
|
|
3
|
+
|
|
4
|
+
export interface Todo {
|
|
5
|
+
id: string
|
|
6
|
+
text: string
|
|
7
|
+
completed: boolean
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const { useCtxState: useTodoCtx } = createAutoCtx(
|
|
11
|
+
createRootCtx(
|
|
12
|
+
"todos",
|
|
13
|
+
({ listId }: { listId: string }) => {
|
|
14
|
+
const [todos, setTodos] = useState<Todo[]>([])
|
|
15
|
+
const [input, setInput] = useState('')
|
|
16
|
+
|
|
17
|
+
const addTodo = useCallback(() => {
|
|
18
|
+
if (input.trim()) {
|
|
19
|
+
setTodos(prev => [...prev, {
|
|
20
|
+
id: Date.now().toString(),
|
|
21
|
+
text: input.trim(),
|
|
22
|
+
completed: false
|
|
23
|
+
}])
|
|
24
|
+
setInput('')
|
|
25
|
+
}
|
|
26
|
+
}, [input])
|
|
27
|
+
|
|
28
|
+
const toggleTodo = useCallback((id: string) => {
|
|
29
|
+
setTodos(prev => prev.map(t =>
|
|
30
|
+
t.id === id ? { ...t, completed: !t.completed } : t
|
|
31
|
+
))
|
|
32
|
+
}, [])
|
|
33
|
+
|
|
34
|
+
const removeTodo = useCallback((id: string) => {
|
|
35
|
+
setTodos(prev => prev.filter(t => t.id !== id))
|
|
36
|
+
}, [])
|
|
37
|
+
|
|
38
|
+
const clearCompleted = useCallback(() => {
|
|
39
|
+
setTodos(prev => prev.filter(t => !t.completed))
|
|
40
|
+
}, [])
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
listId,
|
|
44
|
+
todos,
|
|
45
|
+
input,
|
|
46
|
+
setInput,
|
|
47
|
+
addTodo,
|
|
48
|
+
toggleTodo,
|
|
49
|
+
removeTodo,
|
|
50
|
+
clearCompleted,
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useQuickSubscribe } from '../../index'
|
|
2
|
+
import { useTodoCtx } from './state'
|
|
3
|
+
|
|
4
|
+
export const TodoExample = ({ listId = "main" }: { listId?: string }) => {
|
|
5
|
+
const { todos, input, setInput, addTodo, toggleTodo, removeTodo, clearCompleted } =
|
|
6
|
+
useQuickSubscribe(useTodoCtx({ listId }))
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<div style={{ padding: '1rem', border: '1px solid #ccc', marginBottom: '1rem' }}>
|
|
10
|
+
<h3>Todo List ({listId})</h3>
|
|
11
|
+
<div style={{ display: 'flex', gap: '0.5rem', marginBottom: '1rem' }}>
|
|
12
|
+
<input
|
|
13
|
+
value={input ?? ''}
|
|
14
|
+
onChange={(e) => setInput?.(e.target.value)}
|
|
15
|
+
onKeyDown={(e) => e.key === 'Enter' && addTodo?.()}
|
|
16
|
+
placeholder="Add todo..."
|
|
17
|
+
style={{ flex: 1, padding: '0.25rem' }}
|
|
18
|
+
/>
|
|
19
|
+
<button onClick={addTodo}>Add</button>
|
|
20
|
+
</div>
|
|
21
|
+
<ul style={{ listStyle: 'none', padding: 0 }}>
|
|
22
|
+
{todos?.map(todo => (
|
|
23
|
+
<li key={todo.id} style={{ display: 'flex', gap: '0.5rem', marginBottom: '0.5rem' }}>
|
|
24
|
+
<input
|
|
25
|
+
type="checkbox"
|
|
26
|
+
checked={todo.completed}
|
|
27
|
+
onChange={() => toggleTodo?.(todo.id)}
|
|
28
|
+
/>
|
|
29
|
+
<span style={{
|
|
30
|
+
flex: 1,
|
|
31
|
+
textDecoration: todo.completed ? 'line-through' : 'none',
|
|
32
|
+
opacity: todo.completed ? 0.6 : 1
|
|
33
|
+
}}>
|
|
34
|
+
{todo.text}
|
|
35
|
+
</span>
|
|
36
|
+
<button onClick={() => removeTodo?.(todo.id)}>×</button>
|
|
37
|
+
</li>
|
|
38
|
+
))}
|
|
39
|
+
</ul>
|
|
40
|
+
{todos?.some(t => t.completed) && (
|
|
41
|
+
<button onClick={clearCompleted}>Clear Completed</button>
|
|
42
|
+
)}
|
|
43
|
+
</div>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default TodoExample
|
package/src/index.ts
CHANGED
|
@@ -18,4 +18,5 @@ export { useArrayHash } from "./state-utils/useArrayHash"
|
|
|
18
18
|
|
|
19
19
|
export { useQuickSubscribe } from "./state-utils/useQuickSubscribe"
|
|
20
20
|
|
|
21
|
-
export { DevToolContainer } from "./DevTool"
|
|
21
|
+
export { DevToolContainer } from "./dev-tool/DevTool"
|
|
22
|
+
export type { DataViewComponent } from "./dev-tool/DataViewComponent"
|
package/src/state-utils/ctx.ts
CHANGED
|
@@ -4,12 +4,22 @@ import { useArrayHash } from "./useArrayHash"
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const CHANGE_EVENT = "@--change-event"
|
|
8
|
+
|
|
9
|
+
class DataEvent<D> extends Event {
|
|
8
10
|
constructor(
|
|
9
|
-
public event:
|
|
10
|
-
public value:
|
|
11
|
+
public event: keyof D,
|
|
12
|
+
public value: D[typeof event] | undefined
|
|
11
13
|
) {
|
|
12
|
-
super(event);
|
|
14
|
+
super(String(event));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
class ChangeEvent<D> extends Event {
|
|
19
|
+
constructor(
|
|
20
|
+
public value: DataEvent<D>
|
|
21
|
+
) {
|
|
22
|
+
super(CHANGE_EVENT, value);
|
|
13
23
|
}
|
|
14
24
|
}
|
|
15
25
|
|
|
@@ -28,8 +38,6 @@ export class Context<D> extends EventTarget {
|
|
|
28
38
|
super();
|
|
29
39
|
}
|
|
30
40
|
|
|
31
|
-
// private event = new EventEmitter()
|
|
32
|
-
|
|
33
41
|
/**
|
|
34
42
|
* The current data held by the context.
|
|
35
43
|
*/
|
|
@@ -48,9 +56,9 @@ export class Context<D> extends EventTarget {
|
|
|
48
56
|
|
|
49
57
|
if (value != this.data[key]) {
|
|
50
58
|
this.data[key] = value
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
this.dispatchEvent(new
|
|
59
|
+
let event = new DataEvent(key, value);
|
|
60
|
+
this.dispatchEvent(event);
|
|
61
|
+
this.dispatchEvent(new ChangeEvent(event))
|
|
54
62
|
}
|
|
55
63
|
}
|
|
56
64
|
|
|
@@ -71,7 +79,22 @@ export class Context<D> extends EventTarget {
|
|
|
71
79
|
|
|
72
80
|
if (key in this.data) _listener(this.data[key])
|
|
73
81
|
|
|
74
|
-
return () =>
|
|
82
|
+
return () => this.removeEventListener(String(key), listener)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public subscribeAll(_listener: (changeKey: keyof D, newData: Partial<D>) => void) {
|
|
86
|
+
|
|
87
|
+
const listener = (event: any) => {
|
|
88
|
+
if (event instanceof ChangeEvent) {
|
|
89
|
+
const { value: data } = event
|
|
90
|
+
_listener(data.event as any as keyof D, this.data)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
this.addEventListener(String(CHANGE_EVENT), listener)
|
|
95
|
+
|
|
96
|
+
return () => this.removeEventListener(String(CHANGE_EVENT), listener)
|
|
97
|
+
|
|
75
98
|
}
|
|
76
99
|
|
|
77
100
|
}
|
|
@@ -237,10 +260,10 @@ export const useDataSourceMultiple = <D, T extends readonly (keyof D)[]>(
|
|
|
237
260
|
* @param keys - Keys to subscribe to.
|
|
238
261
|
* @returns An object with the current values for the keys.
|
|
239
262
|
*/
|
|
240
|
-
export const useDataSubscribeMultiple = <D, K extends keyof D>(
|
|
263
|
+
export const useDataSubscribeMultiple = <D, K extends (keyof D)[]>(
|
|
241
264
|
ctx: Context<D> | undefined,
|
|
242
|
-
...keys: K
|
|
243
|
-
):
|
|
265
|
+
...keys: K
|
|
266
|
+
): { [i in keyof K]: D[K[i]] | undefined } => {
|
|
244
267
|
const [, setCounter] = useState(0)
|
|
245
268
|
|
|
246
269
|
const returnValues = keys.map(key => ctx?.data?.[key])
|
package/tsconfig.json
CHANGED
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"target": "esnext",
|
|
4
4
|
"module": "esnext",
|
|
5
|
-
"lib": [
|
|
5
|
+
"lib": [
|
|
6
|
+
"dom",
|
|
7
|
+
"esnext"
|
|
8
|
+
],
|
|
6
9
|
"moduleResolution": "node",
|
|
7
10
|
"jsx": "react-jsx",
|
|
8
11
|
"strict": true,
|
|
@@ -13,6 +16,12 @@
|
|
|
13
16
|
"declaration": true,
|
|
14
17
|
"sourceMap": true
|
|
15
18
|
},
|
|
16
|
-
"include": [
|
|
17
|
-
|
|
19
|
+
"include": [
|
|
20
|
+
"vite/client",
|
|
21
|
+
"src"
|
|
22
|
+
],
|
|
23
|
+
"exclude": [
|
|
24
|
+
"node_modules",
|
|
25
|
+
"dist"
|
|
26
|
+
]
|
|
18
27
|
}
|
package/vite.config.dev.ts
CHANGED
|
@@ -2,10 +2,15 @@ import { defineConfig } from 'vite';
|
|
|
2
2
|
import react from '@vitejs/plugin-react';
|
|
3
3
|
|
|
4
4
|
export default defineConfig({
|
|
5
|
+
base: '/react-state-custom/',
|
|
5
6
|
plugins: [
|
|
6
7
|
react(),
|
|
7
8
|
],
|
|
8
9
|
build: {
|
|
9
10
|
target: 'esnext',
|
|
10
|
-
|
|
11
|
+
outDir: 'demo-dist',
|
|
12
|
+
},
|
|
13
|
+
server: {
|
|
14
|
+
port: 3000,
|
|
15
|
+
},
|
|
11
16
|
});
|
package/dist/DevTool.d.ts
DELETED
package/dist/DevToolState.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { default as React } from 'react';
|
|
2
|
-
export declare const DevToolState: ({}: {}) => import("react/jsx-runtime").JSX.Element;
|
|
3
|
-
export declare const StateView: React.FC<{
|
|
4
|
-
dataKey: string;
|
|
5
|
-
}>;
|
|
6
|
-
export declare const ChangeFlashWrappper: React.FC<React.ComponentProps<'div'> & {
|
|
7
|
-
value: any;
|
|
8
|
-
deepCompare?: boolean;
|
|
9
|
-
}>;
|
|
10
|
-
export declare const JSONView: React.FC<{
|
|
11
|
-
value: any;
|
|
12
|
-
name?: string;
|
|
13
|
-
style?: any;
|
|
14
|
-
expandLevel?: number | boolean;
|
|
15
|
-
}>;
|
package/dist/Test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const Test: ({}: {}) => import("react/jsx-runtime").JSX.Element;
|
package/src/DevTool.css
DELETED
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
:root {
|
|
2
|
-
color-scheme: light dark;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
.react-state-dev-btn {
|
|
6
|
-
position: fixed;
|
|
7
|
-
bottom: 30px;
|
|
8
|
-
right: 30px;
|
|
9
|
-
transition: opacity 0.3s;
|
|
10
|
-
|
|
11
|
-
&[data-active="true"] {
|
|
12
|
-
opacity: 0;
|
|
13
|
-
pointer-events: none;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
.react-state-dev-container {
|
|
19
|
-
--color: light-dark(#333b3c, #efefec);
|
|
20
|
-
--bg-color: light-dark(#f9f9f9, #212121);
|
|
21
|
-
align-items: stretch;
|
|
22
|
-
font-size: 14px;
|
|
23
|
-
color: var(--color);
|
|
24
|
-
background-color: var(--bg-color);
|
|
25
|
-
position: fixed;
|
|
26
|
-
bottom: 0px;
|
|
27
|
-
right: 0px;
|
|
28
|
-
left: 0px;
|
|
29
|
-
opacity: 0;
|
|
30
|
-
pointer-events: none;
|
|
31
|
-
transition: opacity 0.3s, transform 0.3s;
|
|
32
|
-
transform: translateY(100%);
|
|
33
|
-
padding: 0.5em;
|
|
34
|
-
|
|
35
|
-
&[data-active="true"] {
|
|
36
|
-
opacity: 1;
|
|
37
|
-
pointer-events: all;
|
|
38
|
-
transform: translateY(0%);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.close-btn {
|
|
42
|
-
position: absolute;
|
|
43
|
-
top: -20px;
|
|
44
|
-
right: 0px;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
.main-panel {
|
|
48
|
-
display: flex;
|
|
49
|
-
flex-direction: row;
|
|
50
|
-
gap: 1em;
|
|
51
|
-
padding: 1em;
|
|
52
|
-
resize: vertical;
|
|
53
|
-
min-height: 200px;
|
|
54
|
-
max-height: 60vh;
|
|
55
|
-
background-color: #8882;
|
|
56
|
-
overflow: hidden;
|
|
57
|
-
justify-items: stretch;
|
|
58
|
-
|
|
59
|
-
.state-list {
|
|
60
|
-
max-width: 50%;
|
|
61
|
-
min-width: 100px;
|
|
62
|
-
overflow: auto;
|
|
63
|
-
align-self: stretch;
|
|
64
|
-
resize: horizontal;
|
|
65
|
-
|
|
66
|
-
.state-key {
|
|
67
|
-
cursor: pointer;
|
|
68
|
-
padding: 0.2em;
|
|
69
|
-
border-bottom: solid 1px #8884;
|
|
70
|
-
font-family: monospace;
|
|
71
|
-
overflow: hidden;
|
|
72
|
-
text-overflow: ellipsis;
|
|
73
|
-
white-space: nowrap;
|
|
74
|
-
|
|
75
|
-
&[data-active="true"] {
|
|
76
|
-
background-color: light-dark(#0003, #fff3);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
.state-view {
|
|
83
|
-
flex: 1;
|
|
84
|
-
overflow: auto;
|
|
85
|
-
border-inline-start: solid 1px #8888;;
|
|
86
|
-
padding-inline-start: 1em;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
.jv-root {
|
|
92
|
-
font-family: monospace;
|
|
93
|
-
user-select: none;
|
|
94
|
-
|
|
95
|
-
.jv-name {
|
|
96
|
-
opacity: 0.8;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
.jv-type {
|
|
100
|
-
opacity: 0.5;
|
|
101
|
-
font-size: smaller;
|
|
102
|
-
padding-inline: 0.4em;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
.jv-cursor {
|
|
106
|
-
cursor: pointer;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.jv-field {
|
|
110
|
-
margin-block: 1px;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
.jv-field .jv-field {
|
|
114
|
-
transition: border-color 1s, background-color 1s;
|
|
115
|
-
border-color: #0000;
|
|
116
|
-
background-color: #0000;
|
|
117
|
-
border-width: 1px;
|
|
118
|
-
border-style: solid;
|
|
119
|
-
|
|
120
|
-
&.jv-updated {
|
|
121
|
-
transition: border-color 0.00s, background-color 0.00s;
|
|
122
|
-
border-color: #f00;
|
|
123
|
-
background-color: #f001;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
.jv-field-obj>.jv-value {
|
|
128
|
-
padding-inline-start: 1em;
|
|
129
|
-
margin-inline-start: 0.6em;
|
|
130
|
-
border-inline-start: solid 1px #8888;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
.jv-field-obj>:first-child>:first-child>.jv-name {
|
|
134
|
-
cursor: pointer;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
.jv-field-obj {
|
|
139
|
-
--lv: 0;
|
|
140
|
-
|
|
141
|
-
.jv-field-obj {
|
|
142
|
-
--lv: 1;
|
|
143
|
-
|
|
144
|
-
.jv-field-obj {
|
|
145
|
-
--lv: 2;
|
|
146
|
-
|
|
147
|
-
.jv-field-obj {
|
|
148
|
-
--lv: 3;
|
|
149
|
-
|
|
150
|
-
.jv-field-obj {
|
|
151
|
-
--lv: 4;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
.jv-field-obj>:first-child {
|
|
159
|
-
container-type: scroll-state;
|
|
160
|
-
position: sticky;
|
|
161
|
-
top: calc(var(--lv, 0) * 1.25em);
|
|
162
|
-
z-index: calc(10 - var(--lv, 0));
|
|
163
|
-
|
|
164
|
-
@container scroll-state(stuck: top) {
|
|
165
|
-
>div {
|
|
166
|
-
background-color: var(--bg-color);
|
|
167
|
-
border-bottom: solid 1px #8884;
|
|
168
|
-
font-weight: bold;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
.jv-field-string> :is(.jv-type, .jv-value) {
|
|
178
|
-
color: orange;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
.jv-field-number> :is(.jv-type, .jv-value) {
|
|
182
|
-
color: red;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
.jv-field-boolean> :is(.jv-type, .jv-value) {
|
|
186
|
-
color: #08f;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
.jv-field-function> :is(.jv-type, .jv-value) {
|
|
190
|
-
color: #08f;
|
|
191
|
-
}
|
|
192
|
-
}
|