From f22bce8f3a047f09e6e96bbbd22b2a59c13a011d Mon Sep 17 00:00:00 2001 From: artalar Date: Sat, 14 Dec 2024 01:11:00 +0300 Subject: [PATCH] feat(devtools): add ability to edit atoms states --- packages/devtools/src/Graph.tsx | 2 +- .../devtools/src/Graph/reatomInspector.tsx | 103 ++++++++++++++++-- packages/devtools/src/ObservableHQ.tsx | 4 +- 3 files changed, 100 insertions(+), 9 deletions(-) diff --git a/packages/devtools/src/Graph.tsx b/packages/devtools/src/Graph.tsx index 98254562..b6152d7e 100644 --- a/packages/devtools/src/Graph.tsx +++ b/packages/devtools/src/Graph.tsx @@ -220,7 +220,7 @@ export const Graph = ({ clientCtx, getColor, width, height }: Props) => { return search.length < 2 ? '' : search.toLocaleLowerCase() }) - const inspector = reatomInspector({ filters }, `${name}.inspector`) + const inspector = reatomInspector({ clientCtx, filters }, `${name}.inspector`) const listHeight = reatomResource(async (ctx) => { ctx.spy(list) diff --git a/packages/devtools/src/Graph/reatomInspector.tsx b/packages/devtools/src/Graph/reatomInspector.tsx index 9dfffe58..356e3e9b 100644 --- a/packages/devtools/src/Graph/reatomInspector.tsx +++ b/packages/devtools/src/Graph/reatomInspector.tsx @@ -1,22 +1,27 @@ -import { __root, action, atom, AtomCache, parseAtoms, withReset } from '@reatom/framework' +import { __root, action, atom, AtomCache, Ctx, parseAtoms, withReset } from '@reatom/framework' import { h, hf, JSX } from '@reatom/jsx' import { ObservableHQ, ObservableHQActionButton } from '../ObservableHQ' import { reatomFilters } from './reatomFilters' import { actionsStates, history } from './utils' -import { withComputed } from '@reatom/primitives' +import { reatomBoolean, withComputed } from '@reatom/primitives' type InspectorState = | { kind: 'hidden' } | { kind: 'open'; patch: AtomCache } | { kind: 'fixed'; patch: AtomCache; element: HTMLElement } -export const reatomInspector = ({ filters }: { filters: ReturnType }, name: string) => { +export const reatomInspector = ( + { clientCtx, filters }: { clientCtx: Ctx; filters: ReturnType }, + name: string, +) => { const state = atom({ kind: 'hidden' }, `${name}.state`) + const patch = atom((ctx) => { const s = ctx.spy(state) return s.kind === 'hidden' ? null : s.patch }, `${name}.patch`) + const patchState = atom(null, `${name}.patchState`).pipe( withComputed((ctx) => { const patchState = ctx.spy(patch) @@ -29,6 +34,22 @@ export const reatomInspector = ({ filters }: { filters: ReturnType { + ctx.spy(patch) + return false + }), + ) + + const json = atom((ctx) => { + try { + return JSON.stringify(ctx.spy(patch)?.state, null, 2) ?? '' + } catch (error) { + return '' + } + }, `${name}.json`) + const patchHistory = atom((ctx) => { const patchState = ctx.spy(patch) @@ -94,6 +115,16 @@ export const reatomInspector = ({ filters }: { filters: ReturnType { + ctx.get((read, actualize) => { + const proto = ctx.get(patch)?.proto! + actualize!(ctx, proto, (patchCtx: Ctx, patch: AtomCache) => { + patch.state = JSON.parse(value) + }) + }) + }, `${name}.update`) + const OPACITY = { hidden: '0', open: '0.8', @@ -138,8 +169,17 @@ export const reatomInspector = ({ filters }: { filters: ReturnType
(ctx.spy(edit) ? 'none' : 'block'))} + css:form-display={atom((ctx) => (ctx.spy(edit) ? 'block' : 'none'))} css={` min-height: 100px; + + & .observablehq-container { + display: var(--observablehq-display); + } + & form { + display: var(--form-display); + } `} >

- x - + <> + (ctx.spy(patch)?.proto.isAction ? 'none' : ''))} + on:click={edit.toggle} + title="Edit" + aria-label="Toggle editing" + css={` + display: var(--display); + `} + > + ✏️ + + + x + + } - /> + > +
{ + e.preventDefault() + const proto = ctx.get(patch)?.proto + const textarea = e.currentTarget.firstChild + if (proto && textarea instanceof HTMLTextAreaElement) { + update(clientCtx, textarea.value) + textarea.value = ctx.get(json) + } + }} + aria-label="Update state" + > +