tinacms 0.66.9 → 0.67.1

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/index.es.js CHANGED
@@ -29,15 +29,16 @@ var __objRest = (source, exclude) => {
29
29
  }
30
30
  return target;
31
31
  };
32
- import { useCMS, useBranchData, FormMetaPlugin, Form, GlobalFormPlugin, EventBus, Modal, ModalPopup, ModalHeader, ModalBody, ModalActions, Button, LoadingDots, useLocalStorage, TinaCMS, BranchSwitcherPlugin, BranchDataProvider, TinaProvider, Nav, LocalWarning, FormStatus, FormBuilder } from "@tinacms/toolkit";
32
+ import { useCMS, useBranchData, FormMetaPlugin, Form, GlobalFormPlugin, EventBus, Modal, ModalPopup, ModalHeader, ModalBody, ModalActions, Button, LoadingDots, useLocalStorage, TinaCMS, BranchSwitcherPlugin, BranchDataProvider, TinaProvider, Nav, LocalWarning, OverflowMenu, FormStatus, FormBuilder } from "@tinacms/toolkit";
33
33
  export * from "@tinacms/toolkit";
34
34
  import * as G from "graphql";
35
- import { TypeInfo, visit, visitWithTypeInfo, getNamedType, GraphQLObjectType, isLeafType, GraphQLUnionType, isScalarType, getIntrospectionQuery, buildClientSchema, print, parse } from "graphql";
35
+ import { TypeInfo, visit, visitWithTypeInfo, getNamedType, GraphQLObjectType, isLeafType, GraphQLUnionType, isScalarType as isScalarType$1, getIntrospectionQuery, buildClientSchema, print, parse } from "graphql";
36
36
  import set from "lodash.set";
37
37
  import React, { useState, useCallback, useEffect, Fragment, useMemo } from "react";
38
38
  import { getIn, setIn } from "final-form";
39
- import * as yup from "yup";
39
+ import { resolveForm, TinaSchema, addNamespaceToSchema, validateSchema } from "@tinacms/schema-tools";
40
40
  import gql$1 from "graphql-tag";
41
+ import * as yup from "yup";
41
42
  import styled from "styled-components";
42
43
  import { setEditing, TinaDataContext, useEditState } from "@tinacms/sharedctx";
43
44
  import UrlPattern from "url-pattern";
