@tinacms/app 2.2.2 → 2.2.3
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/CHANGELOG.md +13 -6
- package/package.json +2 -2
- package/src/App.tsx +24 -24
- package/src/Playground.tsx +54 -54
- package/src/dummy-client.ts +1 -1
- package/src/fields/rich-text/index.tsx +2 -2
- package/src/fields/rich-text/monaco/error-message.tsx +54 -54
- package/src/fields/rich-text/monaco/index.tsx +56 -56
- package/src/fields/rich-text/monaco/use-debounce.ts +8 -8
- package/src/global.css +3 -3
- package/src/index.css +15 -15
- package/src/lib/build-form.ts +24 -24
- package/src/lib/errors.tsx +7 -7
- package/src/lib/expand-query.ts +66 -61
- package/src/lib/graphql-reducer.ts +272 -265
- package/src/lib/types.ts +34 -34
- package/src/lib/util.ts +41 -41
- package/src/main.tsx +7 -7
- package/src/preflight.css +10 -10
- package/src/preview.tsx +12 -12
- package/src/vite-env.d.ts +3 -3
package/src/lib/types.ts
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
1
|
export type PostMessage =
|
|
2
2
|
| {
|
|
3
|
-
type: 'open' | 'close' | 'isEditMode'
|
|
4
|
-
id: string
|
|
5
|
-
data: object
|
|
3
|
+
type: 'open' | 'close' | 'isEditMode';
|
|
4
|
+
id: string;
|
|
5
|
+
data: object;
|
|
6
6
|
}
|
|
7
7
|
| { type: 'field:selected'; fieldName: string }
|
|
8
8
|
| { type: 'quick-edit'; value: boolean }
|
|
9
|
-
| { type: 'user-select-form'; formId: string }
|
|
9
|
+
| { type: 'user-select-form'; formId: string };
|
|
10
10
|
|
|
11
11
|
export type Payload = {
|
|
12
|
-
id: string
|
|
13
|
-
variables: object
|
|
14
|
-
query: string
|
|
15
|
-
data: object
|
|
16
|
-
expandedQuery?: string
|
|
17
|
-
expandedData?: object
|
|
18
|
-
expandedQueryForResolver?: string
|
|
19
|
-
}
|
|
12
|
+
id: string;
|
|
13
|
+
variables: object;
|
|
14
|
+
query: string;
|
|
15
|
+
data: object;
|
|
16
|
+
expandedQuery?: string;
|
|
17
|
+
expandedData?: object;
|
|
18
|
+
expandedQueryForResolver?: string;
|
|
19
|
+
};
|
|
20
20
|
|
|
21
21
|
export type SystemInfo = {
|
|
22
|
-
breadcrumbs: string[]
|
|
23
|
-
basename: string
|
|
24
|
-
filename: string
|
|
25
|
-
path: string
|
|
26
|
-
extension: string
|
|
27
|
-
relativePath: string
|
|
28
|
-
title?: string | null | undefined
|
|
29
|
-
template: string
|
|
22
|
+
breadcrumbs: string[];
|
|
23
|
+
basename: string;
|
|
24
|
+
filename: string;
|
|
25
|
+
path: string;
|
|
26
|
+
extension: string;
|
|
27
|
+
relativePath: string;
|
|
28
|
+
title?: string | null | undefined;
|
|
29
|
+
template: string;
|
|
30
30
|
// __typename: string
|
|
31
31
|
collection: {
|
|
32
|
-
name: string
|
|
33
|
-
slug: string
|
|
34
|
-
label: string
|
|
35
|
-
path: string
|
|
36
|
-
format?: string | null | undefined
|
|
37
|
-
matches?: string | null | undefined
|
|
32
|
+
name: string;
|
|
33
|
+
slug: string;
|
|
34
|
+
label: string;
|
|
35
|
+
path: string;
|
|
36
|
+
format?: string | null | undefined;
|
|
37
|
+
matches?: string | null | undefined;
|
|
38
38
|
// templates?: object
|
|
39
39
|
// fields?: object
|
|
40
40
|
// __typename: string
|
|
41
|
-
}
|
|
42
|
-
}
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
43
|
|
|
44
44
|
export type Document = {
|
|
45
|
-
_values: Record<string, unknown
|
|
46
|
-
_sys: SystemInfo
|
|
47
|
-
}
|
|
45
|
+
_values: Record<string, unknown>;
|
|
46
|
+
_sys: SystemInfo;
|
|
47
|
+
};
|
|
48
48
|
|
|
49
49
|
export type ResolvedDocument = {
|
|
50
|
-
_internalValues: Record<string, unknown
|
|
51
|
-
_internalSys: SystemInfo
|
|
52
|
-
}
|
|
50
|
+
_internalValues: Record<string, unknown>;
|
|
51
|
+
_internalSys: SystemInfo;
|
|
52
|
+
};
|
package/src/lib/util.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const charCodeOfDot = '.'.charCodeAt(0)
|
|
2
|
-
const reEscapeChar = /\\(\\)?/g
|
|
1
|
+
const charCodeOfDot = '.'.charCodeAt(0);
|
|
2
|
+
const reEscapeChar = /\\(\\)?/g;
|
|
3
3
|
const rePropName = RegExp(
|
|
4
4
|
// Match anything that isn't a dot or bracket.
|
|
5
5
|
'[^.[\\]]+' +
|
|
@@ -16,7 +16,7 @@ const rePropName = RegExp(
|
|
|
16
16
|
// Or match "" as the space between consecutive dots or empty brackets.
|
|
17
17
|
'(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))',
|
|
18
18
|
'g'
|
|
19
|
-
)
|
|
19
|
+
);
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Converts `string` to a property path array.
|
|
@@ -26,31 +26,31 @@ const rePropName = RegExp(
|
|
|
26
26
|
* @returns {Array} Returns the property path array.
|
|
27
27
|
*/
|
|
28
28
|
const stringToPath = (string: string) => {
|
|
29
|
-
const result = []
|
|
29
|
+
const result = [];
|
|
30
30
|
if (string.charCodeAt(0) === charCodeOfDot) {
|
|
31
|
-
result.push('')
|
|
31
|
+
result.push('');
|
|
32
32
|
}
|
|
33
33
|
string.replace(rePropName, (match, expression, quote, subString) => {
|
|
34
|
-
let key = match
|
|
34
|
+
let key = match;
|
|
35
35
|
if (quote) {
|
|
36
|
-
key = subString.replace(reEscapeChar, '$1')
|
|
36
|
+
key = subString.replace(reEscapeChar, '$1');
|
|
37
37
|
} else if (expression) {
|
|
38
|
-
key = expression.trim()
|
|
38
|
+
key = expression.trim();
|
|
39
39
|
}
|
|
40
|
-
result.push(key)
|
|
41
|
-
})
|
|
42
|
-
return result
|
|
43
|
-
}
|
|
40
|
+
result.push(key);
|
|
41
|
+
});
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
44
|
|
|
45
|
-
const keysCache: { [key: string]: string[] } = {}
|
|
46
|
-
const keysRegex = /[.[\]]
|
|
45
|
+
const keysCache: { [key: string]: string[] } = {};
|
|
46
|
+
const keysRegex = /[.[\]]+/;
|
|
47
47
|
|
|
48
48
|
const toPath = (key: string): string[] => {
|
|
49
49
|
if (key === null || key === undefined || !key.length) {
|
|
50
|
-
return []
|
|
50
|
+
return [];
|
|
51
51
|
}
|
|
52
52
|
if (typeof key !== 'string') {
|
|
53
|
-
throw new Error('toPath() expects a string')
|
|
53
|
+
throw new Error('toPath() expects a string');
|
|
54
54
|
}
|
|
55
55
|
if (keysCache[key] == null) {
|
|
56
56
|
/**
|
|
@@ -68,67 +68,67 @@ const toPath = (key: string): string[] => {
|
|
|
68
68
|
*/
|
|
69
69
|
if (key.endsWith('[]')) {
|
|
70
70
|
// v4.20.2 (a `key` like 'choices[]' should map to ['choices'], which is fine).
|
|
71
|
-
keysCache[key] = key.split(keysRegex).filter(Boolean)
|
|
71
|
+
keysCache[key] = key.split(keysRegex).filter(Boolean);
|
|
72
72
|
} else {
|
|
73
73
|
// v4.20.3 (a `key` like 'choices[]' maps to ['choices', ''], which breaks applications relying on inputs like `<input type="checkbox" name="choices[]" />`).
|
|
74
|
-
keysCache[key] = stringToPath(key)
|
|
74
|
+
keysCache[key] = stringToPath(key);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
-
return keysCache[key]
|
|
78
|
-
}
|
|
77
|
+
return keysCache[key];
|
|
78
|
+
};
|
|
79
79
|
export const getDeepestMetadata = (state: Object, complexKey: string): any => {
|
|
80
80
|
// Intentionally using iteration rather than recursion
|
|
81
|
-
const path = toPath(complexKey)
|
|
82
|
-
let current: any = state
|
|
83
|
-
let metadata: any
|
|
81
|
+
const path = toPath(complexKey);
|
|
82
|
+
let current: any = state;
|
|
83
|
+
let metadata: any;
|
|
84
84
|
for (let i = 0; i < path.length; i++) {
|
|
85
|
-
const key = path[i]
|
|
85
|
+
const key = path[i];
|
|
86
86
|
if (
|
|
87
87
|
current === undefined ||
|
|
88
88
|
current === null ||
|
|
89
89
|
typeof current !== 'object' ||
|
|
90
90
|
(Array.isArray(current) && isNaN(Number(key)))
|
|
91
91
|
) {
|
|
92
|
-
return undefined
|
|
92
|
+
return undefined;
|
|
93
93
|
}
|
|
94
|
-
const value = current[key]
|
|
94
|
+
const value = current[key];
|
|
95
95
|
if (value?._tina_metadata) {
|
|
96
96
|
// We're at a reference field, we don't want to select the
|
|
97
97
|
// reference form, just the reference select field
|
|
98
98
|
if (complexKey === value._tina_metadata?.prefix && metadata) {
|
|
99
99
|
} else {
|
|
100
|
-
metadata = value._tina_metadata
|
|
100
|
+
metadata = value._tina_metadata;
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
|
-
current = value
|
|
103
|
+
current = value;
|
|
104
104
|
}
|
|
105
|
-
return metadata
|
|
106
|
-
}
|
|
105
|
+
return metadata;
|
|
106
|
+
};
|
|
107
107
|
export const getFormAndFieldNameFromMetadata = (
|
|
108
108
|
object: object,
|
|
109
109
|
eventFieldName: string
|
|
110
110
|
) => {
|
|
111
|
-
let formId
|
|
112
|
-
let n
|
|
113
|
-
const value = getDeepestMetadata(object, eventFieldName)
|
|
111
|
+
let formId;
|
|
112
|
+
let n;
|
|
113
|
+
const value = getDeepestMetadata(object, eventFieldName);
|
|
114
114
|
if (value) {
|
|
115
115
|
if (value.prefix) {
|
|
116
|
-
const fieldName = eventFieldName.slice(value?.prefix?.length + 1)
|
|
116
|
+
const fieldName = eventFieldName.slice(value?.prefix?.length + 1);
|
|
117
117
|
const localFieldName = value.name
|
|
118
118
|
? fieldName.slice(value?.name?.length + 1)
|
|
119
|
-
: fieldName
|
|
119
|
+
: fieldName;
|
|
120
120
|
if (localFieldName) {
|
|
121
121
|
// If localFieldName is tags.2, just use `tags`
|
|
122
122
|
if (!isNaN(Number(localFieldName.split('.')[1]))) {
|
|
123
|
-
n = value.fields[localFieldName.split('.')[0]]
|
|
123
|
+
n = value.fields[localFieldName.split('.')[0]];
|
|
124
124
|
} else {
|
|
125
|
-
n = value.fields[localFieldName]
|
|
125
|
+
n = value.fields[localFieldName];
|
|
126
126
|
}
|
|
127
127
|
} else {
|
|
128
|
-
n = value.name
|
|
128
|
+
n = value.name;
|
|
129
129
|
}
|
|
130
|
-
formId = value.id
|
|
130
|
+
formId = value.id;
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
|
-
return { formId, fieldName: n }
|
|
134
|
-
}
|
|
133
|
+
return { formId, fieldName: n };
|
|
134
|
+
};
|
package/src/main.tsx
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { createRoot } from 'react-dom/client'
|
|
3
|
-
import App from './App'
|
|
4
|
-
import './index.css'
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { createRoot } from 'react-dom/client';
|
|
3
|
+
import App from './App';
|
|
4
|
+
import './index.css';
|
|
5
5
|
|
|
6
|
-
const container = document.getElementById('root')
|
|
7
|
-
const root = createRoot(container!)
|
|
6
|
+
const container = document.getElementById('root');
|
|
7
|
+
const root = createRoot(container!);
|
|
8
8
|
root.render(
|
|
9
9
|
<React.StrictMode>
|
|
10
10
|
<App />
|
|
11
11
|
</React.StrictMode>
|
|
12
|
-
)
|
|
12
|
+
);
|
package/src/preflight.css
CHANGED
|
@@ -15,7 +15,7 @@ body {
|
|
|
15
15
|
|
|
16
16
|
::before,
|
|
17
17
|
::after {
|
|
18
|
-
--tw-content:
|
|
18
|
+
--tw-content: "";
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
hr {
|
|
@@ -53,14 +53,14 @@ body {
|
|
|
53
53
|
samp,
|
|
54
54
|
pre {
|
|
55
55
|
font-family: theme(
|
|
56
|
-
|
|
56
|
+
"fontFamily.mono",
|
|
57
57
|
ui-monospace,
|
|
58
58
|
SFMono-Regular,
|
|
59
59
|
Menlo,
|
|
60
60
|
Monaco,
|
|
61
61
|
Consolas,
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
"Liberation Mono",
|
|
63
|
+
"Courier New",
|
|
64
64
|
monospace
|
|
65
65
|
); /* 1 */
|
|
66
66
|
font-size: 1em; /* 2 */
|
|
@@ -111,9 +111,9 @@ body {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
button,
|
|
114
|
-
[type=
|
|
115
|
-
[type=
|
|
116
|
-
[type=
|
|
114
|
+
[type="button"],
|
|
115
|
+
[type="reset"],
|
|
116
|
+
[type="submit"] {
|
|
117
117
|
-webkit-appearance: button; /* 1 */
|
|
118
118
|
background-image: none; /* 2 */
|
|
119
119
|
}
|
|
@@ -135,7 +135,7 @@ body {
|
|
|
135
135
|
height: auto;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
[type=
|
|
138
|
+
[type="search"] {
|
|
139
139
|
-webkit-appearance: textfield; /* 1 */
|
|
140
140
|
outline-offset: -2px; /* 2 */
|
|
141
141
|
}
|
|
@@ -197,11 +197,11 @@ body {
|
|
|
197
197
|
input::placeholder,
|
|
198
198
|
textarea::placeholder {
|
|
199
199
|
opacity: 1; /* 1 */
|
|
200
|
-
color: theme(
|
|
200
|
+
color: theme("colors.gray.400", #9ca3af); /* 2 */
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
button,
|
|
204
|
-
[role=
|
|
204
|
+
[role="button"] {
|
|
205
205
|
cursor: pointer;
|
|
206
206
|
}
|
|
207
207
|
|
package/src/preview.tsx
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
|
|
3
3
|
*/
|
|
4
|
-
import React from 'react'
|
|
5
|
-
import { defineConfig } from 'tinacms'
|
|
6
|
-
import { useGraphQLReducer } from './lib/graphql-reducer'
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { defineConfig } from 'tinacms';
|
|
6
|
+
import { useGraphQLReducer } from './lib/graphql-reducer';
|
|
7
7
|
|
|
8
|
-
type Config = Parameters<typeof defineConfig>[0]
|
|
8
|
+
type Config = Parameters<typeof defineConfig>[0];
|
|
9
9
|
|
|
10
10
|
export const Preview = (
|
|
11
11
|
props: Config & {
|
|
12
|
-
url: string
|
|
13
|
-
iframeRef: React.MutableRefObject<HTMLIFrameElement
|
|
12
|
+
url: string;
|
|
13
|
+
iframeRef: React.MutableRefObject<HTMLIFrameElement>;
|
|
14
14
|
}
|
|
15
15
|
) => {
|
|
16
|
-
useGraphQLReducer(props.iframeRef, props.url)
|
|
16
|
+
useGraphQLReducer(props.iframeRef, props.url);
|
|
17
17
|
|
|
18
18
|
return (
|
|
19
19
|
<iframe
|
|
20
|
-
data-test=
|
|
21
|
-
id=
|
|
20
|
+
data-test='tina-iframe'
|
|
21
|
+
id='tina-iframe'
|
|
22
22
|
ref={props.iframeRef}
|
|
23
|
-
className=
|
|
23
|
+
className='h-screen w-full bg-white'
|
|
24
24
|
src={props.url}
|
|
25
25
|
/>
|
|
26
|
-
)
|
|
27
|
-
}
|
|
26
|
+
);
|
|
27
|
+
};
|
package/src/vite-env.d.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
/// <reference types="vite/client" />
|
|
6
|
-
declare const __API_URL__: string
|
|
7
|
-
declare const __BASE_PATH__: string
|
|
8
|
-
declare const __TINA_GRAPHQL_VERSION__: string
|
|
6
|
+
declare const __API_URL__: string;
|
|
7
|
+
declare const __BASE_PATH__: string;
|
|
8
|
+
declare const __TINA_GRAPHQL_VERSION__: string;
|