@sanity/language-filter 3.1.2 → 3.2.0

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/README.md CHANGED
@@ -47,7 +47,7 @@ yarn add @sanity/language-filter
47
47
 
48
48
  Add it as a plugin in sanity.config.ts (or .js), and configure it:
49
49
 
50
- ```
50
+ ```ts
51
51
  import {defineConfig} from 'sanity'
52
52
  import {languageFilter} from '@sanity/language-filter'
53
53
 
@@ -77,12 +77,46 @@ Add it as a plugin in sanity.config.ts (or .js), and configure it:
77
77
 
78
78
  Config properties:
79
79
 
80
- - `supportedLanguages` is an array of languages with `id` and `title`. If your localized fields are defined using our recommended way described here (https://www.sanity.io/docs/localization), you probably want to share this list of supported languages between this config and your schema.
80
+ - `supportedLanguages` can be either:
81
+ -- An static array of language objects with `id` and `title`. If your localized fields are defined using our recommended way described here (https://www.sanity.io/docs/localization), you probably want to share this list of supported languages between this config and your schema.
82
+ -- A function that returns a promise resolving to an array of language objects with `id` and `title`. This is useful if you want to fetch the list of supported languages from an external source. See [Loading languages](#loading-languages) for more details.
81
83
  - `defaultLanguages` (optional) is an array of strings where each entry must match an `id` from the `supportedLanguages` array. These languages will be listed by default and will not be possible to unselect. If no `defaultLanguages` is configured, all localized fields will be selected by default.
82
84
  - `documentTypes` (optional) is an array of strings where each entry must match a `name` from your document schemas. If defined, this property will be used to conditionally show the language filter on specific document schema types. If undefined, the language filter will show on all document schema types.
83
85
  - `filterField` (optional) is a function that must return true if the field should be displayed. It is passed the enclosing type (e.g the object type containing the localized fields, the field, and an array of the currently selected language ids.
84
86
  This function is called for all fields and in objects for documents that have language filter enabled.
85
87
  _Default:_ `!enclosingType.name.startsWith('locale') || selectedLanguageIds.includes(field.name)`
88
+ - `apiVersion` (optional) used for the Sanity Client when asynchronously loading languages.
89
+
90
+ ## Loading languages
91
+
92
+ Languages must be an array of objects with an `id` and `title`.
93
+
94
+ ```ts
95
+ languages: [
96
+ {id: 'en', title: 'English'},
97
+ {id: 'fr', title: 'French'}
98
+ ],
99
+ ```
100
+
101
+ Or an asynchronous function that returns an array of objects with an `id` and `title`.
102
+
103
+ ```ts
104
+ languages: async () => {
105
+ const response = await fetch('https://example.com/languages')
106
+ return response.json()
107
+ }
108
+ ```
109
+
110
+ The async function contains a configured Sanity Client in the first parameter, allowing you to store Language options as documents. Your query should return an array of objects with an `id` and `title`.
111
+
112
+ ```ts
113
+ languages: async (client) => {
114
+ const response = await client.fetch(`*[_type == "language"]{ id, title }`)
115
+ return response
116
+ },
117
+ ```
118
+
119
+ `@sanity/language-filter`'s asynchronous language loading does not currently support modifying the query based on a value in the current document.
86
120
 
87
121
  ## Changes in V3
88
122
 
@@ -106,13 +140,6 @@ export const myDocumentSchema = {
106
140
  }
107
141
  ```
108
142
 
109
- ### State management
110
-
111
- Selected languages are now stored as `langs` url-param state; this allows users to copy paste
112
- a url in the studio with the currently selected languages preselected.
113
-
114
- Previously this state was stored in localstorage.
115
-
116
143
  ## License
117
144
 
118
145
  MIT-licensed. See LICENSE.
package/lib/index.esm.js CHANGED
@@ -1 +1 @@
1
- var e;const t=["members","schemaType","renderDefault"];function n(e,t){if(null==e)return{};var n,r,l=function(e,t){if(null==e)return{};var n,r,l={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(l[n]=e[n]);return l}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(l[n]=e[n])}return l}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){i(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var r=n.call(e,t||"default");if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}import{jsx as o,jsxs as a,Fragment as u}from"react/jsx-runtime";import{useFormValue as c,TextWithTone as s,definePlugin as d,isObjectSchemaType as g}from"sanity";import{useState as f,createContext as p,useMemo as m,useContext as y,useCallback as h}from"react";import{Box as b,useClickOutside as v,Stack as O,Card as L,Button as j,Flex as S,Text as w,TextInput as T,Popover as P,Badge as x}from"@sanity/ui";import D from"styled-components";import{EyeClosedIcon as I,EyeOpenIcon as k,TranslateIcon as C,CheckmarkCircleIcon as N,CircleIcon as F}from"@sanity/icons";const z=(e,t,n)=>!e.name.startsWith("locale")||n.includes(t.name);function A(e,t){var n,r;const l=function(e){return"object"===(null==e?void 0:e.jsonType)&&"document"===E(e).name}(e)&&(null==(n=null==e?void 0:e.options)?void 0:n.languageFilter),i=!t.documentTypes;return!!(i&&!1!==l||!i&&l||e&&(null==(r=t.documentTypes)?void 0:r.includes(e.name)))}function E(e){return e.type?E(e.type):e}const J="@sanity/plugin/language-filter/selected-languages";function _(e){const t=H(e).map((e=>e.id));let n=t;try{const e=window.localStorage.getItem(J);e&&(n=JSON.parse(e))}catch(e){}var r;return r=t,n=n.filter((e=>r.includes(e))),n}function H(e){let{supportedLanguages:t,defaultLanguages:n}=e;return t.filter((e=>!(null==n?void 0:n.includes(e.id))))}const W={options:{supportedLanguages:[],defaultLanguages:[],documentTypes:[],filterField:z},selectedLanguageIds:[],setSelectedLanguageIds:()=>console.error("LanguageFilterStudioContext not initialized")},q=p(W);function B(e){const t=m((()=>l(l({},W.options),e.options)),[e.options]),[n,r]=function(e){return f((()=>{var t;return[...null!=(t=e.defaultLanguages)?t:[],..._(e)]}))}(t);return o(q.Provider,{value:{options:t,selectedLanguageIds:n,setSelectedLanguageIds:r},children:e.renderDefault(e)})}function G(){return y(q)}function K(e){const{members:r,schemaType:i,renderDefault:o}=e,a=n(e,t),{selectedLanguageIds:u,options:c}=G(),{filterField:s}=c,d=m((()=>r.filter((e=>"field"===e.kind&&s(i,e,u)||"fieldSet"===e.kind)).map((e=>"fieldSet"===e.kind?l(l({},e),{},{fieldSet:l(l({},e.fieldSet),{},{members:e.fieldSet.members.filter((e=>"field"===e.kind&&s(i,e,u)))})}):e))),[i,r,s,u]);return o(l(l({},a),{},{members:d,schemaType:i,renderDefault:o}))}const M=e=>Array.from(new Set(e));function Q(){const{selectedLanguageIds:e,setSelectedLanguageIds:t,options:n}=G(),{defaultLanguages:r=[]}=n,l=m((()=>H(n)),[n]),i=h((e=>{var n;t(M([...r,...e])),n=M([...r,...e]),window.localStorage.setItem(J,JSON.stringify(n))}),[r,t]),o=h((()=>i(l.map((e=>e.id)))),[i,l]),a=h((()=>{i(r)}),[r,i]),u=h((t=>{let n=e;n=n.includes(t)?n.filter((e=>e!==t)):M([...n,t]),i(n)}),[i,e]);return{activeLanguages:m((()=>M([...null!=r?r:[],...e])),[r,e]),allSelected:e.length===l.length+r.length,selectAll:o,selectNone:a,toggleLanguage:u}}const R=D(b)(e||(U=["\n max-height: calc(100vh - 200px);\n"],V||(V=U.slice(0)),e=Object.freeze(Object.defineProperties(U,{raw:{value:Object.freeze(V)}}))));var U,V;function X(e){const{options:t}=e,n=t.supportedLanguages.filter((e=>{var n;return null==(n=t.defaultLanguages)?void 0:n.includes(e.id)})),r=t.supportedLanguages.filter((e=>{var n;return!(null==(n=t.defaultLanguages)?void 0:n.includes(e.id))})),[l,i]=f(!1),{activeLanguages:c,allSelected:d,selectAll:g,selectNone:p,toggleLanguage:m}=Q(),[y,x]=f(null),[D,N]=f(null),F=h((e=>{"ALL"===e.currentTarget.value?g():p()}),[g,p]),z=h((()=>i((e=>!e))),[]),A=h((()=>i(!1)),[]);v(A,[y,D]);const E=t.supportedLanguages.length,[J,_]=f(""),H=h((e=>{e.currentTarget.value?_(e.currentTarget.value):_("")}),[]),W=o(R,{overflow:"auto",children:a(O,{padding:1,space:1,children:[n.length>0&&a(u,{children:[n.map((e=>o(Y,{id:e.id,title:e.title,selected:!0},e.id))),o(L,{borderTop:!0})]}),o(j,{mode:"bleed",onClick:F,justify:"flex-start",value:d?"NONE":"ALL",disabled:!!J,children:a(S,{gap:3,align:"center",children:[o(w,{size:2,children:d?o(s,{tone:"primary",children:o(I,{})}):o(k,{})}),o(b,{flex:1,children:o(w,{children:d?"Hide all":"Show all"})})]})}),o(L,{borderTop:!0}),E>4?o(T,{onChange:H,value:J,placeholder:"Filter languages"}):null,r.filter((e=>!J||e.title.toLowerCase().includes(J.toLowerCase()))).map((e=>o(Y,{id:e.id,onToggle:m,selected:c.includes(e.id),title:e.title},e.id)))]})}),q=c.length===E?"Showing all":"Showing ".concat(c.length," / ").concat(E);return o(P,{content:W,open:l,portal:!0,ref:N,children:o(j,{text:q,icon:C,mode:"bleed",onClick:z,ref:x,selected:l})})}function Y(e){const{id:t,onToggle:n,selected:r,title:l}=e,i=h((()=>{n&&n(t)}),[t,n]),u=!n;return o(j,{mode:"bleed",onClick:i,justify:"flex-start",disabled:u,children:a(S,{gap:3,align:"center",children:[o(w,{size:2,children:r?o(s,{tone:u?"default":"positive",children:o(N,{})}):o(F,{})}),o(b,{flex:1,children:o(w,{children:l})}),o(x,{children:t})]})})}const Z=d((e=>{const t=()=>o(X,{options:e}),n=l(l({},W.options),e);return{name:"@sanity/language-filter",studio:{components:{layout:e=>B(l(l({},e),{},{options:n}))}},document:{unstable_languageFilter:(n,r)=>{let{schemaType:l,schema:i}=r;return A(i.get(l),e)?[...n,t]:n}},form:{components:{input:e=>"root"!==e.id&&g(e.schemaType)?function(e){const{options:t}=G(),n=c(["_type"]),{documentTypes:r}=t;return"string"==typeof n&&r.includes(n)?o(K,l({},e)):e.renderDefault(e)}(e):e.renderDefault(e)}}}}));export{z as defaultFilterField,A as isLanguageFilterEnabled,Z as languageFilter,G as useLanguageFilterStudioContext};//# sourceMappingURL=index.esm.js.map
1
+ var e;const t=["members","schemaType","renderDefault"];function n(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){i(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var r=n.call(e,t||"default");if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}import{jsx as l,jsxs as a,Fragment as s}from"react/jsx-runtime";import{useClient as u,useFormValue as c,TextWithTone as d,definePlugin as g,isObjectSchemaType as p}from"sanity";import{useState as f,createContext as m,useEffect as y,useMemo as h,useContext as b,useCallback as v}from"react";import{Box as L,useClickOutside as O,Stack as j,Card as S,Button as w,Flex as T,Text as P,TextInput as x,Popover as A,Badge as D}from"@sanity/ui";import I from"styled-components";import{EyeClosedIcon as k,EyeOpenIcon as C,TranslateIcon as N,CheckmarkCircleIcon as F,CircleIcon as z}from"@sanity/icons";const E=(e,t,n)=>!e.name.startsWith("locale")||n.includes(t.name);function J(e,t){var n,r;const o=function(e){return"object"===(null==e?void 0:e.jsonType)&&"document"===V(e).name}(e)&&(null==(n=null==e?void 0:e.options)?void 0:n.languageFilter),i=!t.documentTypes;return!!(i&&!1!==o||!i&&o||e&&(null==(r=t.documentTypes)?void 0:r.includes(e.name)))}function V(e){return e.type?V(e.type):e}const _="@sanity/plugin/language-filter/selected-languages";function H(e){const t=W(e).map((e=>e.id));let n=t;try{const e=window.localStorage.getItem(_);e&&(n=JSON.parse(e))}catch(e){}var r;return r=t,n=n.filter((e=>r.includes(e))),n}function W(e){let{supportedLanguages:t,defaultLanguages:n}=e;return Array.isArray(t)?t.filter((e=>!(null==n?void 0:n.includes(e.id)))):[]}const q={options:{apiVersion:"2022-11-27",supportedLanguages:[],defaultLanguages:[],documentTypes:[],filterField:E},selectedLanguageIds:[],setSelectedLanguageIds:()=>console.error("LanguageFilterStudioContext not initialized")},B=m(q);function G(e){const t=u({apiVersion:"2023-01-01"}),[n,r]=f(Array.isArray(e.options.supportedLanguages)?e.options.supportedLanguages:[]);y((()=>{let n=[];Array.isArray(e.options.supportedLanguages)||async function(e){n=await e(t,{}),r(n)}(e.options.supportedLanguages)}),[t,e.options.supportedLanguages]);const i=h((()=>o(o(o({},q.options),e.options),{},{supportedLanguages:n})),[e.options,n]),[a,s]=function(e){return f((()=>{var t;return[...null!=(t=e.defaultLanguages)?t:[],...H(e)]}))}(i);return l(B.Provider,{value:{options:i,selectedLanguageIds:a,setSelectedLanguageIds:s},children:e.renderDefault(e)})}function K(){return b(B)}function M(e){const{members:r,schemaType:i,renderDefault:l}=e,a=n(e,t),{selectedLanguageIds:s,options:u}=K(),{filterField:c}=u,d=h((()=>r.filter((e=>"field"===e.kind&&c(i,e,s)||"fieldSet"===e.kind)).map((e=>"fieldSet"===e.kind?o(o({},e),{},{fieldSet:o(o({},e.fieldSet),{},{members:e.fieldSet.members.filter((e=>"field"===e.kind&&c(i,e,s)))})}):e))),[i,r,c,s]);return l(o(o({},a),{},{members:d,schemaType:i,renderDefault:l}))}const Q=e=>Array.from(new Set(e));function R(){const{selectedLanguageIds:e,setSelectedLanguageIds:t,options:n}=K(),{defaultLanguages:r=[]}=n,o=h((()=>W(n)),[n]),i=v((e=>{var n;t(Q([...r,...e])),n=Q([...r,...e]),window.localStorage.setItem(_,JSON.stringify(n))}),[r,t]),l=v((()=>i(o.map((e=>e.id)))),[i,o]),a=v((()=>{i(r)}),[r,i]),s=v((t=>{let n=e;n=n.includes(t)?n.filter((e=>e!==t)):Q([...n,t]),i(n)}),[i,e]);return{activeLanguages:h((()=>Q([...null!=r?r:[],...e])),[r,e]),allSelected:e.length===o.length+r.length,selectAll:l,selectNone:a,toggleLanguage:s}}const U=I(L)(e||(X=["\n max-height: calc(100vh - 200px);\n"],Y||(Y=X.slice(0)),e=Object.freeze(Object.defineProperties(X,{raw:{value:Object.freeze(Y)}}))));var X,Y;function Z(){const{options:e}=K(),t=e.supportedLanguages.filter((t=>{var n;return null==(n=e.defaultLanguages)?void 0:n.includes(t.id)})),n=e.supportedLanguages.filter((t=>{var n;return!(null==(n=e.defaultLanguages)?void 0:n.includes(t.id))})),[r,o]=f(!1),{activeLanguages:i,allSelected:u,selectAll:c,selectNone:g,toggleLanguage:p}=R(),[m,y]=f(null),[h,b]=f(null),D=v((e=>{"ALL"===e.currentTarget.value?c():g()}),[c,g]),I=v((()=>o((e=>!e))),[]),F=v((()=>o(!1)),[]);O(F,[m,h]);const z=e.supportedLanguages.length,[E,J]=f(""),V=v((e=>{e.currentTarget.value?J(e.currentTarget.value):J("")}),[]),_=z>4,H=l(U,{overflow:"auto",children:a(j,{padding:1,space:1,children:[t.length>0&&a(s,{children:[t.map((e=>l($,{id:e.id,title:e.title,selected:!0},e.id))),l(S,{borderTop:!0})]}),l(w,{mode:"bleed",onClick:D,justify:"flex-start",value:u?"NONE":"ALL",disabled:!!E,children:a(T,{gap:3,align:"center",children:[l(P,{size:2,children:u?l(d,{tone:"primary",children:l(k,{})}):l(C,{})}),l(L,{flex:1,children:l(P,{children:u?"Hide all":"Show all"})})]})}),_?l(x,{onChange:V,value:E,placeholder:"Filter languages"}):l(S,{borderTop:!0}),n.filter((e=>!E||e.title.toLowerCase().includes(E.toLowerCase()))).map((e=>l($,{id:e.id,onToggle:p,selected:i.includes(e.id),title:e.title},e.id)))]})}),W=i.length===z?"Showing all":"Showing ".concat(i.length," / ").concat(z);return l(A,{content:H,open:r,portal:!0,ref:b,children:l(w,{text:W,icon:N,mode:"bleed",onClick:I,ref:y,selected:r})})}function $(e){const{id:t,onToggle:n,selected:r,title:o}=e,i=v((()=>{n&&n(t)}),[t,n]),s=!n;return l(w,{mode:"bleed",onClick:i,justify:"flex-start",disabled:s,children:a(T,{gap:3,align:"center",children:[l(P,{size:2,children:r?l(d,{tone:s?"default":"positive",children:l(F,{})}):l(z,{})}),l(L,{flex:1,children:l(P,{children:o})}),l(D,{children:t})]})})}const ee=g((e=>{const t=()=>l(Z,{}),n=o(o({},q.options),e);return{name:"@sanity/language-filter",studio:{components:{layout:e=>G(o(o({},e),{},{options:n}))}},document:{unstable_languageFilter:(n,r)=>{let{schemaType:o,schema:i}=r;return J(i.get(o),e)?[...n,t]:n}},form:{components:{input:e=>"root"!==e.id&&p(e.schemaType)?function(e){const{options:t}=K(),n=c(["_type"]),{documentTypes:r}=t;return"string"==typeof n&&r.includes(n)?l(M,o({},e)):e.renderDefault(e)}(e):e.renderDefault(e)}}}}));export{E as defaultFilterField,J as isLanguageFilterEnabled,ee as languageFilter,K as useLanguageFilterStudioContext};//# sourceMappingURL=index.esm.js.map
package/lib/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e;const t=["members","schemaType","renderDefault"];function n(e,t){if(null==e)return{};var n,r,l=function(e,t){if(null==e)return{};var n,r,l={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(l[n]=e[n]);return l}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(l[n]=e[n])}return l}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function o(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var r=n.call(e,t||"default");if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(exports,"__esModule",{value:!0});var i=require("react/jsx-runtime"),a=require("sanity"),s=require("react"),u=require("@sanity/ui"),c=require("styled-components"),d=require("@sanity/icons");function g(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var f=g(c);const p=(e,t,n)=>!e.name.startsWith("locale")||n.includes(t.name);function m(e,t){var n,r;const l=function(e){return"object"===(null==e?void 0:e.jsonType)&&"document"===x(e).name}(e)&&(null==(n=null==e?void 0:e.options)?void 0:n.languageFilter),o=!t.documentTypes;return!!(o&&!1!==l||!o&&l||e&&(null==(r=t.documentTypes)?void 0:r.includes(e.name)))}function x(e){return e.type?x(e.type):e}const b="@sanity/plugin/language-filter/selected-languages";function j(e){const t=y(e).map((e=>e.id));let n=t;try{const e=window.localStorage.getItem(b);e&&(n=JSON.parse(e))}catch(e){}var r;return r=t,n=n.filter((e=>r.includes(e))),n}function y(e){let{supportedLanguages:t,defaultLanguages:n}=e;return t.filter((e=>!(null==n?void 0:n.includes(e.id))))}const h={options:{supportedLanguages:[],defaultLanguages:[],documentTypes:[],filterField:p},selectedLanguageIds:[],setSelectedLanguageIds:()=>console.error("LanguageFilterStudioContext not initialized")},v=s.createContext(h);function O(e){const t=s.useMemo((()=>l(l({},h.options),e.options)),[e.options]),[n,r]=function(e){return s.useState((()=>{var t;return[...null!=(t=e.defaultLanguages)?t:[],...j(e)]}))}(t);return i.jsx(v.Provider,{value:{options:t,selectedLanguageIds:n,setSelectedLanguageIds:r},children:e.renderDefault(e)})}function S(){return s.useContext(v)}function L(e){const{members:r,schemaType:o,renderDefault:i}=e,a=n(e,t),{selectedLanguageIds:u,options:c}=S(),{filterField:d}=c,g=s.useMemo((()=>r.filter((e=>"field"===e.kind&&d(o,e,u)||"fieldSet"===e.kind)).map((e=>"fieldSet"===e.kind?l(l({},e),{},{fieldSet:l(l({},e.fieldSet),{},{members:e.fieldSet.members.filter((e=>"field"===e.kind&&d(o,e,u)))})}):e))),[o,r,d,u]);return i(l(l({},a),{},{members:g,schemaType:o,renderDefault:i}))}const T=e=>Array.from(new Set(e));function C(){const{selectedLanguageIds:e,setSelectedLanguageIds:t,options:n}=S(),{defaultLanguages:r=[]}=n,l=s.useMemo((()=>y(n)),[n]),o=s.useCallback((e=>{var n;t(T([...r,...e])),n=T([...r,...e]),window.localStorage.setItem(b,JSON.stringify(n))}),[r,t]),i=s.useCallback((()=>o(l.map((e=>e.id)))),[o,l]),a=s.useCallback((()=>{o(r)}),[r,o]),u=s.useCallback((t=>{let n=e;n=n.includes(t)?n.filter((e=>e!==t)):T([...n,t]),o(n)}),[o,e]);return{activeLanguages:s.useMemo((()=>T([...null!=r?r:[],...e])),[r,e]),allSelected:e.length===l.length+r.length,selectAll:i,selectNone:a,toggleLanguage:u}}const w=f.default(u.Box)(e||(k=["\n max-height: calc(100vh - 200px);\n"],P||(P=k.slice(0)),e=Object.freeze(Object.defineProperties(k,{raw:{value:Object.freeze(P)}}))));var k,P;function I(e){const{options:t}=e,n=t.supportedLanguages.filter((e=>{var n;return null==(n=t.defaultLanguages)?void 0:n.includes(e.id)})),r=t.supportedLanguages.filter((e=>{var n;return!(null==(n=t.defaultLanguages)?void 0:n.includes(e.id))})),[l,o]=s.useState(!1),{activeLanguages:c,allSelected:g,selectAll:f,selectNone:p,toggleLanguage:m}=C(),[x,b]=s.useState(null),[j,y]=s.useState(null),h=s.useCallback((e=>{"ALL"===e.currentTarget.value?f():p()}),[f,p]),v=s.useCallback((()=>o((e=>!e))),[]),O=s.useCallback((()=>o(!1)),[]);u.useClickOutside(O,[x,j]);const S=t.supportedLanguages.length,[L,T]=s.useState(""),k=s.useCallback((e=>{e.currentTarget.value?T(e.currentTarget.value):T("")}),[]),P=i.jsx(w,{overflow:"auto",children:i.jsxs(u.Stack,{padding:1,space:1,children:[n.length>0&&i.jsxs(i.Fragment,{children:[n.map((e=>i.jsx(F,{id:e.id,title:e.title,selected:!0},e.id))),i.jsx(u.Card,{borderTop:!0})]}),i.jsx(u.Button,{mode:"bleed",onClick:h,justify:"flex-start",value:g?"NONE":"ALL",disabled:!!L,children:i.jsxs(u.Flex,{gap:3,align:"center",children:[i.jsx(u.Text,{size:2,children:g?i.jsx(a.TextWithTone,{tone:"primary",children:i.jsx(d.EyeClosedIcon,{})}):i.jsx(d.EyeOpenIcon,{})}),i.jsx(u.Box,{flex:1,children:i.jsx(u.Text,{children:g?"Hide all":"Show all"})})]})}),i.jsx(u.Card,{borderTop:!0}),S>4?i.jsx(u.TextInput,{onChange:k,value:L,placeholder:"Filter languages"}):null,r.filter((e=>!L||e.title.toLowerCase().includes(L.toLowerCase()))).map((e=>i.jsx(F,{id:e.id,onToggle:m,selected:c.includes(e.id),title:e.title},e.id)))]})}),I=c.length===S?"Showing all":"Showing ".concat(c.length," / ").concat(S);return i.jsx(u.Popover,{content:P,open:l,portal:!0,ref:y,children:i.jsx(u.Button,{text:I,icon:d.TranslateIcon,mode:"bleed",onClick:v,ref:b,selected:l})})}function F(e){const{id:t,onToggle:n,selected:r,title:l}=e,o=s.useCallback((()=>{n&&n(t)}),[t,n]),c=!n;return i.jsx(u.Button,{mode:"bleed",onClick:o,justify:"flex-start",disabled:c,children:i.jsxs(u.Flex,{gap:3,align:"center",children:[i.jsx(u.Text,{size:2,children:r?i.jsx(a.TextWithTone,{tone:c?"default":"positive",children:i.jsx(d.CheckmarkCircleIcon,{})}):i.jsx(d.CircleIcon,{})}),i.jsx(u.Box,{flex:1,children:i.jsx(u.Text,{children:l})}),i.jsx(u.Badge,{children:t})]})})}const D=a.definePlugin((e=>{const t=()=>i.jsx(I,{options:e}),n=l(l({},h.options),e);return{name:"@sanity/language-filter",studio:{components:{layout:e=>O(l(l({},e),{},{options:n}))}},document:{unstable_languageFilter:(n,r)=>{let{schemaType:l,schema:o}=r;return m(o.get(l),e)?[...n,t]:n}},form:{components:{input:e=>"root"!==e.id&&a.isObjectSchemaType(e.schemaType)?function(e){const{options:t}=S(),n=a.useFormValue(["_type"]),{documentTypes:r}=t;return"string"==typeof n&&r.includes(n)?i.jsx(L,l({},e)):e.renderDefault(e)}(e):e.renderDefault(e)}}}}));exports.defaultFilterField=p,exports.isLanguageFilterEnabled=m,exports.languageFilter=D,exports.useLanguageFilterStudioContext=S;//# sourceMappingURL=index.js.map
1
+ "use strict";var e;const t=["members","schemaType","renderDefault"];function n(e,t){if(null==e)return{};var n,r,l=function(e,t){if(null==e)return{};var n,r,l={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(l[n]=e[n]);return l}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(l[n]=e[n])}return l}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function a(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var r=n.call(e,t||"default");if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}Object.defineProperty(exports,"__esModule",{value:!0});var o=require("react/jsx-runtime"),s=require("sanity"),i=require("react"),u=require("@sanity/ui"),c=require("styled-components"),d=require("@sanity/icons");function g(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var p=g(c);const f=(e,t,n)=>!e.name.startsWith("locale")||n.includes(t.name);function m(e,t){var n,r;const l=function(e){return"object"===(null==e?void 0:e.jsonType)&&"document"===y(e).name}(e)&&(null==(n=null==e?void 0:e.options)?void 0:n.languageFilter),a=!t.documentTypes;return!!(a&&!1!==l||!a&&l||e&&(null==(r=t.documentTypes)?void 0:r.includes(e.name)))}function y(e){return e.type?y(e.type):e}const x="@sanity/plugin/language-filter/selected-languages";function b(e){const t=j(e).map((e=>e.id));let n=t;try{const e=window.localStorage.getItem(x);e&&(n=JSON.parse(e))}catch(e){}var r;return r=t,n=n.filter((e=>r.includes(e))),n}function j(e){let{supportedLanguages:t,defaultLanguages:n}=e;return Array.isArray(t)?t.filter((e=>!(null==n?void 0:n.includes(e.id)))):[]}const h={options:{apiVersion:"2022-11-27",supportedLanguages:[],defaultLanguages:[],documentTypes:[],filterField:f},selectedLanguageIds:[],setSelectedLanguageIds:()=>console.error("LanguageFilterStudioContext not initialized")},v=i.createContext(h);function L(e){const t=s.useClient({apiVersion:"2023-01-01"}),[n,r]=i.useState(Array.isArray(e.options.supportedLanguages)?e.options.supportedLanguages:[]);i.useEffect((()=>{let n=[];Array.isArray(e.options.supportedLanguages)||async function(e){n=await e(t,{}),r(n)}(e.options.supportedLanguages)}),[t,e.options.supportedLanguages]);const a=i.useMemo((()=>l(l(l({},h.options),e.options),{},{supportedLanguages:n})),[e.options,n]),[u,c]=function(e){return i.useState((()=>{var t;return[...null!=(t=e.defaultLanguages)?t:[],...b(e)]}))}(a);return o.jsx(v.Provider,{value:{options:a,selectedLanguageIds:u,setSelectedLanguageIds:c},children:e.renderDefault(e)})}function O(){return i.useContext(v)}function S(e){const{members:r,schemaType:a,renderDefault:o}=e,s=n(e,t),{selectedLanguageIds:u,options:c}=O(),{filterField:d}=c,g=i.useMemo((()=>r.filter((e=>"field"===e.kind&&d(a,e,u)||"fieldSet"===e.kind)).map((e=>"fieldSet"===e.kind?l(l({},e),{},{fieldSet:l(l({},e.fieldSet),{},{members:e.fieldSet.members.filter((e=>"field"===e.kind&&d(a,e,u)))})}):e))),[a,r,d,u]);return o(l(l({},s),{},{members:g,schemaType:a,renderDefault:o}))}const T=e=>Array.from(new Set(e));function C(){const{selectedLanguageIds:e,setSelectedLanguageIds:t,options:n}=O(),{defaultLanguages:r=[]}=n,l=i.useMemo((()=>j(n)),[n]),a=i.useCallback((e=>{var n;t(T([...r,...e])),n=T([...r,...e]),window.localStorage.setItem(x,JSON.stringify(n))}),[r,t]),o=i.useCallback((()=>a(l.map((e=>e.id)))),[a,l]),s=i.useCallback((()=>{a(r)}),[r,a]),u=i.useCallback((t=>{let n=e;n=n.includes(t)?n.filter((e=>e!==t)):T([...n,t]),a(n)}),[a,e]);return{activeLanguages:i.useMemo((()=>T([...null!=r?r:[],...e])),[r,e]),allSelected:e.length===l.length+r.length,selectAll:o,selectNone:s,toggleLanguage:u}}const w=p.default(u.Box)(e||(k=["\n max-height: calc(100vh - 200px);\n"],P||(P=k.slice(0)),e=Object.freeze(Object.defineProperties(k,{raw:{value:Object.freeze(P)}}))));var k,P;function I(){const{options:e}=O(),t=e.supportedLanguages.filter((t=>{var n;return null==(n=e.defaultLanguages)?void 0:n.includes(t.id)})),n=e.supportedLanguages.filter((t=>{var n;return!(null==(n=e.defaultLanguages)?void 0:n.includes(t.id))})),[r,l]=i.useState(!1),{activeLanguages:a,allSelected:c,selectAll:g,selectNone:p,toggleLanguage:f}=C(),[m,y]=i.useState(null),[x,b]=i.useState(null),j=i.useCallback((e=>{"ALL"===e.currentTarget.value?g():p()}),[g,p]),h=i.useCallback((()=>l((e=>!e))),[]),v=i.useCallback((()=>l(!1)),[]);u.useClickOutside(v,[m,x]);const L=e.supportedLanguages.length,[S,T]=i.useState(""),k=i.useCallback((e=>{e.currentTarget.value?T(e.currentTarget.value):T("")}),[]),P=L>4,I=o.jsx(w,{overflow:"auto",children:o.jsxs(u.Stack,{padding:1,space:1,children:[t.length>0&&o.jsxs(o.Fragment,{children:[t.map((e=>o.jsx(F,{id:e.id,title:e.title,selected:!0},e.id))),o.jsx(u.Card,{borderTop:!0})]}),o.jsx(u.Button,{mode:"bleed",onClick:j,justify:"flex-start",value:c?"NONE":"ALL",disabled:!!S,children:o.jsxs(u.Flex,{gap:3,align:"center",children:[o.jsx(u.Text,{size:2,children:c?o.jsx(s.TextWithTone,{tone:"primary",children:o.jsx(d.EyeClosedIcon,{})}):o.jsx(d.EyeOpenIcon,{})}),o.jsx(u.Box,{flex:1,children:o.jsx(u.Text,{children:c?"Hide all":"Show all"})})]})}),P?o.jsx(u.TextInput,{onChange:k,value:S,placeholder:"Filter languages"}):o.jsx(u.Card,{borderTop:!0}),n.filter((e=>!S||e.title.toLowerCase().includes(S.toLowerCase()))).map((e=>o.jsx(F,{id:e.id,onToggle:f,selected:a.includes(e.id),title:e.title},e.id)))]})}),A=a.length===L?"Showing all":"Showing ".concat(a.length," / ").concat(L);return o.jsx(u.Popover,{content:I,open:r,portal:!0,ref:b,children:o.jsx(u.Button,{text:A,icon:d.TranslateIcon,mode:"bleed",onClick:h,ref:y,selected:r})})}function F(e){const{id:t,onToggle:n,selected:r,title:l}=e,a=i.useCallback((()=>{n&&n(t)}),[t,n]),c=!n;return o.jsx(u.Button,{mode:"bleed",onClick:a,justify:"flex-start",disabled:c,children:o.jsxs(u.Flex,{gap:3,align:"center",children:[o.jsx(u.Text,{size:2,children:r?o.jsx(s.TextWithTone,{tone:c?"default":"positive",children:o.jsx(d.CheckmarkCircleIcon,{})}):o.jsx(d.CircleIcon,{})}),o.jsx(u.Box,{flex:1,children:o.jsx(u.Text,{children:l})}),o.jsx(u.Badge,{children:t})]})})}const A=s.definePlugin((e=>{const t=()=>o.jsx(I,{}),n=l(l({},h.options),e);return{name:"@sanity/language-filter",studio:{components:{layout:e=>L(l(l({},e),{},{options:n}))}},document:{unstable_languageFilter:(n,r)=>{let{schemaType:l,schema:a}=r;return m(a.get(l),e)?[...n,t]:n}},form:{components:{input:e=>"root"!==e.id&&s.isObjectSchemaType(e.schemaType)?function(e){const{options:t}=O(),n=s.useFormValue(["_type"]),{documentTypes:r}=t;return"string"==typeof n&&r.includes(n)?o.jsx(S,l({},e)):e.renderDefault(e)}(e):e.renderDefault(e)}}}}));exports.defaultFilterField=f,exports.isLanguageFilterEnabled=m,exports.languageFilter=A,exports.useLanguageFilterStudioContext=O;//# sourceMappingURL=index.js.map
@@ -4,6 +4,7 @@ import {FieldMember} from 'sanity'
4
4
  import {FieldsetState} from 'sanity'
5
5
  import {ObjectSchemaType} from 'sanity'
6
6
  import {Plugin as Plugin_2} from 'sanity'
7
+ import {SanityClient} from 'sanity'
7
8
  import type {SchemaType} from 'sanity'
8
9
 
9
10
  export declare const defaultFilterField: FilterFieldFunction
@@ -19,11 +20,16 @@ export declare function isLanguageFilterEnabled(
19
20
  options: LanguageFilterConfig
20
21
  ): boolean
21
22
 
22
- export declare interface Language {
23
- id: string
23
+ export declare type Language = {
24
+ id: Intl.UnicodeBCP47LocaleIdentifier
24
25
  title: string
25
26
  }
26
27
 
28
+ declare type LanguageCallback = (
29
+ client: SanityClient,
30
+ selectedValue: Record<string, unknown>
31
+ ) => Promise<Language[]>
32
+
27
33
  /**
28
34
  * ## Usage in sanity.config.ts (or .js)
29
35
  *
@@ -60,10 +66,19 @@ export declare interface Language {
60
66
  export declare const languageFilter: Plugin_2<LanguageFilterConfig>
61
67
 
62
68
  export declare interface LanguageFilterConfig {
63
- supportedLanguages: Language[]
69
+ supportedLanguages: Language[] | LanguageCallback
64
70
  defaultLanguages?: string[]
65
71
  documentTypes?: string[]
66
72
  filterField?: FilterFieldFunction
73
+ /**
74
+ * https://www.sanity.io/docs/api-versioning
75
+ * @defaultValue '2022-11-27'
76
+ */
77
+ apiVersion?: string
78
+ }
79
+
80
+ declare interface LanguageFilterConfigProcessed extends LanguageFilterConfig {
81
+ supportedLanguages: Language[]
67
82
  }
68
83
 
69
84
  export declare interface LanguageFilterOptions {
@@ -74,11 +89,11 @@ export declare interface LanguageFilterSchema extends ObjectSchemaType {
74
89
  options?: LanguageFilterOptions
75
90
  }
76
91
 
77
- declare interface LanguageFilterStudioContextProps {
78
- options: Required<LanguageFilterConfig>
92
+ declare interface LanguageFilterStudioContextProcessed {
93
+ options: Required<LanguageFilterConfigProcessed>
79
94
  }
80
95
 
81
- declare interface LanguageFilterStudioContextValue extends LanguageFilterStudioContextProps {
96
+ declare interface LanguageFilterStudioContextValue extends LanguageFilterStudioContextProcessed {
82
97
  selectedLanguageIds: string[]
83
98
  setSelectedLanguageIds: (ids: string[]) => void
84
99
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/language-filter",
3
- "version": "3.1.2",
3
+ "version": "3.2.0",
4
4
  "description": "A Sanity plugin that supports filtering localized fields by language",
5
5
  "homepage": "https://github.com/sanity-io/language-filter#readme",
6
6
  "bugs": {
@@ -12,7 +12,6 @@ import {
12
12
  } from '@sanity/ui'
13
13
  import React, {FormEvent, MouseEventHandler, useCallback, useState} from 'react'
14
14
  import styled from 'styled-components'
15
- import {LanguageFilterConfig} from './types'
16
15
  import {usePaneLanguages} from './usePaneLanguages'
17
16
  import {
18
17
  CheckmarkCircleIcon,
@@ -22,17 +21,14 @@ import {
22
21
  TranslateIcon,
23
22
  } from '@sanity/icons'
24
23
  import {TextWithTone} from 'sanity'
24
+ import {useLanguageFilterStudioContext} from './LanguageFilterStudioContext'
25
25
 
26
26
  const StyledBox = styled(Box)`
27
27
  max-height: calc(100vh - 200px);
28
28
  `
29
29
 
30
- export interface LanguageFilterMenuButtonProps {
31
- options: LanguageFilterConfig
32
- }
33
-
34
- export function LanguageFilterMenuButton(props: LanguageFilterMenuButtonProps) {
35
- const {options} = props
30
+ export function LanguageFilterMenuButton() {
31
+ const {options} = useLanguageFilterStudioContext()
36
32
 
37
33
  const defaultLanguages = options.supportedLanguages.filter((l) =>
38
34
  options.defaultLanguages?.includes(l.id)
@@ -77,6 +73,8 @@ export function LanguageFilterMenuButton(props: LanguageFilterMenuButtonProps) {
77
73
  }
78
74
  }, [])
79
75
 
76
+ const showSearch = langCount > 4
77
+
80
78
  const content = (
81
79
  <StyledBox overflow="auto">
82
80
  <Stack padding={1} space={1}>
@@ -112,11 +110,11 @@ export function LanguageFilterMenuButton(props: LanguageFilterMenuButtonProps) {
112
110
  </Flex>
113
111
  </Button>
114
112
 
115
- <Card borderTop />
116
-
117
- {langCount > 4 ? (
113
+ {showSearch ? (
118
114
  <TextInput onChange={handleQuery} value={query} placeholder="Filter languages" />
119
- ) : null}
115
+ ) : (
116
+ <Card borderTop />
117
+ )}
120
118
 
121
119
  {languageOptions
122
120
  .filter((language) => {
@@ -1,6 +1,11 @@
1
- import React, {createContext, useContext, useMemo} from 'react'
2
- import {LanguageFilterConfig} from './types'
3
- import {LayoutProps} from 'sanity'
1
+ import React, {createContext, useContext, useEffect, useMemo, useState} from 'react'
2
+ import {
3
+ Language,
4
+ LanguageCallback,
5
+ LanguageFilterConfig,
6
+ LanguageFilterConfigProcessed,
7
+ } from './types'
8
+ import {LayoutProps, useClient} from 'sanity'
4
9
  import {defaultFilterField} from './filterField'
5
10
  import {useSelectedLanguageIds} from './useSelectedLanguageIds'
6
11
 
@@ -9,13 +14,18 @@ export interface LanguageFilterStudioContextProps {
9
14
  options: Required<LanguageFilterConfig>
10
15
  }
11
16
 
12
- export interface LanguageFilterStudioContextValue extends LanguageFilterStudioContextProps {
17
+ export interface LanguageFilterStudioContextProcessed {
18
+ options: Required<LanguageFilterConfigProcessed>
19
+ }
20
+
21
+ export interface LanguageFilterStudioContextValue extends LanguageFilterStudioContextProcessed {
13
22
  selectedLanguageIds: string[]
14
23
  setSelectedLanguageIds: (ids: string[]) => void
15
24
  }
16
25
 
17
26
  export const defaultContextValue: LanguageFilterStudioContextValue = {
18
27
  options: {
28
+ apiVersion: '2022-11-27',
19
29
  supportedLanguages: [],
20
30
  defaultLanguages: [],
21
31
  documentTypes: [],
@@ -36,13 +46,31 @@ const LanguageFilterStudioContext =
36
46
  export function LanguageFilterStudioProvider(
37
47
  props: LayoutProps & LanguageFilterStudioContextProps
38
48
  ) {
39
- const options = useMemo(
40
- () => ({
49
+ const client = useClient({apiVersion: '2023-01-01'})
50
+ const [languages, setLanguages] = useState<Language[]>(
51
+ Array.isArray(props.options.supportedLanguages) ? props.options.supportedLanguages : []
52
+ )
53
+ useEffect(() => {
54
+ let asyncLanguages: Language[] = []
55
+
56
+ async function getLanguages(supportedLanguagesCallback: LanguageCallback) {
57
+ asyncLanguages = await supportedLanguagesCallback(client, {})
58
+ setLanguages(asyncLanguages)
59
+ }
60
+
61
+ if (!Array.isArray(props.options.supportedLanguages)) {
62
+ getLanguages(props.options.supportedLanguages)
63
+ }
64
+ }, [client, props.options.supportedLanguages])
65
+
66
+ const options = useMemo<Required<LanguageFilterConfigProcessed>>(() => {
67
+ return {
41
68
  ...defaultContextValue.options,
42
69
  ...props.options,
43
- }),
44
- [props.options]
45
- )
70
+ supportedLanguages: languages,
71
+ }
72
+ }, [props.options, languages])
73
+
46
74
  const [selectedLanguageIds, setSelectedLanguageIds] = useSelectedLanguageIds(options)
47
75
 
48
76
  return (
@@ -0,0 +1,29 @@
1
+ import {get} from 'lodash'
2
+
3
+ export const getSelectedValue = (
4
+ select: Record<string, string> | undefined,
5
+ document:
6
+ | {
7
+ [x: string]: unknown
8
+ }
9
+ | undefined
10
+ ): Record<string, unknown> => {
11
+ if (!select || !document) {
12
+ return {}
13
+ }
14
+
15
+ const selection: Record<string, string> = select || {}
16
+ const selectedValue: Record<string, unknown> = {}
17
+ for (const [key, path] of Object.entries(selection)) {
18
+ let value = get(document, path)
19
+ if (Array.isArray(value)) {
20
+ // If there are references in the array, ensure they have `_ref` set, otherwise they are considered empty and can safely be ignored
21
+ value = value.filter((item) =>
22
+ typeof item === 'object' ? item?._type === 'reference' && '_ref' in item : true
23
+ )
24
+ }
25
+ selectedValue[key] = value
26
+ }
27
+
28
+ return selectedValue
29
+ }
package/src/plugin.tsx CHANGED
@@ -46,7 +46,7 @@ import {defaultContextValue, LanguageFilterStudioProvider} from './LanguageFilte
46
46
  */
47
47
  export const languageFilter = definePlugin<LanguageFilterConfig>((options) => {
48
48
  const RenderLanguageFilter: DocumentLanguageFilterComponent = () => {
49
- return <LanguageFilterMenuButton options={options} />
49
+ return <LanguageFilterMenuButton />
50
50
  }
51
51
 
52
52
  const pluginOptions = {
package/src/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import {FieldMember, FieldsetState, ObjectSchemaType} from 'sanity'
1
+ import {FieldMember, FieldsetState, ObjectSchemaType, SanityClient} from 'sanity'
2
2
 
3
3
  export interface LanguageFilterOptions {
4
4
  languageFilter?: boolean
@@ -8,11 +8,16 @@ export interface LanguageFilterSchema extends ObjectSchemaType {
8
8
  options?: LanguageFilterOptions
9
9
  }
10
10
 
11
- export interface Language {
12
- id: string
11
+ export type Language = {
12
+ id: Intl.UnicodeBCP47LocaleIdentifier
13
13
  title: string
14
14
  }
15
15
 
16
+ export type LanguageCallback = (
17
+ client: SanityClient,
18
+ selectedValue: Record<string, unknown>
19
+ ) => Promise<Language[]>
20
+
16
21
  export type FilterFieldFunction = (
17
22
  enclosingType: ObjectSchemaType,
18
23
  field: FieldMember | FieldsetState,
@@ -20,8 +25,17 @@ export type FilterFieldFunction = (
20
25
  ) => boolean
21
26
 
22
27
  export interface LanguageFilterConfig {
23
- supportedLanguages: Language[]
28
+ supportedLanguages: Language[] | LanguageCallback
24
29
  defaultLanguages?: string[]
25
30
  documentTypes?: string[]
26
31
  filterField?: FilterFieldFunction
32
+ /**
33
+ * https://www.sanity.io/docs/api-versioning
34
+ * @defaultValue '2022-11-27'
35
+ */
36
+ apiVersion?: string
37
+ }
38
+
39
+ export interface LanguageFilterConfigProcessed extends LanguageFilterConfig {
40
+ supportedLanguages: Language[]
27
41
  }
@@ -30,7 +30,9 @@ export function getSelectableLanguages({
30
30
  supportedLanguages,
31
31
  defaultLanguages,
32
32
  }: LanguageFilterConfig): Language[] {
33
- return supportedLanguages.filter((lang) => !defaultLanguages?.includes(lang.id))
33
+ return Array.isArray(supportedLanguages)
34
+ ? supportedLanguages.filter((lang) => !defaultLanguages?.includes(lang.id))
35
+ : []
34
36
  }
35
37
 
36
38
  export function useSelectedLanguageIds(