@@ -287,7 +288,7 @@ const buildSelectionsFields = (fields, callback) => {
287
288
  const result = callback(fields);
288
289
  if (!result.continue) {
289
290
  if (fields.every((field) => {
290
- return !isScalarType(getNamedType(field.type));
291
+ return !isScalarType$1(getNamedType(field.type));
291
292
  })) {
292
293
  return [
293
294
  {
@@ -300,7 +301,7 @@ const buildSelectionsFields = (fields, callback) => {
300
301
  ];
301
302
  }
302
303
  return buildSelectionsFields(result.filteredFields.filter((field) => {
303
- if (isScalarType(getNamedType(field.type))) {
304
+ if (isScalarType$1(getNamedType(field.type))) {
304
305
  return true;
305
306
  }
306
307
  return false;
@@ -380,13 +381,15 @@ const createClient = ({
380
381
  clientId,
381
382
  isLocalClient = true,
382
383
  branch,
383
- tinaioConfig
384
+ tinaioConfig,
385
+ schema
384
386
  }) => {
385
- return isLocalClient ? new LocalClient() : new Client({
387
+ return isLocalClient ? new LocalClient({ schema }) : new Client({
386
388
  clientId: clientId || "",
387
389
  branch: branch || "main",
388
390
  tokenStorage: "LOCAL_STORAGE",
389
- tinaioConfig
391
+ tinaioConfig,
392
+ schema
390
393
  });
391
394
  };
392
395
  function assertShape(value, yupSchema, errorMessage) {
@@ -414,9 +417,6 @@ function useGraphqlFormsUnstable({
414
417
  eventList
415
418
  }) {
416
419
  const cms = useCMS();
417
- React.useEffect(() => {
418
- console.log("NOTE: using unstable formify");
419
- }, []);
420
420
  const state = useFormify({
421
421
  query,
422
422
  cms,
@@ -492,11 +492,12 @@ function useGraphqlForms({
492
492
  setIsLoading(false);
493
493
  return;
494
494
  }
495
+ const useUnstableFormify = (cms == null ? void 0 : cms.flags.get("use-unstable-formify")) === false ? false : true;
495
496
  const formIds = [];
496
497
  setIsLoading(true);
497
498
  cms.api.tina.requestWithForm((gql2) => gql2(query), {
498
499
  variables,
499
- useUnstableFormify: cms.flags.get("use-unstable-formify")
500
+ useUnstableFormify
500
501
  }).then((payload) => {
501
502
  cms.plugins.remove(new FormMetaPlugin({ name: "tina-admin-link" }));
502
503
  setData(payload);
@@ -515,11 +516,10 @@ function useGraphqlForms({
515
516
  values: yup2.object().required(),
516
517
  form: yup2.object().required()
517
518
  }), `Unable to build form shape for fields at ${queryName}`);
518
- const formConfig = {
519
+ let formConfig = {};
520
+ const formCommon = {
519
521
  id: queryName,
520
- label: result.form.label,
521
522
  initialValues: result.values,
522
- fields: result.form.fields,
523
523
  reset: () => {
524
524
  setPendingReset(queryName);
525
525
  },
@@ -551,6 +551,29 @@ function useGraphqlForms({
551
551
  }
552
552
  }
553
553
  };
554
+ if (cms.api.tina.schema) {
555
+ const enrichedSchema = cms.api.tina.schema;
556
+ const collection = enrichedSchema.getCollection(result._internalSys.collection.name);
557
+ const template = enrichedSchema.getTemplateForData({
558
+ collection,
559
+ data: result.values
560
+ });
561
+ const formInfo = resolveForm({
562
+ collection,
563
+ basename: collection.name,
564
+ schema: enrichedSchema,
565
+ template
566
+ });
567
+ formConfig = __spreadValues({
568
+ label: formInfo.label,
569
+ fields: formInfo.fields
570
+ }, formCommon);
571
+ } else {
572
+ formConfig = __spreadValues({
573
+ label: result.form.label,
574
+ fields: result.form.fields
575
+ }, formCommon);
576
+ }
554
577
  const { createForm, createGlobalForm } = generateFormCreators(cms);
555
578
  const SKIPPED = "SKIPPED";
556
579
  let form;
@@ -623,10 +646,8 @@ function useGraphqlForms({
623
646
  }, { values: true });
624
647
  });
625
648
  }).catch((e) => {
626
- cms.alerts.error("There was a problem setting up forms for your query");
627
- console.error("There was a problem setting up forms for your query");
628
- console.error(e);
629
649
  setIsLoading(false);
650
+ throw new Error(`There was a problem setting up forms for your query: ${e.message}`);
630
651
  });
631
652
  return () => {
632
653
  formIds.forEach((name) => {
@@ -722,100 +743,7 @@ const generateFormCreatorsUnstable = (cms, showInSidebar) => {
722
743
  };
723
744
  return { createForm, createGlobalForm };
724
745
  };
725
- const isNodeField = (type) => {
726
- if (G.isUnionType(type)) {
727
- return type.getTypes().every((type2) => {
728
- return type2.getInterfaces().find((intfc) => intfc.name === "Node");
729
- });
730
- } else if (G.isObjectType(type)) {
731
- return !!type.getInterfaces().find((intfc) => intfc.name === "Node");
732
- } else if (G.isInterfaceType(type)) {
733
- if (type.name === "Node") {
734
- return true;
735
- }
736
- } else {
737
- return false;
738
- }
739
- };
740
- const isConnectionField = (type) => {
741
- if (G.isObjectType(type)) {
742
- return !!type.getInterfaces().find((intfc) => intfc.name === "Connection");
743
- } else {
744
- throw new Error(`Expected GraphQLObjectType for isConnectionField check`);
745
- }
746
- };
747
- const getObjectField = (object, selectionNode) => {
748
- return object.getFields()[selectionNode.name.value];
749
- };
750
- const getSelectedUnionType = (unionType, selectionNode) => {
751
- return unionType.getTypes().find((type) => type.name === selectionNode.typeCondition.name.value);
752
- };
753
- function isListType(type) {
754
- if (G.isListType(type)) {
755
- return true;
756
- } else if (G.isNonNullType(type)) {
757
- if (G.isListType(type.ofType)) {
758
- return true;
759
- }
760
- }
761
- return false;
762
- }
763
- function ensureNodeField(field) {
764
- if (!isNodeField(field)) {
765
- throw new Error(`Expected field to implement Node interface`);
766
- }
767
- }
768
- function ensureUnionType(type) {
769
- if (!G.isUnionType(type)) {
770
- throw new Error(`Expected type to be GraphQLUnionType`);
771
- }
772
- }
773
- function ensureObjectType(type) {
774
- if (!G.isObjectType(type)) {
775
- console.log(type);
776
- throw new Error(`Expected type to be GraphQLObjectType`);
777
- }
778
- }
779
- function ensureOperationDefinition(type) {
780
- if (type.kind !== "OperationDefinition") {
781
- throw new Error(`Expected top-level definition to be an OperationDefinition node, ensure your query has been optimized before calling formify`);
782
- }
783
- }
784
- function getNameAndAlias(fieldNode, list, isNode) {
785
- return {
786
- name: fieldNode.name.value,
787
- alias: fieldNode.alias ? fieldNode.alias.value : fieldNode.name.value,
788
- list: !!list,
789
- isNode: !!isNode
790
- };
791
- }
792
- const node = G.parse(`
793
- query Sample {
794
- _internalSys: sys {
795
- path
796
- collection {
797
- name
798
- }
799
- }
800
- form
801
- values
802
- }`);
803
- const metaFields = node.definitions[0].selectionSet.selections;
804
- const getRelativeBlueprint = (path) => {
805
- let indexOfLastNode = 0;
806
- path.forEach((item, i) => {
807
- if (item.isNode) {
808
- if (i === path.length - 1)
809
- ;
810
- else {
811
- indexOfLastNode = i;
812
- }
813
- }
814
- });
815
- const documentBlueprintPath = path.slice(0, indexOfLastNode + 1);
816
- return getBlueprintNamePath({ path: documentBlueprintPath });
817
- };
818
- const getIn2 = (state, path) => {
746
+ const getValueForBlueprint = (state, path) => {
819
747
  const pathArray = path.split(".");
820
748
  let latest = state;
821
749
  pathArray.every((item, index) => {
@@ -825,7 +753,7 @@ const getIn2 = (state, path) => {
825
753
  const next = [];
826
754
  if (Array.isArray(latest)) {
827
755
  latest.forEach((latest2, index2) => {
828
- const res = getIn2(latest2, restOfItems.join("."));
756
+ const res = getValueForBlueprint(latest2, restOfItems.join("."));
829
757
  next.push(res);
830
758
  });
831
759
  } else {
@@ -892,9 +820,8 @@ const buildForm = (doc, cms, formify2, showInSidebar = false, onSubmit) => {
892
820
  if (skipped)
893
821
  return;
894
822
  const id = doc._internalSys.path;
895
- const formConfig = __spreadProps(__spreadValues({
896
- id
897
- }, doc.form), {
823
+ const formCommon = {
824
+ id,
898
825
  label: doc.form.label,
899
826
  initialValues: doc.values,
900
827
  onSubmit: async (payload) => {
@@ -924,7 +851,31 @@ const buildForm = (doc, cms, formify2, showInSidebar = false, onSubmit) => {
924
851
  cms.alerts.error("There was a problem saving your document");
925
852
  }
926
853
  }
927
- });
854
+ };
855
+ let formConfig = {};
856
+ if (cms.api.tina.schema) {
857
+ const enrichedSchema = cms.api.tina.schema;
858
+ const collection = enrichedSchema.getCollection(doc._internalSys.collection.name);
859
+ const template = enrichedSchema.getTemplateForData({
860
+ collection,
861
+ data: doc.values
862
+ });
863
+ const formInfo = resolveForm({
864
+ collection,
865
+ basename: collection.name,
866
+ schema: enrichedSchema,
867
+ template
868
+ });
869
+ formConfig = __spreadValues({
870
+ label: formInfo.label,
871
+ fields: formInfo.fields
872
+ }, formCommon);
873
+ } else {
874
+ formConfig = __spreadValues({
875
+ label: doc.form.label,
876
+ fields: doc.form.fields
877
+ }, formCommon);
878
+ }
928
879
  if (formify2) {
929
880
  form = formify2({
930
881
  formConfig,
@@ -970,19 +921,6 @@ const sequential = async (items, callback) => {
970
921
  }
971
922
  return accum;
972
923
  };
973
- const getBlueprintId = (path) => {
974
- const namePath = [];
975
- const aliasPath = [];
976
- path.forEach((p) => {
977
- namePath.push(p.name);
978
- aliasPath.push(p.alias);
979
- if (p.list) {
980
- namePath.push("[]");
981
- aliasPath.push("[]");
982
- }
983
- });
984
- return namePath.join(".");
985
- };
986
924
  const getFormNodesStartingWith = (string, state) => {
987
925
  return state.formNodes.filter((subFormNode) => {
988
926
  return subFormNode.documentBlueprintId.startsWith(string);
@@ -998,44 +936,6 @@ const getFormNodesForField = (fieldBlueprint, formNode, event, state) => {
998
936
  const existing = getIn(state.data, pathToChange);
999
937
  return { pathToChange, formNodes, eventLocation, existing };
1000
938
  };
1001
- const matchLocation = (eventLocation, formNode) => {
1002
- return eventLocation.every((item, index) => item === formNode.location[index]);
1003
- };
1004
- const bumpLocation = (location) => {
1005
- return location.map((item, index) => {
1006
- if (index === location.length - 1) {
1007
- return item + 1;
1008
- }
1009
- return item;
1010
- });
1011
- };
1012
- const maybeLowerLocation = (location, at) => {
1013
- return location.map((item, index) => {
1014
- if (index === location.length - 1) {
1015
- return item < at ? item : item - 1;
1016
- }
1017
- return item;
1018
- });
1019
- };
1020
- const matchesAt = (location, at) => {
1021
- let matches = false;
1022
- location.map((item, index) => {
1023
- if (index === location.length - 1) {
1024
- if (item === at) {
1025
- matches = true;
1026
- }
1027
- }
1028
- });
1029
- return matches;
1030
- };
1031
- const swapLocation = (location, mapping) => {
1032
- return location.map((item, index) => {
1033
- if (index === location.length - 1) {
1034
- return mapping[item];
1035
- }
1036
- return item;
1037
- });
1038
- };
1039
939
  const getBlueprintAliasPath = (blueprint) => {
1040
940
  const namePath = [];
1041
941
  const aliasPath = [];
@@ -1051,22 +951,56 @@ const getBlueprintAliasPath = (blueprint) => {
1051
951
  };
1052
952
  const getBlueprintFieldsForEvent = (blueprint, event) => {
1053
953
  return blueprint.fields.filter((fbp) => {
1054
- return getBlueprintNamePath(fbp) === getEventPath(event, blueprint);
954
+ if (getBlueprintNamePath(fbp) === getEventPath(event, blueprint)) {
955
+ return true;
956
+ }
957
+ }).filter((fbp) => {
958
+ return filterFieldBlueprintsByParentTypename(fbp, event.field.data.tinaField.parentTypename);
959
+ });
960
+ };
961
+ const filterFieldBlueprintsByParentTypename = (fbp, typename) => {
962
+ let lastDisambiguator;
963
+ fbp.path.forEach((path) => {
964
+ if (path.parentTypename) {
965
+ lastDisambiguator = path.parentTypename;
966
+ }
1055
967
  });
968
+ if (lastDisambiguator) {
969
+ return typename === lastDisambiguator;
970
+ } else {
971
+ return true;
972
+ }
1056
973
  };
1057
- const getBlueprintNamePath = (blueprint) => {
974
+ const getBlueprintNamePath = (blueprint, disambiguator) => {
1058
975
  const namePath = [];
1059
- const aliasPath = [];
1060
976
  blueprint.path.forEach((p) => {
977
+ if (disambiguator) {
978
+ if (p.parentTypename) {
979
+ namePath.push(p.parentTypename);
980
+ }
981
+ }
1061
982
  namePath.push(p.name);
1062
- aliasPath.push(p.alias);
1063
983
  if (p.list) {
1064
984
  namePath.push("[]");
1065
- aliasPath.push("[]");
1066
985
  }
1067
986
  });
1068
987
  return namePath.join(".");
1069
988
  };
989
+ const getEventPath = (event, blueprint) => {
990
+ const stringArray = event.field.name.split(".");
991
+ const eventPath = stringArray.map((item) => {
992
+ if (isNaN(Number(item))) {
993
+ return item;
994
+ }
995
+ return `[]`;
996
+ }).join(".");
997
+ const items = [blueprint.id, DATA_NODE_NAME$1, eventPath];
998
+ const isList = event.field.data.tinaField.list;
999
+ if (isList && !eventPath.endsWith("[]")) {
1000
+ items.push(`[]`);
1001
+ }
1002
+ return items.join(".");
1003
+ };
1070
1004
  const stripIndices = (string) => {
1071
1005
  const accum = [];
1072
1006
  const stringArray = string.split(".");
@@ -1088,20 +1022,21 @@ const replaceRealNum = (string) => {
1088
1022
  return "[]";
1089
1023
  }).join(".");
1090
1024
  };
1025
+ const getMatchName = ({ field, prefix, blueprint }) => {
1026
+ const fieldName = field.list ? `${field.name}.[]` : field.name;
1027
+ const blueprintName = getBlueprintNamePath(blueprint);
1028
+ const extra = [];
1029
+ if (prefix) {
1030
+ extra.push(prefix);
1031
+ }
1032
+ const matchName = [blueprintName, DATA_NODE_NAME$1, ...extra, fieldName].join(".");
1033
+ return { matchName, fieldName };
1034
+ };
1091
1035
  const getFormNodesFromEvent = (state, event) => {
1092
1036
  const formNodes = state.formNodes.filter((formNode) => formNode.documentFormId === event.formId);
1093
1037
  return formNodes;
1094
1038
  };
1095
1039
  const DATA_NODE_NAME$1 = "data";
1096
- const getEventPath = (event, blueprint) => {
1097
- const eventPath = replaceRealNum(event.field.name);
1098
- const items = [blueprint.id, DATA_NODE_NAME$1, eventPath];
1099
- const isList = event.field.data.tinaField.list;
1100
- if (isList && !eventPath.endsWith("[]")) {
1101
- items.push("[]");
1102
- }
1103
- return items.join(".");
1104
- };
1105
1040
  const printEvent = (event) => {
1106
1041
  var _a, _b;
1107
1042
  return {
@@ -1170,17 +1105,43 @@ const getMoveMapping = (existing, from, to) => {
1170
1105
  }
1171
1106
  return newOrderObject;
1172
1107
  };
1173
- const getPathsToChange = (event, state) => {
1174
- const pathsToChange = [];
1175
- const formNodes = getFormNodesFromEvent(state, event);
1176
- formNodes.forEach((formNode) => {
1177
- const blueprint = getFormNodeBlueprint(formNode, state);
1178
- getBlueprintFieldsForEvent(blueprint, event).forEach((fieldBlueprint) => {
1179
- const pathToChange = getPathToChange(fieldBlueprint, formNode, event);
1180
- pathsToChange.push({ pathToChange, formNode });
1181
- });
1108
+ const matchLocation = (eventLocation, formNode) => {
1109
+ return eventLocation.every((item, index) => item === formNode.location[index]);
1110
+ };
1111
+ const bumpLocation = (location) => {
1112
+ return location.map((item, index) => {
1113
+ if (index === location.length - 1) {
1114
+ return item + 1;
1115
+ }
1116
+ return item;
1117
+ });
1118
+ };
1119
+ const maybeLowerLocation = (location, at) => {
1120
+ return location.map((item, index) => {
1121
+ if (index === location.length - 1) {
1122
+ return item < at ? item : item - 1;
1123
+ }
1124
+ return item;
1125
+ });
1126
+ };
1127
+ const matchesAt = (location, at) => {
1128
+ let matches = false;
1129
+ location.map((item, index) => {
1130
+ if (index === location.length - 1) {
1131
+ if (item === at) {
1132
+ matches = true;
1133
+ }
1134
+ }
1135
+ });
1136
+ return matches;
1137
+ };
1138
+ const swapLocation = (location, mapping) => {
1139
+ return location.map((item, index) => {
1140
+ if (index === location.length - 1) {
1141
+ return mapping[item];
1142
+ }
1143
+ return item;
1182
1144
  });
1183
- return pathsToChange;
1184
1145
  };
1185
1146
  const getSubFields = (changeSet) => {
1186
1147
  var _a;
@@ -1191,6 +1152,133 @@ const getSubFields = (changeSet) => {
1191
1152
  }
1192
1153
  return { fields, __typename };
1193
1154
  };
1155
+ const isFormifiableDocument = (t) => {
1156
+ const type = G.getNamedType(t);
1157
+ if (G.isUnionType(type)) {
1158
+ return type.getTypes().every((type2) => {
1159
+ return type2.getInterfaces().find((intfc) => intfc.name === "Node");
1160
+ });
1161
+ } else if (G.isObjectType(type)) {
1162
+ return !!type.getInterfaces().find((intfc) => intfc.name === "Node");
1163
+ } else {
1164
+ return false;
1165
+ }
1166
+ };
1167
+ const isScalarType = (t) => {
1168
+ const namedType = G.getNamedType(t);
1169
+ return G.isScalarType(namedType);
1170
+ };
1171
+ const isConnectionField = (t) => {
1172
+ const type = G.getNamedType(t);
1173
+ if (G.isObjectType(type)) {
1174
+ return !!type.getInterfaces().find((intfc) => intfc.name === "Connection");
1175
+ } else {
1176
+ throw new Error(`Expected GraphQLObjectType for isConnectionField check`);
1177
+ }
1178
+ };
1179
+ const getObjectField = (object, selectionNode) => {
1180
+ const namedType = G.getNamedType(object);
1181
+ ensureObjectOrInterfaceType(namedType);
1182
+ return namedType.getFields()[selectionNode.name.value];
1183
+ };
1184
+ const getSelectedUnionType = (unionType, selectionNode) => {
1185
+ const namedType = G.getNamedType(unionType);
1186
+ if (!G.isUnionType(namedType)) {
1187
+ return;
1188
+ }
1189
+ const types = namedType.getTypes();
1190
+ const typeCondition = selectionNode.typeCondition.name.value;
1191
+ let intfc;
1192
+ types.forEach((type) => {
1193
+ intfc = type.getInterfaces().find((intfc2) => intfc2.name === typeCondition);
1194
+ });
1195
+ if (intfc) {
1196
+ return intfc;
1197
+ }
1198
+ return namedType.getTypes().find((type) => type.name === typeCondition);
1199
+ };
1200
+ function isListType(type) {
1201
+ if (G.isListType(type)) {
1202
+ return true;
1203
+ } else if (G.isNonNullType(type)) {
1204
+ if (G.isListType(type.ofType)) {
1205
+ return true;
1206
+ }
1207
+ }
1208
+ return false;
1209
+ }
1210
+ function ensureObjectOrInterfaceType(type) {
1211
+ if (G.isInterfaceType(type) || G.isObjectType(type))
1212
+ ;
1213
+ else {
1214
+ console.log("Expected type to be GraphQLObjectType or GraphQLInterfaceType", type);
1215
+ throw new Error(`Expected type to be GraphQLObjectType or GraphQLInterfaceType`);
1216
+ }
1217
+ }
1218
+ function ensureOperationDefinition(type) {
1219
+ if (type.kind !== "OperationDefinition") {
1220
+ throw new Error(`Expected top-level definition to be an OperationDefinition node, ensure your query has been optimized before calling formify`);
1221
+ }
1222
+ }
1223
+ function buildPath({
1224
+ fieldNode,
1225
+ type,
1226
+ parentTypename,
1227
+ path
1228
+ }) {
1229
+ const p = path || [];
1230
+ const list = isListType(type);
1231
+ const isNode = isFormifiableDocument(type);
1232
+ return [
1233
+ ...p,
1234
+ {
1235
+ name: fieldNode.name.value,
1236
+ alias: fieldNode.alias ? fieldNode.alias.value : fieldNode.name.value,
1237
+ parentTypename,
1238
+ list: !!list,
1239
+ isNode: !!isNode
1240
+ }
1241
+ ];
1242
+ }
1243
+ const node = G.parse(`
1244
+ query Sample {
1245
+ _internalSys: sys {
1246
+ path
1247
+ collection {
1248
+ name
1249
+ }
1250
+ }
1251
+ form
1252
+ values
1253
+ }`);
1254
+ const metaFields = node.definitions[0].selectionSet.selections;
1255
+ const getRelativeBlueprint = (path) => {
1256
+ let indexOfLastNode = 0;
1257
+ path.forEach((item, i) => {
1258
+ if (item.isNode) {
1259
+ if (i === path.length - 1)
1260
+ ;
1261
+ else {
1262
+ indexOfLastNode = i;
1263
+ }
1264
+ }
1265
+ });
1266
+ const documentBlueprintPath = path.slice(0, indexOfLastNode + 1);
1267
+ return getBlueprintNamePath({ path: documentBlueprintPath });
1268
+ };
1269
+ const getBlueprintId = (path) => {
1270
+ const namePath = [];
1271
+ const aliasPath = [];
1272
+ path.forEach((p) => {
1273
+ namePath.push(p.name);
1274
+ aliasPath.push(p.alias);
1275
+ if (p.list) {
1276
+ namePath.push("[]");
1277
+ aliasPath.push("[]");
1278
+ }
1279
+ });
1280
+ return namePath.join(".");
1281
+ };
1194
1282
  const NOOP = "This is either an error or is not yet supported";
1195
1283
  const UNEXPECTED = "Formify encountered an unexpected error, please contact support";
1196
1284
  const EDGES_NODE_NAME = "edges";
@@ -1223,11 +1311,10 @@ const formify = async ({
1223
1311
  const optimizedQuery = await getOptimizedQuery(documentNodeWithName);
1224
1312
  const typeInfo = new G.TypeInfo(schema);
1225
1313
  const formifyConnection = ({
1226
- namedFieldType,
1314
+ parentType,
1227
1315
  selectionNode,
1228
1316
  path
1229
1317
  }) => {
1230
- ensureObjectType(namedFieldType);
1231
1318
  return __spreadProps(__spreadValues({}, selectionNode), {
1232
1319
  selectionSet: {
1233
1320
  kind: "SelectionSet",
@@ -1235,13 +1322,12 @@ const formify = async ({
1235
1322
  switch (selectionNode2.kind) {
1236
1323
  case "Field":
1237
1324
  if (selectionNode2.name.value === EDGES_NODE_NAME) {
1238
- const edgeField = namedFieldType.getFields()[EDGES_NODE_NAME];
1239
- const edgeType = G.getNamedType(edgeField.type);
1240
- ensureObjectType(edgeType);
1241
- const path2 = [
1242
- ...path,
1243
- getNameAndAlias(selectionNode2, true, false)
1244
- ];
1325
+ const edgeField = getObjectField(parentType, selectionNode2);
1326
+ const edgesPath = buildPath({
1327
+ fieldNode: selectionNode2,
1328
+ type: edgeField.type,
1329
+ path
1330
+ });
1245
1331
  return __spreadProps(__spreadValues({}, selectionNode2), {
1246
1332
  selectionSet: {
1247
1333
  kind: "SelectionSet",
@@ -1249,15 +1335,15 @@ const formify = async ({
1249
1335
  switch (subSelectionNode.kind) {
1250
1336
  case "Field":
1251
1337
  if (subSelectionNode.name.value === NODE_NAME) {
1252
- const nodeField = edgeType.getFields()[NODE_NAME];
1253
- const path3 = [
1254
- ...path2,
1255
- getNameAndAlias(subSelectionNode, false, true)
1256
- ];
1257
- return formifyNode({
1258
- fieldOrInlineFragmentNode: subSelectionNode,
1338
+ const nodeField = getObjectField(edgeField.type, subSelectionNode);
1339
+ return formifyFieldNodeDocument({
1340
+ fieldNode: subSelectionNode,
1259
1341
  type: nodeField.type,
1260
- path: path3,
1342
+ path: buildPath({
1343
+ fieldNode: subSelectionNode,
1344
+ type: nodeField.type,
1345
+ path: edgesPath
1346
+ }),
1261
1347
  showInSidebar: false
1262
1348
  });
1263
1349
  } else {
@@ -1278,28 +1364,48 @@ const formify = async ({
1278
1364
  }
1279
1365
  });
1280
1366
  };
1281
- function formifyNode({
1282
- fieldOrInlineFragmentNode,
1367
+ function formifyInlineFragmentDocument({
1368
+ inlineFragmentNode,
1369
+ type,
1370
+ path,
1371
+ showInSidebar = false
1372
+ }) {
1373
+ return formifyDocument({
1374
+ selection: inlineFragmentNode,
1375
+ type,
1376
+ path,
1377
+ showInSidebar
1378
+ });
1379
+ }
1380
+ function formifyFieldNodeDocument({
1381
+ fieldNode,
1382
+ type,
1383
+ path,
1384
+ showInSidebar = false
1385
+ }) {
1386
+ return formifyDocument({ selection: fieldNode, type, path, showInSidebar });
1387
+ }
1388
+ function formifyDocument({
1389
+ selection,
1283
1390
  type,
1284
1391
  path,
1285
1392
  showInSidebar = false
1286
1393
  }) {
1287
1394
  let extraFields = [];
1288
- const namedType = G.getNamedType(type);
1289
1395
  let hasDataJSONField = false;
1290
1396
  let hasValuesField = false;
1291
1397
  let shouldFormify = false;
1292
- fieldOrInlineFragmentNode.selectionSet.selections.forEach((selection) => {
1293
- if (selection.kind === "Field") {
1294
- if (selection.name.value === "dataJSON") {
1398
+ selection.selectionSet.selections.forEach((selection2) => {
1399
+ if (selection2.kind === "Field") {
1400
+ if (selection2.name.value === "dataJSON") {
1295
1401
  shouldFormify = true;
1296
1402
  hasDataJSONField = true;
1297
1403
  }
1298
- if (selection.name.value === "values") {
1404
+ if (selection2.name.value === "values") {
1299
1405
  shouldFormify = true;
1300
1406
  hasValuesField = true;
1301
1407
  }
1302
- if (selection.name.value === "data") {
1408
+ if (selection2.name.value === "data") {
1303
1409
  shouldFormify = true;
1304
1410
  }
1305
1411
  }
@@ -1308,7 +1414,7 @@ const formify = async ({
1308
1414
  blueprints.push({
1309
1415
  id: getBlueprintId(path),
1310
1416
  path,
1311
- selection: fieldOrInlineFragmentNode,
1417
+ selection,
1312
1418
  fields: [],
1313
1419
  showInSidebar,
1314
1420
  hasDataJSONField,
@@ -1316,71 +1422,58 @@ const formify = async ({
1316
1422
  });
1317
1423
  extraFields = metaFields;
1318
1424
  }
1319
- const formifiedNode = __spreadProps(__spreadValues({}, fieldOrInlineFragmentNode), {
1425
+ return __spreadProps(__spreadValues({}, selection), {
1320
1426
  selectionSet: {
1321
1427
  kind: "SelectionSet",
1322
1428
  selections: [
1323
- ...fieldOrInlineFragmentNode.selectionSet.selections.map((selectionNode) => {
1429
+ ...selection.selectionSet.selections.map((selectionNode) => {
1324
1430
  switch (selectionNode.kind) {
1325
- case "InlineFragment":
1431
+ case "InlineFragment": {
1432
+ const namedType = G.getNamedType(type);
1326
1433
  if (G.isInterfaceType(namedType)) {
1327
- const subType2 = schema.getImplementations(namedType).objects.find((item) => item.name === selectionNode.typeCondition.name.value);
1328
- return formifyNode({
1329
- fieldOrInlineFragmentNode: selectionNode,
1330
- type: subType2,
1434
+ const subType = schema.getImplementations(namedType).objects.find((item) => item.name === selectionNode.typeCondition.name.value);
1435
+ return formifyInlineFragmentDocument({
1436
+ inlineFragmentNode: selectionNode,
1437
+ type: subType,
1331
1438
  path,
1332
- showInSidebar: false
1439
+ showInSidebar: true
1333
1440
  });
1334
1441
  }
1335
- ensureUnionType(namedType);
1336
- const subType = getSelectedUnionType(namedType, selectionNode);
1337
- return formifyNode({
1338
- fieldOrInlineFragmentNode: selectionNode,
1339
- type: subType,
1340
- path,
1341
- showInSidebar
1442
+ return formifyInlineFragmentNode({
1443
+ inlineFragmentNode: selectionNode,
1444
+ parentType: type,
1445
+ path
1342
1446
  });
1343
- case "Field":
1447
+ }
1448
+ case "Field": {
1344
1449
  if (selectionNode.name.value === DATA_NODE_NAME) {
1345
- const path2 = [
1346
- ...path,
1347
- getNameAndAlias(selectionNode, false, false)
1348
- ];
1349
- if (G.isObjectType(namedType)) {
1350
- const field = getObjectField(namedType, selectionNode);
1351
- const namedSubType = G.getNamedType(field.type);
1352
- ensureObjectType(namedSubType);
1353
- return __spreadProps(__spreadValues({}, selectionNode), {
1354
- selectionSet: {
1355
- kind: "SelectionSet",
1356
- selections: [
1357
- ...selectionNode.selectionSet.selections.map((subSelectionNode) => {
1358
- switch (subSelectionNode.kind) {
1359
- case "Field":
1360
- const subSelectionField = getObjectField(namedSubType, subSelectionNode);
1361
- if (!subSelectionField) {
1362
- return subSelectionNode;
1363
- }
1364
- const subSelectionType = G.getNamedType(subSelectionField.type);
1365
- return formifyField({
1366
- fieldNode: subSelectionNode,
1367
- parentType: field.type,
1368
- path: [
1369
- ...path2,
1370
- getNameAndAlias(subSelectionNode, isListType(subSelectionField.type), isNodeField(subSelectionType))
1371
- ]
1372
- });
1373
- default:
1374
- throw new FormifyError("UNEXPECTED", `selection ${subSelectionNode.kind}`);
1375
- }
1376
- })
1377
- ]
1378
- }
1379
- });
1380
- }
1381
- throw new FormifyError("UNEXPECTED");
1450
+ const field = getObjectField(type, selectionNode);
1451
+ return __spreadProps(__spreadValues({}, selectionNode), {
1452
+ selectionSet: {
1453
+ kind: "SelectionSet",
1454
+ selections: [
1455
+ ...selectionNode.selectionSet.selections.map((subSelectionNode) => {
1456
+ switch (subSelectionNode.kind) {
1457
+ case "Field":
1458
+ return formifyFieldNode({
1459
+ fieldNode: subSelectionNode,
1460
+ parentType: field.type,
1461
+ path: buildPath({
1462
+ fieldNode: selectionNode,
1463
+ type: field.type,
1464
+ path
1465
+ })
1466
+ });
1467
+ default:
1468
+ throw new FormifyError("UNEXPECTED", `selection ${subSelectionNode.kind}`);
1469
+ }
1470
+ })
1471
+ ]
1472
+ }
1473
+ });
1382
1474
  }
1383
1475
  return selectionNode;
1476
+ }
1384
1477
  default:
1385
1478
  throw new FormifyError("UNEXPECTED");
1386
1479
  }
@@ -1389,32 +1482,35 @@ const formify = async ({
1389
1482
  ]
1390
1483
  }
1391
1484
  });
1392
- return formifiedNode;
1393
1485
  }
1394
- const formifyField = ({
1486
+ const formifyFieldNode = ({
1395
1487
  fieldNode,
1396
1488
  parentType,
1397
1489
  path
1398
1490
  }) => {
1399
- const namedParentType = G.getNamedType(parentType);
1400
- ensureObjectType(namedParentType);
1401
- const field = getObjectField(namedParentType, fieldNode);
1491
+ if (fieldNode.name.value === "__typename") {
1492
+ return fieldNode;
1493
+ }
1494
+ const field = getObjectField(parentType, fieldNode);
1402
1495
  if (!field) {
1403
- if (fieldNode.name.value === "__typename") {
1404
- return fieldNode;
1405
- } else {
1406
- throw new FormifyError("UNEXPECTED", `field with no associated type ${fieldNode.name.value}`);
1407
- }
1496
+ return fieldNode;
1408
1497
  }
1409
- const namedType = G.getNamedType(field.type);
1410
- const fieldBlueprint = {
1411
- id: getBlueprintId([...path]),
1412
- documentBlueprintId: getRelativeBlueprint(path),
1413
- path: [...path]
1414
- };
1415
1498
  const blueprint = blueprints.find((blueprint2) => blueprint2.id === getRelativeBlueprint(path));
1416
- blueprint.fields.push(fieldBlueprint);
1417
- if (G.isScalarType(namedType)) {
1499
+ if (!blueprint) {
1500
+ return fieldNode;
1501
+ }
1502
+ const fieldPath = buildPath({
1503
+ fieldNode,
1504
+ type: field.type,
1505
+ parentTypename: G.getNamedType(parentType).name,
1506
+ path
1507
+ });
1508
+ blueprint.fields.push({
1509
+ id: getBlueprintId(fieldPath),
1510
+ documentBlueprintId: blueprint.id,
1511
+ path: fieldPath
1512
+ });
1513
+ if (isScalarType(field.type)) {
1418
1514
  return fieldNode;
1419
1515
  }
1420
1516
  return __spreadProps(__spreadValues({}, fieldNode), {
@@ -1423,121 +1519,20 @@ const formify = async ({
1423
1519
  selections: [
1424
1520
  ...fieldNode.selectionSet.selections.map((selectionNode) => {
1425
1521
  switch (selectionNode.kind) {
1426
- case "Field":
1427
- if (selectionNode.name.value === "__typename") {
1428
- return selectionNode;
1429
- }
1430
- ensureObjectType(namedType);
1431
- const subField = getObjectField(namedType, selectionNode);
1432
- if (!subField) {
1433
- return fieldNode;
1434
- }
1435
- if (G.isScalarType(G.getNamedType(subField.type))) {
1436
- const newPath2 = [
1437
- ...path,
1438
- getNameAndAlias(selectionNode, isListType(subField.type), false)
1439
- ];
1440
- const fieldBlueprint3 = {
1441
- id: getBlueprintId(newPath2),
1442
- documentBlueprintId: getRelativeBlueprint(newPath2),
1443
- path: newPath2
1444
- };
1445
- const blueprint3 = blueprints.find((blueprint4) => blueprint4.id === getRelativeBlueprint(path));
1446
- blueprint3.fields.push(fieldBlueprint3);
1447
- return selectionNode;
1448
- }
1449
- const subFieldType = subField.type;
1450
- const namedSubFieldType = G.getNamedType(subFieldType);
1451
- const newPath = [
1452
- ...path,
1453
- getNameAndAlias(selectionNode, isListType(subFieldType), isNodeField(namedSubFieldType))
1454
- ];
1455
- const fieldBlueprint2 = {
1456
- id: getBlueprintId(newPath),
1457
- documentBlueprintId: getRelativeBlueprint(newPath),
1458
- path: newPath
1459
- };
1460
- const blueprint2 = blueprints.find((blueprint3) => blueprint3.id === getRelativeBlueprint(path));
1461
- blueprint2.fields.push(fieldBlueprint2);
1462
- return __spreadProps(__spreadValues({}, selectionNode), {
1463
- selectionSet: {
1464
- kind: "SelectionSet",
1465
- selections: selectionNode.selectionSet.selections.map((subSelectionNode) => {
1466
- switch (subSelectionNode.kind) {
1467
- case "Field":
1468
- if (subSelectionNode.name.value === "__typename") {
1469
- return subSelectionNode;
1470
- }
1471
- ensureObjectType(namedSubFieldType);
1472
- const subField1 = getObjectField(namedSubFieldType, subSelectionNode);
1473
- const subType1 = subField1.type;
1474
- const namedSubType2 = G.getNamedType(subType1);
1475
- return formifyField({
1476
- fieldNode: subSelectionNode,
1477
- parentType: subFieldType,
1478
- path: [
1479
- ...path,
1480
- getNameAndAlias(subSelectionNode, isListType(subType1), isNodeField(namedSubType2))
1481
- ]
1482
- });
1483
- case "InlineFragment":
1484
- const subNamedType = G.getNamedType(subField.type);
1485
- ensureNodeField(subNamedType);
1486
- ensureUnionType(subNamedType);
1487
- const subType2 = getSelectedUnionType(subNamedType, subSelectionNode);
1488
- const newPath2 = [
1489
- ...path,
1490
- getNameAndAlias(selectionNode, isListType(subField.type), true)
1491
- ];
1492
- return formifyNode({
1493
- fieldOrInlineFragmentNode: subSelectionNode,
1494
- type: subType2,
1495
- path: newPath2,
1496
- showInSidebar: false
1497
- });
1498
- default:
1499
- throw new FormifyError("UNEXPECTED", `selection ${subSelectionNode.kind}`);
1500
- }
1501
- })
1502
- }
1522
+ case "Field": {
1523
+ return formifyFieldNode({
1524
+ fieldNode: selectionNode,
1525
+ parentType: field.type,
1526
+ path: fieldPath
1503
1527
  });
1504
- case "InlineFragment":
1505
- ensureUnionType(namedType);
1506
- if (isNodeField(namedType)) {
1507
- const parentType2 = getSelectedUnionType(namedType, selectionNode);
1508
- return formifyNode({
1509
- fieldOrInlineFragmentNode: selectionNode,
1510
- type: parentType2,
1511
- path,
1512
- showInSidebar: false
1513
- });
1514
- }
1515
- const subType = getSelectedUnionType(namedType, selectionNode);
1516
- const namedSubType = G.getNamedType(subType);
1517
- return __spreadProps(__spreadValues({}, selectionNode), {
1518
- selectionSet: {
1519
- kind: "SelectionSet",
1520
- selections: selectionNode.selectionSet.selections.map((subSelectionNode) => {
1521
- switch (subSelectionNode.kind) {
1522
- case "Field":
1523
- ensureObjectType(namedSubType);
1524
- const subField2 = getObjectField(namedSubType, subSelectionNode);
1525
- const subType2 = subField2.type;
1526
- const namedSubType2 = G.getNamedType(subType2);
1527
- return formifyField({
1528
- fieldNode: subSelectionNode,
1529
- parentType: subType,
1530
- path: [
1531
- ...path,
1532
- getNameAndAlias(subSelectionNode, isListType(subType2), isNodeField(namedSubType2))
1533
- ]
1534
- });
1535
- default:
1536
- throw new FormifyError("UNEXPECTED", `selection ${subSelectionNode.kind}`);
1537
- }
1538
- })
1539
- }
1528
+ }
1529
+ case "InlineFragment": {
1530
+ return formifyInlineFragmentNode({
1531
+ inlineFragmentNode: selectionNode,
1532
+ parentType: field.type,
1533
+ path: fieldPath
1540
1534
  });
1535
+ }
1541
1536
  default:
1542
1537
  throw new FormifyError("UNEXPECTED", `selection ${selectionNode.kind}`);
1543
1538
  }
@@ -1546,43 +1541,77 @@ const formify = async ({
1546
1541
  }
1547
1542
  });
1548
1543
  };
1544
+ const formifyInlineFragmentNode = ({
1545
+ inlineFragmentNode,
1546
+ parentType,
1547
+ path
1548
+ }) => {
1549
+ const type = getSelectedUnionType(parentType, inlineFragmentNode);
1550
+ if (!type) {
1551
+ return inlineFragmentNode;
1552
+ }
1553
+ if (isFormifiableDocument(type)) {
1554
+ return formifyInlineFragmentDocument({
1555
+ inlineFragmentNode,
1556
+ type,
1557
+ path,
1558
+ showInSidebar: false
1559
+ });
1560
+ }
1561
+ return __spreadProps(__spreadValues({}, inlineFragmentNode), {
1562
+ selectionSet: {
1563
+ kind: "SelectionSet",
1564
+ selections: inlineFragmentNode.selectionSet.selections.map((selectionNode) => {
1565
+ switch (selectionNode.kind) {
1566
+ case "Field":
1567
+ return formifyFieldNode({
1568
+ fieldNode: selectionNode,
1569
+ parentType: type,
1570
+ path
1571
+ });
1572
+ default:
1573
+ throw new FormifyError("UNEXPECTED", `selection ${selectionNode.kind}`);
1574
+ }
1575
+ })
1576
+ }
1577
+ });
1578
+ };
1549
1579
  const formifiedQuery = {
1550
1580
  kind: "Document",
1551
1581
  definitions: optimizedQuery.definitions.map((definition) => {
1552
1582
  typeInfo.enter(definition);
1553
1583
  ensureOperationDefinition(definition);
1554
- const type = typeInfo.getType();
1555
- const namedType = G.getNamedType(type);
1556
- ensureObjectType(namedType);
1584
+ const parentType = typeInfo.getType();
1557
1585
  return __spreadProps(__spreadValues({}, definition), {
1558
1586
  selectionSet: {
1559
1587
  kind: "SelectionSet",
1560
1588
  selections: definition.selectionSet.selections.map((selectionNode) => {
1561
1589
  switch (selectionNode.kind) {
1562
1590
  case "Field":
1563
- const parentType = type;
1564
- const namedParentType = G.getNamedType(parentType);
1565
- ensureObjectType(namedParentType);
1566
- const field = getObjectField(namedParentType, selectionNode);
1567
- const namedFieldType = G.getNamedType(field.type);
1568
- if (isNodeField(namedFieldType)) {
1569
- return formifyNode({
1570
- fieldOrInlineFragmentNode: selectionNode,
1591
+ const field = getObjectField(parentType, selectionNode);
1592
+ const path = buildPath({
1593
+ fieldNode: selectionNode,
1594
+ type: field.type
1595
+ });
1596
+ if (isFormifiableDocument(field.type)) {
1597
+ return formifyFieldNodeDocument({
1598
+ fieldNode: selectionNode,
1571
1599
  type: field.type,
1572
- path: [getNameAndAlias(selectionNode, false, true)],
1600
+ path,
1573
1601
  showInSidebar: true
1574
1602
  });
1575
- } else if (isConnectionField(namedFieldType)) {
1603
+ } else if (isConnectionField(field.type)) {
1576
1604
  return formifyConnection({
1577
- namedFieldType,
1605
+ parentType: field.type,
1578
1606
  selectionNode,
1579
- path: [getNameAndAlias(selectionNode, false, false)]
1607
+ path
1580
1608
  });
1581
1609
  }
1582
1610
  if (selectionNode.name.value === COLLECTION_FIELD_NAME || selectionNode.name.value === COLLECTIONS_FIELD_NAME) {
1583
- const path = [
1584
- getNameAndAlias(selectionNode, false, false)
1585
- ];
1611
+ const path2 = buildPath({
1612
+ fieldNode: selectionNode,
1613
+ type: field.type
1614
+ });
1586
1615
  return __spreadProps(__spreadValues({}, selectionNode), {
1587
1616
  selectionSet: {
1588
1617
  kind: "SelectionSet",
@@ -1590,16 +1619,15 @@ const formify = async ({
1590
1619
  switch (subSelectionNode.kind) {
1591
1620
  case "Field":
1592
1621
  if (subSelectionNode.name.value === COLLECTIONS_DOCUMENTS_NAME) {
1593
- ensureObjectType(namedFieldType);
1594
- const n = namedFieldType.getFields()[COLLECTIONS_DOCUMENTS_NAME];
1595
- const docType = G.getNamedType(n.type);
1622
+ const subField = getObjectField(field.type, subSelectionNode);
1596
1623
  return formifyConnection({
1597
- namedFieldType: docType,
1624
+ parentType: subField.type,
1598
1625
  selectionNode: subSelectionNode,
1599
- path: [
1600
- ...path,
1601
- getNameAndAlias(subSelectionNode, isListType(docType), isNodeField(docType))
1602
- ]
1626
+ path: buildPath({
1627
+ fieldNode: subSelectionNode,
1628
+ type: subField.type,
1629
+ path: path2
1630
+ })
1603
1631
  });
1604
1632
  }
1605
1633
  return subSelectionNode;
@@ -1639,9 +1667,27 @@ class FormifyError extends Error {
1639
1667
  this.name = "FormifyError";
1640
1668
  }
1641
1669
  }
1670
+ const defaultState = {
1671
+ status: "idle",
1672
+ schema: void 0,
1673
+ query: null,
1674
+ queryString: null,
1675
+ data: {},
1676
+ changeSets: [],
1677
+ count: 0,
1678
+ blueprints: [],
1679
+ formNodes: [],
1680
+ documentForms: []
1681
+ };
1642
1682
  function reducer(state, action) {
1643
1683
  var _a, _b, _c, _d;
1644
1684
  switch (action.type) {
1685
+ case "start":
1686
+ return __spreadProps(__spreadValues(__spreadValues({}, state), defaultState), {
1687
+ query: action.value.query ? G.parse(action.value.query) : null,
1688
+ queryString: action.value.query,
1689
+ status: "initialized"
1690
+ });
1645
1691
  case "addDocumentBlueprints":
1646
1692
  return __spreadProps(__spreadValues({}, state), {
1647
1693
  status: "formified",
@@ -1696,16 +1742,21 @@ function reducer(state, action) {
1696
1742
  }
1697
1743
  if (event.mutationType.type === "change") {
1698
1744
  if (!action.value.form) {
1699
- getPathsToChange(event, state).forEach(({ formNode: formNode2, pathToChange }) => {
1745
+ getBlueprintFieldsForEvent(blueprint, event).forEach((fieldBlueprint) => {
1746
+ const { pathToChange } = getFormNodesForField(fieldBlueprint, formNode, event, state);
1700
1747
  changeSets.push(__spreadValues({
1701
1748
  path: pathToChange
1702
- }, buildChangeSet(event, formNode2)));
1749
+ }, buildChangeSet(event, formNode)));
1703
1750
  });
1704
1751
  }
1705
1752
  } else if (event.mutationType.type === "referenceChange") {
1706
1753
  getBlueprintFieldsForEvent(blueprint, event).forEach((fieldBlueprint) => {
1707
- const { pathToChange, formNodes, eventLocation } = getFormNodesForField(fieldBlueprint, formNode, event, state);
1708
- if (action.value.form) {
1754
+ const {
1755
+ pathToChange,
1756
+ formNodes: subFormNodes,
1757
+ eventLocation
1758
+ } = getFormNodesForField(fieldBlueprint, formNode, event, state);
1759
+ if (action.value.form && state.blueprints.find((blueprint2) => blueprint2.id === fieldBlueprint.id)) {
1709
1760
  const newFormNode = {
1710
1761
  documentBlueprintId: fieldBlueprint.id,
1711
1762
  documentFormId: action.value.form.id,
@@ -1716,8 +1767,15 @@ function reducer(state, action) {
1716
1767
  path: pathToChange
1717
1768
  }, buildChangeSet(event, newFormNode)));
1718
1769
  }
1719
- formNodes.forEach((subFormNode) => {
1770
+ subFormNodes.forEach((subFormNode) => {
1720
1771
  if (matchLocation(eventLocation, subFormNode)) {
1772
+ if (!action.value.form) {
1773
+ changeSets.push(__spreadProps(__spreadValues({
1774
+ path: pathToChange
1775
+ }, buildChangeSet(event, subFormNode)), {
1776
+ value: null
1777
+ }));
1778
+ }
1721
1779
  formNodesToReplace.push(subFormNode);
1722
1780
  }
1723
1781
  });
@@ -1870,7 +1928,7 @@ const useFormify = ({
1870
1928
  }) => {
1871
1929
  const formIds = React.useRef([]);
1872
1930
  const [state, dispatch] = React.useReducer(reducer, {
1873
- status: "initialized",
1931
+ status: "idle",
1874
1932
  schema: void 0,
1875
1933
  query: query ? G.parse(query) : null,
1876
1934
  queryString: query,
@@ -1881,6 +1939,17 @@ const useFormify = ({
1881
1939
  formNodes: [],
1882
1940
  documentForms: []
1883
1941
  });
1942
+ React.useEffect(() => {
1943
+ if (query) {
1944
+ dispatch({ type: "start", value: { query } });
1945
+ formIds.current.forEach((formId) => {
1946
+ const form = cms.forms.find(formId);
1947
+ if (form) {
1948
+ cms.plugins.remove(form);
1949
+ }
1950
+ });
1951
+ }
1952
+ }, [query, JSON.stringify(variables)]);
1884
1953
  React.useEffect(() => {
1885
1954
  if (state.status === "initialized") {
1886
1955
  cms.api.tina.request(query, { variables }).then((res) => {
@@ -1912,7 +1981,7 @@ const useFormify = ({
1912
1981
  variables
1913
1982
  });
1914
1983
  state.blueprints.map((blueprint) => {
1915
- const responseAtBlueprint = getIn2(result, getBlueprintAliasPath(blueprint));
1984
+ const responseAtBlueprint = getValueForBlueprint(result, getBlueprintAliasPath(blueprint));
1916
1985
  const location = [];
1917
1986
  const findFormNodes = (res, location2) => {
1918
1987
  if (Array.isArray(res)) {
@@ -1961,6 +2030,9 @@ const useFormify = ({
1961
2030
  React.useEffect(() => {
1962
2031
  if (state.status === "ready") {
1963
2032
  cms.events.subscribe(`forms:reset`, (event) => {
2033
+ if (eventList) {
2034
+ eventList.push(printEvent(event));
2035
+ }
1964
2036
  dispatch({ type: "formOnReset", value: { event } });
1965
2037
  });
1966
2038
  cms.events.subscribe(`forms:fields:onChange`, async (event) => {
@@ -1982,6 +2054,9 @@ const useFormify = ({
1982
2054
  values
1983
2055
  _internalSys: sys {
1984
2056
  path
2057
+ collection {
2058
+ name
2059
+ }
1985
2060
  }
1986
2061
  }
1987
2062
  }
@@ -2012,7 +2087,8 @@ const useFormify = ({
2012
2087
  const form = cms.forms.find(changeSet.formId);
2013
2088
  resolveSubFields({
2014
2089
  formNode: changeSet.formNode,
2015
- form
2090
+ form,
2091
+ loc: []
2016
2092
  }).then((res) => {
2017
2093
  dispatch({
2018
2094
  type: "setIn",
@@ -2121,22 +2197,15 @@ const useFormify = ({
2121
2197
  const data = {};
2122
2198
  await sequential(form.fields, async (field) => {
2123
2199
  const value = form.values[field.name];
2124
- const fieldName = field.list ? `${field.name}.[]` : field.name;
2125
2200
  const blueprint = getFormNodeBlueprint(formNode, state);
2126
- const blueprintName = getBlueprintNamePath(blueprint);
2127
- const extra = [];
2128
- if (prefix) {
2129
- extra.push(prefix);
2130
- }
2131
- const matchName = [
2132
- blueprintName,
2133
- DATA_NODE_NAME,
2134
- ...extra,
2135
- fieldName
2136
- ].join(".");
2201
+ const { matchName, fieldName } = getMatchName({
2202
+ field,
2203
+ prefix,
2204
+ blueprint
2205
+ });
2137
2206
  const fieldBlueprints = blueprint.fields.filter((fieldBlueprint) => {
2138
2207
  return matchName === getBlueprintNamePath(fieldBlueprint);
2139
- });
2208
+ }).filter((fbp) => filterFieldBlueprintsByParentTypename(fbp, field.parentTypename));
2140
2209
  switch (field.type) {
2141
2210
  case "object":
2142
2211
  if (field.templates) {
@@ -2150,18 +2219,17 @@ const useFormify = ({
2150
2219
  if (!Array.isArray(value)) {
2151
2220
  throw new Error(`Expected value for object list field to be an array`);
2152
2221
  }
2153
- const d = [];
2154
- await sequential(value, async (item, index) => {
2222
+ data[keyName] = await sequential(value, async (item, index) => {
2155
2223
  const template = field.templates[item._template];
2156
- const d2 = await resolveSubFields({
2224
+ return __spreadProps(__spreadValues({}, await resolveSubFields({
2157
2225
  formNode,
2158
2226
  form: { fields: template.fields, values: item },
2159
- prefix: [prefix, fieldName].join("."),
2227
+ prefix: prefix ? [prefix, fieldName].join(".") : fieldName,
2160
2228
  loc: [...loc, index]
2229
+ })), {
2230
+ __typename: field.typeMap[item._template]
2161
2231
  });
2162
- d.push(d2);
2163
2232
  });
2164
- data[keyName] = d;
2165
2233
  });
2166
2234
  } else {
2167
2235
  throw new Error("blocks without list true is not yet supported");
@@ -2177,18 +2245,14 @@ const useFormify = ({
2177
2245
  if (!Array.isArray(value)) {
2178
2246
  throw new Error(`Expected value for object list field to be an array`);
2179
2247
  }
2180
- const d = [];
2181
- await sequential(value, async (item, index) => {
2182
- const d2 = await resolveSubFields({
2248
+ data[keyName] = await sequential(value, async (item, index) => {
2249
+ return resolveSubFields({
2183
2250
  formNode,
2184
2251
  form: { fields: field.fields, values: item },
2185
2252
  prefix: [prefix, fieldName].join("."),
2186
2253
  loc: [...loc, index]
2187
2254
  });
2188
- d.push(d2);
2189
- return true;
2190
2255
  });
2191
- data[keyName] = d;
2192
2256
  return true;
2193
2257
  });
2194
2258
  } else {
@@ -2198,13 +2262,12 @@ const useFormify = ({
2198
2262
  data[keyName] = null;
2199
2263
  return true;
2200
2264
  }
2201
- const d = await resolveSubFields({
2265
+ data[keyName] = await resolveSubFields({
2202
2266
  formNode,
2203
2267
  form: { fields: field.fields, values: value },
2204
2268
  prefix: [prefix, fieldName].join("."),
2205
2269
  loc
2206
2270
  });
2207
- data[keyName] = d;
2208
2271
  return true;
2209
2272
  });
2210
2273
  }
@@ -2225,6 +2288,9 @@ const useFormify = ({
2225
2288
  values
2226
2289
  _internalSys: sys {
2227
2290
  path
2291
+ collection {
2292
+ name
2293
+ }
2228
2294
  }
2229
2295
  }
2230
2296
  }
@@ -2259,12 +2325,13 @@ const useFormify = ({
2259
2325
  }
2260
2326
  }
2261
2327
  `, { variables: { id: value } });
2262
- const d = await resolveSubFields({
2263
- formNode: subDocumentFormNode,
2264
- form: form2,
2265
- loc: location
2328
+ data[keyName] = __spreadProps(__spreadValues({}, res.node), {
2329
+ data: await resolveSubFields({
2330
+ formNode: subDocumentFormNode,
2331
+ form: form2,
2332
+ loc: location
2333
+ })
2266
2334
  });
2267
- data[keyName] = __spreadProps(__spreadValues({}, res.node), { data: d });
2268
2335
  });
2269
2336
  break;
2270
2337
  default:
@@ -2332,13 +2399,13 @@ mutation addPendingDocumentMutation(
2332
2399
  return result;
2333
2400
  };
2334
2401
  this.getSchema = async () => {
2335
- if (!this.schema) {
2402
+ if (!this.gqlSchema) {
2336
2403
  const data = await this.request(getIntrospectionQuery(), {
2337
2404
  variables: {}
2338
2405
  });
2339
- this.schema = buildClientSchema(data);
2406
+ this.gqlSchema = buildClientSchema(data);
2340
2407
  }
2341
- return this.schema;
2408
+ return this.gqlSchema;
2342
2409
  };
2343
2410
  this.getOptimizedQuery = async (documentNode) => {
2344
2411
  const data = await this.request(`query GetOptimizedQuery($queryString: String!) {
@@ -2348,6 +2415,13 @@ mutation addPendingDocumentMutation(
2348
2415
  });
2349
2416
  return parse(data.getOptimizedQuery);
2350
2417
  };
2418
+ if (options.schema) {
2419
+ const enrichedSchema = new TinaSchema(__spreadValues({
2420
+ version: { fullVersion: "", major: "", minor: "", patch: "" },
2421
+ meta: { flags: [] }
2422
+ }, addNamespaceToSchema(options.schema, [])));
2423
+ this.schema = enrichedSchema;
2424
+ }
2351
2425
  this.options = options;
2352
2426
  this.setBranch(options.branch);
2353
2427
  this.events.subscribe("branch:change", ({ branchName }) => {
@@ -2557,11 +2631,11 @@ mutation addPendingDocumentMutation(
2557
2631
  const DEFAULT_LOCAL_TINA_GQL_SERVER_URL = "http://localhost:4001/graphql";
2558
2632
  class LocalClient extends Client {
2559
2633
  constructor(props) {
2560
- const clientProps = {
2634
+ const clientProps = __spreadProps(__spreadValues({}, props), {
2561
2635
  clientId: "",
2562
2636
  branch: "",
2563
2637
  customContentApiUrl: props && props.customContentApiUrl ? props.customContentApiUrl : DEFAULT_LOCAL_TINA_GQL_SERVER_URL
2564
- };
2638
+ });
2565
2639
  super(clientProps);
2566
2640
  }
2567
2641
  async isAuthorized() {
@@ -2632,6 +2706,17 @@ class TinaAdminApi {
2632
2706
  }`, { variables: {} });
2633
2707
  return response;
2634
2708
  }
2709
+ async deleteDocument({
2710
+ collection,
2711
+ relativePath
2712
+ }) {
2713
+ await this.api.request(`#graphql
2714
+ mutation DeleteDocument($collection: String!, $relativePath: String! ){
2715
+ deleteDocument(collection: $collection, relativePath: $relativePath){
2716
+ __typename
2717
+ }
2718
+ }`, { variables: { collection, relativePath } });
2719
+ }
2635
2720
  async fetchCollection(collectionName, includeDocuments) {
2636
2721
  const response = await this.api.request(`#graphql
2637
2722
  query($collection: String!, $includeDocuments: Boolean!){
@@ -2856,6 +2941,7 @@ const TinaCloudProvider = (props) => {
2856
2941
  }))));
2857
2942
  };
2858
2943
  const TinaCloudAuthWall = TinaCloudProvider;
2944
+ var styles = '*, ::before, ::after {\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-rotate: 0;\n --tw-skew-x: 0;\n --tw-skew-y: 0;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-pan-x: ;\n --tw-pan-y: ;\n --tw-pinch-zoom: ;\n --tw-scroll-snap-strictness: proximity;\n --tw-ordinal: ;\n --tw-slashed-zero: ;\n --tw-numeric-figure: ;\n --tw-numeric-spacing: ;\n --tw-numeric-fraction: ;\n --tw-ring-inset: ;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-color: rgb(0 132 255 / 0.5);\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-ring-shadow: 0 0 #0000;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-colored: 0 0 #0000;\n --tw-blur: ;\n --tw-brightness: ;\n --tw-contrast: ;\n --tw-grayscale: ;\n --tw-hue-rotate: ;\n --tw-invert: ;\n --tw-saturate: ;\n --tw-sepia: ;\n --tw-drop-shadow: ;\n --tw-backdrop-blur: ;\n --tw-backdrop-brightness: ;\n --tw-backdrop-contrast: ;\n --tw-backdrop-grayscale: ;\n --tw-backdrop-hue-rotate: ;\n --tw-backdrop-invert: ;\n --tw-backdrop-opacity: ;\n --tw-backdrop-saturate: ;\n --tw-backdrop-sepia: ;\n}\n.tina-tailwind .static {\n position: static;\n}\n.tina-tailwind .fixed {\n position: fixed;\n}\n.tina-tailwind .absolute {\n position: absolute;\n}\n.tina-tailwind .relative {\n position: relative;\n}\n.tina-tailwind .left-0 {\n left: 0px;\n}\n.tina-tailwind .right-0 {\n right: 0px;\n}\n.tina-tailwind .mx-auto {\n margin-left: auto;\n margin-right: auto;\n}\n.tina-tailwind .mr-2 {\n margin-right: 8px;\n}\n.tina-tailwind .mb-2 {\n margin-bottom: 8px;\n}\n.tina-tailwind .mb-1 {\n margin-bottom: 4px;\n}\n.tina-tailwind .-mt-0\\.5 {\n margin-top: -2px;\n}\n.tina-tailwind .-mt-0 {\n margin-top: -0px;\n}\n.tina-tailwind .ml-1 {\n margin-left: 4px;\n}\n.tina-tailwind .mt-2 {\n margin-top: 8px;\n}\n.tina-tailwind .mr-1\\.5 {\n margin-right: 6px;\n}\n.tina-tailwind .mr-1 {\n margin-right: 4px;\n}\n.tina-tailwind .block {\n display: block;\n}\n.tina-tailwind .inline-block {\n display: inline-block;\n}\n.tina-tailwind .inline {\n display: inline;\n}\n.tina-tailwind .flex {\n display: flex;\n}\n.tina-tailwind .inline-flex {\n display: inline-flex;\n}\n.tina-tailwind .table {\n display: table;\n}\n.tina-tailwind .h-screen {\n height: 100vh;\n}\n.tina-tailwind .h-auto {\n height: auto;\n}\n.tina-tailwind .h-full {\n height: 100%;\n}\n.tina-tailwind .h-6 {\n height: 24px;\n}\n.tina-tailwind .h-10 {\n height: 40px;\n}\n.tina-tailwind .h-5 {\n height: 20px;\n}\n.tina-tailwind .h-12 {\n height: 48px;\n}\n.tina-tailwind .w-full {\n width: 100%;\n}\n.tina-tailwind .w-10 {\n width: 40px;\n}\n.tina-tailwind .w-auto {\n width: auto;\n}\n.tina-tailwind .w-5 {\n width: 20px;\n}\n.tina-tailwind .w-56 {\n width: 224px;\n}\n.tina-tailwind .w-0 {\n width: 0px;\n}\n.tina-tailwind .w-6 {\n width: 24px;\n}\n.tina-tailwind .max-w-lg {\n max-width: 32rem;\n}\n.tina-tailwind .max-w-screen-xl {\n max-width: 1280px;\n}\n.tina-tailwind .max-w-form {\n max-width: 900px;\n}\n.tina-tailwind .max-w-full {\n max-width: 100%;\n}\n.tina-tailwind .flex-1 {\n flex: 1 1 0%;\n}\n.tina-tailwind .flex-shrink-0 {\n flex-shrink: 0;\n}\n.tina-tailwind .flex-grow-0 {\n flex-grow: 0;\n}\n.tina-tailwind .table-auto {\n table-layout: auto;\n}\n.tina-tailwind .origin-top-right {\n transform-origin: top right;\n}\n.tina-tailwind .scale-95 {\n --tw-scale-x: .95;\n --tw-scale-y: .95;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.tina-tailwind .scale-100 {\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.tina-tailwind .transform {\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.tina-tailwind .cursor-pointer {\n cursor: pointer;\n}\n.tina-tailwind .flex-col {\n flex-direction: column;\n}\n.tina-tailwind .items-end {\n align-items: flex-end;\n}\n.tina-tailwind .items-center {\n align-items: center;\n}\n.tina-tailwind .items-stretch {\n align-items: stretch;\n}\n.tina-tailwind .justify-end {\n justify-content: flex-end;\n}\n.tina-tailwind .justify-center {\n justify-content: center;\n}\n.tina-tailwind .justify-between {\n justify-content: space-between;\n}\n.tina-tailwind .gap-0\\.5 {\n gap: 2px;\n}\n.tina-tailwind .gap-0 {\n gap: 0px;\n}\n.tina-tailwind .gap-4 {\n gap: 16px;\n}\n.tina-tailwind .gap-3 {\n gap: 12px;\n}\n.tina-tailwind .divide-y > :not([hidden]) ~ :not([hidden]) {\n --tw-divide-y-reverse: 0;\n border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));\n border-bottom-width: calc(1px * var(--tw-divide-y-reverse));\n}\n.tina-tailwind .divide-gray-150 > :not([hidden]) ~ :not([hidden]) {\n --tw-divide-opacity: 1;\n border-color: rgb(230 227 239 / var(--tw-divide-opacity));\n}\n.tina-tailwind .overflow-hidden {\n overflow: hidden;\n}\n.tina-tailwind .overflow-y-auto {\n overflow-y: auto;\n}\n.tina-tailwind .whitespace-nowrap {\n white-space: nowrap;\n}\n.tina-tailwind .rounded-lg {\n border-radius: 8px;\n}\n.tina-tailwind .rounded-full {\n border-radius: 9999px;\n}\n.tina-tailwind .rounded-md {\n border-radius: 6px;\n}\n.tina-tailwind .border {\n border-width: 1px;\n}\n.tina-tailwind .border-b {\n border-bottom-width: 1px;\n}\n.tina-tailwind .border-gray-150 {\n --tw-border-opacity: 1;\n border-color: rgb(230 227 239 / var(--tw-border-opacity));\n}\n.tina-tailwind .border-gray-200 {\n --tw-border-opacity: 1;\n border-color: rgb(225 221 236 / var(--tw-border-opacity));\n}\n.tina-tailwind .bg-white {\n --tw-bg-opacity: 1;\n background-color: rgb(255 255 255 / var(--tw-bg-opacity));\n}\n.tina-tailwind .bg-gray-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(246 246 249 / var(--tw-bg-opacity));\n}\n.tina-tailwind .bg-blue-500 {\n --tw-bg-opacity: 1;\n background-color: rgb(0 132 255 / var(--tw-bg-opacity));\n}\n.tina-tailwind .bg-gradient-to-b {\n background-image: linear-gradient(to bottom, var(--tw-gradient-stops));\n}\n.tina-tailwind .from-blue-900 {\n --tw-gradient-from: #1D2C6C;\n --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to, rgb(29 44 108 / 0));\n}\n.tina-tailwind .to-gray-900 {\n --tw-gradient-to: #252336;\n}\n.tina-tailwind .px-4 {\n padding-left: 16px;\n padding-right: 16px;\n}\n.tina-tailwind .py-6 {\n padding-top: 24px;\n padding-bottom: 24px;\n}\n.tina-tailwind .px-5 {\n padding-left: 20px;\n padding-right: 20px;\n}\n.tina-tailwind .py-4 {\n padding-top: 16px;\n padding-bottom: 16px;\n}\n.tina-tailwind .px-12 {\n padding-left: 48px;\n padding-right: 48px;\n}\n.tina-tailwind .py-10 {\n padding-top: 40px;\n padding-bottom: 40px;\n}\n.tina-tailwind .px-20 {\n padding-left: 80px;\n padding-right: 80px;\n}\n.tina-tailwind .px-6 {\n padding-left: 24px;\n padding-right: 24px;\n}\n.tina-tailwind .py-1 {\n padding-top: 4px;\n padding-bottom: 4px;\n}\n.tina-tailwind .py-2 {\n padding-top: 8px;\n padding-bottom: 8px;\n}\n.tina-tailwind .pt-4 {\n padding-top: 16px;\n}\n.tina-tailwind .pb-4 {\n padding-bottom: 16px;\n}\n.tina-tailwind .pt-18 {\n padding-top: 72px;\n}\n.tina-tailwind .text-left {\n text-align: left;\n}\n.tina-tailwind .text-center {\n text-align: center;\n}\n.tina-tailwind .font-sans {\n font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";\n}\n.tina-tailwind .text-2xl {\n font-size: 24px;\n line-height: 1.33;\n}\n.tina-tailwind .text-base {\n font-size: 16px;\n line-height: 1.5;\n}\n.tina-tailwind .text-sm {\n font-size: 14px;\n line-height: 1.43;\n}\n.tina-tailwind .text-xl {\n font-size: 20px;\n line-height: 1.4;\n}\n.tina-tailwind .text-md {\n font-size: 16px;\n line-height: 1.5;\n}\n.tina-tailwind .text-xs {\n font-size: 13px;\n line-height: 1.33;\n}\n.tina-tailwind .font-medium {\n font-weight: 500;\n}\n.tina-tailwind .uppercase {\n text-transform: uppercase;\n}\n.tina-tailwind .italic {\n font-style: italic;\n}\n.tina-tailwind .leading-normal {\n line-height: 1.5;\n}\n.tina-tailwind .leading-tight {\n line-height: 1.25;\n}\n.tina-tailwind .leading-5 {\n line-height: 20px;\n}\n.tina-tailwind .tracking-wide {\n letter-spacing: 0.025em;\n}\n.tina-tailwind .text-gray-600 {\n --tw-text-opacity: 1;\n color: rgb(86 81 101 / var(--tw-text-opacity));\n}\n.tina-tailwind .text-gray-700 {\n --tw-text-opacity: 1;\n color: rgb(67 62 82 / var(--tw-text-opacity));\n}\n.tina-tailwind .text-blue-600 {\n --tw-text-opacity: 1;\n color: rgb(5 116 228 / var(--tw-text-opacity));\n}\n.tina-tailwind .text-gray-500 {\n --tw-text-opacity: 1;\n color: rgb(113 108 127 / var(--tw-text-opacity));\n}\n.tina-tailwind .text-gray-400 {\n --tw-text-opacity: 1;\n color: rgb(145 140 158 / var(--tw-text-opacity));\n}\n.tina-tailwind .text-current {\n color: currentColor;\n}\n.tina-tailwind .text-white {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity));\n}\n.tina-tailwind .text-gray-800 {\n --tw-text-opacity: 1;\n color: rgb(54 49 69 / var(--tw-text-opacity));\n}\n.tina-tailwind .text-gray-900 {\n --tw-text-opacity: 1;\n color: rgb(37 35 54 / var(--tw-text-opacity));\n}\n.tina-tailwind .text-red-500 {\n --tw-text-opacity: 1;\n color: rgb(239 68 68 / var(--tw-text-opacity));\n}\n.tina-tailwind .underline {\n text-decoration-line: underline;\n}\n.tina-tailwind .opacity-100 {\n opacity: 1;\n}\n.tina-tailwind .opacity-90 {\n opacity: .9;\n}\n.tina-tailwind .opacity-80 {\n opacity: .8;\n}\n.tina-tailwind .opacity-50 {\n opacity: .5;\n}\n.tina-tailwind .opacity-70 {\n opacity: .7;\n}\n.tina-tailwind .opacity-0 {\n opacity: 0;\n}\n.tina-tailwind .shadow-lg {\n --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.tina-tailwind .shadow-2xl {\n --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);\n --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.tina-tailwind .shadow {\n --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.tina-tailwind .ring-1 {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);\n}\n.tina-tailwind .ring-black {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity));\n}\n.tina-tailwind .ring-opacity-5 {\n --tw-ring-opacity: .05;\n}\n.tina-tailwind .filter {\n filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);\n}\n.tina-tailwind .transition-opacity {\n transition-property: opacity;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.tina-tailwind .transition-colors {\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.tina-tailwind .transition-all {\n transition-property: all;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.tina-tailwind .transition {\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.tina-tailwind .duration-300 {\n transition-duration: 300ms;\n}\n.tina-tailwind .duration-150 {\n transition-duration: 150ms;\n}\n.tina-tailwind .duration-100 {\n transition-duration: 100ms;\n}\n.tina-tailwind .duration-75 {\n transition-duration: 75ms;\n}\n.tina-tailwind .ease-out {\n transition-timing-function: cubic-bezier(0, 0, 0.2, 1);\n}\n.tina-tailwind .ease-in {\n transition-timing-function: cubic-bezier(0.4, 0, 1, 1);\n}\n.tina-tailwind .icon-parent svg {\n fill: currentColor;\n }\n\n.tina-tailwind {\n font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";\n font-size: 16px;\n line-height: 1.5;\n --tw-text-opacity: 1;\n color: rgb(86 81 101 / var(--tw-text-opacity));\n}\n\n.tina-tailwind .hover\\:bg-blue-600:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(5 116 228 / var(--tw-bg-opacity));\n}\n\n.tina-tailwind .hover\\:text-blue-600:hover {\n --tw-text-opacity: 1;\n color: rgb(5 116 228 / var(--tw-text-opacity));\n}\n\n.tina-tailwind .hover\\:text-blue-400:hover {\n --tw-text-opacity: 1;\n color: rgb(34 150 254 / var(--tw-text-opacity));\n}\n\n.tina-tailwind .hover\\:opacity-100:hover {\n opacity: 1;\n}\n\n.tina-tailwind .focus\\:text-blue-400:focus {\n --tw-text-opacity: 1;\n color: rgb(34 150 254 / var(--tw-text-opacity));\n}\n\n.tina-tailwind .focus\\:underline:focus {\n text-decoration-line: underline;\n}\n\n.tina-tailwind .focus\\:shadow-outline:focus {\n --tw-shadow: 0 0 0 3px rgba(66, 153, 225, 0.5);\n --tw-shadow-colored: 0 0 0 3px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n\n.tina-tailwind .focus\\:outline-none:focus {\n outline: 2px solid transparent;\n outline-offset: 2px;\n}\n\n.tina-tailwind .focus\\:ring-2:focus {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);\n}\n\n.tina-tailwind .focus\\:ring-blue-500:focus {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(0 132 255 / var(--tw-ring-opacity));\n}\n';
2859
2945
  class ContentCreatorPlugin {
2860
2946
  constructor(options) {
2861
2947
  this.__type = "content-creator";
@@ -3018,7 +3104,6 @@ const useDocumentCreatorPlugin = (args) => {
3018
3104
  };
3019
3105
  }, [plugin]);
3020
3106
  };
3021
- var styles = '*, ::before, ::after {\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-rotate: 0;\n --tw-skew-x: 0;\n --tw-skew-y: 0;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-pan-x: ;\n --tw-pan-y: ;\n --tw-pinch-zoom: ;\n --tw-scroll-snap-strictness: proximity;\n --tw-ordinal: ;\n --tw-slashed-zero: ;\n --tw-numeric-figure: ;\n --tw-numeric-spacing: ;\n --tw-numeric-fraction: ;\n --tw-ring-inset: ;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-color: rgb(0 132 255 / 0.5);\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-ring-shadow: 0 0 #0000;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-colored: 0 0 #0000;\n --tw-blur: ;\n --tw-brightness: ;\n --tw-contrast: ;\n --tw-grayscale: ;\n --tw-hue-rotate: ;\n --tw-invert: ;\n --tw-saturate: ;\n --tw-sepia: ;\n --tw-drop-shadow: ;\n --tw-backdrop-blur: ;\n --tw-backdrop-brightness: ;\n --tw-backdrop-contrast: ;\n --tw-backdrop-grayscale: ;\n --tw-backdrop-hue-rotate: ;\n --tw-backdrop-invert: ;\n --tw-backdrop-opacity: ;\n --tw-backdrop-saturate: ;\n --tw-backdrop-sepia: ;\n}\n.tina-tailwind .static {\n position: static;\n}\n.tina-tailwind .fixed {\n position: fixed;\n}\n.tina-tailwind .absolute {\n position: absolute;\n}\n.tina-tailwind .relative {\n position: relative;\n}\n.tina-tailwind .left-0 {\n left: 0px;\n}\n.tina-tailwind .right-0 {\n right: 0px;\n}\n.tina-tailwind .mx-auto {\n margin-left: auto;\n margin-right: auto;\n}\n.tina-tailwind .mr-2 {\n margin-right: 8px;\n}\n.tina-tailwind .mb-2 {\n margin-bottom: 8px;\n}\n.tina-tailwind .mb-1 {\n margin-bottom: 4px;\n}\n.tina-tailwind .-mt-0\\.5 {\n margin-top: -2px;\n}\n.tina-tailwind .-mt-0 {\n margin-top: -0px;\n}\n.tina-tailwind .ml-1 {\n margin-left: 4px;\n}\n.tina-tailwind .mt-2 {\n margin-top: 8px;\n}\n.tina-tailwind .mr-1\\.5 {\n margin-right: 6px;\n}\n.tina-tailwind .mr-1 {\n margin-right: 4px;\n}\n.tina-tailwind .block {\n display: block;\n}\n.tina-tailwind .inline-block {\n display: inline-block;\n}\n.tina-tailwind .inline {\n display: inline;\n}\n.tina-tailwind .flex {\n display: flex;\n}\n.tina-tailwind .inline-flex {\n display: inline-flex;\n}\n.tina-tailwind .table {\n display: table;\n}\n.tina-tailwind .h-screen {\n height: 100vh;\n}\n.tina-tailwind .h-auto {\n height: auto;\n}\n.tina-tailwind .h-full {\n height: 100%;\n}\n.tina-tailwind .h-6 {\n height: 24px;\n}\n.tina-tailwind .h-10 {\n height: 40px;\n}\n.tina-tailwind .h-5 {\n height: 20px;\n}\n.tina-tailwind .h-12 {\n height: 48px;\n}\n.tina-tailwind .w-full {\n width: 100%;\n}\n.tina-tailwind .w-10 {\n width: 40px;\n}\n.tina-tailwind .w-auto {\n width: auto;\n}\n.tina-tailwind .w-5 {\n width: 20px;\n}\n.tina-tailwind .w-56 {\n width: 224px;\n}\n.tina-tailwind .w-6 {\n width: 24px;\n}\n.tina-tailwind .max-w-lg {\n max-width: 32rem;\n}\n.tina-tailwind .max-w-screen-xl {\n max-width: 1280px;\n}\n.tina-tailwind .max-w-form {\n max-width: 900px;\n}\n.tina-tailwind .max-w-full {\n max-width: 100%;\n}\n.tina-tailwind .flex-1 {\n flex: 1 1 0%;\n}\n.tina-tailwind .flex-shrink-0 {\n flex-shrink: 0;\n}\n.tina-tailwind .flex-grow-0 {\n flex-grow: 0;\n}\n.tina-tailwind .table-auto {\n table-layout: auto;\n}\n.tina-tailwind .origin-top-right {\n transform-origin: top right;\n}\n.tina-tailwind .scale-95 {\n --tw-scale-x: .95;\n --tw-scale-y: .95;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.tina-tailwind .scale-100 {\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.tina-tailwind .transform {\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.tina-tailwind .cursor-pointer {\n cursor: pointer;\n}\n.tina-tailwind .flex-col {\n flex-direction: column;\n}\n.tina-tailwind .items-end {\n align-items: flex-end;\n}\n.tina-tailwind .items-center {\n align-items: center;\n}\n.tina-tailwind .items-stretch {\n align-items: stretch;\n}\n.tina-tailwind .justify-end {\n justify-content: flex-end;\n}\n.tina-tailwind .justify-center {\n justify-content: center;\n}\n.tina-tailwind .justify-between {\n justify-content: space-between;\n}\n.tina-tailwind .gap-0\\.5 {\n gap: 2px;\n}\n.tina-tailwind .gap-0 {\n gap: 0px;\n}\n.tina-tailwind .gap-4 {\n gap: 16px;\n}\n.tina-tailwind .gap-3 {\n gap: 12px;\n}\n.tina-tailwind .divide-y > :not([hidden]) ~ :not([hidden]) {\n --tw-divide-y-reverse: 0;\n border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));\n border-bottom-width: calc(1px * var(--tw-divide-y-reverse));\n}\n.tina-tailwind .divide-gray-150 > :not([hidden]) ~ :not([hidden]) {\n --tw-divide-opacity: 1;\n border-color: rgb(230 227 239 / var(--tw-divide-opacity));\n}\n.tina-tailwind .overflow-hidden {\n overflow: hidden;\n}\n.tina-tailwind .overflow-y-auto {\n overflow-y: auto;\n}\n.tina-tailwind .whitespace-nowrap {\n white-space: nowrap;\n}\n.tina-tailwind .rounded-lg {\n border-radius: 8px;\n}\n.tina-tailwind .rounded-full {\n border-radius: 9999px;\n}\n.tina-tailwind .rounded-md {\n border-radius: 6px;\n}\n.tina-tailwind .border {\n border-width: 1px;\n}\n.tina-tailwind .border-b {\n border-bottom-width: 1px;\n}\n.tina-tailwind .border-gray-150 {\n --tw-border-opacity: 1;\n border-color: rgb(230 227 239 / var(--tw-border-opacity));\n}\n.tina-tailwind .border-gray-200 {\n --tw-border-opacity: 1;\n border-color: rgb(225 221 236 / var(--tw-border-opacity));\n}\n.tina-tailwind .bg-white {\n --tw-bg-opacity: 1;\n background-color: rgb(255 255 255 / var(--tw-bg-opacity));\n}\n.tina-tailwind .bg-gray-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(246 246 249 / var(--tw-bg-opacity));\n}\n.tina-tailwind .bg-blue-500 {\n --tw-bg-opacity: 1;\n background-color: rgb(0 132 255 / var(--tw-bg-opacity));\n}\n.tina-tailwind .bg-gradient-to-b {\n background-image: linear-gradient(to bottom, var(--tw-gradient-stops));\n}\n.tina-tailwind .from-blue-900 {\n --tw-gradient-from: #1D2C6C;\n --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to, rgb(29 44 108 / 0));\n}\n.tina-tailwind .to-gray-900 {\n --tw-gradient-to: #252336;\n}\n.tina-tailwind .px-4 {\n padding-left: 16px;\n padding-right: 16px;\n}\n.tina-tailwind .py-6 {\n padding-top: 24px;\n padding-bottom: 24px;\n}\n.tina-tailwind .px-5 {\n padding-left: 20px;\n padding-right: 20px;\n}\n.tina-tailwind .py-4 {\n padding-top: 16px;\n padding-bottom: 16px;\n}\n.tina-tailwind .px-12 {\n padding-left: 48px;\n padding-right: 48px;\n}\n.tina-tailwind .py-10 {\n padding-top: 40px;\n padding-bottom: 40px;\n}\n.tina-tailwind .px-20 {\n padding-left: 80px;\n padding-right: 80px;\n}\n.tina-tailwind .px-6 {\n padding-left: 24px;\n padding-right: 24px;\n}\n.tina-tailwind .py-1 {\n padding-top: 4px;\n padding-bottom: 4px;\n}\n.tina-tailwind .py-2 {\n padding-top: 8px;\n padding-bottom: 8px;\n}\n.tina-tailwind .pt-4 {\n padding-top: 16px;\n}\n.tina-tailwind .pb-4 {\n padding-bottom: 16px;\n}\n.tina-tailwind .pt-18 {\n padding-top: 72px;\n}\n.tina-tailwind .text-left {\n text-align: left;\n}\n.tina-tailwind .text-center {\n text-align: center;\n}\n.tina-tailwind .font-sans {\n font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";\n}\n.tina-tailwind .text-2xl {\n font-size: 24px;\n line-height: 1.33;\n}\n.tina-tailwind .text-base {\n font-size: 16px;\n line-height: 1.5;\n}\n.tina-tailwind .text-sm {\n font-size: 14px;\n line-height: 1.43;\n}\n.tina-tailwind .text-xl {\n font-size: 20px;\n line-height: 1.4;\n}\n.tina-tailwind .text-md {\n font-size: 16px;\n line-height: 1.5;\n}\n.tina-tailwind .text-xs {\n font-size: 13px;\n line-height: 1.33;\n}\n.tina-tailwind .font-medium {\n font-weight: 500;\n}\n.tina-tailwind .uppercase {\n text-transform: uppercase;\n}\n.tina-tailwind .italic {\n font-style: italic;\n}\n.tina-tailwind .leading-normal {\n line-height: 1.5;\n}\n.tina-tailwind .leading-tight {\n line-height: 1.25;\n}\n.tina-tailwind .leading-5 {\n line-height: 20px;\n}\n.tina-tailwind .tracking-wide {\n letter-spacing: 0.025em;\n}\n.tina-tailwind .text-gray-700 {\n --tw-text-opacity: 1;\n color: rgb(67 62 82 / var(--tw-text-opacity));\n}\n.tina-tailwind .text-blue-600 {\n --tw-text-opacity: 1;\n color: rgb(5 116 228 / var(--tw-text-opacity));\n}\n.tina-tailwind .text-gray-500 {\n --tw-text-opacity: 1;\n color: rgb(113 108 127 / var(--tw-text-opacity));\n}\n.tina-tailwind .text-gray-400 {\n --tw-text-opacity: 1;\n color: rgb(145 140 158 / var(--tw-text-opacity));\n}\n.tina-tailwind .text-current {\n color: currentColor;\n}\n.tina-tailwind .text-white {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity));\n}\n.tina-tailwind .text-gray-600 {\n --tw-text-opacity: 1;\n color: rgb(86 81 101 / var(--tw-text-opacity));\n}\n.tina-tailwind .text-gray-800 {\n --tw-text-opacity: 1;\n color: rgb(54 49 69 / var(--tw-text-opacity));\n}\n.tina-tailwind .text-gray-900 {\n --tw-text-opacity: 1;\n color: rgb(37 35 54 / var(--tw-text-opacity));\n}\n.tina-tailwind .underline {\n text-decoration-line: underline;\n}\n.tina-tailwind .opacity-100 {\n opacity: 1;\n}\n.tina-tailwind .opacity-90 {\n opacity: .9;\n}\n.tina-tailwind .opacity-80 {\n opacity: .8;\n}\n.tina-tailwind .opacity-50 {\n opacity: .5;\n}\n.tina-tailwind .opacity-70 {\n opacity: .7;\n}\n.tina-tailwind .opacity-0 {\n opacity: 0;\n}\n.tina-tailwind .shadow-lg {\n --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.tina-tailwind .shadow-2xl {\n --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);\n --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.tina-tailwind .shadow {\n --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.tina-tailwind .ring-1 {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);\n}\n.tina-tailwind .ring-black {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity));\n}\n.tina-tailwind .ring-opacity-5 {\n --tw-ring-opacity: .05;\n}\n.tina-tailwind .filter {\n filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);\n}\n.tina-tailwind .transition-opacity {\n transition-property: opacity;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.tina-tailwind .transition-colors {\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.tina-tailwind .transition-all {\n transition-property: all;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.tina-tailwind .transition {\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.tina-tailwind .duration-300 {\n transition-duration: 300ms;\n}\n.tina-tailwind .duration-150 {\n transition-duration: 150ms;\n}\n.tina-tailwind .duration-100 {\n transition-duration: 100ms;\n}\n.tina-tailwind .duration-75 {\n transition-duration: 75ms;\n}\n.tina-tailwind .ease-out {\n transition-timing-function: cubic-bezier(0, 0, 0.2, 1);\n}\n.tina-tailwind .ease-in {\n transition-timing-function: cubic-bezier(0.4, 0, 1, 1);\n}\n.tina-tailwind .icon-parent svg {\n fill: currentColor;\n }\n\n.tina-tailwind {\n font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";\n font-size: 16px;\n line-height: 1.5;\n --tw-text-opacity: 1;\n color: rgb(86 81 101 / var(--tw-text-opacity));\n}\n\n.tina-tailwind .hover\\:bg-blue-600:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(5 116 228 / var(--tw-bg-opacity));\n}\n\n.tina-tailwind .hover\\:text-blue-600:hover {\n --tw-text-opacity: 1;\n color: rgb(5 116 228 / var(--tw-text-opacity));\n}\n\n.tina-tailwind .hover\\:text-blue-400:hover {\n --tw-text-opacity: 1;\n color: rgb(34 150 254 / var(--tw-text-opacity));\n}\n\n.tina-tailwind .hover\\:opacity-100:hover {\n opacity: 1;\n}\n\n.tina-tailwind .focus\\:text-blue-400:focus {\n --tw-text-opacity: 1;\n color: rgb(34 150 254 / var(--tw-text-opacity));\n}\n\n.tina-tailwind .focus\\:underline:focus {\n text-decoration-line: underline;\n}\n\n.tina-tailwind .focus\\:shadow-outline:focus {\n --tw-shadow: 0 0 0 3px rgba(66, 153, 225, 0.5);\n --tw-shadow-colored: 0 0 0 3px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n\n.tina-tailwind .focus\\:outline-none:focus {\n outline: 2px solid transparent;\n outline-offset: 2px;\n}\n\n.tina-tailwind .focus\\:ring-2:focus {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);\n}\n\n.tina-tailwind .focus\\:ring-blue-500:focus {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(0 132 255 / var(--tw-ring-opacity));\n}\n';
3022
3107
  function useTina({
3023
3108
  query,
3024
3109
  variables,
@@ -3097,13 +3182,23 @@ class ErrorBoundary extends React.Component {
3097
3182
  style: { color: "#eb6337" }
3098
3183
  }, "TinaCMS Render Error"), /* @__PURE__ */ React.createElement("p", null, "Tina caught an error while updating the page:"), /* @__PURE__ */ React.createElement("pre", {
3099
3184
  style: { marginTop: "1rem", overflowX: "auto" }
3100
- }, this.state.message), /* @__PURE__ */ React.createElement("br", null), /* @__PURE__ */ React.createElement("p", null, `If you've just updated the form, undo your most recent changes and click "refresh". If after a few refreshes, you're still encountering this error. There is a bigger issue with the site. Please reach out to your site admin.`), /* @__PURE__ */ React.createElement("button", {
3185
+ }, this.state.message), /* @__PURE__ */ React.createElement("br", null), /* @__PURE__ */ React.createElement("p", null, `If you've just updated the form, undo your most recent changes and click "refresh". If after a few refreshes, you're still encountering this error. There is a bigger issue with the site. Please reach out to your site admin.`), /* @__PURE__ */ React.createElement("p", null, "See our", " ", /* @__PURE__ */ React.createElement("a", {
3186
+ className: "text-gray-600",
3187
+ style: { textDecoration: "underline" },
3188
+ href: "https://tina.io/docs/errors/faq/",
3189
+ target: "_blank"
3190
+ }, " ", "Error FAQ", " "), " ", "for more information."), /* @__PURE__ */ React.createElement("button", {
3101
3191
  style: errorButtonStyles,
3102
3192
  onClick: () => {
3103
3193
  this.setState({ pageRefresh: true });
3104
3194
  setTimeout(() => this.setState({ hasError: false, pageRefresh: false }), 3e3);
3105
3195
  }
3106
- }, "Refresh"), hasBranchData && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("p", null, `If you're using the branch switcher, you may currently be on a "stale" branch that has been deleted or whose content is not compatible with the latest version of the site's layout. Click the button below to switch back to the default branch for this deployment.`), /* @__PURE__ */ React.createElement("button", {
3196
+ }, "Refresh"), hasBranchData && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("p", null, `If you're using the branch switcher, you may currently be on a "stale" branch that has been deleted or whose content is not compatible with the latest version of the site's layout. Click the button below to switch back to the default branch for this deployment.`), /* @__PURE__ */ React.createElement("p", null, "See our", " ", /* @__PURE__ */ React.createElement("a", {
3197
+ className: "text-gray-600",
3198
+ style: { textDecoration: "underline" },
3199
+ href: "https://tina.io/docs/errors/faq/",
3200
+ target: "_blank"
3201
+ }, " ", "Error FAQ", " "), " ", "for more information."), /* @__PURE__ */ React.createElement("button", {
3107
3202
  style: errorButtonStyles,
3108
3203
  onClick: () => {
3109
3204
  window.localStorage.removeItem("tinacms-current-branch");
@@ -3136,11 +3231,13 @@ const TinaCMSProvider2 = (_c) => {
3136
3231
  var _d = _c, {
3137
3232
  query,
3138
3233
  documentCreatorCallback,
3139
- formifyCallback
3234
+ formifyCallback,
3235
+ schema
3140
3236
  } = _d, props = __objRest(_d, [
3141
3237
  "query",
3142
3238
  "documentCreatorCallback",
3143
- "formifyCallback"
3239
+ "formifyCallback",
3240
+ "schema"
3144
3241
  ]);
3145
3242
  const validOldSetup = new Boolean(props == null ? void 0 : props.isLocalClient) || new Boolean(props == null ? void 0 : props.clientId) && new Boolean(props == null ? void 0 : props.branch);
3146
3243
  if (!props.apiURL && !validOldSetup) {
@@ -3157,7 +3254,8 @@ const TinaCMSProvider2 = (_c) => {
3157
3254
  tinaioConfig: props.tinaioConfig,
3158
3255
  isLocalClient,
3159
3256
  cmsCallback: props.cmsCallback,
3160
- mediaStore: props.mediaStore
3257
+ mediaStore: props.mediaStore,
3258
+ schema
3161
3259
  }, /* @__PURE__ */ React.createElement("style", null, styles), /* @__PURE__ */ React.createElement(ErrorBoundary, null, /* @__PURE__ */ React.createElement(DocumentCreator, {
3162
3260
  documentCreatorCallback
3163
3261
  }), /* @__PURE__ */ React.createElement(TinaDataProvider, {
@@ -3201,10 +3299,10 @@ const TinaDataProvider = ({
3201
3299
  });
3202
3300
  const cms = useCMS();
3203
3301
  const useUnstableFormify = React.useMemo(() => {
3204
- if (cms == null ? void 0 : cms.flags.get("use-unstable-formify")) {
3205
- return true;
3302
+ if ((cms == null ? void 0 : cms.flags.get("use-unstable-formify")) === false) {
3303
+ return false;
3206
3304
  }
3207
- return false;
3305
+ return true;
3208
3306
  }, [cms == null ? void 0 : cms.flags]);
3209
3307
  return /* @__PURE__ */ React.createElement(TinaDataContext.Provider, {
3210
3308
  value: {
@@ -3522,10 +3620,10 @@ const useGetCollections = (cms) => {
3522
3620
  const response = await api.fetchCollections();
3523
3621
  setCollections(response.getCollections);
3524
3622
  } catch (error2) {
3525
- cms.alerts.error(`[${error2.name}] GetCollections failed: ${error2.message}`, 30 * 1e3);
3526
3623
  console.error(error2);
3527
3624
  setCollections([]);
3528
3625
  setError(error2);
3626
+ throw new Error(`[${error2.name}] GetCollections failed: ${error2.message}`);
3529
3627
  }
3530
3628
  setLoading(false);
3531
3629
  }
@@ -3590,6 +3688,9 @@ function BiLogOut(props) {
3590
3688
  function BiPlus(props) {
3591
3689
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "M19 11h-6V5h-2v6H5v2h6v6h2v-6h6z" } }] })(props);
3592
3690
  }
3691
+ function BiTrash(props) {
3692
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "M5 20a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8h2V6h-4V4a2 2 0 0 0-2-2H9a2 2 0 0 0-2 2v2H3v2h2zM9 4h6v2H9zM8 8h9v12H7V8z" } }, { "tag": "path", "attr": { "d": "M9 10h2v8H9zm4 0h2v8h-2z" } }] })(props);
3693
+ }
3593
3694
  function MdOutlineArrowBack(props) {
3594
3695
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "fill": "none", "d": "M0 0h24v24H0V0z" } }, { "tag": "path", "attr": { "d": "M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" } }] })(props);
3595
3696
  }
@@ -3815,6 +3916,7 @@ const useGetCollection = (cms, collectionName, includeDocuments = true) => {
3815
3916
  const [collection, setCollection] = useState(void 0);
3816
3917
  const [loading, setLoading] = useState(true);
3817
3918
  const [error, setError] = useState(void 0);
3919
+ const [resetState, setResetSate] = useState(0);
3818
3920
  useEffect(() => {
3819
3921
  const fetchCollection = async () => {
3820
3922
  if (await api.isAuthenticated()) {
@@ -3832,8 +3934,9 @@ const useGetCollection = (cms, collectionName, includeDocuments = true) => {
3832
3934
  };
3833
3935
  setLoading(true);
3834
3936
  fetchCollection();
3835
- }, [cms, collectionName]);
3836
- return { collection, loading, error };
3937
+ }, [cms, collectionName, resetState]);
3938
+ const reFetchCollection = () => setResetSate((x) => x + 1);
3939
+ return { collection, loading, error, reFetchCollection };
3837
3940
  };
3838
3941
  const GetCollection = ({
3839
3942
  cms,
@@ -3841,14 +3944,14 @@ const GetCollection = ({
3841
3944
  includeDocuments = true,
3842
3945
  children
3843
3946
  }) => {
3844
- const { collection, loading, error } = useGetCollection(cms, collectionName, includeDocuments);
3947
+ const { collection, loading, error, reFetchCollection } = useGetCollection(cms, collectionName, includeDocuments);
3845
3948
  if (error) {
3846
3949
  return null;
3847
3950
  }
3848
3951
  if (loading) {
3849
3952
  return /* @__PURE__ */ React.createElement(LoadingPage, null);
3850
3953
  }
3851
- return /* @__PURE__ */ React.createElement(React.Fragment, null, children(collection, loading));
3954
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, children(collection, loading, reFetchCollection));
3852
3955
  };
3853
3956
  const TemplateMenu = ({ templates }) => {
3854
3957
  return /* @__PURE__ */ React.createElement(Menu, {
@@ -3885,22 +3988,42 @@ const handleNavigate = (navigate, cms, collection, document) => {
3885
3988
  window.location.href = routeOverride;
3886
3989
  return null;
3887
3990
  } else {
3888
- navigate(document.sys.filename);
3991
+ navigate(document.sys.breadcrumbs.join("/"));
3889
3992
  }
3890
3993
  };
3891
3994
  const CollectionListPage = () => {
3892
3995
  const navigate = useNavigate();
3893
3996
  const { collectionName } = useParams();
3997
+ const [open, setOpen] = React.useState(false);
3998
+ const [vars, setVars] = React.useState({
3999
+ collection: collectionName,
4000
+ relativePath: ""
4001
+ });
3894
4002
  return /* @__PURE__ */ React.createElement(GetCMS, null, (cms) => {
3895
4003
  return /* @__PURE__ */ React.createElement(GetCollection, {
3896
4004
  cms,
3897
4005
  collectionName,
3898
4006
  includeDocuments: true
3899
- }, (collection) => {
4007
+ }, (collection, _loading, reFetchCollection) => {
3900
4008
  var _a, _b;
3901
4009
  const totalCount = collection.documents.totalCount;
3902
4010
  const documents = collection.documents.edges;
3903
- return /* @__PURE__ */ React.createElement(PageWrapper, null, /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(PageHeader, {
4011
+ const admin = cms.api.admin;
4012
+ return /* @__PURE__ */ React.createElement(PageWrapper, null, /* @__PURE__ */ React.createElement(React.Fragment, null, open && /* @__PURE__ */ React.createElement(DeleteModal, {
4013
+ filename: vars.relativePath,
4014
+ deleteFunc: async () => {
4015
+ try {
4016
+ await admin.deleteDocument(vars);
4017
+ cms.alerts.info("Document was successfully deleted");
4018
+ reFetchCollection();
4019
+ } catch (error) {
4020
+ cms.alerts.warn("Document was not deleted, ask a developer for help or check the console for an error message");
4021
+ console.error(error);
4022
+ throw error;
4023
+ }
4024
+ },
4025
+ close: () => setOpen(false)
4026
+ }), /* @__PURE__ */ React.createElement(PageHeader, {
3904
4027
  isLocalMode: (_b = (_a = cms == null ? void 0 : cms.api) == null ? void 0 : _a.tina) == null ? void 0 : _b.isLocalMode
3905
4028
  }, /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("h3", {
3906
4029
  className: "text-2xl text-gray-700"
@@ -3918,8 +4041,9 @@ const CollectionListPage = () => {
3918
4041
  }, /* @__PURE__ */ React.createElement("tbody", {
3919
4042
  className: "divide-y divide-gray-150"
3920
4043
  }, documents.map((document) => {
4044
+ const subfolders = document.node.sys.breadcrumbs.slice(0, -1).join("/");
3921
4045
  return /* @__PURE__ */ React.createElement("tr", {
3922
- key: `document-${document.node.sys.filename}`,
4046
+ key: `document-${document.node.sys.relativePath}`,
3923
4047
  className: ""
3924
4048
  }, /* @__PURE__ */ React.createElement("td", {
3925
4049
  className: "px-6 py-2 whitespace-nowrap"
@@ -3934,7 +4058,9 @@ const CollectionListPage = () => {
3934
4058
  className: "block text-xs text-gray-400 mb-1 uppercase"
3935
4059
  }, "Filename"), /* @__PURE__ */ React.createElement("span", {
3936
4060
  className: "h-5 leading-5 block whitespace-nowrap"
3937
- }, document.node.sys.filename)))), /* @__PURE__ */ React.createElement("td", {
4061
+ }, subfolders && /* @__PURE__ */ React.createElement("span", {
4062
+ className: "text-xs text-gray-400"
4063
+ }, `${subfolders}/`), /* @__PURE__ */ React.createElement("span", null, document.node.sys.filename))))), /* @__PURE__ */ React.createElement("td", {
3938
4064
  className: "px-6 py-4 whitespace-nowrap"
3939
4065
  }, /* @__PURE__ */ React.createElement("span", {
3940
4066
  className: "block text-xs text-gray-400 mb-1 uppercase"
@@ -3946,14 +4072,59 @@ const CollectionListPage = () => {
3946
4072
  className: "block text-xs text-gray-400 mb-1 uppercase"
3947
4073
  }, "Template"), /* @__PURE__ */ React.createElement("span", {
3948
4074
  className: "h-5 leading-5 block text-sm font-medium text-gray-900"
3949
- }, document.node.sys.template)));
4075
+ }, document.node.sys.template)), /* @__PURE__ */ React.createElement("td", {
4076
+ className: "w-0"
4077
+ }, /* @__PURE__ */ React.createElement(OverflowMenu, {
4078
+ showEmbed: true,
4079
+ toolbarItems: [
4080
+ {
4081
+ name: "edit",
4082
+ label: "Edit in Admin",
4083
+ Icon: /* @__PURE__ */ React.createElement(BiEdit, {
4084
+ size: "1.3rem"
4085
+ }),
4086
+ onMouseDown: () => {
4087
+ navigate(`${document.node.sys.filename}`, { replace: true });
4088
+ }
4089
+ },
4090
+ {
4091
+ name: "delete",
4092
+ label: "Delete",
4093
+ Icon: /* @__PURE__ */ React.createElement(BiTrash, {
4094
+ size: "1.3rem",
4095
+ className: "text-red-500"
4096
+ }),
4097
+ onMouseDown: () => {
4098
+ setVars({
4099
+ collection: collectionName,
4100
+ relativePath: document.node.sys.filename + document.node.sys.extension
4101
+ });
4102
+ setOpen(true);
4103
+ }
4104
+ }
4105
+ ]
4106
+ })));
3950
4107
  })))))));
3951
4108
  });
3952
4109
  });
3953
4110
  };
3954
- function HiChevronRight(props) {
3955
- return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 20 20", "fill": "currentColor" }, "child": [{ "tag": "path", "attr": { "fillRule": "evenodd", "d": "M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z", "clipRule": "evenodd" } }] })(props);
3956
- }
4111
+ const DeleteModal = ({ close: close2, deleteFunc, filename }) => {
4112
+ return /* @__PURE__ */ React.createElement(Modal, null, /* @__PURE__ */ React.createElement(ModalPopup, null, /* @__PURE__ */ React.createElement(ModalHeader, {
4113
+ close: close2
4114
+ }, "Reset"), /* @__PURE__ */ React.createElement(ModalBody, {
4115
+ padded: true
4116
+ }, /* @__PURE__ */ React.createElement("p", null, `Are you sure you want to delete ${filename}?`)), /* @__PURE__ */ React.createElement(ModalActions, null, /* @__PURE__ */ React.createElement(Button, {
4117
+ style: { flexGrow: 2 },
4118
+ onClick: close2
4119
+ }, "Cancel"), /* @__PURE__ */ React.createElement(Button, {
4120
+ style: { flexGrow: 3 },
4121
+ variant: "danger",
4122
+ onClick: async () => {
4123
+ await deleteFunc();
4124
+ close2();
4125
+ }
4126
+ }, "Delete"))));
4127
+ };
3957
4128
  const useGetDocumentFields = (cms, collectionName, templateName) => {
3958
4129
  const api = new TinaAdminApi(cms);
3959
4130
  const [info, setInfo] = useState({
@@ -4020,6 +4191,9 @@ const GetDocumentFields = ({
4020
4191
  }
4021
4192
  return /* @__PURE__ */ React.createElement(React.Fragment, null, children({ collection, template, fields, mutationInfo, loading }));
4022
4193
  };
4194
+ function HiChevronRight(props) {
4195
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 20 20", "fill": "currentColor" }, "child": [{ "tag": "path", "attr": { "fillRule": "evenodd", "d": "M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z", "clipRule": "evenodd" } }] })(props);
4196
+ }
4023
4197
  const createDocument = async (cms, collection, template, mutationInfo, values) => {
4024
4198
  const api = new TinaAdminApi(cms);
4025
4199
  const _a = values, { filename } = _a, leftover = __objRest(_a, ["filename"]);
@@ -4058,6 +4232,22 @@ const RenderForm$1 = ({ cms, collection, template, fields, mutationInfo }) => {
4058
4232
  var _a, _b;
4059
4233
  const navigate = useNavigate();
4060
4234
  const [formIsPristine, setFormIsPristine] = useState(true);
4235
+ const schema = cms.api.tina.schema;
4236
+ let schemaFields = fields;
4237
+ if (schema) {
4238
+ const schemaCollection = schema.getCollection(collection.name);
4239
+ const template2 = schema.getTemplateForData({
4240
+ collection: schemaCollection,
4241
+ data: {}
4242
+ });
4243
+ const formInfo = resolveForm({
4244
+ collection: schemaCollection,
4245
+ basename: schemaCollection.name,
4246
+ schema,
4247
+ template: template2
4248
+ });
4249
+ schemaFields = formInfo.fields;
4250
+ }
4061
4251
  const form = useMemo(() => {
4062
4252
  return new Form({
4063
4253
  id: "create-form",
@@ -4067,7 +4257,7 @@ const RenderForm$1 = ({ cms, collection, template, fields, mutationInfo }) => {
4067
4257
  name: "filename",
4068
4258
  label: "Filename",
4069
4259
  component: "text",
4070
- description: `A unique filename for the content. Example: My_Document`,
4260
+ description: /* @__PURE__ */ React.createElement("span", null, "A unique filename for the content.", /* @__PURE__ */ React.createElement("br", null), "Examples: ", /* @__PURE__ */ React.createElement("code", null, "My_Document"), ", ", /* @__PURE__ */ React.createElement("code", null, "My_Document.en"), ",", " ", /* @__PURE__ */ React.createElement("code", null, "sub-folder/My_Document")),
4071
4261
  placeholder: `My_Document`,
4072
4262
  validate: (value, allValues, meta) => {
4073
4263
  if (!value) {
@@ -4076,13 +4266,13 @@ const RenderForm$1 = ({ cms, collection, template, fields, mutationInfo }) => {
4076
4266
  }
4077
4267
  return true;
4078
4268
  }
4079
- const isValid = /^[_a-zA-Z][.,-,_a-zA-Z0-9]*$/.test(value);
4269
+ const isValid = /^[_a-zA-Z][\.\-_\/a-zA-Z0-9]*$/.test(value);
4080
4270
  if (value && !isValid) {
4081
- return "Must begin with a-z, A-Z, or _ and contain only a-z, A-Z, 0-9, -, ., or _";
4271
+ return "Must begin with a-z, A-Z, or _ and contain only a-z, A-Z, 0-9, -, _, ., or /.";
4082
4272
  }
4083
4273
  }
4084
4274
  },
4085
- ...fields
4275
+ ...schemaFields
4086
4276
  ],
4087
4277
  onSubmit: async (values) => {
4088
4278
  try {
@@ -4090,8 +4280,8 @@ const RenderForm$1 = ({ cms, collection, template, fields, mutationInfo }) => {
4090
4280
  cms.alerts.success("Document created!");
4091
4281
  navigate(`/collections/${collection.name}`);
4092
4282
  } catch (error) {
4093
- cms.alerts.error(`[${error.name}] CreateDocument failed: ${error.message}`, 30 * 1e3);
4094
4283
  console.error(error);
4284
+ throw new Error(`[${error.name}] CreateDocument failed: ${error.message}`);
4095
4285
  }
4096
4286
  }
4097
4287
  });
@@ -4175,7 +4365,8 @@ const updateDocument = async (cms, relativePath, collection, mutationInfo, value
4175
4365
  }
4176
4366
  };
4177
4367
  const CollectionUpdatePage = () => {
4178
- const { collectionName, filename } = useParams();
4368
+ const _a = useParams(), { collectionName } = _a, rest = __objRest(_a, ["collectionName"]);
4369
+ const { "*": filename } = rest;
4179
4370
  return /* @__PURE__ */ React.createElement(GetCMS, null, (cms) => /* @__PURE__ */ React.createElement(GetDocumentFields, {
4180
4371
  cms,
4181
4372
  collectionName
@@ -4204,21 +4395,36 @@ const RenderForm = ({
4204
4395
  mutationInfo
4205
4396
  }) => {
4206
4397
  var _a, _b;
4207
- useNavigate();
4208
4398
  const [formIsPristine, setFormIsPristine] = useState(true);
4399
+ const schema = cms.api.tina.schema;
4400
+ let schemaFields = document.form.fields;
4401
+ if (schema) {
4402
+ const schemaCollection = schema.getCollection(collection.name);
4403
+ const template = schema.getTemplateForData({
4404
+ collection: schemaCollection,
4405
+ data: document.value
4406
+ });
4407
+ const formInfo = resolveForm({
4408
+ collection: schemaCollection,
4409
+ basename: schemaCollection.name,
4410
+ schema,
4411
+ template
4412
+ });
4413
+ schemaFields = formInfo.fields;
4414
+ }
4209
4415
  const form = useMemo(() => {
4210
4416
  return new Form({
4211
4417
  id: "update-form",
4212
4418
  label: "form",
4213
- fields: document.form.fields,
4419
+ fields: schemaFields,
4214
4420
  initialValues: document.values,
4215
4421
  onSubmit: async (values) => {
4216
4422
  try {
4217
4423
  await updateDocument(cms, relativePath, collection, mutationInfo, values);
4218
4424
  cms.alerts.success("Document updated!");
4219
4425
  } catch (error) {
4220
- cms.alerts.error(`[${error.name}] UpdateDocument failed: ${error.message}`, 30 * 1e3);
4221
4426
  console.error(error);
4427
+ throw new Error(`[${error.name}] UpdateDocument failed: ${error.message}`);
4222
4428
  }
4223
4429
  }
4224
4430
  });
@@ -4294,7 +4500,7 @@ const TinaAdmin = () => {
4294
4500
  path: "collections/:collectionName/:templateName/new",
4295
4501
  element: /* @__PURE__ */ React.createElement(CollectionCreatePage, null)
4296
4502
  }), /* @__PURE__ */ React.createElement(Route, {
4297
- path: "collections/:collectionName/:filename",
4503
+ path: "collections/:collectionName/*",
4298
4504
  element: /* @__PURE__ */ React.createElement(CollectionUpdatePage, null)
4299
4505
  }), /* @__PURE__ */ React.createElement(Route, {
4300
4506
  path: "collections/:collectionName",
@@ -4325,6 +4531,7 @@ class RouteMappingPlugin {
4325
4531
  }
4326
4532
  }
4327
4533
  const defineSchema = (config) => {
4534
+ validateSchema({ config });
4328
4535
  return config;
4329
4536
  };
4330
4537
  const defineConfig = (config) => {