tinacms 2.2.0 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,6 @@
1
+ export { NodeCache } from './node-cache';
2
+ export type Cache = {
3
+ get: (key: string) => Promise<any>;
4
+ makeKey: (key: any) => string;
5
+ set: (key: string, value: any) => Promise<void>;
6
+ };
@@ -0,0 +1,2 @@
1
+ import type { Cache } from './index';
2
+ export declare const NodeCache: (dir: string, fs: any) => Cache;
@@ -0,0 +1,4 @@
1
+ /**
2
+
3
+ */
4
+ export * from './cache/index';
package/dist/cache.js ADDED
@@ -0,0 +1,36 @@
1
+ (function(global, factory) {
2
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.tinacms = {}));
3
+ })(this, function(exports2) {
4
+ "use strict";
5
+ const { createHash } = require("crypto");
6
+ const makeKey = (key) => {
7
+ const input = key && key instanceof Object ? JSON.stringify(key) : key || "";
8
+ return createHash("sha256").update(input).digest("hex");
9
+ };
10
+ const NodeCache = (dir, fs) => {
11
+ return {
12
+ makeKey,
13
+ get: async (key) => {
14
+ try {
15
+ const data = await fs.promises.readFile(`${dir}/${key}`, "utf-8");
16
+ return JSON.parse(data);
17
+ } catch (e) {
18
+ if (e.code === "ENOENT") {
19
+ return void 0;
20
+ }
21
+ throw e;
22
+ }
23
+ },
24
+ set: async (key, value) => {
25
+ await fs.promises.mkdir(dir, { recursive: true });
26
+ await fs.promises.writeFile(
27
+ `${dir}/${key}`,
28
+ JSON.stringify(value),
29
+ "utf-8"
30
+ );
31
+ }
32
+ };
33
+ };
34
+ exports2.NodeCache = NodeCache;
35
+ Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
36
+ });
package/dist/cache.mjs ADDED
@@ -0,0 +1,32 @@
1
+ const { createHash } = require("crypto");
2
+ const makeKey = (key) => {
3
+ const input = key && key instanceof Object ? JSON.stringify(key) : key || "";
4
+ return createHash("sha256").update(input).digest("hex");
5
+ };
6
+ const NodeCache = (dir, fs) => {
7
+ return {
8
+ makeKey,
9
+ get: async (key) => {
10
+ try {
11
+ const data = await fs.promises.readFile(`${dir}/${key}`, "utf-8");
12
+ return JSON.parse(data);
13
+ } catch (e) {
14
+ if (e.code === "ENOENT") {
15
+ return void 0;
16
+ }
17
+ throw e;
18
+ }
19
+ },
20
+ set: async (key, value) => {
21
+ await fs.promises.mkdir(dir, { recursive: true });
22
+ await fs.promises.writeFile(
23
+ `${dir}/${key}`,
24
+ JSON.stringify(value),
25
+ "utf-8"
26
+ );
27
+ }
28
+ };
29
+ };
30
+ export {
31
+ NodeCache
32
+ };
package/dist/client.js CHANGED
@@ -11,12 +11,17 @@
11
11
  token,
12
12
  url,
13
13
  queries,
14
- errorPolicy
14
+ errorPolicy,
15
+ cacheDir
15
16
  }) {
16
17
  this.apiUrl = url;
17
18
  this.readonlyToken = token == null ? void 0 : token.trim();
18
19
  this.queries = queries(this);
19
20
  this.errorPolicy = errorPolicy || "throw";
21
+ if (cacheDir && typeof require !== "undefined") {
22
+ const { NodeCache } = require("tinacms/dist/cache");
23
+ this.cache = NodeCache(cacheDir, require("fs"));
24
+ }
20
25
  }
