atom.io 0.28.1 → 0.28.2

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.
Files changed (65) hide show
  1. package/dist/{chunk-6WL4RQMQ.js → chunk-D3ZPRYEW.js} +15 -17
  2. package/eslint-plugin/dist/index.js +0 -1
  3. package/eslint-plugin/src/walk.ts +0 -1
  4. package/internal/dist/index.d.ts +3 -3
  5. package/internal/dist/index.js +1 -1
  6. package/internal/src/operation.ts +7 -7
  7. package/internal/src/selector/create-writable-selector.ts +1 -1
  8. package/internal/src/set-state/become.ts +1 -3
  9. package/internal/src/set-state/evict-downstream.ts +2 -2
  10. package/internal/src/set-state/set-atom.ts +1 -1
  11. package/internal/src/set-state/set-into-store.ts +1 -1
  12. package/internal/src/set-state/stow-update.ts +2 -2
  13. package/internal/src/store/store.ts +1 -1
  14. package/introspection/dist/index.d.ts +15 -6
  15. package/introspection/dist/index.js +620 -1
  16. package/introspection/src/attach-atom-index.ts +5 -6
  17. package/introspection/src/attach-introspection-states.ts +5 -6
  18. package/introspection/src/attach-selector-index.ts +6 -7
  19. package/introspection/src/attach-timeline-family.ts +3 -4
  20. package/introspection/src/attach-timeline-index.ts +4 -8
  21. package/introspection/src/attach-transaction-index.ts +4 -8
  22. package/introspection/src/attach-transaction-logs.ts +4 -8
  23. package/introspection/src/attach-type-selectors.ts +13 -6
  24. package/introspection/src/differ.ts +1 -1
  25. package/introspection/src/index.ts +1 -0
  26. package/introspection/src/refinery.ts +9 -7
  27. package/introspection/src/sprawl.ts +42 -0
  28. package/json/dist/index.d.ts +12 -1
  29. package/json/dist/index.js +111 -2
  30. package/json/src/index.ts +29 -0
  31. package/package.json +8 -8
  32. package/react-devtools/dist/index.d.ts +159 -2
  33. package/react-devtools/dist/index.js +260 -663
  34. package/react-devtools/src/AtomIODevtools.tsx +24 -13
  35. package/react-devtools/src/StateEditor.tsx +5 -47
  36. package/react-devtools/src/StateIndex.tsx +15 -9
  37. package/react-devtools/src/TimelineIndex.tsx +9 -6
  38. package/react-devtools/src/TransactionIndex.tsx +9 -11
  39. package/react-devtools/src/elastic-input/ElasticInput.tsx +86 -0
  40. package/react-devtools/src/elastic-input/NumberInput.tsx +199 -0
  41. package/react-devtools/src/elastic-input/TextInput.tsx +47 -0
  42. package/react-devtools/src/elastic-input/index.ts +3 -0
  43. package/react-devtools/src/error-boundary/DefaultFallback.tsx +49 -0
  44. package/react-devtools/src/error-boundary/ReactErrorBoundary.tsx +56 -0
  45. package/react-devtools/src/error-boundary/index.ts +2 -0
  46. package/react-devtools/src/index.ts +3 -0
  47. package/react-devtools/src/json-editor/assets/Untitled-1.ai +1436 -2
  48. package/react-devtools/src/json-editor/assets/data-vis.ai +1548 -1
  49. package/react-devtools/src/json-editor/comp/json-editor-sketches.ai +1451 -3
  50. package/react-devtools/src/json-editor/default-components.tsx +101 -0
  51. package/react-devtools/src/json-editor/developer-interface.tsx +81 -0
  52. package/react-devtools/src/json-editor/editors-by-type/array-editor.tsx +38 -0
  53. package/react-devtools/src/json-editor/editors-by-type/non-json.tsx +23 -0
  54. package/react-devtools/src/json-editor/editors-by-type/object-editor.tsx +128 -0
  55. package/react-devtools/src/json-editor/editors-by-type/primitive-editors.tsx +73 -0
  56. package/react-devtools/src/json-editor/editors-by-type/utilities/array-elements.ts +16 -0
  57. package/react-devtools/src/json-editor/editors-by-type/utilities/cast-json.ts +57 -0
  58. package/react-devtools/src/json-editor/editors-by-type/utilities/cast-to-json.ts +156 -0
  59. package/react-devtools/src/json-editor/editors-by-type/utilities/object-properties.ts +106 -0
  60. package/react-devtools/src/json-editor/index.ts +32 -0
  61. package/react-devtools/src/json-editor/json-editor-internal.tsx +128 -0
  62. package/react-devtools/src/json-editor/todo.md +7 -0
  63. package/react-devtools/src/store.ts +70 -46
  64. package/dist/chunk-D52JNVER.js +0 -721
  65. package/dist/chunk-YQ46F5O2.js +0 -95
