tinacms 1.5.5 → 1.5.6
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/dist/admin/pages/CollectionCreatePage.d.ts +9 -1
- package/dist/index.es.js +31 -4
- package/dist/index.js +31 -4
- package/dist/react.d.ts +15 -9
- package/dist/react.es.js +167 -10
- package/dist/react.js +168 -9
- package/dist/style.css +3 -0
- package/package.json +3 -3
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
+
import type { TinaCMS } from '@tinacms/toolkit';
|
|
2
3
|
declare const CollectionCreatePage: () => JSX.Element;
|
|
3
|
-
export declare const RenderForm: ({ cms, collection, folder, templateName, mutationInfo, customDefaults, }:
|
|
4
|
+
export declare const RenderForm: ({ cms, collection, folder, templateName, mutationInfo, customDefaults, }: {
|
|
5
|
+
cms: TinaCMS;
|
|
6
|
+
collection: any;
|
|
7
|
+
folder: any;
|
|
8
|
+
templateName: any;
|
|
9
|
+
mutationInfo: any;
|
|
10
|
+
customDefaults?: any;
|
|
11
|
+
}) => JSX.Element;
|
|
4
12
|
export default CollectionCreatePage;
|
package/dist/index.es.js
CHANGED
|
@@ -1962,6 +1962,9 @@ var styles = `.tina-tailwind {
|
|
|
1962
1962
|
--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
|
|
1963
1963
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
|
1964
1964
|
}
|
|
1965
|
+
.tina-tailwind .outline {
|
|
1966
|
+
outline-style: solid;
|
|
1967
|
+
}
|
|
1965
1968
|
.tina-tailwind .ring-1 {
|
|
1966
1969
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
|
1967
1970
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
|
@@ -4104,6 +4107,18 @@ const RenderForm$1 = ({
|
|
|
4104
4107
|
const windowWidth = useWindowWidth();
|
|
4105
4108
|
const renderNavToggle = windowWidth < navBreakpoint + 1;
|
|
4106
4109
|
const headerPadding = renderNavToggle ? "px-20" : "px-6";
|
|
4110
|
+
React.useEffect(() => {
|
|
4111
|
+
cms.dispatch({ type: "forms:add", value: form });
|
|
4112
|
+
cms.dispatch({ type: "forms:set-active-form-id", value: form.id });
|
|
4113
|
+
return () => {
|
|
4114
|
+
cms.dispatch({ type: "forms:remove", value: form.id });
|
|
4115
|
+
cms.dispatch({ type: "forms:set-active-form-id", value: null });
|
|
4116
|
+
};
|
|
4117
|
+
}, [JSON.stringify(formInfo.fields)]);
|
|
4118
|
+
if (!cms.state.activeFormId) {
|
|
4119
|
+
return null;
|
|
4120
|
+
}
|
|
4121
|
+
const activeForm = cms.state.forms.find(({ tinaForm }) => tinaForm.id === form.id);
|
|
4107
4122
|
return /* @__PURE__ */ React.createElement(PageWrapper, null, /* @__PURE__ */ React.createElement(React.Fragment, null, ((_f = (_e = cms == null ? void 0 : cms.api) == null ? void 0 : _e.tina) == null ? void 0 : _f.isLocalMode) ? /* @__PURE__ */ React.createElement(LocalWarning, null) : /* @__PURE__ */ React.createElement(BillingWarning, null), /* @__PURE__ */ React.createElement("div", {
|
|
4108
4123
|
className: `py-4 border-b border-gray-200 bg-white ${headerPadding}`
|
|
4109
4124
|
}, /* @__PURE__ */ React.createElement("div", {
|
|
@@ -4121,8 +4136,8 @@ const RenderForm$1 = ({
|
|
|
4121
4136
|
className: "text-xl text-gray-700 font-medium leading-tight"
|
|
4122
4137
|
}, "Create New")), /* @__PURE__ */ React.createElement(FormStatus, {
|
|
4123
4138
|
pristine: formIsPristine
|
|
4124
|
-
}))), /* @__PURE__ */ React.createElement(FormBuilder, {
|
|
4125
|
-
form,
|
|
4139
|
+
}))), activeForm && /* @__PURE__ */ React.createElement(FormBuilder, {
|
|
4140
|
+
form: activeForm,
|
|
4126
4141
|
onPristineChange: setFormIsPristine
|
|
4127
4142
|
})));
|
|
4128
4143
|
};
|
|
@@ -4284,6 +4299,18 @@ const RenderForm = ({
|
|
|
4284
4299
|
const windowWidth = useWindowWidth();
|
|
4285
4300
|
const renderNavToggle = windowWidth < navBreakpoint + 1;
|
|
4286
4301
|
const headerPadding = renderNavToggle ? "px-20" : "px-6";
|
|
4302
|
+
React.useEffect(() => {
|
|
4303
|
+
cms.dispatch({ type: "forms:add", value: form });
|
|
4304
|
+
cms.dispatch({ type: "forms:set-active-form-id", value: form.id });
|
|
4305
|
+
return () => {
|
|
4306
|
+
cms.dispatch({ type: "forms:remove", value: form.id });
|
|
4307
|
+
cms.dispatch({ type: "forms:set-active-form-id", value: null });
|
|
4308
|
+
};
|
|
4309
|
+
}, [JSON.stringify(document._values)]);
|
|
4310
|
+
if (!cms.state.activeFormId) {
|
|
4311
|
+
return null;
|
|
4312
|
+
}
|
|
4313
|
+
const activeForm = cms.state.forms.find(({ tinaForm }) => tinaForm.id === form.id);
|
|
4287
4314
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, ((_b = (_a = cms == null ? void 0 : cms.api) == null ? void 0 : _a.tina) == null ? void 0 : _b.isLocalMode) ? /* @__PURE__ */ React.createElement(LocalWarning, null) : /* @__PURE__ */ React.createElement(BillingWarning, null), /* @__PURE__ */ React.createElement("div", {
|
|
4288
4315
|
className: `py-4 border-b border-gray-200 bg-white ${headerPadding}`
|
|
4289
4316
|
}, /* @__PURE__ */ React.createElement("div", {
|
|
@@ -4301,8 +4328,8 @@ const RenderForm = ({
|
|
|
4301
4328
|
className: "text-xl text-gray-700 font-medium leading-tight"
|
|
4302
4329
|
}, "Edit ", `${filename}.${collection.format}`)), /* @__PURE__ */ React.createElement(FormStatus, {
|
|
4303
4330
|
pristine: formIsPristine
|
|
4304
|
-
}))), /* @__PURE__ */ React.createElement(FormBuilder, {
|
|
4305
|
-
form,
|
|
4331
|
+
}))), activeForm && /* @__PURE__ */ React.createElement(FormBuilder, {
|
|
4332
|
+
form: activeForm,
|
|
4306
4333
|
onPristineChange: setFormIsPristine
|
|
4307
4334
|
}));
|
|
4308
4335
|
};
|
package/dist/index.js
CHANGED
|
@@ -1977,6 +1977,9 @@ mutation addPendingDocumentMutation(
|
|
|
1977
1977
|
--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
|
|
1978
1978
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
|
1979
1979
|
}
|
|
1980
|
+
.tina-tailwind .outline {
|
|
1981
|
+
outline-style: solid;
|
|
1982
|
+
}
|
|
1980
1983
|
.tina-tailwind .ring-1 {
|
|
1981
1984
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
|
1982
1985
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
|
@@ -4119,6 +4122,18 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
4119
4122
|
const windowWidth = windowSize.useWindowWidth();
|
|
4120
4123
|
const renderNavToggle = windowWidth < navBreakpoint + 1;
|
|
4121
4124
|
const headerPadding = renderNavToggle ? "px-20" : "px-6";
|
|
4125
|
+
React__default["default"].useEffect(() => {
|
|
4126
|
+
cms.dispatch({ type: "forms:add", value: form });
|
|
4127
|
+
cms.dispatch({ type: "forms:set-active-form-id", value: form.id });
|
|
4128
|
+
return () => {
|
|
4129
|
+
cms.dispatch({ type: "forms:remove", value: form.id });
|
|
4130
|
+
cms.dispatch({ type: "forms:set-active-form-id", value: null });
|
|
4131
|
+
};
|
|
4132
|
+
}, [JSON.stringify(formInfo.fields)]);
|
|
4133
|
+
if (!cms.state.activeFormId) {
|
|
4134
|
+
return null;
|
|
4135
|
+
}
|
|
4136
|
+
const activeForm = cms.state.forms.find(({ tinaForm }) => tinaForm.id === form.id);
|
|
4122
4137
|
return /* @__PURE__ */ React__default["default"].createElement(PageWrapper, null, /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, ((_f = (_e = cms == null ? void 0 : cms.api) == null ? void 0 : _e.tina) == null ? void 0 : _f.isLocalMode) ? /* @__PURE__ */ React__default["default"].createElement(toolkit.LocalWarning, null) : /* @__PURE__ */ React__default["default"].createElement(toolkit.BillingWarning, null), /* @__PURE__ */ React__default["default"].createElement("div", {
|
|
4123
4138
|
className: `py-4 border-b border-gray-200 bg-white ${headerPadding}`
|
|
4124
4139
|
}, /* @__PURE__ */ React__default["default"].createElement("div", {
|
|
@@ -4136,8 +4151,8 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
4136
4151
|
className: "text-xl text-gray-700 font-medium leading-tight"
|
|
4137
4152
|
}, "Create New")), /* @__PURE__ */ React__default["default"].createElement(toolkit.FormStatus, {
|
|
4138
4153
|
pristine: formIsPristine
|
|
4139
|
-
}))), /* @__PURE__ */ React__default["default"].createElement(toolkit.FormBuilder, {
|
|
4140
|
-
form,
|
|
4154
|
+
}))), activeForm && /* @__PURE__ */ React__default["default"].createElement(toolkit.FormBuilder, {
|
|
4155
|
+
form: activeForm,
|
|
4141
4156
|
onPristineChange: setFormIsPristine
|
|
4142
4157
|
})));
|
|
4143
4158
|
};
|
|
@@ -4299,6 +4314,18 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
4299
4314
|
const windowWidth = windowSize.useWindowWidth();
|
|
4300
4315
|
const renderNavToggle = windowWidth < navBreakpoint + 1;
|
|
4301
4316
|
const headerPadding = renderNavToggle ? "px-20" : "px-6";
|
|
4317
|
+
React__default["default"].useEffect(() => {
|
|
4318
|
+
cms.dispatch({ type: "forms:add", value: form });
|
|
4319
|
+
cms.dispatch({ type: "forms:set-active-form-id", value: form.id });
|
|
4320
|
+
return () => {
|
|
4321
|
+
cms.dispatch({ type: "forms:remove", value: form.id });
|
|
4322
|
+
cms.dispatch({ type: "forms:set-active-form-id", value: null });
|
|
4323
|
+
};
|
|
4324
|
+
}, [JSON.stringify(document._values)]);
|
|
4325
|
+
if (!cms.state.activeFormId) {
|
|
4326
|
+
return null;
|
|
4327
|
+
}
|
|
4328
|
+
const activeForm = cms.state.forms.find(({ tinaForm }) => tinaForm.id === form.id);
|
|
4302
4329
|
return /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, ((_b = (_a = cms == null ? void 0 : cms.api) == null ? void 0 : _a.tina) == null ? void 0 : _b.isLocalMode) ? /* @__PURE__ */ React__default["default"].createElement(toolkit.LocalWarning, null) : /* @__PURE__ */ React__default["default"].createElement(toolkit.BillingWarning, null), /* @__PURE__ */ React__default["default"].createElement("div", {
|
|
4303
4330
|
className: `py-4 border-b border-gray-200 bg-white ${headerPadding}`
|
|
4304
4331
|
}, /* @__PURE__ */ React__default["default"].createElement("div", {
|
|
@@ -4316,8 +4343,8 @@ This will work when developing locally but NOT when deployed to production.
|
|
|
4316
4343
|
className: "text-xl text-gray-700 font-medium leading-tight"
|
|
4317
4344
|
}, "Edit ", `${filename}.${collection.format}`)), /* @__PURE__ */ React__default["default"].createElement(toolkit.FormStatus, {
|
|
4318
4345
|
pristine: formIsPristine
|
|
4319
|
-
}))), /* @__PURE__ */ React__default["default"].createElement(toolkit.FormBuilder, {
|
|
4320
|
-
form,
|
|
4346
|
+
}))), activeForm && /* @__PURE__ */ React__default["default"].createElement(toolkit.FormBuilder, {
|
|
4347
|
+
form: activeForm,
|
|
4321
4348
|
onPristineChange: setFormIsPristine
|
|
4322
4349
|
}));
|
|
4323
4350
|
};
|
package/dist/react.d.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This is an experimental version of the useTina hook,
|
|
3
|
-
* it is only meant to be used with Tina in "iframe mode".
|
|
4
|
-
*/
|
|
5
1
|
export declare function useTina<T extends object>(props: {
|
|
6
2
|
query: string;
|
|
7
3
|
variables: object;
|
|
@@ -19,9 +15,19 @@ export declare function useEditState(): {
|
|
|
19
15
|
* is working with.
|
|
20
16
|
*/
|
|
21
17
|
export declare const tinaField: <T extends object & {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
fields: Record<string, string>;
|
|
18
|
+
_content_source?: {
|
|
19
|
+
queryId: string;
|
|
20
|
+
path: (number | string)[];
|
|
26
21
|
};
|
|
27
|
-
}>(
|
|
22
|
+
}>(object: T, property?: Exclude<keyof T, "__typename" | "_sys">, index?: number) => string;
|
|
23
|
+
export declare const addMetadata: <T extends object>(id: string, object: T & {
|
|
24
|
+
type?: string;
|
|
25
|
+
_content_source?: unknown;
|
|
26
|
+
}, path: (string | number)[]) => T;
|
|
27
|
+
/**
|
|
28
|
+
* This is a pretty rudimentary approach to hashing the query and variables to
|
|
29
|
+
* ensure we treat multiple queries on the page uniquely. It's possible
|
|
30
|
+
* that we would have collisions, and I'm not sure of the likeliness but seems
|
|
31
|
+
* like it'd be rare.
|
|
32
|
+
*/
|
|
33
|
+
export declare const hashFromQuery: (input: string) => string;
|
package/dist/react.es.js
CHANGED
|
@@ -1,23 +1,110 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
function useTina(props) {
|
|
3
|
+
const stringifiedQuery = JSON.stringify({
|
|
4
|
+
query: props.query,
|
|
5
|
+
variables: props.variables
|
|
6
|
+
});
|
|
7
|
+
const id = React.useMemo(() => hashFromQuery(stringifiedQuery), [stringifiedQuery]);
|
|
3
8
|
const [data, setData] = React.useState(props.data);
|
|
4
9
|
const [isClient, setIsClient] = React.useState(false);
|
|
5
|
-
const
|
|
10
|
+
const [quickEditEnabled, setQuickEditEnabled] = React.useState(false);
|
|
11
|
+
const [isInTinaIframe, setIsInTinaIframe] = React.useState(false);
|
|
6
12
|
React.useEffect(() => {
|
|
7
13
|
setIsClient(true);
|
|
8
14
|
setData(props.data);
|
|
9
15
|
}, [id]);
|
|
16
|
+
React.useEffect(() => {
|
|
17
|
+
if (quickEditEnabled) {
|
|
18
|
+
let mouseDownHandler = function(e) {
|
|
19
|
+
const attributeNames = e.target.getAttributeNames();
|
|
20
|
+
const tinaAttribute = attributeNames.find((name) => name.startsWith("data-tina-field"));
|
|
21
|
+
let fieldName;
|
|
22
|
+
if (tinaAttribute) {
|
|
23
|
+
e.preventDefault();
|
|
24
|
+
e.stopPropagation();
|
|
25
|
+
fieldName = e.target.getAttribute(tinaAttribute);
|
|
26
|
+
} else {
|
|
27
|
+
const ancestor = e.target.closest("[data-tina-field], [data-tina-field-overlay]");
|
|
28
|
+
if (ancestor) {
|
|
29
|
+
const attributeNames2 = ancestor.getAttributeNames();
|
|
30
|
+
const tinaAttribute2 = attributeNames2.find((name) => name.startsWith("data-tina-field"));
|
|
31
|
+
if (tinaAttribute2) {
|
|
32
|
+
e.preventDefault();
|
|
33
|
+
e.stopPropagation();
|
|
34
|
+
fieldName = ancestor.getAttribute(tinaAttribute2);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (fieldName) {
|
|
39
|
+
if (isInTinaIframe) {
|
|
40
|
+
parent.postMessage({ type: "field:selected", fieldName }, window.location.origin);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
const style = document.createElement("style");
|
|
45
|
+
style.type = "text/css";
|
|
46
|
+
style.textContent = `
|
|
47
|
+
[data-tina-field] {
|
|
48
|
+
outline: 2px dashed rgba(34,150,254,0.5);
|
|
49
|
+
transition: box-shadow ease-out 150ms;
|
|
50
|
+
}
|
|
51
|
+
[data-tina-field]:hover {
|
|
52
|
+
box-shadow: inset 100vi 100vh rgba(34,150,254,0.3);
|
|
53
|
+
outline: 2px solid rgba(34,150,254,1);
|
|
54
|
+
cursor: pointer;
|
|
55
|
+
}
|
|
56
|
+
[data-tina-field-overlay] {
|
|
57
|
+
outline: 2px dashed rgba(34,150,254,0.5);
|
|
58
|
+
position: relative;
|
|
59
|
+
}
|
|
60
|
+
[data-tina-field-overlay]:hover {
|
|
61
|
+
cursor: pointer;
|
|
62
|
+
outline: 2px solid rgba(34,150,254,1);
|
|
63
|
+
}
|
|
64
|
+
[data-tina-field-overlay]::after {
|
|
65
|
+
content: '';
|
|
66
|
+
position: absolute;
|
|
67
|
+
inset: 0;
|
|
68
|
+
z-index: 20;
|
|
69
|
+
transition: opacity ease-out 150ms;
|
|
70
|
+
background-color: rgba(34,150,254,0.3);
|
|
71
|
+
opacity: 0;
|
|
72
|
+
}
|
|
73
|
+
[data-tina-field-overlay]:hover::after {
|
|
74
|
+
opacity: 1;
|
|
75
|
+
}
|
|
76
|
+
`;
|
|
77
|
+
document.head.appendChild(style);
|
|
78
|
+
document.body.classList.add("__tina-quick-editing-enabled");
|
|
79
|
+
document.addEventListener("click", mouseDownHandler, true);
|
|
80
|
+
return () => {
|
|
81
|
+
document.removeEventListener("click", mouseDownHandler, true);
|
|
82
|
+
document.body.classList.remove("__tina-quick-editing-enabled");
|
|
83
|
+
style.remove();
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}, [quickEditEnabled, isInTinaIframe]);
|
|
10
87
|
React.useEffect(() => {
|
|
11
88
|
parent.postMessage({ type: "open", ...props, id }, window.location.origin);
|
|
12
89
|
window.addEventListener("message", (event) => {
|
|
90
|
+
if (event.data.type === "quickEditEnabled") {
|
|
91
|
+
setQuickEditEnabled(event.data.value);
|
|
92
|
+
}
|
|
13
93
|
if (event.data.id === id && event.data.type === "updateData") {
|
|
14
94
|
setData(event.data.data);
|
|
95
|
+
setIsInTinaIframe(true);
|
|
96
|
+
const anyTinaField = document.querySelector("[data-tina-field]");
|
|
97
|
+
if (anyTinaField) {
|
|
98
|
+
parent.postMessage({ type: "quick-edit", value: true }, window.location.origin);
|
|
99
|
+
} else {
|
|
100
|
+
parent.postMessage({ type: "quick-edit", value: false }, window.location.origin);
|
|
101
|
+
}
|
|
15
102
|
}
|
|
16
103
|
});
|
|
17
104
|
return () => {
|
|
18
105
|
parent.postMessage({ type: "close", id }, window.location.origin);
|
|
19
106
|
};
|
|
20
|
-
}, [id]);
|
|
107
|
+
}, [id, setQuickEditEnabled]);
|
|
21
108
|
return { data, isClient };
|
|
22
109
|
}
|
|
23
110
|
function useEditState() {
|
|
@@ -35,16 +122,86 @@ function useEditState() {
|
|
|
35
122
|
}, []);
|
|
36
123
|
return { edit };
|
|
37
124
|
}
|
|
38
|
-
const tinaField = (
|
|
125
|
+
const tinaField = (object, property, index) => {
|
|
39
126
|
var _a, _b, _c;
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
127
|
+
if (object._content_source) {
|
|
128
|
+
if (!property) {
|
|
129
|
+
return [
|
|
130
|
+
(_a = object._content_source) == null ? void 0 : _a.queryId,
|
|
131
|
+
object._content_source.path.join(".")
|
|
132
|
+
].join("---");
|
|
133
|
+
}
|
|
134
|
+
if (typeof index === "number") {
|
|
135
|
+
return [
|
|
136
|
+
(_b = object._content_source) == null ? void 0 : _b.queryId,
|
|
137
|
+
[...object._content_source.path, property, index].join(".")
|
|
138
|
+
].join("---");
|
|
46
139
|
}
|
|
140
|
+
return [
|
|
141
|
+
(_c = object._content_source) == null ? void 0 : _c.queryId,
|
|
142
|
+
[...object._content_source.path, property].join(".")
|
|
143
|
+
].join("---");
|
|
47
144
|
}
|
|
48
145
|
return "";
|
|
49
146
|
};
|
|
50
|
-
|
|
147
|
+
const addMetadata = (id, object, path) => {
|
|
148
|
+
Object.entries(object).forEach(([key, value]) => {
|
|
149
|
+
if (Array.isArray(value)) {
|
|
150
|
+
value.forEach((item, index) => {
|
|
151
|
+
if (isScalarOrUndefined(item)) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (Array.isArray(item)) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const itemObject = item;
|
|
158
|
+
addMetadata(id, itemObject, [...path, key, index]);
|
|
159
|
+
});
|
|
160
|
+
} else {
|
|
161
|
+
if (isScalarOrUndefined(value)) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const itemObject = value;
|
|
165
|
+
addMetadata(id, itemObject, [...path, key]);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
if ((object == null ? void 0 : object.type) === "root") {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
object._content_source = {
|
|
172
|
+
queryId: id,
|
|
173
|
+
path
|
|
174
|
+
};
|
|
175
|
+
return object;
|
|
176
|
+
};
|
|
177
|
+
function isScalarOrUndefined(value) {
|
|
178
|
+
const type = typeof value;
|
|
179
|
+
if (type === "string")
|
|
180
|
+
return true;
|
|
181
|
+
if (type === "number")
|
|
182
|
+
return true;
|
|
183
|
+
if (type === "boolean")
|
|
184
|
+
return true;
|
|
185
|
+
if (type === "undefined")
|
|
186
|
+
return true;
|
|
187
|
+
if (value == null)
|
|
188
|
+
return true;
|
|
189
|
+
if (value instanceof String)
|
|
190
|
+
return true;
|
|
191
|
+
if (value instanceof Number)
|
|
192
|
+
return true;
|
|
193
|
+
if (value instanceof Boolean)
|
|
194
|
+
return true;
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
const hashFromQuery = (input) => {
|
|
198
|
+
let hash = 0;
|
|
199
|
+
for (let i = 0; i < input.length; i++) {
|
|
200
|
+
const char = input.charCodeAt(i);
|
|
201
|
+
hash = (hash << 5) - hash + char & 4294967295;
|
|
202
|
+
}
|
|
203
|
+
const nonNegativeHash = Math.abs(hash);
|
|
204
|
+
const alphanumericHash = nonNegativeHash.toString(36);
|
|
205
|
+
return alphanumericHash;
|
|
206
|
+
};
|
|
207
|
+
export { addMetadata, hashFromQuery, tinaField, useEditState, useTina };
|
package/dist/react.js
CHANGED
|
@@ -7,24 +7,111 @@
|
|
|
7
7
|
}
|
|
8
8
|
var React__default = /* @__PURE__ */ _interopDefaultLegacy(React);
|
|
9
9
|
function useTina(props) {
|
|
10
|
+
const stringifiedQuery = JSON.stringify({
|
|
11
|
+
query: props.query,
|
|
12
|
+
variables: props.variables
|
|
13
|
+
});
|
|
14
|
+
const id = React__default["default"].useMemo(() => hashFromQuery(stringifiedQuery), [stringifiedQuery]);
|
|
10
15
|
const [data, setData] = React__default["default"].useState(props.data);
|
|
11
16
|
const [isClient, setIsClient] = React__default["default"].useState(false);
|
|
12
|
-
const
|
|
17
|
+
const [quickEditEnabled, setQuickEditEnabled] = React__default["default"].useState(false);
|
|
18
|
+
const [isInTinaIframe, setIsInTinaIframe] = React__default["default"].useState(false);
|
|
13
19
|
React__default["default"].useEffect(() => {
|
|
14
20
|
setIsClient(true);
|
|
15
21
|
setData(props.data);
|
|
16
22
|
}, [id]);
|
|
23
|
+
React__default["default"].useEffect(() => {
|
|
24
|
+
if (quickEditEnabled) {
|
|
25
|
+
let mouseDownHandler = function(e) {
|
|
26
|
+
const attributeNames = e.target.getAttributeNames();
|
|
27
|
+
const tinaAttribute = attributeNames.find((name) => name.startsWith("data-tina-field"));
|
|
28
|
+
let fieldName;
|
|
29
|
+
if (tinaAttribute) {
|
|
30
|
+
e.preventDefault();
|
|
31
|
+
e.stopPropagation();
|
|
32
|
+
fieldName = e.target.getAttribute(tinaAttribute);
|
|
33
|
+
} else {
|
|
34
|
+
const ancestor = e.target.closest("[data-tina-field], [data-tina-field-overlay]");
|
|
35
|
+
if (ancestor) {
|
|
36
|
+
const attributeNames2 = ancestor.getAttributeNames();
|
|
37
|
+
const tinaAttribute2 = attributeNames2.find((name) => name.startsWith("data-tina-field"));
|
|
38
|
+
if (tinaAttribute2) {
|
|
39
|
+
e.preventDefault();
|
|
40
|
+
e.stopPropagation();
|
|
41
|
+
fieldName = ancestor.getAttribute(tinaAttribute2);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (fieldName) {
|
|
46
|
+
if (isInTinaIframe) {
|
|
47
|
+
parent.postMessage({ type: "field:selected", fieldName }, window.location.origin);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const style = document.createElement("style");
|
|
52
|
+
style.type = "text/css";
|
|
53
|
+
style.textContent = `
|
|
54
|
+
[data-tina-field] {
|
|
55
|
+
outline: 2px dashed rgba(34,150,254,0.5);
|
|
56
|
+
transition: box-shadow ease-out 150ms;
|
|
57
|
+
}
|
|
58
|
+
[data-tina-field]:hover {
|
|
59
|
+
box-shadow: inset 100vi 100vh rgba(34,150,254,0.3);
|
|
60
|
+
outline: 2px solid rgba(34,150,254,1);
|
|
61
|
+
cursor: pointer;
|
|
62
|
+
}
|
|
63
|
+
[data-tina-field-overlay] {
|
|
64
|
+
outline: 2px dashed rgba(34,150,254,0.5);
|
|
65
|
+
position: relative;
|
|
66
|
+
}
|
|
67
|
+
[data-tina-field-overlay]:hover {
|
|
68
|
+
cursor: pointer;
|
|
69
|
+
outline: 2px solid rgba(34,150,254,1);
|
|
70
|
+
}
|
|
71
|
+
[data-tina-field-overlay]::after {
|
|
72
|
+
content: '';
|
|
73
|
+
position: absolute;
|
|
74
|
+
inset: 0;
|
|
75
|
+
z-index: 20;
|
|
76
|
+
transition: opacity ease-out 150ms;
|
|
77
|
+
background-color: rgba(34,150,254,0.3);
|
|
78
|
+
opacity: 0;
|
|
79
|
+
}
|
|
80
|
+
[data-tina-field-overlay]:hover::after {
|
|
81
|
+
opacity: 1;
|
|
82
|
+
}
|
|
83
|
+
`;
|
|
84
|
+
document.head.appendChild(style);
|
|
85
|
+
document.body.classList.add("__tina-quick-editing-enabled");
|
|
86
|
+
document.addEventListener("click", mouseDownHandler, true);
|
|
87
|
+
return () => {
|
|
88
|
+
document.removeEventListener("click", mouseDownHandler, true);
|
|
89
|
+
document.body.classList.remove("__tina-quick-editing-enabled");
|
|
90
|
+
style.remove();
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}, [quickEditEnabled, isInTinaIframe]);
|
|
17
94
|
React__default["default"].useEffect(() => {
|
|
18
95
|
parent.postMessage({ type: "open", ...props, id }, window.location.origin);
|
|
19
96
|
window.addEventListener("message", (event) => {
|
|
97
|
+
if (event.data.type === "quickEditEnabled") {
|
|
98
|
+
setQuickEditEnabled(event.data.value);
|
|
99
|
+
}
|
|
20
100
|
if (event.data.id === id && event.data.type === "updateData") {
|
|
21
101
|
setData(event.data.data);
|
|
102
|
+
setIsInTinaIframe(true);
|
|
103
|
+
const anyTinaField = document.querySelector("[data-tina-field]");
|
|
104
|
+
if (anyTinaField) {
|
|
105
|
+
parent.postMessage({ type: "quick-edit", value: true }, window.location.origin);
|
|
106
|
+
} else {
|
|
107
|
+
parent.postMessage({ type: "quick-edit", value: false }, window.location.origin);
|
|
108
|
+
}
|
|
22
109
|
}
|
|
23
110
|
});
|
|
24
111
|
return () => {
|
|
25
112
|
parent.postMessage({ type: "close", id }, window.location.origin);
|
|
26
113
|
};
|
|
27
|
-
}, [id]);
|
|
114
|
+
}, [id, setQuickEditEnabled]);
|
|
28
115
|
return { data, isClient };
|
|
29
116
|
}
|
|
30
117
|
function useEditState() {
|
|
@@ -42,18 +129,90 @@
|
|
|
42
129
|
}, []);
|
|
43
130
|
return { edit };
|
|
44
131
|
}
|
|
45
|
-
const tinaField = (
|
|
132
|
+
const tinaField = (object, property, index) => {
|
|
46
133
|
var _a, _b, _c;
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
134
|
+
if (object._content_source) {
|
|
135
|
+
if (!property) {
|
|
136
|
+
return [
|
|
137
|
+
(_a = object._content_source) == null ? void 0 : _a.queryId,
|
|
138
|
+
object._content_source.path.join(".")
|
|
139
|
+
].join("---");
|
|
140
|
+
}
|
|
141
|
+
if (typeof index === "number") {
|
|
142
|
+
return [
|
|
143
|
+
(_b = object._content_source) == null ? void 0 : _b.queryId,
|
|
144
|
+
[...object._content_source.path, property, index].join(".")
|
|
145
|
+
].join("---");
|
|
53
146
|
}
|
|
147
|
+
return [
|
|
148
|
+
(_c = object._content_source) == null ? void 0 : _c.queryId,
|
|
149
|
+
[...object._content_source.path, property].join(".")
|
|
150
|
+
].join("---");
|
|
54
151
|
}
|
|
55
152
|
return "";
|
|
56
153
|
};
|
|
154
|
+
const addMetadata = (id, object, path) => {
|
|
155
|
+
Object.entries(object).forEach(([key, value]) => {
|
|
156
|
+
if (Array.isArray(value)) {
|
|
157
|
+
value.forEach((item, index) => {
|
|
158
|
+
if (isScalarOrUndefined(item)) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (Array.isArray(item)) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const itemObject = item;
|
|
165
|
+
addMetadata(id, itemObject, [...path, key, index]);
|
|
166
|
+
});
|
|
167
|
+
} else {
|
|
168
|
+
if (isScalarOrUndefined(value)) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const itemObject = value;
|
|
172
|
+
addMetadata(id, itemObject, [...path, key]);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
if ((object == null ? void 0 : object.type) === "root") {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
object._content_source = {
|
|
179
|
+
queryId: id,
|
|
180
|
+
path
|
|
181
|
+
};
|
|
182
|
+
return object;
|
|
183
|
+
};
|
|
184
|
+
function isScalarOrUndefined(value) {
|
|
185
|
+
const type = typeof value;
|
|
186
|
+
if (type === "string")
|
|
187
|
+
return true;
|
|
188
|
+
if (type === "number")
|
|
189
|
+
return true;
|
|
190
|
+
if (type === "boolean")
|
|
191
|
+
return true;
|
|
192
|
+
if (type === "undefined")
|
|
193
|
+
return true;
|
|
194
|
+
if (value == null)
|
|
195
|
+
return true;
|
|
196
|
+
if (value instanceof String)
|
|
197
|
+
return true;
|
|
198
|
+
if (value instanceof Number)
|
|
199
|
+
return true;
|
|
200
|
+
if (value instanceof Boolean)
|
|
201
|
+
return true;
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
const hashFromQuery = (input) => {
|
|
205
|
+
let hash = 0;
|
|
206
|
+
for (let i = 0; i < input.length; i++) {
|
|
207
|
+
const char = input.charCodeAt(i);
|
|
208
|
+
hash = (hash << 5) - hash + char & 4294967295;
|
|
209
|
+
}
|
|
210
|
+
const nonNegativeHash = Math.abs(hash);
|
|
211
|
+
const alphanumericHash = nonNegativeHash.toString(36);
|
|
212
|
+
return alphanumericHash;
|
|
213
|
+
};
|
|
214
|
+
exports2.addMetadata = addMetadata;
|
|
215
|
+
exports2.hashFromQuery = hashFromQuery;
|
|
57
216
|
exports2.tinaField = tinaField;
|
|
58
217
|
exports2.useEditState = useEditState;
|
|
59
218
|
exports2.useTina = useTina;
|
package/dist/style.css
CHANGED
|
@@ -991,6 +991,9 @@
|
|
|
991
991
|
--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
|
|
992
992
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
|
993
993
|
}
|
|
994
|
+
.tina-tailwind .outline {
|
|
995
|
+
outline-style: solid;
|
|
996
|
+
}
|
|
994
997
|
.tina-tailwind .ring-1 {
|
|
995
998
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
|
996
999
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tinacms",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.6",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "./dist/index.es.js",
|
|
6
6
|
"exports": {
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"@react-hook/window-size": "^3.0.7",
|
|
59
59
|
"@tinacms/schema-tools": "1.4.4",
|
|
60
60
|
"@tinacms/sharedctx": "1.0.1",
|
|
61
|
-
"@tinacms/toolkit": "1.7.
|
|
61
|
+
"@tinacms/toolkit": "1.7.2",
|
|
62
62
|
"crypto-js": "^4.0.0",
|
|
63
63
|
"encoding": "0.1.13",
|
|
64
64
|
"fetch-ponyfill": "^7.1.0",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"lodash.set": "^4.3.2",
|
|
69
69
|
"prism-react-renderer": "^1.3.5",
|
|
70
70
|
"react-icons": "^4.3.1",
|
|
71
|
-
"react-router-dom": "6",
|
|
71
|
+
"react-router-dom": "6.3.0",
|
|
72
72
|
"yup": "^0.32.0",
|
|
73
73
|
"zod": "^3.14.3"
|
|
74
74
|
},
|