21
26
  async request({ errorPolicy, ...args }, options) {
22
27
  var _a;
@@ -28,8 +33,8 @@
28
33
  headers.append("Content-Type", "application/json");
29
34
  if (options == null ? void 0 : options.fetchOptions) {
30
35
  if ((_a = options == null ? void 0 : options.fetchOptions) == null ? void 0 : _a.headers) {
31
- Object.entries(options.fetchOptions.headers).forEach(([key, value]) => {
32
- headers.append(key, value);
36
+ Object.entries(options.fetchOptions.headers).forEach(([key2, value]) => {
37
+ headers.append(key2, value);
33
38
  });
34
39
  }
35
40
  }
@@ -46,6 +51,14 @@
46
51
  redirect: "follow",
47
52
  ...providedFetchOptions
48
53
  };
54
+ let key = "";
55
+ if (this.cache) {
56
+ key = this.cache.makeKey(bodyString);
57
+ const value = await this.cache.get(key);
58
+ if (value) {
59
+ return value;
60
+ }
61
+ }
49
62
  const res = await fetchDefined(url, optionsObject);
50
63
  if (!res.ok) {
51
64
  let additionalInfo = "";
@@ -64,11 +77,15 @@
64
77
  ${json.errors.map((error) => error.message).join("\n")}`
65
78
  );
66
79
  }
67
- return {
80
+ const result = {
68
81
  data: json == null ? void 0 : json.data,
69
82
  errors: (json == null ? void 0 : json.errors) || null,
70
83
  query: args.query
71
84
  };
85
+ if (this.cache) {
86
+ await this.cache.set(key, result);
87
+ }
88
+ return result;
72
89
  }
73
90
  }
74
91
  function createClient(args) {
package/dist/client.mjs CHANGED
@@ -8,12 +8,17 @@ class TinaClient {
8
8
  token,
9
9
  url,
10
10
  queries,
11
- errorPolicy
11
+ errorPolicy,
12
+ cacheDir
12
13
  }) {
13
14
  this.apiUrl = url;
14
15
  this.readonlyToken = token == null ? void 0 : token.trim();
15
16
  this.queries = queries(this);
16
17
  this.errorPolicy = errorPolicy || "throw";
18
+ if (cacheDir && typeof require !== "undefined") {
19
+ const { NodeCache } = require("tinacms/dist/cache");
20
+ this.cache = NodeCache(cacheDir, require("fs"));
21
+ }
17
22
  }
18
23
  async request({ errorPolicy, ...args }, options) {
19
24
  var _a;
@@ -25,8 +30,8 @@ class TinaClient {
25
30
  headers.append("Content-Type", "application/json");
26
31
  if (options == null ? void 0 : options.fetchOptions) {
27
32
  if ((_a = options == null ? void 0 : options.fetchOptions) == null ? void 0 : _a.headers) {
28
- Object.entries(options.fetchOptions.headers).forEach(([key, value]) => {
29
- headers.append(key, value);
33
+ Object.entries(options.fetchOptions.headers).forEach(([key2, value]) => {
34
+ headers.append(key2, value);
30
35
  });
31
36
  }
32
37
  }
@@ -43,6 +48,14 @@ class TinaClient {
43
48
  redirect: "follow",
44
49
  ...providedFetchOptions
45
50
  };
51
+ let key = "";
52
+ if (this.cache) {
53
+ key = this.cache.makeKey(bodyString);
54
+ const value = await this.cache.get(key);
55
+ if (value) {
56
+ return value;
57
+ }
58
+ }
46
59
  const res = await fetchDefined(url, optionsObject);
47
60
  if (!res.ok) {
48
61
  let additionalInfo = "";
@@ -61,11 +74,15 @@ class TinaClient {
61
74
  ${json.errors.map((error) => error.message).join("\n")}`
62
75
  );
63
76
  }
64
- return {
77
+ const result = {
65
78
  data: json == null ? void 0 : json.data,
66
79
  errors: (json == null ? void 0 : json.errors) || null,
67
80
  query: args.query
68
81
  };
82
+ if (this.cache) {
83
+ await this.cache.set(key, result);
84
+ }
85
+ return result;
69
86
  }
70
87
  }
71
88
  function createClient(args) {
package/dist/index.js CHANGED
@@ -2745,13 +2745,13 @@ var __publicField = (obj, key, value) => {
2745
2745
  {
2746
2746
  type: "string",
2747
2747
  label: "Alt",
2748
- name: [templateName, "alt"].join("."),
2748
+ name: [templateName.replace(/\.props$/, ""), "alt"].join("."),
2749
2749
  component: "text"
2750
2750
  },
2751
2751
  {
2752
2752
  type: "string",
2753
2753
  label: "Caption",
2754
- name: [templateName, "caption"].join("."),
2754
+ name: [templateName.replace(/\.props$/, ""), "caption"].join("."),
2755
2755
  component: "text"
2756
2756
  }
2757
2757
  ]
@@ -4508,6 +4508,26 @@ var __publicField = (obj, key, value) => {
4508
4508
  }
4509
4509
  ));
4510
4510
  CommandItem.displayName = cmdk.Command.Item.displayName;
4511
+ const OptionComponent = ({
4512
+ id,
4513
+ value,
4514
+ field,
4515
+ _values,
4516
+ node,
4517
+ onSelect
4518
+ }) => {
4519
+ return /* @__PURE__ */ React.createElement(
4520
+ CommandItem,
4521
+ {
4522
+ key: `${id}-option`,
4523
+ value: id,
4524
+ onSelect: (currentValue) => {
4525
+ onSelect(currentValue === value ? "" : currentValue);
4526
+ }
4527
+ },
4528
+ /* @__PURE__ */ React.createElement("div", { className: "flex flex-col w-full" }, (field == null ? void 0 : field.optionComponent) && _values ? field.optionComponent(_values, node._internalSys) : /* @__PURE__ */ React.createElement("span", { className: "text-x" }, id))
4529
+ );
4530
+ };
4511
4531
  const Popover = PopoverPrimitive__namespace.Root;
4512
4532
  const PopoverTrigger = PopoverPrimitive__namespace.Trigger;