@@ -0,0 +1,106 @@
1
+ import { become } from "atom.io/internal"
2
+ import type { Json, JsonTypeName } from "atom.io/json"
3
+ import { fromEntries, JSON_DEFAULTS, toEntries } from "atom.io/json"
4
+ import type { MutableRefObject } from "react"
5
+
6
+ import type { SetterOrUpdater } from "../.."
7
+ import { castToJson } from "./cast-to-json"
8
+
9
+ export const makePropertySetters = <T extends Json.Tree.Object>(
10
+ data: T,
11
+ set: SetterOrUpdater<T>,
12
+ ): { [K in keyof T]: SetterOrUpdater<T[K]> } =>
13
+ fromEntries(
14
+ toEntries(data).map(([key, value]) => [
15
+ key,
16
+ (newValue) => {
17
+ set({ ...data, [key]: become(newValue)(value) })
18
+ },
19
+ ]),
20
+ )
21
+
22
+ export const makePropertyRenamers = <T extends Json.Tree.Object>(
23
+ data: T,
24
+ set: SetterOrUpdater<T>,
25
+ stableKeyMapRef: MutableRefObject<{ [Key in keyof T]: keyof T }>,
26
+ ): { [K in keyof T]: (newKey: string) => void } =>
27
+ fromEntries(
28
+ toEntries(data).map(([key, value]) => [
29
+ key,
30
+ (newKey: string) => {
31
+ if (!Object.hasOwn(data, newKey)) {
32
+ set(() => {
33
+ const entries = Object.entries(data)
34
+ const index = entries.findIndex(([k]) => k === key)
35
+ entries[index] = [newKey, value]
36
+ const stableKeyMap = stableKeyMapRef.current
37
+ stableKeyMapRef.current = {
38
+ ...stableKeyMap,
39
+ [newKey]: stableKeyMap[key],
40
+ }
41
+ return Object.fromEntries(entries) as T
42
+ })
43
+ }
44
+ },
45
+ ]),
46
+ )
47
+
48
+ export const makePropertyRemovers = <T extends Json.Tree.Object>(
49
+ data: T,
50
+ set: SetterOrUpdater<T>,
51
+ ): { [K in keyof T]: () => void } =>
52
+ fromEntries(
53
+ toEntries(data).map(([key]) => [
54
+ key,
55
+ () => {
56
+ set(() => {
57
+ const { [key]: _, ...rest } = data
58
+ return rest as T
59
+ })
60
+ },
61
+ ]),
62
+ )
63
+
64
+ export const makePropertyRecasters = <T extends Json.Tree.Object>(
65
+ data: T,
66
+ set: SetterOrUpdater<T>,
67
+ ): { [K in keyof T]: (newType: JsonTypeName) => void } =>
68
+ fromEntries(
69
+ toEntries(data).map(([key, value]) => [
70
+ key,
71
+ (newType: JsonTypeName) => {
72
+ set(() => ({
73
+ ...data,
74
+ [key]: castToJson(value)[newType],
75
+ }))
76
+ },
77
+ ]),
78
+ )
79
+
80
+ export const makePropertyCreationInterface =
81
+ <T extends Json.Tree.Object>(
82
+ data: T,
83
+ set: SetterOrUpdater<T>,
84
+ ): ((
85
+ key: string,
86
+ type: JsonTypeName,
87
+ ) => (value?: Json.Serializable) => void) =>
88
+ (key, type) =>
89
+ (value) => {
90
+ set({ ...data, [key]: value ?? JSON_DEFAULTS[type] })
91
+ }
92
+
93
+ export const makePropertySorter =
94
+ <T extends Json.Tree.Object>(
95
+ data: T,
96
+ set: SetterOrUpdater<T>,
97
+ sortFn?: (a: string, b: string) => number,
98
+ ): (() => void) =>
99
+ () => {
100
+ const sortedKeys = Object.keys(data).sort(sortFn)
101
+ const sortedObj = {} as Record<string, unknown>
102
+ for (const key of sortedKeys) {
103
+ sortedObj[key] = data[key]
104
+ }
105
+ set(sortedObj as T)
106
+ }
@@ -0,0 +1,32 @@
1
+ import type { JsonTypes } from "atom.io/json"
2
+ import type { FC } from "react"
3
+
4
+ import { ArrayEditor } from "./editors-by-type/array-editor"
5
+ import { ObjectEditor } from "./editors-by-type/object-editor"
6
+ import {
7
+ BooleanEditor,
8
+ NullEditor,
9
+ NumberEditor,
10
+ StringEditor,
11
+ } from "./editors-by-type/primitive-editors"
12
+ import type { JsonEditorProps_INTERNAL } from "./json-editor-internal"
13
+
14
+ export * from "./default-components"
15
+ export * from "./developer-interface"
16
+ export * from "./editors-by-type/utilities/cast-to-json"
17
+
18
+ export type SetterOrUpdater<T> = <New extends T>(
19
+ next: New | ((old: T) => New),
20
+ ) => void
21
+
22
+ export const SubEditors: Record<
23
+ keyof JsonTypes,
24
+ FC<JsonEditorProps_INTERNAL<any>>
25
+ > = {
26
+ array: ArrayEditor,
27
+ boolean: BooleanEditor,
28
+ null: NullEditor,
29
+ number: NumberEditor,
30
+ object: ObjectEditor,
31
+ string: StringEditor,
32
+ }
@@ -0,0 +1,128 @@
1
+ import { jsonRefinery } from "atom.io/introspection"
2
+ import type { JsonTypes } from "atom.io/json"
3
+ import { isJson } from "atom.io/json"
4
+ import type { CSSProperties, FC, ReactElement } from "react"
5
+
6
+ import { ElasticInput } from "../elastic-input"
7
+ import type { SetterOrUpdater } from "."
8
+ import { SubEditors } from "."
9
+ import type { JsonEditorComponents } from "./default-components"
10
+ import { NonJsonEditor } from "./editors-by-type/non-json"
11
+
12
+ export type JsonEditorProps_INTERNAL<T> = {
13
+ data: T
14
+ set: SetterOrUpdater<T>
15
+ name?: string | undefined
16
+ rename?: ((newKey: string) => void) | undefined
17
+ remove?: (() => void) | undefined
18
+ recast?: (newType: keyof JsonTypes) => void
19
+ path?: ReadonlyArray<number | string>
20
+ isReadonly?: (path: ReadonlyArray<number | string>) => boolean
21
+ isHidden?: (path: ReadonlyArray<number | string>) => boolean
22
+ className?: string | undefined
23
+ style?: CSSProperties | undefined
24
+ Header?: FC<{ data: T }> | undefined
25
+ Components: JsonEditorComponents
26
+ testid?: string | undefined
27
+ }
28
+
29
+ export const JsonEditor_INTERNAL = <T,>({
30
+ data,
31
+ set,
32
+ name,
33
+ rename,
34
+ remove,
35
+ recast,
36
+ path = [],
37
+ isReadonly = () => false,
38
+ isHidden = () => false,
39
+ className,
40
+ style,
41
+ Header: HeaderDisplay,
42
+ Components,
43
+ testid,
44
+ }: JsonEditorProps_INTERNAL<T>): ReactElement | null => {
45
+ const dataIsJson = isJson(data)
46
+ const refined = jsonRefinery.refine<unknown>(data) ?? {
47
+ type: `non-json`,
48
+ data,
49
+ }
50
+ const SubEditor = dataIsJson ? SubEditors[refined.type] : NonJsonEditor
51
+
52
+ const disabled = isReadonly(path)
53
+
54
+ return isHidden(path) ? null : (
55
+ <Components.ErrorBoundary>
56
+ <Components.EditorWrapper
57
+ className={className}
58
+ style={style}
59
+ testid={testid}
60
+ >
61
+ {remove ? (
62
+ disabled ? (
63
+ <Components.Button disabled testid={`${testid}-delete`}>
64
+ <Components.DeleteIcon />
65
+ </Components.Button>
66
+ ) : (
67
+ <Components.Button
68
+ testid={`${testid}-delete`}
69
+ onClick={() => {
70
+ remove()
71
+ }}
72
+ >
73
+ <Components.DeleteIcon />
74
+ </Components.Button>
75
+ )
76
+ ) : null}
77
+ {HeaderDisplay && <HeaderDisplay data={data} />}
78
+ {rename && (
79
+ <Components.KeyWrapper>
80
+ <ElasticInput
81
+ value={name}
82
+ onChange={
83
+ disabled
84
+ ? undefined
85
+ : (e) => {
86
+ rename(e.target.value)
87
+ }
88
+ }
89
+ disabled={disabled}
90
+ data-testid={`${testid}-rename`}
91
+ />
92
+ </Components.KeyWrapper>
93
+ )}
94
+ <SubEditor
95
+ data={refined.data}
96
+ set={set}
97
+ remove={remove}
98
+ rename={rename}
99
+ path={path}
100
+ isReadonly={isReadonly}
101
+ isHidden={isHidden}
102
+ Components={Components}
103
+ testid={testid}
104
+ />
105
+ {recast && dataIsJson ? (
106
+ <select
107
+ onChange={
108
+ disabled
109
+ ? undefined
110
+ : (e) => {
111
+ recast(e.target.value as keyof JsonTypes)
112
+ }
113
+ }
114
+ value={refined.type}
115
+ disabled={disabled}
116
+ data-testid={`${testid}-recast`}
117
+ >
118
+ {Object.keys(SubEditors).map((type) => (
119
+ <option key={type} value={type}>
120
+ {type}
121
+ </option>
122
+ ))}
123
+ </select>
124
+ ) : null}
125
+ </Components.EditorWrapper>
126
+ </Components.ErrorBoundary>
127
+ )
128
+ }
@@ -0,0 +1,7 @@
1
+
2
+ - [x] add an ErrorBoundary to the Components prop
3
+ - [x] wrap each JsonEditor_INTERNAL in an ErrorBoundary
4
+ - [ ] add display of miscast properties with button to fix
5
+ - [ ] fixing a miscast generates a template from the schema
6
+ - [ ] sort official properties as listed in schema
7
+ - [ ] add extra line break in JSON before unofficial properties
@@ -1,51 +1,75 @@
1
- import { atom, atomFamily } from "atom.io"
1
+ import type { RegularAtomFamilyToken, RegularAtomToken } from "atom.io"
2
+ import {
3
+ createAtomFamily,
4
+ createStandaloneAtom,
5
+ IMPLICIT,
6
+ type Store,
7
+ } from "atom.io/internal"
8
+ import type { IntrospectionStates } from "atom.io/introspection"
2
9
  import { attachIntrospectionStates } from "atom.io/introspection"
