@tinacms/app 0.0.0-00f6525-20241015065741

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.
@@ -0,0 +1,51 @@
1
+ export type PostMessage =
2
+ | {
3
+ type: 'open' | 'close' | 'isEditMode'
4
+ id: string
5
+ data: object
6
+ }
7
+ | { type: 'field:selected'; fieldName: string }
8
+ | { type: 'quick-edit'; value: boolean }
9
+
10
+ export type Payload = {
11
+ id: string
12
+ variables: object
13
+ query: string
14
+ data: object
15
+ expandedQuery?: string
16
+ expandedData?: object
17
+ expandedQueryForResolver?: string
18
+ }
19
+
20
+ export type SystemInfo = {
21
+ breadcrumbs: string[]
22
+ basename: string
23
+ filename: string
24
+ path: string
25
+ extension: string
26
+ relativePath: string
27
+ title?: string | null | undefined
28
+ template: string
29
+ // __typename: string
30
+ collection: {
31
+ name: string
32
+ slug: string
33
+ label: string
34
+ path: string
35
+ format?: string | null | undefined
36
+ matches?: string | null | undefined
37
+ // templates?: object
38
+ // fields?: object
39
+ // __typename: string
40
+ }
41
+ }
42
+
43
+ export type Document = {
44
+ _values: Record<string, unknown>
45
+ _sys: SystemInfo
46
+ }
47
+
48
+ export type ResolvedDocument = {
49
+ _internalValues: Record<string, unknown>
50
+ _internalSys: SystemInfo
51
+ }
@@ -0,0 +1,134 @@
1
+ const charCodeOfDot = '.'.charCodeAt(0)
2
+ const reEscapeChar = /\\(\\)?/g
3
+ const rePropName = RegExp(
4
+ // Match anything that isn't a dot or bracket.
5
+ '[^.[\\]]+' +
6
+ '|' +
7
+ // Or match property names within brackets.
8
+ '\\[(?:' +
9
+ // Match a non-string expression.
10
+ '([^"\'][^[]*)' +
11
+ '|' +
12
+ // Or match strings (supports escaping characters).
13
+ '(["\'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2' +
14
+ ')\\]' +
15
+ '|' +
16
+ // Or match "" as the space between consecutive dots or empty brackets.
17
+ '(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))',
18
+ 'g'
19
+ )
20
+
21
+ /**
22
+ * Converts `string` to a property path array.
23
+ *
24
+ * @private
25
+ * @param {string} string The string to convert.
26
+ * @returns {Array} Returns the property path array.
27
+ */
28
+ const stringToPath = (string: string) => {
29
+ const result = []
30
+ if (string.charCodeAt(0) === charCodeOfDot) {
31
+ result.push('')
32
+ }
33
+ string.replace(rePropName, (match, expression, quote, subString) => {
34
+ let key = match
35
+ if (quote) {
36
+ key = subString.replace(reEscapeChar, '$1')
37
+ } else if (expression) {
38
+ key = expression.trim()
39
+ }
40
+ result.push(key)
41
+ })
42
+ return result
43
+ }
44
+
45
+ const keysCache: { [key: string]: string[] } = {}
46
+ const keysRegex = /[.[\]]+/
47
+
48
+ const toPath = (key: string): string[] => {
49
+ if (key === null || key === undefined || !key.length) {
50
+ return []
51
+ }
52
+ if (typeof key !== 'string') {
53
+ throw new Error('toPath() expects a string')
54
+ }
55
+ if (keysCache[key] == null) {
56
+ /**
57
+ * The following patch fixes issue 456, introduced since v4.20.3:
58
+ *
59
+ * Before v4.20.3, i.e. in v4.20.2, a `key` like 'choices[]' would map to ['choices']
60
+ * (e.g. an array of choices used where 'choices[]' is name attribute of an input of type checkbox).
61
+ *
62
+ * Since v4.20.3, a `key` like 'choices[]' would map to ['choices', ''] which is wrong and breaks
63
+ * this kind of inputs e.g. in React.
64
+ *
65
+ * v4.20.3 introduced an unwanted breaking change, this patch fixes it, see the issue at the link below.
66
+ *
67
+ * @see https://github.com/final-form/final-form/issues/456
68
+ */
69
+ if (key.endsWith('[]')) {
70
+ // v4.20.2 (a `key` like 'choices[]' should map to ['choices'], which is fine).
71
+ keysCache[key] = key.split(keysRegex).filter(Boolean)
72
+ } else {
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)
75
+ }
76
+ }
77
+ return keysCache[key]
78
+ }
79
+ export const getDeepestMetadata = (state: Object, complexKey: string): any => {
80
+ // Intentionally using iteration rather than recursion
81
+ const path = toPath(complexKey)
82
+ let current: any = state
83
+ let metadata: any
84
+ for (let i = 0; i < path.length; i++) {
85
+ const key = path[i]
86
+ if (
87
+ current === undefined ||
88
+ current === null ||
89
+ typeof current !== 'object' ||
90
+ (Array.isArray(current) && isNaN(Number(key)))
91
+ ) {
92
+ return undefined
93
+ }
94
+ const value = current[key]
95
+ if (value?._tina_metadata) {
96
+ // We're at a reference field, we don't want to select the
97
+ // reference form, just the reference select field
98
+ if (complexKey === value._tina_metadata?.prefix && metadata) {
99
+ } else {
100
+ metadata = value._tina_metadata
101
+ }
102
+ }
103
+ current = value
104
+ }
105
+ return metadata
106
+ }
107
+ export const getFormAndFieldNameFromMetadata = (
108
+ object: object,
109
+ eventFieldName: string
110
+ ) => {
111
+ let formId
112
+ let n
113
+ const value = getDeepestMetadata(object, eventFieldName)
114
+ if (value) {
115
+ if (value.prefix) {
116
+ const fieldName = eventFieldName.slice(value?.prefix?.length + 1)
117
+ const localFieldName = value.name
118
+ ? fieldName.slice(value?.name?.length + 1)
119
+ : fieldName
120
+ if (localFieldName) {
121
+ // If localFieldName is tags.2, just use `tags`
122
+ if (!isNaN(Number(localFieldName.split('.')[1]))) {
123
+ n = value.fields[localFieldName.split('.')[0]]
124
+ } else {
125
+ n = value.fields[localFieldName]
126
+ }
127
+ } else {
128
+ n = value.name
129
+ }
130
+ formId = value.id
131
+ }
132
+ }
133
+ return { formId, fieldName: n }
134
+ }
package/src/main.tsx ADDED
@@ -0,0 +1,12 @@
1
+ import React from 'react'
2
+ import { createRoot } from 'react-dom/client'
3
+ import App from './App'
4
+ import './index.css'
5
+
6
+ const container = document.getElementById('root')
7
+ const root = createRoot(container!)
8
+ root.render(
9
+ <React.StrictMode>
10
+ <App />
11
+ </React.StrictMode>
12
+ )
@@ -0,0 +1,233 @@
1
+ body {
2
+ line-height: 1.5;
3
+ -webkit-text-size-adjust: 100%;
4
+ -moz-tab-size: 4;
5
+ tab-size: 4;
6
+
7
+ *,
8
+ ::before,
9
+ ::after {
10
+ box-sizing: border-box;
11
+ border-width: 0;
12
+ border-style: solid;
13
+ border-color: transparent;
14
+ }
15
+
16
+ ::before,
17
+ ::after {
18
+ --tw-content: '';
19
+ }
20
+
21
+ hr {
22
+ height: 0; /* 1 */
23
+ color: inherit; /* 2 */
24
+ border-top-width: 1px; /* 3 */
25
+ }
26
+
27
+ abbr:where([title]) {
28
+ text-decoration: underline dotted;
29
+ }
30
+
31
+ h1,
32
+ h2,
33
+ h3,
34
+ h4,
35
+ h5,
36
+ h6 {
37
+ font-size: inherit;
38
+ font-weight: inherit;
39
+ }
40
+
41
+ a {
42
+ color: inherit;
43
+ text-decoration: inherit;
44
+ }
45
+
46
+ b,
47
+ strong {
48
+ font-weight: bolder;
49
+ }
50
+
51
+ code,
52
+ kbd,
53
+ samp,
54
+ pre {
55
+ font-family: theme(
56
+ 'fontFamily.mono',
57
+ ui-monospace,
58
+ SFMono-Regular,
59
+ Menlo,
60
+ Monaco,
61
+ Consolas,
62
+ 'Liberation Mono',
63
+ 'Courier New',
64
+ monospace
65
+ ); /* 1 */
66
+ font-size: 1em; /* 2 */
67
+ }
68
+
69
+ small {
70
+ font-size: 80%;
71
+ }
72
+
73
+ sub,
74
+ sup {
75
+ font-size: 75%;
76
+ line-height: 0;
77
+ position: relative;
78
+ vertical-align: baseline;
79
+ }
80
+
81
+ sub {
82
+ bottom: -0.25em;
83
+ }
84
+
85
+ sup {
86
+ top: -0.5em;
87
+ }
88
+
89
+ table {
90
+ text-indent: 0; /* 1 */
91
+ border-color: inherit; /* 2 */
92
+ border-collapse: collapse; /* 3 */
93
+ }
94
+
95
+ button,
96
+ input,
97
+ optgroup,
98
+ select,
99
+ textarea {
100
+ font-family: inherit; /* 1 */
101
+ font-size: 100%; /* 1 */
102
+ line-height: inherit; /* 1 */
103
+ color: inherit; /* 1 */
104
+ margin: 0; /* 2 */
105
+ padding: 0; /* 3 */
106
+ }
107
+
108
+ button,
109
+ select {
110
+ text-transform: none;
111
+ }
112
+
113
+ button,
114
+ [type='button'],
115
+ [type='reset'],
116
+ [type='submit'] {
117
+ -webkit-appearance: button; /* 1 */
118
+ background-image: none; /* 2 */
119
+ }
120
+
121
+ :-moz-focusring {
122
+ outline: auto;
123
+ }
124
+
125
+ :-moz-ui-invalid {
126
+ box-shadow: none;
127
+ }
128
+
129
+ progress {
130
+ vertical-align: baseline;
131
+ }
132
+
133
+ ::-webkit-inner-spin-button,
134
+ ::-webkit-outer-spin-button {
135
+ height: auto;
136
+ }
137
+
138
+ [type='search'] {
139
+ -webkit-appearance: textfield; /* 1 */
140
+ outline-offset: -2px; /* 2 */
141
+ }
142
+
143
+ ::-webkit-search-decoration {
144
+ -webkit-appearance: none;
145
+ }
146
+
147
+ ::-webkit-file-upload-button {
148
+ -webkit-appearance: button; /* 1 */
149
+ font: inherit; /* 2 */
150
+ }
151
+
152
+ summary {
153
+ display: list-item;
154
+ }
155
+
156
+ blockquote,
157
+ dl,
158
+ dd,
159
+ h1,
160
+ h2,
161
+ h3,
162
+ h4,
163
+ h5,
164
+ h6,
165
+ hr,
166
+ figure,
167
+ p,
168
+ pre {
169
+ margin: 0;
170
+ }
171
+
172
+ fieldset {
173
+ margin: 0;
174
+ padding: 0;
175
+ }
176
+
177
+ legend {
178
+ padding: 0;
179
+ }
180
+
181
+ ol,
182
+ ul,
183
+ menu {
184
+ list-style: none;
185
+ margin: 0;
186
+ padding: 0;
187
+ }
188
+
189
+ li:before {
190
+ display: none;
191
+ }
192
+
193
+ textarea {
194
+ resize: vertical;
195
+ }
196
+
197
+ input::placeholder,
198
+ textarea::placeholder {
199
+ opacity: 1; /* 1 */
200
+ color: theme('colors.gray.400', #9ca3af); /* 2 */
201
+ }
202
+
203
+ button,
204
+ [role='button'] {
205
+ cursor: pointer;
206
+ }
207
+
208
+ :disabled {
209
+ cursor: default;
210
+ }
211
+
212
+ img,
213
+ svg,
214
+ video,
215
+ canvas,
216
+ audio,
217
+ iframe,
218
+ embed,
219
+ object {
220
+ display: block; /* 1 */
221
+ vertical-align: middle; /* 2 */
222
+ }
223
+
224
+ img,
225
+ video {
226
+ max-width: 100%;
227
+ height: auto;
228
+ }
229
+
230
+ [hidden] {
231
+ display: none;
232
+ }
233
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+
3
+ */
4
+ import React from 'react'
5
+ import { defineConfig } from 'tinacms'
6
+ import { useGraphQLReducer } from './lib/graphql-reducer'
7
+
8
+ type Config = Parameters<typeof defineConfig>[0]
9
+
10
+ export const Preview = (
11
+ props: Config & {
12
+ url: string
13
+ iframeRef: React.MutableRefObject<HTMLIFrameElement>
14
+ }
15
+ ) => {
16
+ useGraphQLReducer(props.iframeRef, props.url)
17
+
18
+ return (
19
+ <iframe
20
+ data-test="tina-iframe"
21
+ id="tina-iframe"
22
+ ref={props.iframeRef}
23
+ className="h-screen w-full bg-white"
24
+ src={props.url}
25
+ />
26
+ )
27
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+
3
+ */
4
+
5
+ /// <reference types="vite/client" />
6
+ declare const __API_URL__: string
7
+ declare const __BASE_PATH__: string
8
+ declare const __TINA_GRAPHQL_VERSION__: string
package/tsconfig.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "useDefineForClassFields": true,
5
+ "lib": [
6
+ "DOM",
7
+ "DOM.Iterable",
8
+ "ESNext"
9
+ ],
10
+ "allowJs": false,
11
+ "skipLibCheck": true,
12
+ "esModuleInterop": false,
13
+ "allowSyntheticDefaultImports": true,
14
+ "strict": true,
15
+ "forceConsistentCasingInFileNames": true,
16
+ "module": "ESNext",
17
+ "moduleResolution": "Node",
18
+ "resolveJsonModule": true,
19
+ "isolatedModules": true,
20
+ "noEmit": true,
21
+ "jsx": "react-jsx"
22
+ },
23
+ "exclude": [
24
+ "node_modules",
25
+ "**/node_modules/*"
26
+ ],
27
+ "references": [
28
+ {
29
+ "path": "./tsconfig.node.json"
30
+ }
31
+ ]
32
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "compilerOptions": {
3
+ "composite": true,
4
+ "module": "ESNext",
5
+ "moduleResolution": "Node",
6
+ "allowSyntheticDefaultImports": true
7
+ },
8
+ "include": ["vite.config.ts"],
9
+ "exclude": ["node_modules", "**/node_modules/*"]
10
+ }