4513
4533
  const PopoverContent = React__namespace.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ React__namespace.createElement(PopoverPrimitive__namespace.Portal, null, /* @__PURE__ */ React__namespace.createElement(
@@ -4520,7 +4540,7 @@ var __publicField = (obj, key, value) => {
4520
4540
  side: "bottom",
4521
4541
  className: cn(
4522
4542
  "rounded-md border bg-white p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
4523
- "max-h-[30vh] overflow-y-auto",
4543
+ "max-h-[30vh] max-w-[30vh] overflow-y-auto",
4524
4544
  className
4525
4545
  ),
4526
4546
  ...props
@@ -4549,6 +4569,7 @@ var __publicField = (obj, key, value) => {
4549
4569
  _values
4550
4570
  _internalSys: _sys {
4551
4571
  filename
4572
+ path
4552
4573
  }
4553
4574
  }
4554
4575
  }
@@ -4598,10 +4619,16 @@ var __publicField = (obj, key, value) => {
4598
4619
  const [value, setValue] = React__namespace.useState(input.value);
4599
4620
  const [displayText, setDisplayText] = React__namespace.useState(null);
4600
4621
  const { optionSets, loading } = useGetOptionSets(cms, field.collections);
4622
+ const [filteredOptionsList, setFilteredOptionsList] = React__namespace.useState(optionSets);
4601
4623
  React__namespace.useEffect(() => {
4602
4624
  setDisplayText(getFilename(optionSets, value));
4603
4625
  input.onChange(value);
4604
4626
  }, [value, input, optionSets]);
4627
+ React__namespace.useEffect(() => {
4628
+ if (field.experimental___filter && optionSets.length > 0) {
4629
+ setFilteredOptionsList(field.experimental___filter(optionSets, void 0));
4630
+ }
4631
+ }, [optionSets, field.experimental___filter]);
4605
4632
  if (loading === true) {
4606
4633
  return /* @__PURE__ */ React__namespace.createElement(LoadingDots, { color: "var(--tina-color-primary)" });
4607
4634
  }
@@ -4618,41 +4645,52 @@ var __publicField = (obj, key, value) => {
4618
4645
  )), /* @__PURE__ */ React__namespace.createElement(PopoverContent, { className: "p-0 relative" }, /* @__PURE__ */ React__namespace.createElement(
4619
4646
  Command,
4620
4647
  {
4648
+ shouldFilter: !field.experimental___filter,
4621
4649
  filter: (value2, search) => {
4622
- if (value2.includes(search))
4650
+ if (value2.toLowerCase().replace(/\//g, "").includes(search.toLowerCase()))
4623
4651
  return 1;
4624
4652
  return 0;
4625
4653
  }
4626
4654
  },
4627
- /* @__PURE__ */ React__namespace.createElement(CommandInput, { placeholder: "Search reference..." }),
4655
+ /* @__PURE__ */ React__namespace.createElement(
4656
+ CommandInput,
4657
+ {
4658
+ placeholder: "Search reference...",
4659
+ onValueChange: (search) => {
4660
+ if (field.experimental___filter) {
4661
+ setFilteredOptionsList(
4662
+ field.experimental___filter(optionSets, search)
4663
+ );
4664
+ }
4665
+ }
4666
+ }
4667
+ ),
4628
4668
  /* @__PURE__ */ React__namespace.createElement(CommandEmpty, null, "No reference found"),
4629
- /* @__PURE__ */ React__namespace.createElement(CommandList, null, optionSets.length > 0 && optionSets.map(({ collection, edges }) => /* @__PURE__ */ React__namespace.createElement(
4669
+ /* @__PURE__ */ React__namespace.createElement(CommandList, null, filteredOptionsList.length > 0 && (filteredOptionsList == null ? void 0 : filteredOptionsList.map(({ collection, edges }) => /* @__PURE__ */ React__namespace.createElement(
4630
4670
  CommandGroup,
4631
4671
  {
4632
4672
  key: `${collection}-group`,
4633
4673
  heading: collection
4634
4674
  },
4635
- /* @__PURE__ */ React__namespace.createElement(CommandList, null, edges.map(
4636
- ({
4637
- node: {
4638
- id,
4639
- _internalSys: { filename },
4640
- _values: { title, name }
4641
- }
4642
- }) => /* @__PURE__ */ React__namespace.createElement(
4643
- CommandItem,
4675
+ /* @__PURE__ */ React__namespace.createElement(CommandList, null, edges == null ? void 0 : edges.map(({ node }) => {
4676
+ const { id, _values } = node;
4677
+ return /* @__PURE__ */ React__namespace.createElement(
4678
+ OptionComponent,
4644
4679
  {
4645
- key: `${id}-option`,
4646
- value: id || title,
4647
- onSelect: () => {
4648
- setValue(id);
4680
+ id,
4681
+ key: id,
4682
+ value,
4683
+ field,
4684
+ _values,
4685
+ node,
4686
+ onSelect: (currentValue) => {
4687
+ setValue(currentValue);
4649
4688
  setOpen(false);
4650
4689
  }
4651
- },
4652
- /* @__PURE__ */ React__namespace.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ React__namespace.createElement("span", { className: "font-semibold text-sm" }, title || name || id), (title || name) && /* @__PURE__ */ React__namespace.createElement("span", { className: "text-x" }, filename))
4653
- )
4654
- ))
4655
- )))
4690
+ }
4691
+ );
4692
+ }))
4693
+ ))))
4656
4694
  ))));
4657
4695
  };