3
10
  import { persistSync } from "atom.io/web"
4
-
5
- export const {
6
- atomIndex,
7
- selectorIndex,
8
- transactionIndex,
9
- transactionLogSelectors,
10
- timelineIndex,
11
- timelineSelectors,
12
- typeSelectors,
13
- } = attachIntrospectionStates()
14
-
15
- export const devtoolsAreOpenState = atom<boolean>({
16
- key: `👁‍🗨 Devtools Are Open`,
17
- default: true,
18
- effects:
19
- typeof window === `undefined`
20
- ? []
21
- : [persistSync(window.localStorage, JSON, `👁‍🗨 Devtools Are Open`)],
22
- })
11
+ import { createContext } from "react"
23
12
 
24
13
  type DevtoolsView = `atoms` | `selectors` | `timelines` | `transactions`
25
14
 
26
- export const devtoolsViewSelectionState = atom<DevtoolsView>({
27
- key: `👁‍🗨 Devtools View Selection`,
28
- default: `atoms`,
29
- effects:
30
- typeof window === `undefined`
31
- ? []
32
- : [persistSync(window.localStorage, JSON, `👁‍🗨 Devtools View`)],
33
- })
34
-
35
- export const devtoolsViewOptionsState = atom<DevtoolsView[]>({
36
- key: `👁‍🗨 Devtools View Options`,
37
- default: [`atoms`, `selectors`, `transactions`, `timelines`],
38
- effects:
39
- typeof window === `undefined`
40
- ? []
41
- : [persistSync(window.localStorage, JSON, `👁‍🗨 Devtools View Options`)],
42
- })
43
-
44
- export const viewIsOpenAtoms = atomFamily<boolean, string>({
45
- key: `👁‍🗨 Devtools View Is Open`,
46
- default: false,
47
- effects: (key) =>
48
- typeof window === `undefined`
49
- ? []
50
- : [persistSync(window.localStorage, JSON, key + `:view-is-open`)],
51
- })
15
+ export type DevtoolsStates = {
16
+ devtoolsAreOpenState: RegularAtomToken<boolean>
17
+ devtoolsViewSelectionState: RegularAtomToken<DevtoolsView>
18
+ devtoolsViewOptionsState: RegularAtomToken<DevtoolsView[]>
19
+ viewIsOpenAtoms: RegularAtomFamilyToken<boolean, string>
20
+ }
21
+
22
+ export function attachDevtoolsStates(
23
+ store: Store,
24
+ ): DevtoolsStates & IntrospectionStates & { store: Store } {
25
+ const introspectionStates = attachIntrospectionStates(store)
26
+
27
+ const devtoolsAreOpenState = createStandaloneAtom<boolean>(store, {
28
+ key: `🔍 Devtools Are Open`,
29
+ default: true,
30
+ effects:
31
+ typeof window === `undefined`
32
+ ? []
33
+ : [persistSync(window.localStorage, JSON, `🔍 Devtools Are Open`)],
34
+ })
35
+
36
+ const devtoolsViewSelectionState = createStandaloneAtom<DevtoolsView>(store, {
37
+ key: `🔍 Devtools View Selection`,
38
+ default: `atoms`,
39
+ effects:
40
+ typeof window === `undefined`
41
+ ? []
42
+ : [persistSync(window.localStorage, JSON, `🔍 Devtools View`)],
43
+ })
44
+
45
+ const devtoolsViewOptionsState = createStandaloneAtom<DevtoolsView[]>(store, {
46
+ key: `🔍 Devtools View Options`,
47
+ default: [`atoms`, `selectors`, `transactions`, `timelines`],
48
+ effects:
49
+ typeof window === `undefined`
50
+ ? []
51
+ : [persistSync(window.localStorage, JSON, `🔍 Devtools View Options`)],
52
+ })
53
+
54
+ const viewIsOpenAtoms = createAtomFamily<boolean, string>(store, {
55
+ key: `🔍 Devtools View Is Open`,
56
+ default: false,
57
+ effects: (key) =>
58
+ typeof window === `undefined`
59
+ ? []
60
+ : [persistSync(window.localStorage, JSON, key + `:view-is-open`)],
61
+ })
62
+
63
+ return {
64
+ ...introspectionStates,
65
+ devtoolsAreOpenState,
66
+ devtoolsViewSelectionState,
67
+ devtoolsViewOptionsState,
68
+ viewIsOpenAtoms,
69
+ store,
70
+ }
71
+ }
72
+
73
+ export const DevtoolsContext = createContext<
74
+ DevtoolsStates & IntrospectionStates & { store: Store }
75
+ >(attachDevtoolsStates(IMPLICIT.STORE))