tinacms 1.5.22 → 1.5.23

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/dev-tools.js CHANGED
@@ -72,7 +72,7 @@
72
72
  return MNode;
73
73
  };
74
74
  const Node = ({ components, child }) => {
75
- var _a, _b, _c, _d, _e;
75
+ var _a, _b, _c, _d, _e, _f;
76
76
  const { children, ...props } = child;
77
77
  switch (child.type) {
78
78
  case "h1":
@@ -154,23 +154,18 @@
154
154
  const header = (_e = (_d = child.props) == null ? void 0 : _d.tableRows) == null ? void 0 : _e.at(0);
155
155
  const TableComponent = components["table"] || ((props2) => /* @__PURE__ */ React.createElement("table", { ...props2 }));
156
156
  const TrComponent = components["tr"] || ((props2) => /* @__PURE__ */ React.createElement("tr", { ...props2 }));
157
- const ThComponent = components["th"] || ((props2) => /* @__PURE__ */ React.createElement("th", { ...props2 }));
158
- const TdComponent = components["td"] || ((props2) => /* @__PURE__ */ React.createElement("td", { ...props2 }));
157
+ const ThComponent = components["th"] || ((props2) => /* @__PURE__ */ React.createElement("th", { style: { textAlign: (props2 == null ? void 0 : props2.align) || "auto" }, ...props2 }));
158
+ const TdComponent = components["td"] || ((props2) => /* @__PURE__ */ React.createElement("td", { style: { textAlign: (props2 == null ? void 0 : props2.align) || "auto" }, ...props2 }));
159
+ const align = ((_f = child.props) == null ? void 0 : _f.align) || [];
159
160
  return /* @__PURE__ */ React.createElement(TableComponent, null, firstRowHeader && /* @__PURE__ */ React.createElement("thead", null, /* @__PURE__ */ React.createElement(TrComponent, null, header.tableCells.map((c, i) => {
160
161
  return /* @__PURE__ */ React.createElement(
161
162
  TinaMarkdown,
162
163
  {
163
164
  key: i,
164
165
  components: {
165
- p: (props2) => {
166
- if (ThComponent) {
167
- return /* @__PURE__ */ React.createElement(ThComponent, { ...props2 });
168
- } else {
169
- return /* @__PURE__ */ React.createElement("th", { ...props2 });
170
- }
171
- }
166
+ p: (props2) => /* @__PURE__ */ React.createElement(ThComponent, { align: align[i], ...props2 })
172
167
  },
173
- content: c.tableCell
168
+ content: c.value
174
169
  }
175
170
  );
176
171
  }))), /* @__PURE__ */ React.createElement("tbody", null, rows.map((row, i) => {
@@ -181,15 +176,9 @@
181
176
  {
182
177
  key: i2,
183
178
  components: {
184
- p: (props2) => {
185
- if (TdComponent) {
186
- return /* @__PURE__ */ React.createElement(TdComponent, { ...props2 });
187
- } else {
188
- return /* @__PURE__ */ React.createElement("td", { ...props2 });
189
- }
190
- }
179
+ p: (props2) => /* @__PURE__ */ React.createElement(TdComponent, { align: align[i2], ...props2 })
191
180
  },
192
- content: c.tableCell
181
+ content: c.value
193
182
  }
194
183
  );
195
184
  }));
@@ -69,7 +69,7 @@ const MemoNode = (props) => {
69
69
  return MNode;
70
70
  };
71
71
  const Node = ({ components, child }) => {
72
- var _a, _b, _c, _d, _e;
72
+ var _a, _b, _c, _d, _e, _f;
73
73
  const { children, ...props } = child;
74
74
  switch (child.type) {
75
75
  case "h1":
@@ -151,23 +151,18 @@ const Node = ({ components, child }) => {
151
151
  const header = (_e = (_d = child.props) == null ? void 0 : _d.tableRows) == null ? void 0 : _e.at(0);
152
152
  const TableComponent = components["table"] || ((props2) => /* @__PURE__ */ React.createElement("table", { ...props2 }));
153
153
  const TrComponent = components["tr"] || ((props2) => /* @__PURE__ */ React.createElement("tr", { ...props2 }));
154
- const ThComponent = components["th"] || ((props2) => /* @__PURE__ */ React.createElement("th", { ...props2 }));
155
- const TdComponent = components["td"] || ((props2) => /* @__PURE__ */ React.createElement("td", { ...props2 }));
154
+ const ThComponent = components["th"] || ((props2) => /* @__PURE__ */ React.createElement("th", { style: { textAlign: (props2 == null ? void 0 : props2.align) || "auto" }, ...props2 }));
155
+ const TdComponent = components["td"] || ((props2) => /* @__PURE__ */ React.createElement("td", { style: { textAlign: (props2 == null ? void 0 : props2.align) || "auto" }, ...props2 }));
156
+ const align = ((_f = child.props) == null ? void 0 : _f.align) || [];
156
157
  return /* @__PURE__ */ React.createElement(TableComponent, null, firstRowHeader && /* @__PURE__ */ React.createElement("thead", null, /* @__PURE__ */ React.createElement(TrComponent, null, header.tableCells.map((c, i) => {
157
158
  return /* @__PURE__ */ React.createElement(
158
159
  TinaMarkdown,
159
160
  {
160
161
  key: i,
161
162
  components: {
162
- p: (props2) => {
163
- if (ThComponent) {
164
- return /* @__PURE__ */ React.createElement(ThComponent, { ...props2 });
165
- } else {
166
- return /* @__PURE__ */ React.createElement("th", { ...props2 });
167
- }
168
- }
163
+ p: (props2) => /* @__PURE__ */ React.createElement(ThComponent, { align: align[i], ...props2 })
169
164
  },
170
- content: c.tableCell
165
+ content: c.value
171
166
  }
172
167
  );
173
168
  }))), /* @__PURE__ */ React.createElement("tbody", null, rows.map((row, i) => {
@@ -178,15 +173,9 @@ const Node = ({ components, child }) => {
178
173
  {
179
174
  key: i2,
180
175
  components: {
181
- p: (props2) => {
182
- if (TdComponent) {
183
- return /* @__PURE__ */ React.createElement(TdComponent, { ...props2 });
184
- } else {
185
- return /* @__PURE__ */ React.createElement("td", { ...props2 });
186
- }
187
- }
176
+ p: (props2) => /* @__PURE__ */ React.createElement(TdComponent, { align: align[i2], ...props2 })
188
177
  },
189
- content: c.tableCell
178
+ content: c.value
190
179
  }
191
180
  );
192
181
  }));
package/dist/index.d.ts CHANGED
@@ -19,7 +19,6 @@ export type { TinaCMSProviderDefaultProps };
19
19
  export default TinaCMSProvider2;
20
20
  import { MediaStore, TinaCMS } from '@tinacms/toolkit';
21
21
  import { formifyCallback } from './hooks/use-graphql-forms';
22
- import { RichTextTemplate } from '@tinacms/schema-tools';
23
22
  export { NAMER, resolveField } from '@tinacms/schema-tools';
24
23
  import { TinaSchema, TinaField, Config, Schema, Collection, Template } from '@tinacms/schema-tools';
25
24
  export type { Config, Schema, Collection, Template, TinaField, TinaSchema };
@@ -58,7 +57,4 @@ interface MediaStoreClass {
58
57
  }
59
58
  export declare const defineStaticConfig: (config: Config<(cms: TinaCMS) => TinaCMS, formifyCallback, import("./hooks/use-content-creator").DocumentCreatorArgs, MediaStoreClass, undefined>) => Config<(cms: TinaCMS) => TinaCMS, formifyCallback, import("./hooks/use-content-creator").DocumentCreatorArgs, MediaStoreClass, undefined>;
60
59
  export declare const defineConfig: (config: Config<(cms: TinaCMS) => TinaCMS, formifyCallback, import("./hooks/use-content-creator").DocumentCreatorArgs, MediaStoreClass, undefined>) => Config<(cms: TinaCMS) => TinaCMS, formifyCallback, import("./hooks/use-content-creator").DocumentCreatorArgs, MediaStoreClass, undefined>;
61
- /**
62
- * Out-of-the-box template for rendering basic markdown tables
63
- */
64
- export declare const tinaTableTemplate: RichTextTemplate;
60
+ export { tinaTableTemplate } from './table';
package/dist/index.js CHANGED
@@ -1810,8 +1810,15 @@ var __publicField = (obj, key, value) => {
1810
1810
  return this.finalForm.subscribe(cb, options2);
1811
1811
  };
1812
1812
  this.handleSubmit = async (values, form, cb) => {
1813
+ var _a;
1813
1814
  try {
1814
- const response = await this.onSubmit(values, form, cb);
1815
+ const valOverride = await ((_a = this.beforeSubmit) == null ? void 0 : _a.call(this, values));
1816
+ if (valOverride) {
1817
+ for (const [key, value] of Object.entries(valOverride)) {
1818
+ form.change(key, value);
1819
+ }
1820
+ }
1821
+ const response = await this.onSubmit(valOverride || values, form, cb);
1815
1822
  form.initialize(values);
1816
1823
  return response;
1817
1824
  } catch (error) {
@@ -2349,6 +2356,7 @@ var __publicField = (obj, key, value) => {
2349
2356
  {
2350
2357
  name: field.name,
2351
2358
  key: field.name,
2359
+ isEqual: (a, b) => isEqual(field, a, b),
2352
2360
  type,
2353
2361
  parse: parse2 ? (value, name) => parse2(value, name, field) : void 0,
2354
2362
  format: format2 ? (value, name) => format2(value, name, field) : void 0,
@@ -2406,6 +2414,18 @@ var __publicField = (obj, key, value) => {
2406
2414
  }
2407
2415
  return prop;
2408
2416
  }
2417
+ const isEqual = (field, a, b) => {
2418
+ const replacer = (key, value) => {
2419
+ if (key === "id") {
2420
+ return void 0;
2421
+ }
2422
+ return value;
2423
+ };
2424
+ if (field.type === "rich-text") {
2425
+ return JSON.stringify(a, replacer) === JSON.stringify(b, replacer);
2426
+ }
2427
+ return a === b;
2428
+ };
2409
2429
  const FF = reactFinalForm.Form;
2410
2430
  const FormLegacy = ({ form, children }) => {
2411
2431
  const [i, setI] = React__namespace.useState(0);
@@ -2450,7 +2470,7 @@ var __publicField = (obj, key, value) => {
2450
2470
  disabled,
2451
2471
  rounded = "full",
2452
2472
  children,
2453
- className,
2473
+ className = "",
2454
2474
  ...props
2455
2475
  }) => {
2456
2476
  const baseClasses = "icon-parent inline-flex items-center font-medium focus:outline-none focus:ring-2 focus:shadow-outline text-center inline-flex justify-center transition-all duration-150 ease-out ";
@@ -7113,7 +7133,7 @@ var __publicField = (obj, key, value) => {
7113
7133
  toolbarItems: [
7114
7134
  branch.githubPullRequestUrl && {
7115
7135
  name: "github-pr",
7116
- label: "View in Github",
7136
+ label: "View in GitHub",
7117
7137
  Icon: /* @__PURE__ */ React__namespace.createElement(BiLinkExternal, { className: "w-5 h-auto text-blue-500 opacity-70" }),
7118
7138
  onMouseDown: () => {
7119
7139
  window.open(branch.githubPullRequestUrl, "_blank");
@@ -7535,6 +7555,10 @@ var __publicField = (obj, key, value) => {
7535
7555
  `${this.url}/upload_url/${path}`,
7536
7556
  { method: "GET" }
7537
7557
  );
7558
+ if (res.status === 412) {
7559
+ const { message = "Unexpected error generating upload url" } = await res.json();
7560
+ throw new Error(message);
7561
+ }
7538
7562
  const { signedUrl } = await res.json();
7539
7563
  if (!signedUrl) {
7540
7564
  throw new Error("Unexpected error generating upload url");
@@ -10111,7 +10135,7 @@ var __publicField = (obj, key, value) => {
10111
10135
  return {
10112
10136
  error: event.error,
10113
10137
  level: "error",
10114
- message: `Failed to upload file(s) ${event == null ? void 0 : event.uploaded.map((x) => x.file.name).join(", ")}. See error message:
10138
+ message: `Failed to upload file(s) ${event == null ? void 0 : event.uploaded.map((x) => x.file.name).join(", ")}.
10115
10139
 
10116
10140
  ${event == null ? void 0 : event.error.toString()}`
10117
10141
  };
@@ -10822,6 +10846,16 @@ var __publicField = (obj, key, value) => {
10822
10846
  const [createBranchModalOpen, setCreateBranchModalOpen] = React__namespace.useState(false);
10823
10847
  const tinaForm = form.tinaForm;
10824
10848
  const finalForm2 = form.tinaForm.finalForm;
10849
+ const schema = cms.api.tina.schema;
10850
+ React__namespace.useEffect(() => {
10851
+ var _a;
10852
+ const collection = schema.getCollectionByFullPath(tinaForm.relativePath);
10853
+ if ((_a = collection == null ? void 0 : collection.ui) == null ? void 0 : _a.beforeSubmit) {
10854
+ tinaForm.beforeSubmit = (values) => collection.ui.beforeSubmit({ cms, form: tinaForm, values });
10855
+ } else {
10856
+ tinaForm.beforeSubmit = void 0;
10857
+ }
10858
+ }, [tinaForm.relativePath]);
10825
10859
  const moveArrayItem = React__namespace.useCallback(
10826
10860
  (result) => {
10827
10861
  if (!result.destination || !finalForm2)
@@ -10854,18 +10888,7 @@ var __publicField = (obj, key, value) => {
10854
10888
  {
10855
10889
  key: tinaForm.id,
10856
10890
  form: tinaForm.finalForm,
10857
- onSubmit: async (values, form2, cb) => {
10858
- var _a, _b;
10859
- const schema = cms.api.tina.schema;
10860
- const collection = schema.getCollectionByFullPath(tinaForm.relativePath);
10861
- const valOverride = ((_a = collection == null ? void 0 : collection.ui) == null ? void 0 : _a.beforeSubmit) ? await ((_b = collection == null ? void 0 : collection.ui) == null ? void 0 : _b.beforeSubmit({ cms, values, form: tinaForm })) : false;
10862
- if (valOverride) {
10863
- for (const [key, value] of Object.entries(valOverride)) {
10864
- form2.change(key, value);
10865
- }
10866
- }
10867
- return tinaForm.onSubmit(valOverride || values, form2, cb);
10868
- }
10891
+ onSubmit: tinaForm.onSubmit
10869
10892
  },
10870
10893
  ({
10871
10894
  handleSubmit,
@@ -29430,8 +29453,7 @@ This will work when developing locally but NOT when deployed to production.
29430
29453
  setSearch(searchInput);
29431
29454
  setSearchLoaded(false);
29432
29455
  },
29433
- variant: "primary",
29434
- type: "submit"
29456
+ variant: "primary"
29435
29457
  },
29436
29458
  "Search ",
29437
29459
  /* @__PURE__ */ React.createElement(BiSearch, { className: "w-5 h-full ml-1.5 opacity-70" })
@@ -29715,13 +29737,13 @@ This will work when developing locally but NOT when deployed to production.
29715
29737
  }
29716
29738
  const defaultItem = customDefaults || // @ts-ignore internal types aren't up to date
29717
29739
  ((_d = template.ui) == null ? void 0 : _d.defaultItem) || // @ts-ignore
29718
- (template == null ? void 0 : template.defaultItem);
29740
+ (template == null ? void 0 : template.defaultItem) || {};
29719
29741
  const form = React.useMemo(() => {
29720
29742
  var _a2, _b2;
29721
29743
  const folderName = folder.fullyQualifiedName ? folder.name : "";
29722
29744
  return new Form({
29723
29745
  crudType: "create",
29724
- initialValues: typeof defaultItem === "function" ? defaultItem() : defaultItem,
29746
+ initialValues: typeof defaultItem === "function" ? { ...defaultItem(), _template: templateName } : { ...defaultItem, _template: templateName },
29725
29747
  extraSubscribeValues: { active: true, submitting: true, touched: true },
29726
29748
  onChange: (values) => {
29727
29749
  var _a3, _b3;
@@ -30253,10 +30275,12 @@ This will work when developing locally but NOT when deployed to production.
30253
30275
  redirect,
30254
30276
  children
30255
30277
  }) => {
30278
+ const cms = useCMS$1();
30256
30279
  const navigate = reactRouterDom.useNavigate();
30257
30280
  React.useEffect(() => {
30281
+ const basePath = cms.flags.get("tina-basepath");
30258
30282
  if (redirect) {
30259
- navigate("/~");
30283
+ navigate(`/~${basePath ? `/${basePath}` : ""}`);
30260
30284
  }
30261
30285
  }, [redirect]);
30262
30286
  return children;
@@ -30500,22 +30524,6 @@ This will work when developing locally but NOT when deployed to production.
30500
30524
  this.mapper = mapper;
30501
30525
  }
30502
30526
  }
30503
- const defineSchema = (config) => {
30504
- schemaTools.validateSchema({ schema: config });
30505
- return config;
30506
- };
30507
- const defineLegacyConfig = (config) => {
30508
- schemaTools.validateSchema({ schema: config.schema });
30509
- return config;
30510
- };
30511
- const defineStaticConfig = (config) => {
30512
- if (!config.schema) {
30513
- throw new Error("Static config must have a schema");
30514
- }
30515
- schemaTools.validateSchema({ schema: config.schema });
30516
- return config;
30517
- };
30518
- const defineConfig = defineStaticConfig;
30519
30527
  const tinaTableTemplate = {
30520
30528
  name: "table",
30521
30529
  label: "Table",
@@ -30525,6 +30533,13 @@ This will work when developing locally but NOT when deployed to production.
30525
30533
  label: "First row is a header",
30526
30534
  type: "boolean"
30527
30535
  },
30536
+ {
30537
+ name: "align",
30538
+ label: "Align",
30539
+ type: "string",
30540
+ list: true,
30541
+ description: 'Possible values: "left", "right", or "center".'
30542
+ },
30528
30543
  {
30529
30544
  name: "tableRows",
30530
30545
  label: "Rows",
@@ -30537,7 +30552,7 @@ This will work when developing locally but NOT when deployed to production.
30537
30552
  return {
30538
30553
  label: value.tableCells.map((cellItem) => {
30539
30554
  var _a;
30540
- return (_a = stringifyCell(cellItem.tableCell)) == null ? void 0 : _a.trim();
30555
+ return (_a = stringifyCell(cellItem.value)) == null ? void 0 : _a.trim();
30541
30556
  }).join(" | ")
30542
30557
  };
30543
30558
  }
@@ -30552,24 +30567,36 @@ This will work when developing locally but NOT when deployed to production.
30552
30567
  list: true,
30553
30568
  type: "object",
30554
30569
  ui: {
30555
- itemProps: (value) => {
30570
+ itemProps: (cell) => {
30556
30571
  var _a;
30557
- if (value) {
30558
- if (value.tableCell) {
30572
+ if (cell) {
30573
+ if (cell.value) {
30559
30574
  return {
30560
- label: (_a = stringifyCell(value.tableCell)) == null ? void 0 : _a.trim()
30575
+ label: (_a = stringifyCell(cell.value)) == null ? void 0 : _a.trim()
30561
30576
  };
30562
30577
  }
30563
30578
  }
30564
- return { label: "Table Cell" };
30579
+ return { label: "Value" };
30565
30580
  }
30566
30581
  },
30567
30582
  fields: [
30568
30583
  {
30569
- label: "Table Cell",
30570
- description: "Note: table cells do not support block-level elements like headers, code blocks, or lists. Any block-level items other than the first paragraph will be ignored.",
30571
- name: "tableCell",
30572
- type: "rich-text"
30584
+ label: "Value",
30585
+ description: "Note: table cells do not support block-level elements like headers, code blocks, or lists. Any block-level items other than the first paragraph will be considered invalid.",
30586
+ name: "value",
30587
+ type: "rich-text",
30588
+ ui: {
30589
+ validate(value) {
30590
+ try {
30591
+ tableCellSchema.parse(value);
30592
+ } catch (e) {
30593
+ if (e instanceof zod.z.ZodError) {
30594
+ return e.errors[0].message;
30595
+ }
30596
+ return e.message;
30597
+ }
30598
+ }
30599
+ }
30573
30600
  }
30574
30601
  ]
30575
30602
  }
@@ -30577,9 +30604,54 @@ This will work when developing locally but NOT when deployed to production.
30577
30604
  }
30578
30605
  ]
30579
30606
  };
30607
+ const tableCellSchema = zod.z.object({
30608
+ type: zod.z.literal("root"),
30609
+ children: zod.z.array(
30610
+ zod.z.object({
30611
+ type: zod.z.string(),
30612
+ children: zod.z.any().array()
30613
+ })
30614
+ ).refine(
30615
+ (value) => {
30616
+ const firstValue = value[0];
30617
+ return firstValue && firstValue.type === "p";
30618
+ },
30619
+ {
30620
+ message: `Table cell content cannot contain block elements like headers, blockquotes, or lists.`
30621
+ }
30622
+ ).refine(
30623
+ (value) => {
30624
+ var _a;
30625
+ if (value.length > 1) {
30626
+ const secondBlock = value[1];
30627
+ return secondBlock && secondBlock.children.length === 1 && !((_a = secondBlock.children[0]) == null ? void 0 : _a.text);
30628
+ }
30629
+ return true;
30630
+ },
30631
+ {
30632
+ message: `Table cells can only have 1 block level element.`
30633
+ }
30634
+ )
30635
+ });
30580
30636
  const stringifyCell = (cell) => {
30581
30637
  return mdx.stringifyMDX(cell, { name: "body", type: "rich-text" }, () => "");
30582
30638
  };
30639
+ const defineSchema = (config) => {
30640
+ schemaTools.validateSchema({ schema: config });
30641
+ return config;
30642
+ };
30643
+ const defineLegacyConfig = (config) => {
30644
+ schemaTools.validateSchema({ schema: config.schema });
30645
+ return config;
30646
+ };
30647
+ const defineStaticConfig = (config) => {
30648
+ if (!config.schema) {
30649
+ throw new Error("Static config must have a schema");
30650
+ }
30651
+ schemaTools.validateSchema({ schema: config.schema });
30652
+ return config;
30653
+ };
30654
+ const defineConfig = defineStaticConfig;
30583
30655
  Object.defineProperty(exports2, "NAMER", {
30584
30656
  enumerable: true,
30585
30657
  get: () => schemaTools.NAMER
package/dist/index.mjs CHANGED
@@ -1817,8 +1817,15 @@ class Form {
1817
1817
  return this.finalForm.subscribe(cb, options2);
1818
1818
  };
1819
1819
  this.handleSubmit = async (values, form, cb) => {
1820
+ var _a;
1820
1821
  try {
1821
- const response = await this.onSubmit(values, form, cb);
1822
+ const valOverride = await ((_a = this.beforeSubmit) == null ? void 0 : _a.call(this, values));
1823
+ if (valOverride) {
1824
+ for (const [key, value] of Object.entries(valOverride)) {
1825
+ form.change(key, value);
1826
+ }
1827
+ }
1828
+ const response = await this.onSubmit(valOverride || values, form, cb);
1822
1829
  form.initialize(values);
1823
1830
  return response;
1824
1831
  } catch (error) {
@@ -2356,6 +2363,7 @@ const InnerField = ({ field, form, fieldPlugins, index, activeFieldName }) => {
2356
2363
  {
2357
2364
  name: field.name,
2358
2365
  key: field.name,
2366
+ isEqual: (a, b) => isEqual(field, a, b),
2359
2367
  type,
2360
2368
  parse: parse2 ? (value, name) => parse2(value, name, field) : void 0,
2361
2369
  format: format2 ? (value, name) => format2(value, name, field) : void 0,
@@ -2413,6 +2421,18 @@ function getProp(name, field, plugin) {
2413
2421
  }
2414
2422
  return prop;
2415
2423
  }
2424
+ const isEqual = (field, a, b) => {
2425
+ const replacer = (key, value) => {
2426
+ if (key === "id") {
2427
+ return void 0;
2428
+ }
2429
+ return value;
2430
+ };
2431
+ if (field.type === "rich-text") {
2432
+ return JSON.stringify(a, replacer) === JSON.stringify(b, replacer);
2433
+ }
2434
+ return a === b;
2435
+ };
2416
2436
  const FF = Form$1;
2417
2437
  const FormLegacy = ({ form, children }) => {
2418
2438
  const [i, setI] = React.useState(0);
@@ -2457,7 +2477,7 @@ const Button = ({
2457
2477
  disabled,
2458
2478
  rounded = "full",
2459
2479
  children,
2460
- className,
2480
+ className = "",
2461
2481
  ...props
2462
2482
  }) => {
2463
2483
  const baseClasses = "icon-parent inline-flex items-center font-medium focus:outline-none focus:ring-2 focus:shadow-outline text-center inline-flex justify-center transition-all duration-150 ease-out ";
@@ -7120,7 +7140,7 @@ const BranchSelector = ({
7120
7140
  toolbarItems: [
7121
7141
  branch.githubPullRequestUrl && {
7122
7142
  name: "github-pr",
7123
- label: "View in Github",
7143
+ label: "View in GitHub",
7124
7144
  Icon: /* @__PURE__ */ React.createElement(BiLinkExternal, { className: "w-5 h-auto text-blue-500 opacity-70" }),
7125
7145
  onMouseDown: () => {
7126
7146
  window.open(branch.githubPullRequestUrl, "_blank");
@@ -7542,6 +7562,10 @@ class TinaMediaStore {
7542
7562
  `${this.url}/upload_url/${path}`,
7543
7563
  { method: "GET" }
7544
7564
  );
7565
+ if (res.status === 412) {
7566
+ const { message = "Unexpected error generating upload url" } = await res.json();
7567
+ throw new Error(message);
7568
+ }
7545
7569
  const { signedUrl } = await res.json();
7546
7570
  if (!signedUrl) {
7547
7571
  throw new Error("Unexpected error generating upload url");
@@ -10118,7 +10142,7 @@ class TinaCMS extends CMS {
10118
10142
  return {
10119
10143
  error: event.error,
10120
10144
  level: "error",
10121
- message: `Failed to upload file(s) ${event == null ? void 0 : event.uploaded.map((x) => x.file.name).join(", ")}. See error message:
10145
+ message: `Failed to upload file(s) ${event == null ? void 0 : event.uploaded.map((x) => x.file.name).join(", ")}.
10122
10146
 
10123
10147
  ${event == null ? void 0 : event.error.toString()}`
10124
10148
  };
@@ -10829,6 +10853,16 @@ const FormBuilder = ({
10829
10853
  const [createBranchModalOpen, setCreateBranchModalOpen] = React.useState(false);
10830
10854
  const tinaForm = form.tinaForm;
10831
10855
  const finalForm = form.tinaForm.finalForm;
10856
+ const schema = cms.api.tina.schema;
10857
+ React.useEffect(() => {
10858
+ var _a;
10859
+ const collection = schema.getCollectionByFullPath(tinaForm.relativePath);
10860
+ if ((_a = collection == null ? void 0 : collection.ui) == null ? void 0 : _a.beforeSubmit) {
10861
+ tinaForm.beforeSubmit = (values) => collection.ui.beforeSubmit({ cms, form: tinaForm, values });
10862
+ } else {
10863
+ tinaForm.beforeSubmit = void 0;
10864
+ }
10865
+ }, [tinaForm.relativePath]);
10832
10866
  const moveArrayItem = React.useCallback(
10833
10867
  (result) => {
10834
10868
  if (!result.destination || !finalForm)
@@ -10861,18 +10895,7 @@ const FormBuilder = ({
10861
10895
  {
10862
10896
  key: tinaForm.id,
10863
10897
  form: tinaForm.finalForm,
10864
- onSubmit: async (values, form2, cb) => {
10865
- var _a, _b;
10866
- const schema = cms.api.tina.schema;
10867
- const collection = schema.getCollectionByFullPath(tinaForm.relativePath);
10868
- const valOverride = ((_a = collection == null ? void 0 : collection.ui) == null ? void 0 : _a.beforeSubmit) ? await ((_b = collection == null ? void 0 : collection.ui) == null ? void 0 : _b.beforeSubmit({ cms, values, form: tinaForm })) : false;
10869
- if (valOverride) {
10870
- for (const [key, value] of Object.entries(valOverride)) {
10871
- form2.change(key, value);
10872
- }
10873
- }
10874
- return tinaForm.onSubmit(valOverride || values, form2, cb);
10875
- }
10898
+ onSubmit: tinaForm.onSubmit
10876
10899
  },
10877
10900
  ({
10878
10901
  handleSubmit,
@@ -29437,8 +29460,7 @@ const SearchInput = ({
29437
29460
  setSearch(searchInput);
29438
29461
  setSearchLoaded(false);
29439
29462
  },
29440
- variant: "primary",
29441
- type: "submit"
29463
+ variant: "primary"
29442
29464
  },
29443
29465
  "Search ",
29444
29466
  /* @__PURE__ */ React__default.createElement(BiSearch, { className: "w-5 h-full ml-1.5 opacity-70" })
@@ -29722,13 +29744,13 @@ const RenderForm$1 = ({
29722
29744
  }
29723
29745
  const defaultItem = customDefaults || // @ts-ignore internal types aren't up to date
29724
29746
  ((_d = template.ui) == null ? void 0 : _d.defaultItem) || // @ts-ignore
29725
- (template == null ? void 0 : template.defaultItem);
29747
+ (template == null ? void 0 : template.defaultItem) || {};
29726
29748
  const form = useMemo(() => {
29727
29749
  var _a2, _b2;
29728
29750
  const folderName = folder.fullyQualifiedName ? folder.name : "";
29729
29751
  return new Form({
29730
29752
  crudType: "create",
29731
- initialValues: typeof defaultItem === "function" ? defaultItem() : defaultItem,
29753
+ initialValues: typeof defaultItem === "function" ? { ...defaultItem(), _template: templateName } : { ...defaultItem, _template: templateName },
29732
29754
  extraSubscribeValues: { active: true, submitting: true, touched: true },
29733
29755
  onChange: (values) => {
29734
29756
  var _a3, _b3;
@@ -30260,10 +30282,12 @@ const MaybeRedirectToPreview = ({
30260
30282
  redirect,
30261
30283
  children
30262
30284
  }) => {
30285
+ const cms = useCMS$1();
30263
30286
  const navigate = useNavigate();
30264
30287
  React__default.useEffect(() => {
30288
+ const basePath = cms.flags.get("tina-basepath");
30265
30289
  if (redirect) {
30266
- navigate("/~");
30290
+ navigate(`/~${basePath ? `/${basePath}` : ""}`);
30267
30291
  }
30268
30292
  }, [redirect]);
30269
30293
  return children;
@@ -30507,22 +30531,6 @@ class RouteMappingPlugin {
30507
30531
  this.mapper = mapper;
30508
30532
  }
30509
30533
  }
30510
- const defineSchema = (config) => {
30511
- validateSchema({ schema: config });
30512
- return config;
30513
- };
30514
- const defineLegacyConfig = (config) => {
30515
- validateSchema({ schema: config.schema });
30516
- return config;
30517
- };
30518
- const defineStaticConfig = (config) => {
30519
- if (!config.schema) {
30520
- throw new Error("Static config must have a schema");
30521
- }
30522
- validateSchema({ schema: config.schema });
30523
- return config;
30524
- };
30525
- const defineConfig = defineStaticConfig;
30526
30534
  const tinaTableTemplate = {
30527
30535
  name: "table",
30528
30536
  label: "Table",
@@ -30532,6 +30540,13 @@ const tinaTableTemplate = {
30532
30540
  label: "First row is a header",
30533
30541
  type: "boolean"
30534
30542
  },
30543
+ {
30544
+ name: "align",
30545
+ label: "Align",
30546
+ type: "string",
30547
+ list: true,
30548
+ description: 'Possible values: "left", "right", or "center".'
30549
+ },
30535
30550
  {
30536
30551
  name: "tableRows",
30537
30552
  label: "Rows",
@@ -30544,7 +30559,7 @@ const tinaTableTemplate = {
30544
30559
  return {
30545
30560
  label: value.tableCells.map((cellItem) => {
30546
30561
  var _a;
30547
- return (_a = stringifyCell(cellItem.tableCell)) == null ? void 0 : _a.trim();
30562
+ return (_a = stringifyCell(cellItem.value)) == null ? void 0 : _a.trim();
30548
30563
  }).join(" | ")
30549
30564
  };
30550
30565
  }
@@ -30559,24 +30574,36 @@ const tinaTableTemplate = {
30559
30574
  list: true,
30560
30575
  type: "object",
30561
30576
  ui: {
30562
- itemProps: (value) => {
30577
+ itemProps: (cell) => {
30563
30578
  var _a;
30564
- if (value) {
30565
- if (value.tableCell) {
30579
+ if (cell) {
30580
+ if (cell.value) {
30566
30581
  return {
30567
- label: (_a = stringifyCell(value.tableCell)) == null ? void 0 : _a.trim()
30582
+ label: (_a = stringifyCell(cell.value)) == null ? void 0 : _a.trim()
30568
30583
  };
30569
30584
  }
30570
30585
  }
30571
- return { label: "Table Cell" };
30586
+ return { label: "Value" };
30572
30587
  }
30573
30588
  },
30574
30589
  fields: [
30575
30590
  {
30576
- label: "Table Cell",
30577
- description: "Note: table cells do not support block-level elements like headers, code blocks, or lists. Any block-level items other than the first paragraph will be ignored.",
30578
- name: "tableCell",
30579
- type: "rich-text"
30591
+ label: "Value",
30592
+ description: "Note: table cells do not support block-level elements like headers, code blocks, or lists. Any block-level items other than the first paragraph will be considered invalid.",
30593
+ name: "value",
30594
+ type: "rich-text",
30595
+ ui: {
30596
+ validate(value) {
30597
+ try {
30598
+ tableCellSchema.parse(value);
30599
+ } catch (e) {
30600
+ if (e instanceof z.ZodError) {
30601
+ return e.errors[0].message;
30602
+ }
30603
+ return e.message;
30604
+ }
30605
+ }
30606
+ }
30580
30607
  }
30581
30608
  ]
30582
30609
  }
@@ -30584,9 +30611,54 @@ const tinaTableTemplate = {
30584
30611
  }
30585
30612
  ]
30586
30613
  };
30614
+ const tableCellSchema = z.object({
30615
+ type: z.literal("root"),
30616
+ children: z.array(
30617
+ z.object({
30618
+ type: z.string(),
30619
+ children: z.any().array()
30620
+ })
30621
+ ).refine(
30622
+ (value) => {
30623
+ const firstValue = value[0];
30624
+ return firstValue && firstValue.type === "p";
30625
+ },
30626
+ {
30627
+ message: `Table cell content cannot contain block elements like headers, blockquotes, or lists.`
30628
+ }
30629
+ ).refine(
30630
+ (value) => {
30631
+ var _a;
30632
+ if (value.length > 1) {
30633
+ const secondBlock = value[1];
30634
+ return secondBlock && secondBlock.children.length === 1 && !((_a = secondBlock.children[0]) == null ? void 0 : _a.text);
30635
+ }
30636
+ return true;
30637
+ },
30638
+ {
30639
+ message: `Table cells can only have 1 block level element.`
30640
+ }
30641
+ )
30642
+ });
30587
30643
  const stringifyCell = (cell) => {
30588
30644
  return stringifyMDX(cell, { name: "body", type: "rich-text" }, () => "");
30589
30645
  };
30646
+ const defineSchema = (config) => {
30647
+ validateSchema({ schema: config });
30648
+ return config;
30649
+ };
30650
+ const defineLegacyConfig = (config) => {
30651
+ validateSchema({ schema: config.schema });
30652
+ return config;
30653
+ };
30654
+ const defineStaticConfig = (config) => {
30655
+ if (!config.schema) {
30656
+ throw new Error("Static config must have a schema");
30657
+ }
30658
+ validateSchema({ schema: config.schema });
30659
+ return config;
30660
+ };
30661
+ const defineConfig = defineStaticConfig;
30590
30662
  export {
30591
30663
  ActionButton,
30592
30664
  AddIcon,
@@ -81,17 +81,13 @@ declare type BaseComponents = {
81
81
  html_inline?: {
82
82
  value: string;
83
83
  };
84
- th?: {
85
- children: JSX.Element;
86
- };
87
- td?: {
88
- children: JSX.Element;
89
- };
90
- tr?: {
91
- children: JSX.Element;
92
- };
93
84
  table?: {
94
- children: JSX.Element;
85
+ align?: ('left' | 'right' | 'center')[];
86
+ tableRows: {
87
+ tableCells: {
88
+ value: TinaMarkdownContent;
89
+ }[];
90
+ }[];
95
91
  };
96
92
  component_missing?: {
97
93
  name: string;
@@ -72,7 +72,7 @@
72
72
  return MNode;
73
73
  };
74
74
  const Node = ({ components, child }) => {
75
- var _a, _b, _c, _d, _e;
75
+ var _a, _b, _c, _d, _e, _f;
76
76
  const { children, ...props } = child;
77
77
  switch (child.type) {
78
78
  case "h1":
@@ -154,23 +154,18 @@
154
154
  const header = (_e = (_d = child.props) == null ? void 0 : _d.tableRows) == null ? void 0 : _e.at(0);
155
155
  const TableComponent = components["table"] || ((props2) => /* @__PURE__ */ React.createElement("table", { ...props2 }));
156
156
  const TrComponent = components["tr"] || ((props2) => /* @__PURE__ */ React.createElement("tr", { ...props2 }));
157
- const ThComponent = components["th"] || ((props2) => /* @__PURE__ */ React.createElement("th", { ...props2 }));
158
- const TdComponent = components["td"] || ((props2) => /* @__PURE__ */ React.createElement("td", { ...props2 }));
157
+ const ThComponent = components["th"] || ((props2) => /* @__PURE__ */ React.createElement("th", { style: { textAlign: (props2 == null ? void 0 : props2.align) || "auto" }, ...props2 }));
158
+ const TdComponent = components["td"] || ((props2) => /* @__PURE__ */ React.createElement("td", { style: { textAlign: (props2 == null ? void 0 : props2.align) || "auto" }, ...props2 }));
159
+ const align = ((_f = child.props) == null ? void 0 : _f.align) || [];
159
160
  return /* @__PURE__ */ React.createElement(TableComponent, null, firstRowHeader && /* @__PURE__ */ React.createElement("thead", null, /* @__PURE__ */ React.createElement(TrComponent, null, header.tableCells.map((c, i) => {
160
161
  return /* @__PURE__ */ React.createElement(
161
162
  TinaMarkdown,
162
163
  {
163
164
  key: i,
164
165
  components: {
165
- p: (props2) => {
166
- if (ThComponent) {
167
- return /* @__PURE__ */ React.createElement(ThComponent, { ...props2 });
168
- } else {
169
- return /* @__PURE__ */ React.createElement("th", { ...props2 });
170
- }
171
- }
166
+ p: (props2) => /* @__PURE__ */ React.createElement(ThComponent, { align: align[i], ...props2 })
172
167
  },
173
- content: c.tableCell
168
+ content: c.value
174
169
  }
175
170
  );
176
171
  }))), /* @__PURE__ */ React.createElement("tbody", null, rows.map((row, i) => {
@@ -181,15 +176,9 @@
181
176
  {
182
177
  key: i2,
183
178
  components: {
184
- p: (props2) => {
185
- if (TdComponent) {
186
- return /* @__PURE__ */ React.createElement(TdComponent, { ...props2 });
187
- } else {
188
- return /* @__PURE__ */ React.createElement("td", { ...props2 });
189
- }
190
- }
179
+ p: (props2) => /* @__PURE__ */ React.createElement(TdComponent, { align: align[i2], ...props2 })
191
180
  },
192
- content: c.tableCell
181
+ content: c.value
193
182
  }
194
183
  );
195
184
  }));
@@ -69,7 +69,7 @@ const MemoNode = (props) => {
69
69
  return MNode;
70
70
  };
71
71
  const Node = ({ components, child }) => {
72
- var _a, _b, _c, _d, _e;
72
+ var _a, _b, _c, _d, _e, _f;
73
73
  const { children, ...props } = child;
74
74
  switch (child.type) {
75
75
  case "h1":
@@ -151,23 +151,18 @@ const Node = ({ components, child }) => {
151
151
  const header = (_e = (_d = child.props) == null ? void 0 : _d.tableRows) == null ? void 0 : _e.at(0);
152
152
  const TableComponent = components["table"] || ((props2) => /* @__PURE__ */ React.createElement("table", { ...props2 }));
153
153
  const TrComponent = components["tr"] || ((props2) => /* @__PURE__ */ React.createElement("tr", { ...props2 }));
154
- const ThComponent = components["th"] || ((props2) => /* @__PURE__ */ React.createElement("th", { ...props2 }));
155
- const TdComponent = components["td"] || ((props2) => /* @__PURE__ */ React.createElement("td", { ...props2 }));
154
+ const ThComponent = components["th"] || ((props2) => /* @__PURE__ */ React.createElement("th", { style: { textAlign: (props2 == null ? void 0 : props2.align) || "auto" }, ...props2 }));
155
+ const TdComponent = components["td"] || ((props2) => /* @__PURE__ */ React.createElement("td", { style: { textAlign: (props2 == null ? void 0 : props2.align) || "auto" }, ...props2 }));
156
+ const align = ((_f = child.props) == null ? void 0 : _f.align) || [];
156
157
  return /* @__PURE__ */ React.createElement(TableComponent, null, firstRowHeader && /* @__PURE__ */ React.createElement("thead", null, /* @__PURE__ */ React.createElement(TrComponent, null, header.tableCells.map((c, i) => {
157
158
  return /* @__PURE__ */ React.createElement(
158
159
  TinaMarkdown,
159
160
  {
160
161
  key: i,
161
162
  components: {
162
- p: (props2) => {
163
- if (ThComponent) {
164
- return /* @__PURE__ */ React.createElement(ThComponent, { ...props2 });
165
- } else {
166
- return /* @__PURE__ */ React.createElement("th", { ...props2 });
167
- }
168
- }
163
+ p: (props2) => /* @__PURE__ */ React.createElement(ThComponent, { align: align[i], ...props2 })
169
164
  },
170
- content: c.tableCell
165
+ content: c.value
171
166
  }
172
167
  );
173
168
  }))), /* @__PURE__ */ React.createElement("tbody", null, rows.map((row, i) => {
@@ -178,15 +173,9 @@ const Node = ({ components, child }) => {
178
173
  {
179
174
  key: i2,
180
175
  components: {
181
- p: (props2) => {
182
- if (TdComponent) {
183
- return /* @__PURE__ */ React.createElement(TdComponent, { ...props2 });
184
- } else {
185
- return /* @__PURE__ */ React.createElement("td", { ...props2 });
186
- }
187
- }
176
+ p: (props2) => /* @__PURE__ */ React.createElement(TdComponent, { align: align[i2], ...props2 })
188
177
  },
189
- content: c.tableCell
178
+ content: c.value
190
179
  }
191
180
  );
192
181
  }));
@@ -0,0 +1,5 @@
1
+ import { RichTextTemplate } from '@tinacms/schema-tools';
2
+ /**
3
+ * Out-of-the-box template for rendering basic markdown tables
4
+ */
5
+ export declare const tinaTableTemplate: RichTextTemplate;
@@ -44,6 +44,7 @@ export declare class Form<S = any, F extends Field = AnyField> implements Plugin
44
44
  loading: boolean;
45
45
  relativePath: string;
46
46
  crudType?: 'create' | 'update';
47
+ beforeSubmit?: (values: S) => Promise<void | S>;
47
48
  constructor({ id, label, fields, actions, buttons, global, reset, loadInitialValues, onChange, queries, ...options }: FormOptions<S, F>);
48
49
  /**
49
50
  * A unique identifier for Forms.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tinacms",
3
- "version": "1.5.22",
3
+ "version": "1.5.23",
4
4
  "main": "dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "exports": {
@@ -70,8 +70,8 @@
70
70
  "@react-types/shared": "^3.10.0",
71
71
  "@sambego/storybook-styles": "^1.0.0",
72
72
  "@tinacms/schema-tools": "1.4.13",
73
- "@tinacms/search": "1.0.12",
74
- "@tinacms/mdx": "1.3.20",
73
+ "@tinacms/search": "1.0.13",
74
+ "@tinacms/mdx": "1.3.21",
75
75
  "@tinacms/sharedctx": "1.0.2",
76
76
  "@udecode/plate-headless": "^21.4.0",
77
77
  "atob": "2.1.2",
@@ -80,7 +80,7 @@
80
80
  "date-fns": "2.30.0",
81
81
  "encoding": "0.1.13",
82
82
  "fetch-ponyfill": "^7.1.0",
83
- "final-form": "4.20.4",
83
+ "final-form": "4.20.10",
84
84
  "final-form-arrays": "^3.0.1",
85
85
  "final-form-set-field-data": "^1.0.2",
86
86
  "graphql": "15.8.0",