4658
4696
  const useGetNode = (cms, id) => {
@@ -5814,19 +5852,17 @@ var __publicField = (obj, key, value) => {
5814
5852
  return "Required";
5815
5853
  }
5816
5854
  };
5817
- const TextareaField = wrapFieldsWithMeta(
5818
- (props) => {
5819
- const ref = React__namespace.useRef(null);
5820
- React__namespace.useEffect(() => {
5821
- if (ref.current && props.field.experimental_focusIntent) {
5822
- const el = ref.current;
5823
- el.focus();
5824
- el.setSelectionRange(el.value.length, el.value.length);
5825
- }
5826
- }, [props.field.experimental_focusIntent, ref]);
5827
- return /* @__PURE__ */ React__namespace.createElement(TextArea, { ref, ...props.input });
5828
- }
5829
- );
5855
+ const TextareaField = wrapFieldsWithMeta((props) => {
5856
+ const ref = React__namespace.useRef(null);
5857
+ React__namespace.useEffect(() => {
5858
+ if (ref.current && props.field.experimental_focusIntent) {
5859
+ const el = ref.current;
5860
+ el.focus();
5861
+ el.setSelectionRange(el.value.length, el.value.length);
5862
+ }
5863
+ }, [props.field.experimental_focusIntent, ref]);
5864
+ return /* @__PURE__ */ React__namespace.createElement(TextArea, { ref, ...props.input });
5865
+ });
5830
5866
  const TextareaFieldPlugin = {
5831
5867
  name: "textarea",
5832
5868
  Component: TextareaField,
@@ -10684,6 +10720,7 @@ var __publicField = (obj, key, value) => {
10684
10720
  setLoadFolders(true);
10685
10721
  resetOffset();
10686
10722
  resetList();
10723
+ setActiveItem(false);
10687
10724
  } else {
10688
10725
  setActiveItem(item);
10689
10726
  }
@@ -10846,6 +10883,7 @@ var __publicField = (obj, key, value) => {
10846
10883
  setLoadFolders(true);
10847
10884
  resetOffset();
10848
10885
  resetList();
10886
+ setActiveItem(false);
10849
10887
  }
10850
10888
  }
10851
10889
  )), cms.media.store.isStatic ? null : /* @__PURE__ */ React.createElement("div", { className: "flex flex-wrap items-center gap-4" }, /* @__PURE__ */ React.createElement(
@@ -10857,6 +10895,7 @@ var __publicField = (obj, key, value) => {
10857
10895
  setRefreshing(true);
10858
10896
  resetOffset();
10859
10897
  resetList();
10898
+ setActiveItem(false);
10860
10899
  },
10861
10900
  className: "whitespace-nowrap"
10862
10901
  },
@@ -31187,7 +31226,8 @@ This will work when developing locally but NOT when deployed to production.
31187
31226
  )), /* @__PURE__ */ React.createElement("div", { className: "flex w-full md:w-auto gap-3" }, /* @__PURE__ */ React.createElement(
31188
31227
  Button$1,
31189
31228
  {
31190
- onClick: () => {
31229
+ onClick: (e) => {
31230
+ e.preventDefault();
31191
31231
  setSearch(searchInput);
31192
31232
  setSearchLoaded(false);
31193
31233
  },
@@ -31199,7 +31239,8 @@ This will work when developing locally but NOT when deployed to production.
31199
31239
  ), search && searchLoaded && /* @__PURE__ */ React.createElement(
31200
31240
  Button$1,
31201
31241
  {
31202
- onClick: () => {
31242
+ onClick: (e) => {
31243
+ e.preventDefault();
31203
31244
  setSearch("");
31204
31245
  setSearchInput("");
31205
31246
  },
@@ -32576,7 +32617,6 @@ This will work when developing locally but NOT when deployed to production.
32576
32617
  exports2.TextArea = TextArea;
32577
32618
  exports2.TextField = TextField;
32578
32619
  exports2.TextFieldPlugin = TextFieldPlugin;
32579
- exports2.TextareaField = TextareaField;
32580
32620
  exports2.TextareaFieldPlugin = TextareaFieldPlugin;
32581
32621
  exports2.Tina = Tina;
32582
32622
  exports2.TinaAdmin = TinaAdmin;
package/dist/index.mjs CHANGED
@@ -2768,13 +2768,13 @@ class Form {
2768
2768
  {
2769
2769
  type: "string",
2770
2770
  label: "Alt",
2771
- name: [templateName, "alt"].join("."),
2771
+ name: [templateName.replace(/\.props$/, ""), "alt"].join("."),
2772
2772
  component: "text"
2773
2773
  },
2774
2774
  {
2775
2775
  type: "string",
2776
2776
  label: "Caption",
2777
- name: [templateName, "caption"].join("."),
2777
+ name: [templateName.replace(/\.props$/, ""), "caption"].join("."),
2778
2778
  component: "text"
2779
2779
  }
2780
2780
  ]
@@ -4531,6 +4531,26 @@ const CommandItem = React.forwardRef(({ className, ...props }, ref) => /* @__PUR
4531
4531
  }
4532
4532
  ));
4533
4533
  CommandItem.displayName = Command$1.Item.displayName;
4534
+ const OptionComponent = ({
4535
+ id,
4536
+ value,
4537
+ field,
4538
+ _values,
4539
+ node,
4540
+ onSelect
4541
+ }) => {
4542
+ return /* @__PURE__ */ React__default.createElement(
4543
+ CommandItem,
4544
+ {
4545
+ key: `${id}-option`,
4546
+ value: id,
4547
+ onSelect: (currentValue) => {
4548
+ onSelect(currentValue === value ? "" : currentValue);
4549
+ }
4550
+ },
4551
+ /* @__PURE__ */ React__default.createElement("div", { className: "flex flex-col w-full" }, (field == null ? void 0 : field.optionComponent) && _values ? field.optionComponent(_values, node._internalSys) : /* @__PURE__ */ React__default.createElement("span", { className: "text-x" }, id))
4552
+ );
4553
+ };
4534
4554
  const Popover = PopoverPrimitive.Root;
4535
4555
  const PopoverTrigger = PopoverPrimitive.Trigger;
4536
4556
  const PopoverContent = React.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ React.createElement(PopoverPrimitive.Portal, null, /* @__PURE__ */ React.createElement(
@@ -4543,7 +4563,7 @@ const PopoverContent = React.forwardRef(({ className, align = "center", sideOffs
4543
4563
  side: "bottom",
4544
4564
  className: cn(
4545
4565
  "rounded-md border bg-white p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
4546
- "max-h-[30vh] overflow-y-auto",
4566
+ "max-h-[30vh] max-w-[30vh] overflow-y-auto",
4547
4567
  className
4548
4568
  ),
4549
4569
  ...props
@@ -4572,6 +4592,7 @@ const useGetOptionSets = (cms, collections) => {
4572
4592
  _values
4573
4593
  _internalSys: _sys {
4574
4594
  filename
4595
+ path
4575
4596
  }
4576
4597
  }
4577
4598
  }
@@ -4621,10 +4642,16 @@ const ComboboxDemo = ({
4621
4642
  const [value, setValue] = React.useState(input.value);
4622
4643
  const [displayText, setDisplayText] = React.useState(null);
4623
4644
  const { optionSets, loading } = useGetOptionSets(cms, field.collections);
4645
+ const [filteredOptionsList, setFilteredOptionsList] = React.useState(optionSets);
4624
4646
  React.useEffect(() => {
4625
4647
  setDisplayText(getFilename(optionSets, value));
4626
4648
  input.onChange(value);
4627
4649
  }, [value, input, optionSets]);
4650
+ React.useEffect(() => {
4651
+ if (field.experimental___filter && optionSets.length > 0) {
4652
+ setFilteredOptionsList(field.experimental___filter(optionSets, void 0));
4653
+ }
4654
+ }, [optionSets, field.experimental___filter]);
4628
4655
  if (loading === true) {
4629
4656
  return /* @__PURE__ */ React.createElement(LoadingDots, { color: "var(--tina-color-primary)" });
4630
4657
  }
@@ -4641,41 +4668,52 @@ const ComboboxDemo = ({
4641
4668
  )), /* @__PURE__ */ React.createElement(PopoverContent, { className: "p-0 relative" }, /* @__PURE__ */ React.createElement(
4642
4669
  Command,
4643
4670
  {
4671
+ shouldFilter: !field.experimental___filter,
4644
4672
  filter: (value2, search) => {
4645
- if (value2.includes(search))
4673
+ if (value2.toLowerCase().replace(/\//g, "").includes(search.toLowerCase()))
4646
4674
  return 1;
4647
4675
  return 0;
4648
4676
  }
4649
4677
  },
4650
- /* @__PURE__ */ React.createElement(CommandInput, { placeholder: "Search reference..." }),
4678
+ /* @__PURE__ */ React.createElement(
4679
+ CommandInput,
4680
+ {
4681
+ placeholder: "Search reference...",
4682
+ onValueChange: (search) => {
4683
+ if (field.experimental___filter) {
4684
+ setFilteredOptionsList(
4685
+ field.experimental___filter(optionSets, search)
4686
+ );
4687
+ }
4688
+ }
4689
+ }
4690
+ ),
4651
4691
  /* @__PURE__ */ React.createElement(CommandEmpty, null, "No reference found"),
4652
- /* @__PURE__ */ React.createElement(CommandList, null, optionSets.length > 0 && optionSets.map(({ collection, edges }) => /* @__PURE__ */ React.createElement(
4692
+ /* @__PURE__ */ React.createElement(CommandList, null, filteredOptionsList.length > 0 && (filteredOptionsList == null ? void 0 : filteredOptionsList.map(({ collection, edges }) => /* @__PURE__ */ React.createElement(
4653
4693
  CommandGroup,
4654
4694
  {
4655
4695
  key: `${collection}-group`,
4656
4696
  heading: collection
4657
4697
  },
4658
- /* @__PURE__ */ React.createElement(CommandList, null, edges.map(
4659
- ({
4660
- node: {
4661
- id,
4662
- _internalSys: { filename },
4663
- _values: { title, name }
4664
- }
4665
- }) => /* @__PURE__ */ React.createElement(
4666
- CommandItem,
4698
+ /* @__PURE__ */ React.createElement(CommandList, null, edges == null ? void 0 : edges.map(({ node }) => {
4699
+ const { id, _values } = node;
4700
+ return /* @__PURE__ */ React.createElement(
4701
+ OptionComponent,
4667
4702
  {
4668
- key: `${id}-option`,
4669
- value: id || title,
4670
- onSelect: () => {
4671
- setValue(id);
4703
+ id,
4704
+ key: id,
4705
+ value,
4706
+ field,
4707
+ _values,
4708
+ node,
4709
+ onSelect: (currentValue) => {
4710
+ setValue(currentValue);
4672
4711
  setOpen(false);
4673
4712
  }
4674
- },
4675
- /* @__PURE__ */ React.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ React.createElement("span", { className: "font-semibold text-sm" }, title || name || id), (title || name) && /* @__PURE__ */ React.createElement("span", { className: "text-x" }, filename))
4676
- )
4677
- ))
4678
- )))
4713
+ }
4714
+ );
4715
+ }))
4716
+ ))))
4679
4717
  ))));
4680
4718
  };
4681
4719
  const useGetNode = (cms, id) => {
@@ -5837,19 +5875,17 @@ const RadioGroupFieldPlugin = {
5837
5875
  return "Required";
5838
5876
  }
5839
5877
  };
5840
- const TextareaField = wrapFieldsWithMeta(
5841
- (props) => {
5842
- const ref = React.useRef(null);
5843
- React.useEffect(() => {
5844
- if (ref.current && props.field.experimental_focusIntent) {
5845
- const el = ref.current;
5846
- el.focus();
5847
- el.setSelectionRange(el.value.length, el.value.length);
5848
- }
5849
- }, [props.field.experimental_focusIntent, ref]);
5850
- return /* @__PURE__ */ React.createElement(TextArea, { ref, ...props.input });
5851
- }
5852
- );
5878
+ const TextareaField = wrapFieldsWithMeta((props) => {
5879
+ const ref = React.useRef(null);
5880
+ React.useEffect(() => {
5881
+ if (ref.current && props.field.experimental_focusIntent) {
5882
+ const el = ref.current;
5883
+ el.focus();
5884
+ el.setSelectionRange(el.value.length, el.value.length);
5885
+ }
5886
+ }, [props.field.experimental_focusIntent, ref]);
5887
+ return /* @__PURE__ */ React.createElement(TextArea, { ref, ...props.input });
5888
+ });
5853
5889
  const TextareaFieldPlugin = {
5854
5890
  name: "textarea",
5855
5891
  Component: TextareaField,
@@ -10707,6 +10743,7 @@ function MediaPicker({
10707
10743
  setLoadFolders(true);
10708
10744
  resetOffset();
10709
10745
  resetList();
10746
+ setActiveItem(false);
10710
10747
  } else {
10711
10748
  setActiveItem(item);
10712
10749
  }
@@ -10869,6 +10906,7 @@ function MediaPicker({
10869
10906
  setLoadFolders(true);
10870
10907
  resetOffset();
10871
10908
  resetList();
10909
+ setActiveItem(false);
10872
10910
  }
10873
10911
  }
10874
10912
  )), cms.media.store.isStatic ? null : /* @__PURE__ */ React__default.createElement("div", { className: "flex flex-wrap items-center gap-4" }, /* @__PURE__ */ React__default.createElement(
@@ -10880,6 +10918,7 @@ function MediaPicker({
10880
10918
  setRefreshing(true);
10881
10919
  resetOffset();
10882
10920
  resetList();
10921
+ setActiveItem(false);
10883
10922
  },
10884
10923
  className: "whitespace-nowrap"
10885
10924
  },
@@ -31210,7 +31249,8 @@ const SearchInput = ({
31210
31249
  )), /* @__PURE__ */ React__default.createElement("div", { className: "flex w-full md:w-auto gap-3" }, /* @__PURE__ */ React__default.createElement(
31211
31250
  Button$1,
31212
31251
  {
31213
- onClick: () => {
31252
+ onClick: (e) => {
31253
+ e.preventDefault();
31214
31254
  setSearch(searchInput);
31215
31255
  setSearchLoaded(false);
31216
31256
  },
@@ -31222,7 +31262,8 @@ const SearchInput = ({
31222
31262
  ), search && searchLoaded && /* @__PURE__ */ React__default.createElement(
31223
31263
  Button$1,
31224
31264
  {
31225
- onClick: () => {
31265
+ onClick: (e) => {
31266
+ e.preventDefault();
31226
31267
  setSearch("");
31227
31268
  setSearchInput("");
31228
31269
  },
@@ -32593,7 +32634,6 @@ export {
32593
32634
  TextArea,
32594
32635
  TextField,
32595
32636
  TextFieldPlugin,
32596
- TextareaField,
32597
32637
  TextareaFieldPlugin,
32598
32638
  Tina,
32599
32639
  TinaAdmin,
@@ -104,7 +104,7 @@
104
104
  const Component2 = components[child.type];
105
105
  return /* @__PURE__ */ React.createElement(Component2, { ...props });
106
106
  }
107
- return /* @__PURE__ */ React.createElement("img", { src: child.url, alt: child.caption });
107
+ return /* @__PURE__ */ React.createElement("img", { src: child.url, alt: child.alt });
108
108
  case "a":
109
109
  if (components[child.type]) {
110
110
  const Component2 = components[child.type];
@@ -101,7 +101,7 @@ const Node = ({ components, child }) => {
101
101
  const Component2 = components[child.type];
102
102
  return /* @__PURE__ */ React.createElement(Component2, { ...props });
103
103
  }
104
- return /* @__PURE__ */ React.createElement("img", { src: child.url, alt: child.caption });
104
+ return /* @__PURE__ */ React.createElement("img", { src: child.url, alt: child.alt });
105
105
  case "a":
106
106
  if (components[child.type]) {
107
107
  const Component2 = components[child.type];
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import { OptionComponentProps } from '../model/option-component-props';
3
+ declare const OptionComponent: React.FC<OptionComponentProps>;
4
+ export default OptionComponent;
@@ -3,7 +3,16 @@ type Option = {
3
3
  value: string;
4
4
  label: string;
5
5
  };
6
- export interface ReferenceFieldProps {
6
+ type ReferenceFieldOptions = {
7
+ optionComponent?: OptionComponent;
8
+ experimental___filter?: (list: Array<any>, searchQuery: string) => Array<any>;
9
+ };
10
+ type OptionComponent = (props: unknown, _sys: InternalSys) => React.ReactElement | string;
11
+ export interface InternalSys {
12
+ filename: string;
13
+ path: string;
14
+ }
15
+ export interface ReferenceFieldProps extends ReferenceFieldOptions {
7
16
  label?: string;
8
17
  name: string;
9
18
  component: string;
@@ -0,0 +1,13 @@
1
+ import { InternalSys } from './reference-field-props';
2
+ export interface OptionComponentProps {
3
+ id: string;
4
+ value: string;
5
+ field?: {
6
+ optionComponent?: (values: unknown, internalSys: InternalSys) => React.ReactNode;
7
+ };
8
+ _values?: unknown;
9
+ node: {
10
+ _internalSys: InternalSys;
11
+ };
12
+ onSelect: (currentValue: string) => void;
13
+ }
@@ -0,0 +1,21 @@
1
+ export type Option = {
2
+ value: string;
3
+ label: string;
4
+ };
5
+ type OptionComponent = (props: unknown, _sys: InternalSys) => React.ReactElement | string;
6
+ export interface InternalSys {
7
+ filename: string;
8
+ path: string;
9
+ }
10
+ type ReferenceFieldOptions = {
11
+ optionComponent?: OptionComponent;
12
+ experimental___filter?: (list: Array<any>, searchQuery: string) => Array<any>;
13
+ };
14
+ export interface ReferenceFieldProps extends ReferenceFieldOptions {
15
+ label?: string;
16
+ name: string;
17
+ component: string;
18
+ collections: string[];
19
+ options: (Option | string)[];
20
+ }
21
+ export {};
@@ -0,0 +1,16 @@
1
+ import { TinaCMS } from '../../../../tina-cms';
2
+ export interface ReferenceLinkProps {
3
+ cms: TinaCMS;
4
+ input: any;
5
+ }
6
+ export type Document = {
7
+ _sys: {
8
+ collection: {
9
+ name: string;
10
+ };
11
+ breadcrumbs: string[];
12
+ };
13
+ };
14
+ export interface Response {
15
+ node: Document;
16
+ }
@@ -0,0 +1,8 @@
1
+ import { ReferenceFieldProps, Option } from './reference-field-props';
2
+ export interface ReferenceProps {
3
+ name: string;
4
+ input: any;
5
+ field: ReferenceFieldProps;
6
+ disabled?: boolean;
7
+ options?: (Option | string)[];
8
+ }
@@ -1,8 +1,4 @@
1
1
  import * as React from 'react';
2
- import type { TinaCMS } from '../../../tina-cms';
3
- interface ReferenceLinkProps {
4
- cms: TinaCMS;
5
- input: any;
6
- }
2
+ import { ReferenceLinkProps } from './model/reference-link-props';
7
3
  declare const ReferenceLink: React.FC<ReferenceLinkProps>;
8
4
  export default ReferenceLink;
@@ -1,7 +1,7 @@
1
- import { Field } from '../../../forms';
1
+ import type { Field } from '../../../forms';
2
2
  import type { TinaCMS } from '../../../tina-cms';
3
3
  import * as React from 'react';
4
- import type { ReferenceFieldProps } from './index';
4
+ import type { ReferenceFieldProps } from './model/reference-field-props';
5
5
  interface ReferenceSelectProps {
6
6
  cms: TinaCMS;
7
7
  input: any;
@@ -1,8 +1,5 @@
1
1
  import * as React from 'react';
2
2
  import { InputProps } from '../components';
3
- export declare const TextareaField: (props: import("./wrap-field-with-meta").InputFieldType<{
4
- input: InputProps;
5
- }, {}>) => React.JSX.Element;
6
3
  export declare const TextareaFieldPlugin: {
7
4
  name: string;
8
5
  Component: (props: import("./wrap-field-with-meta").InputFieldType<{
@@ -1,11 +1,12 @@
1
- import type { GraphQLError } from 'graphql';
2
1
  import type { Config } from '@tinacms/schema-tools';
2
+ import type { Cache } from '../cache/index';
3
3
  export declare const TINA_HOST = "content.tinajs.io";
4
4
  export interface TinaClientArgs<GenQueries = Record<string, unknown>> {
5
5
  url: string;
6
6
  token?: string;
7
7
  queries: (client: TinaClient<GenQueries>) => GenQueries;
8
8
  errorPolicy?: Config['client']['errorPolicy'];
9
+ cacheDir?: string;
9
10
  }
10
11
  export type TinaClientRequestArgs = {
11
12
  variables?: Record<string, any>;
@@ -23,13 +24,10 @@ export declare class TinaClient<GenQueries> {
23
24
  readonlyToken?: string;
24
25
  queries: GenQueries;
25
26
  errorPolicy: Config['client']['errorPolicy'];
26
- constructor({ token, url, queries, errorPolicy, }: TinaClientArgs<GenQueries>);
27
+ cache: Cache;
28
+ constructor({ token, url, queries, errorPolicy, cacheDir, }: TinaClientArgs<GenQueries>);
27
29
  request<DataType extends Record<string, any> = any>({ errorPolicy, ...args }: TinaClientRequestArgs, options: {
28
30
  fetchOptions?: Parameters<typeof fetch>[1];
29
- }): Promise<{
30
- data: DataType;
31
- errors: GraphQLError[] | null;
32
- query: string;
33
- }>;
31
+ }): Promise<any>;
34
32
  }
35
33
  export declare function createClient<GenQueries>(args: TinaClientArgs<GenQueries>): TinaClient<GenQueries>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tinacms",
3
- "version": "2.2.0",
3
+ "version": "2.2.2",
4
4
  "main": "dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "exports": {
@@ -14,6 +14,11 @@
14
14
  "import": "./dist/client.mjs",
15
15
  "require": "./dist/client.js"
16
16
  },
17
+ "./dist/cache": {
18
+ "types": "./dist/cache.d.ts",
19
+ "import": "./dist/cache.mjs",
20
+ "require": "./dist/cache.js"
21
+ },
17
22
  "./dist/edit-state": {
18
23
  "types": "./dist/edit-state.d.ts",
19
24
  "import": "./dist/edit-state.mjs",
@@ -44,7 +49,8 @@
44
49
  "src/rich-text/index.tsx",
45
50
  "src/rich-text/prism.tsx",
46
51
  "src/react.tsx",
47
- "src/client.ts"
52
+ "src/client.ts",
53
+ "src/cache.ts"
48
54
  ]
49
55
  },
50
56
  "typings": "dist/index.d.ts",
@@ -117,9 +123,9 @@
117
123
  "clsx": "^2.1.1",
118
124
  "yup": "^1.4.0",
119
125
  "zod": "^3.23.8",
120
- "@tinacms/mdx": "1.4.0",
121
- "@tinacms/schema-tools": "1.6.0",
122
- "@tinacms/search": "1.0.26"
126
+ "@tinacms/mdx": "1.4.2",
127
+ "@tinacms/schema-tools": "1.6.2",
128
+ "@tinacms/search": "1.0.28"
123
129
  },
124
130
  "devDependencies": {
125
131
  "@graphql-tools/utils": "^10.3.3",
@@ -152,7 +158,7 @@
152
158
  "typescript": "^5.5.4",
153
159
  "vite": "^5.3.5",
154
160
  "vitest": "^2.0.5",
155
- "@tinacms/scripts": "1.2.0"
161
+ "@tinacms/scripts": "1.2.1"
156
162
  },
157
163
  "peerDependencies": {
158
164
  "react": ">=16.14.0",