@sanity/orderable-document-list 1.0.2 → 1.0.4
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/LICENSE +1 -1
- package/README.md +1 -1
- package/lib/index.esm.js +1 -2
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +1 -2
- package/lib/index.js.map +1 -1
- package/lib/src/index.d.ts +2 -8
- package/package.json +3 -4
- package/src/Document.tsx +13 -7
- package/src/DocumentListQuery.tsx +6 -6
- package/src/DraggableList.tsx +9 -7
- package/src/desk-structure/orderableDocumentListDeskItem.ts +1 -1
- package/src/fields/orderRankOrdering.ts +2 -1
- package/src/helpers/initialRank.ts +1 -1
- package/src/helpers/reorderDocuments.ts +19 -15
- package/src/helpers/resetOrder.ts +1 -1
- package/src/types.ts +8 -0
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -110,7 +110,7 @@ You cannot override the `name`, `type` or `initialValue` attributes.
|
|
|
110
110
|
// sanity.config.js
|
|
111
111
|
import {defineConfig} from "sanity";
|
|
112
112
|
import {deskTool, StructureBuilder} from "sanity/desk";
|
|
113
|
-
import {
|
|
113
|
+
import {orderRankField, orderRankOrdering} from '@sanity/orderable-document-list'
|
|
114
114
|
|
|
115
115
|
export default defineConfig({
|
|
116
116
|
//...
|
package/lib/index.esm.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
function e(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 t(t){for(var r=1;r<arguments.length;r++){var i=null!=arguments[r]?arguments[r]:{};r%2?e(Object(i),!0).forEach((function(e){n(t,e,i[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(i)):e(Object(i)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(i,e))}))}return t}function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}import{defineField as r,useSchema as i,Preview as o,useClient as s}from"sanity";import{LexoRank as l}from"lexorank";import{DragHandleIcon as d,ChevronUpIcon as a,ChevronDownIcon as c,GenerateIcon as u,SortIcon as p}from"@sanity/icons";import{jsxs as h,jsx as g,Fragment as m}from"react/jsx-runtime";import f,{useContext as y,useState as v,useEffect as b,useCallback as w,useMemo as k,Component as R}from"react";import{Flex as O,Box as x,Text as I,Button as S,useToast as _,Card as D,Spinner as j,Stack as E}from"@sanity/ui";import{DragDropContext as P,Droppable as L,Draggable as T}from"react-beautiful-dnd";import{usePaneRouter as C}from"sanity/desk";const $=e=>{if(!(null==e?void 0:e.type))throw new Error("\n type must be provided.\n Example: orderRankField({type: 'category'})\n ");const{type:n}=e;return r(t(t({title:"Order Rank",readOnly:!0,hidden:!0},e),{},{name:"orderRank",type:"string",initialValue:async(e,t)=>{let{getClient:r}=t;return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";const t=e?l.parse(e):l.min();return t.genNext().genNext().value}(await r({apiVersion:"2021-09-01"}).fetch("*[_type == $type]|order(@[$order] desc)[0][$order]",{type:n,order:"orderRank"}))}}))},z={title:"Ordered",name:"ordered",by:[{field:"orderRank",direction:"asc"}]},N=f.createContext({});function V(e){let{doc:t,increment:n,entities:r,handleSelect:s,index:l,isFirst:u,isLast:p}=e;const{showIncrements:m}=y(N),f=i();return h(O,{align:"center",children:[g(x,{paddingX:3,style:{flexShrink:0},children:g(I,{size:4,children:g(d,{})})}),m&&h(O,{style:{flexShrink:0},align:"center",gap:1,paddingRight:1,children:[g(S,{padding:2,mode:"ghost",onClick:()=>n(l,l+-1,t._id,r),disabled:u,icon:a}),g(S,{padding:2,mode:"ghost",disabled:p,onClick:()=>n(l,l+1,t._id,r),icon:c})]}),g(S,{style:{width:"100%"},padding:2,mode:"bleed",onClick:e=>s(t._id,l,e.nativeEvent),children:g(O,{flex:1,align:"center",children:g(x,{flex:1,children:g(o,{layout:"default",value:t,schemaType:f.get(t._type)})})})})]})}function B(e,t){return e.orderRank<t.orderRank?-1:e.orderRank>t.orderRank?1:0}function U(){return s({apiVersion:"2021-09-01"})}function F(e){let{data:n,type:r,listIsUpdating:i,setListIsUpdating:o}=e;const s=_(),d=C(),{navigateIntent:a}=d,[c,u]=v(n);b((()=>{i||u(n)}),[n]);const[p,m]=v(""),[f,y]=v([]),R=w((()=>y([])),[y]),O=w(((e,t,n)=>{const i=f.includes(e),o=n.shiftKey,s=-1!==navigator.appVersion.indexOf("Win")?n.ctrlKey:n.metaKey;let l=[];if(!o&&!s)return a("edit",{id:e,type:r}),y([e]);if(o&&!i){const n=f[f.length-1],r=c.findIndex((e=>e._id===n)),i=t<r?t:r,o=t>r?t:r,s=c.filter(((e,t)=>t>i&&t<o)).map((e=>e._id));l=[...f,...s,e]}else l=i?f.filter((t=>t!==e)):[...f,e];return y(l)}),[y,a,c,f,r]),I=U(),S=w((async(e,t)=>{const n=I.transaction();e.forEach((e=>{let[t,r]=e;return n.patch(t,r)})),await n.commit().then((e=>{R(),m(""),o(!1),s.push({title:"".concat(1===e.results.length?"1 Document":"".concat(e.results.length," Documents")," Reordered"),status:"success",description:t})})).catch((()=>{m(""),o(!1),s.push({title:"Reordering failed",status:"error"})}))}),[I,m,R,o,s]),j=w(((e,t)=>{m("");const{source:n,destination:r,draggableId:i}=null!=e?e:{};if((null==n?void 0:n.index)===(null==r?void 0:r.index))return;if(!(null==t?void 0:t.length)||!i)return;const s=(null==f?void 0:f.length)?f:[i];if(!(null==s?void 0:s.length))return;o(!0),y(s);const{newOrder:d,patches:a,message:c}=(e=>{let{entities:t,selectedIds:n,source:r,destination:i,debug:o=!1}=e;const s=r.index,d=i.index,a=s>d,c=t.filter((e=>n.includes(e._id))),u=["Moved",1===c.length?"1 Document":"".concat(c.length," Documents"),a?"up":"down","from position","".concat(s+1," to ").concat(d+1)].join(" "),{all:p,selected:h}=t.reduce(((e,r,i)=>{var o,s,u,p;if(n.includes(r._id))return{all:e.all,selected:e.selected};if(i===d){const n=i-1,d=(null==(o=t[n])?void 0:o.orderRank)?l.parse(null==(s=t[n])?void 0:s.orderRank):l.min(),h=l.parse(t[i].orderRank),g=i+1,m=(null==(u=t[g])?void 0:u.orderRank)?l.parse(null==(p=t[g])?void 0:p.orderRank):l.max();let f=a?d.between(h):h.between(m);for(let e=0;e<c.length;e+=1)c[e].orderRank=f.value,f=a?f.between(h):f.between(m);return{all:a?[...e.all,...c,r]:[...e.all,r,...c],selected:c}}return{all:[...e.all,r],selected:e.selected}}),{all:[],selected:[]}),g=h.map((e=>[e._id,{set:{orderRank:e.orderRank}}]));return{newOrder:p.sort(B),patches:g,message:u}})({entities:t,selectedIds:s,source:n,destination:r});(null==d?void 0:d.length)&&u(d),(null==a?void 0:a.length)&&S(a,c)}),[f,m,y,S,o]),E=w((e=>{const t=e.draggableId;f.includes(t)||R(),m(t)}),[f,R,m]),$=w(((e,t,n,r)=>j({draggableId:n,source:{index:e},destination:{index:t}},r)),[j]),z=w((e=>{"Escape"===e.key&&R()}),[R]);b((()=>(window.addEventListener("keydown",z),()=>{window.removeEventListener("keydown",z)})),[z]);const N=k((()=>{if(!c.length)return[];const e=c.map((e=>e.orderRank));return e.filter(((t,n)=>e.indexOf(t)!==n))}),[c]),F=w((e=>j(e,c)),[c,j]);return g(P,{onDragStart:E,onDragEnd:F,children:g(L,{droppableId:"documentSortZone",children:e=>h("div",t(t({},e.droppableProps),{},{ref:e.innerRef,children:[c.map(((e,n)=>g(T,{draggableId:e._id,index:n,children:(r,o)=>{const s=f.includes(e._id),l=o.isDragging,d=Boolean(!l&&p&&s),a=i&&s,u=Boolean(!e.orderRank),h=(e=>{const{isDuplicate:t,isGhosting:n,isDragging:r,isSelected:i}=e;return n?"transparent":r||i?"primary":t?"caution":void 0})({isDuplicate:N.includes(e.orderRank),isGhosting:d,isDragging:l,isSelected:s});return g("div",t(t(t({ref:r.innerRef},r.draggableProps),r.dragHandleProps),{},{style:u?{opacity:.2,pointerEvents:"none"}:(m=r.draggableProps.style,y=a,t({userSelect:"none",transition:"opacity 500ms ease-in-out",opacity:y?.2:1,pointerEvents:y?"none":void 0},m)),children:g(x,{paddingBottom:1,children:g(D,{tone:h,shadow:l?2:void 0,radius:2,children:g(V,{doc:e,entities:c,handleSelect:O,increment:$,index:n,isFirst:0===n,isLast:n===c.length-1})})})}));var m,y}},"".concat(e._id,"-").concat(e.orderRank)))),e.placeholder]}))})})}function K(e){let{children:t}=e;return g(x,{padding:3,children:g(D,{padding:4,radius:2,shadow:1,tone:"caution",children:g(I,{children:t})})})}const G={};function H(e){let{type:t,filter:n,params:r=G}=e;const[i,o]=v(!0),[s,l]=v(!1),[d,a]=v([]),c=U();b((()=>{const e="*[_type == $type ".concat(n?"&& ".concat(n):"","]|order(@[$order] asc){\n _id, _type, ").concat("orderRank","\n }"),l=Object.assign(r,{type:t,order:"orderRank"});let u;const p=async()=>{c.fetch(e,l).then((e=>{const t=e.reduce(((t,n)=>{if(!n._id.startsWith("drafts.")){return e.some((e=>e._id==="drafts.".concat(n._id)))?t:[...t,n]}return[...t,n]}),[]);a(t),i&&o(!1)}))};return s||d.length||(async()=>{o(!0),await p(),u||(u=c.listen(e,l).subscribe((()=>p())))})(),()=>null==u?void 0:u.unsubscribe()}),[t]);const u=k((()=>d.length?d.filter((e=>!e.orderRank)).length:0),[d]);return i?g(O,{style:{width:"100%",height:"100%"},align:"center",justify:"center",children:g(j,{})}):h(E,{space:1,style:{overflow:"scroll",height:"100%"},children:[u>0&&h(K,{children:[u,"/",d.length," Documents have no Order. Select"," ",g("strong",{children:"Reset Order"})," from the Menu above to fix."]}),g(x,{padding:1,children:g(F,{data:d,type:t,listIsUpdating:s,setListIsUpdating:l})})]})}function M(e){let{type:t,showIncrements:n,resetOrderTransaction:r,filter:o,params:s}=e;const l=_(),d=i();b((()=>{(null==r?void 0:r.title)&&(null==r?void 0:r.status)&&l.push(r)}),[r,l]);const a=k((()=>{if(!t)return h(m,{children:["No ",g("code",{children:"type"})," was configured"]});const e=d.get(t);return e?"fields"in e&&e.fields.some((e=>"orderRank"===(null==e?void 0:e.name)))?"fields"in e&&e.fields.some((e=>{var t;return"orderRank"===(null==e?void 0:e.name)&&"string"!==(null==(t=null==e?void 0:e.type)?void 0:t.name)}))?h(m,{children:[g("code",{children:"orderRank"})," field on Schema ",g("code",{children:t})," must be"," ",g("code",{children:"string"})," type"]}):"":h(m,{children:["Schema ",g("code",{children:t})," must have an ",g("code",{children:"orderRank"})," field of type"," ",g("code",{children:"string"})]}):h(m,{children:["Schema ",g("code",{children:t})," not found"]})}),[t,d]);return a?g(K,{children:a}):g(N.Provider,{value:{showIncrements:n},children:g(H,{type:t,filter:o,params:s})})}class W extends R{constructor(e){super(e),this.actionHandlers={showIncrements:()=>{this.setState((e=>({showIncrements:!e.showIncrements})))},resetOrder:async()=>{var e;this.setState((()=>({resetOrderTransaction:{status:"info",title:"Reordering started...",closable:!0}})));const t=await async function(){let e=arguments.length>1?arguments[1]:void 0;const t="*[_type == $type]|order(@[$order] asc)._id",n={type:arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",order:"orderRank"},r=await e.fetch(t,n);if(!r.length)return null;const i=e.transaction();let o=l.min();for(let e=0;e<r.length;e+=1)o=o.genNext().genNext(),i.patch(r[e],{set:{orderRank:o.value}});return i.commit().then((e=>e)).catch((e=>e))}(this.props.options.type,this.props.options.client),n=null==(e=null==t?void 0:t.results)?void 0:e.length;this.setState((()=>({resetOrderTransaction:{status:n?"success":"info",title:n?"Reordered ".concat(1===t.results.length?"Document":"Documents"):"Reordering failed",closable:!0}})))}},this.state={showIncrements:!1,resetOrderTransaction:{}}}render(){var e,t,n,r,i,o;const s=null==(t=null==(e=null==this?void 0:this.props)?void 0:e.options)?void 0:t.type;return s?g(M,{filter:null==(r=null==(n=null==this?void 0:this.props)?void 0:n.options)?void 0:r.filter,params:null==(o=null==(i=null==this?void 0:this.props)?void 0:i.options)?void 0:o.params,type:s,showIncrements:this.state.showIncrements,resetOrderTransaction:this.state.resetOrderTransaction}):null}}function X(e){var t,n;if(!(null==e?void 0:e.type)||!e.context||!e.S)throw new Error("\n type, context and S (StructureBuilder) must be provided.\n context and S are available when configuring structure.\n Example: orderableDocumentListDeskItem({type: 'category'})\n ");const{type:r,filter:i,params:o,title:s,icon:l,id:d,context:a,S:c}=e,{schema:h,getClient:g}=a,m=g({apiVersion:"2021-09-01"}),f=null!=s?s:"Orderable ".concat(r),y=null!=d?d:"orderable-".concat(r),v=null!=l?l:p,b=null!=(n=null==(t=h.get(r))?void 0:t.title)?n:r;return c.listItem().title(f).id(y).icon(v).child(Object.assign(c.documentTypeList(r).serialize(),{__preserveInstance:!0,key:y,type:"component",component:W,options:{type:r,filter:i,params:o,client:m},menuItems:[c.menuItem().title("Create new ".concat(b)).intent({type:"create",params:{type:r}}).serialize(),c.menuItem().title("Reset Order").icon(u).action("resetOrder").serialize(),c.menuItem().title("Show Increments").icon(p).action("showIncrements").serialize()]})).serialize()}export{$ as orderRankField,z as orderRankOrdering,X as orderableDocumentListDeskItem};
|
|
2
|
-
//# sourceMappingURL=index.esm.js.map
|
|
1
|
+
function e(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 t(t){for(var r=1;r<arguments.length;r++){var i=null!=arguments[r]?arguments[r]:{};r%2?e(Object(i),!0).forEach((function(e){n(t,e,i[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(i)):e(Object(i)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(i,e))}))}return t}function n(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{defineField as r,useSchema as i,Preview as o,useClient as s}from"sanity";import{LexoRank as l}from"lexorank";import{DragHandleIcon as c,ChevronUpIcon as d,ChevronDownIcon as a,GenerateIcon as u,SortIcon as p}from"@sanity/icons";import{jsxs as h,jsx as g,Fragment as m}from"react/jsx-runtime";import f,{useContext as y,useState as v,useEffect as b,useCallback as w,useMemo as O,Component as x}from"react";import{Flex as I,Box as S,Text as _,Button as D,Card as j,useToast as k,Spinner as P,Stack as E}from"@sanity/ui";import{DragDropContext as R,Droppable as T,Draggable as L}from"@hello-pangea/dnd";import{usePaneRouter as C}from"sanity/desk";const $="orderRank";const z=e=>{if(!(null==e?void 0:e.type))throw new Error("\n type must be provided.\n Example: orderRankField({type: 'category'})\n ");const{type:n}=e;return r(t(t({title:"Order Rank",readOnly:!0,hidden:!0},e),{},{name:$,type:"string",initialValue:async(e,t)=>{let{getClient:r}=t;return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";return(e?l.parse(e):l.min()).genNext().genNext().toString()}(await r({apiVersion:"2021-09-01"}).fetch("*[_type == $type]|order(@[$order] desc)[0][$order]",{type:n,order:$}))}}))},N={title:"Ordered",name:"ordered",by:[{field:$,direction:"asc"}]},V=f.createContext({});function B(e){let{doc:t,increment:n,entities:r,handleSelect:s,index:l,isFirst:u,isLast:p}=e;const{showIncrements:m}=y(V),f=i();return h(I,{align:"center",children:[g(S,{paddingX:3,style:{flexShrink:0},children:g(_,{size:4,children:g(c,{})})}),m&&h(I,{style:{flexShrink:0},align:"center",gap:1,paddingRight:1,children:[g(D,{padding:2,mode:"ghost",onClick:()=>n(l,l+-1,t._id,r),disabled:u,icon:d}),g(D,{padding:2,mode:"ghost",disabled:p,onClick:()=>n(l,l+1,t._id,r),icon:a})]}),g(D,{style:{width:"100%"},padding:2,mode:"bleed",onClick:e=>s(t._id,l,e.nativeEvent),children:g(I,{flex:1,align:"center",children:g(j,{tone:"default",children:g(o,{layout:"default",value:t,schemaType:f.get(t._type)})})})})]})}function U(e,t){return e[$]&&t[$]?e[$]<t[$]?-1:e[$]>t[$]?1:0:0}const F=e=>{let{entities:t,selectedIds:n,source:r,destination:i}=e;const o=r.index,s=i.index,c=o>s,d=t.filter((e=>n.includes(e._id))),a=["Moved",1===d.length?"1 Document":"".concat(d.length," Documents"),c?"up":"down","from position","".concat(o+1," to ").concat(s+1)].join(" "),{all:u,selected:p}=t.reduce(((e,r,i)=>{var o,a,u,p;if(n.includes(r._id))return{all:e.all,selected:e.selected};if(i===s){const n=i-1,s=(null==(o=t[n])?void 0:o[$])?l.parse(null==(a=t[n])?void 0:a[$]):l.min(),h=l.parse(t[i][$]),g=i+1,m=(null==(u=t[g])?void 0:u[$])?l.parse(null==(p=t[g])?void 0:p[$]):l.max();let f=c?s.between(h):h.between(m);for(let e=0;e<d.length;e+=1)d[e][$]=f.toString(),f=c?f.between(h):f.between(m);return{all:c?[...e.all,...d,r]:[...e.all,r,...d],selected:d}}return{all:[...e.all,r],selected:e.selected}}),{all:[],selected:[]}),h=p.map((e=>[e._id,{set:{[$]:e[$]}}]));return{newOrder:u.sort(U),patches:h,message:a}};function K(){return s({apiVersion:"2021-09-01"})}const G=(e,n)=>t({userSelect:"none",transition:"opacity 500ms ease-in-out",opacity:n?.2:1,pointerEvents:n?"none":void 0},e),H=e=>{const{isDuplicate:t,isGhosting:n,isDragging:r,isSelected:i}=e;return n?"transparent":r||i?"primary":t?"caution":void 0};function M(e){let{data:n,type:r,listIsUpdating:i,setListIsUpdating:o}=e;const s=k(),l=C(),{navigateIntent:c}=l,[d,a]=v(n);b((()=>{i||a(n)}),[n]);const[u,p]=v(""),[m,f]=v([]),y=w((()=>f([])),[f]),x=w(((e,t,n)=>{const i=m.includes(e),o=n.shiftKey,s=-1!==navigator.appVersion.indexOf("Win")?n.ctrlKey:n.metaKey;let l=[];if(!o&&!s)return c("edit",{id:e,type:r}),f([e]);if(o&&!i){const n=m[m.length-1],r=d.findIndex((e=>e._id===n)),i=t<r?t:r,o=t>r?t:r,s=d.filter(((e,t)=>t>i&&t<o)).map((e=>e._id));l=[...m,...s,e]}else l=i?m.filter((t=>t!==e)):[...m,e];return f(l)}),[f,c,d,m,r]),I=K(),_=w((async(e,t)=>{const n=I.transaction();e.forEach((e=>{let[t,r]=e;return n.patch(t,r)})),await n.commit().then((e=>{y(),p(""),o(!1),s.push({title:"".concat(1===e.results.length?"1 Document":"".concat(e.results.length," Documents")," Reordered"),status:"success",description:t})})).catch((()=>{p(""),o(!1),s.push({title:"Reordering failed",status:"error"})}))}),[I,p,y,o,s]),D=w(((e,t)=>{p("");const{source:n,destination:r,draggableId:i}=null!=e?e:{};if((null==n?void 0:n.index)===(null==r?void 0:r.index))return;if(!(null==t?void 0:t.length)||!i)return;const s=(null==m?void 0:m.length)?m:[i];if(!(null==s?void 0:s.length))return;o(!0),f(s);const{newOrder:l,patches:c,message:d}=F({entities:t,selectedIds:s,source:n,destination:r});(null==l?void 0:l.length)&&a(l),(null==c?void 0:c.length)&&_(c,d)}),[m,p,f,_,o]),P=w((e=>{const t=e.draggableId;m.includes(t)||y(),p(t)}),[m,y,p]),E=w(((e,t,n,r)=>D({draggableId:n,source:{index:e},destination:{index:t}},r)),[D]),z=w((e=>{"Escape"===e.key&&y()}),[y]);b((()=>(window.addEventListener("keydown",z),()=>{window.removeEventListener("keydown",z)})),[z]);const N=O((()=>{if(!d.length)return[];const e=d.map((e=>e[$]));return e.filter(((t,n)=>e.indexOf(t)!==n))}),[d]),V=w((e=>D(e,d)),[d,D]);return g(R,{onDragStart:P,onDragEnd:V,children:g(T,{droppableId:"documentSortZone",children:e=>h("div",t(t({},e.droppableProps),{},{ref:e.innerRef,children:[d.map(((e,n)=>g(L,{draggableId:e._id,index:n,children:(r,o)=>{const s=m.includes(e._id),l=o.isDragging,c=Boolean(!l&&u&&s),a=i&&s,p=Boolean(!e[$]),h=N.includes(e[$]),f=H({isDuplicate:h,isGhosting:c,isDragging:l,isSelected:s});return g("div",t(t(t({ref:r.innerRef},r.draggableProps),r.dragHandleProps),{},{style:p?{opacity:.2,pointerEvents:"none"}:G(r.draggableProps.style,a),children:g(S,{paddingBottom:1,children:g(j,{tone:f,shadow:l?2:void 0,radius:2,children:g(B,{doc:e,entities:d,handleSelect:x,increment:E,index:n,isFirst:0===n,isLast:n===d.length-1})})})}))}},"".concat(e._id,"-").concat(e[$])))),e.placeholder]}))})})}function W(e){let{children:t}=e;return g(S,{padding:3,children:g(j,{padding:4,radius:2,shadow:1,tone:"caution",children:g(_,{children:t})})})}const X={};function Z(e){let{type:t,filter:n,params:r=X}=e;const[i,o]=v(!0),[s,l]=v(!1),[c,d]=v([]),a=K();b((()=>{const e="*[_type == $type ".concat(n?"&& ".concat(n):"","]|order(@[$order] asc){\n _id, _type, ").concat($,"\n }"),l=Object.assign(r,{type:t,order:$});let u;const p=async()=>{a.fetch(e,l).then((e=>{const t=e.reduce(((t,n)=>{if(!n._id.startsWith("drafts.")){return e.some((e=>e._id==="drafts.".concat(n._id)))?t:[...t,n]}return[...t,n]}),[]);d(t),i&&o(!1)}))};return s||c.length||(async()=>{o(!0),await p(),u||(u=a.listen(e,l).subscribe((()=>p())))})(),()=>null==u?void 0:u.unsubscribe()}),[t]);const u=O((()=>c.length?c.filter((e=>!e[$])).length:0),[c]);return i?g(I,{style:{width:"100%",height:"100%"},align:"center",justify:"center",children:g(P,{})}):h(E,{space:1,style:{overflow:"auto",height:"100%"},children:[u>0&&h(W,{children:[u,"/",c.length," Documents have no Order. Select"," ",g("strong",{children:"Reset Order"})," from the Menu above to fix."]}),g(S,{padding:1,children:g(M,{data:c,type:t,listIsUpdating:s,setListIsUpdating:l})})]})}function q(e){let{type:t,showIncrements:n,resetOrderTransaction:r,filter:o,params:s}=e;const l=k(),c=i();b((()=>{(null==r?void 0:r.title)&&(null==r?void 0:r.status)&&l.push(r)}),[r,l]);const d=O((()=>{if(!t)return h(m,{children:["No ",g("code",{children:"type"})," was configured"]});const e=c.get(t);return e?"fields"in e&&e.fields.some((e=>(null==e?void 0:e.name)===$))?"fields"in e&&e.fields.some((e=>{var t;return(null==e?void 0:e.name)===$&&"string"!==(null==(t=null==e?void 0:e.type)?void 0:t.name)}))?h(m,{children:[g("code",{children:$})," field on Schema ",g("code",{children:t})," must be"," ",g("code",{children:"string"})," type"]}):"":h(m,{children:["Schema ",g("code",{children:t})," must have an ",g("code",{children:$})," field of type"," ",g("code",{children:"string"})]}):h(m,{children:["Schema ",g("code",{children:t})," not found"]})}),[t,c]);return d?g(W,{children:d}):g(V.Provider,{value:{showIncrements:n},children:g(Z,{type:t,filter:o,params:s})})}class A extends x{constructor(e){super(e),this.actionHandlers={showIncrements:()=>{this.setState((e=>({showIncrements:!e.showIncrements})))},resetOrder:async()=>{var e;this.setState((()=>({resetOrderTransaction:{status:"info",title:"Reordering started...",closable:!0}})));const t=await async function(){let e=arguments.length>1?arguments[1]:void 0;const t={type:arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",order:$},n=await e.fetch("*[_type == $type]|order(@[$order] asc)._id",t);if(!n.length)return null;const r=e.transaction();let i=l.min();for(let e=0;e<n.length;e+=1)i=i.genNext().genNext(),r.patch(n[e],{set:{[$]:i.toString()}});return r.commit().then((e=>e)).catch((e=>e))}(this.props.options.type,this.props.options.client),n=null==(e=null==t?void 0:t.results)?void 0:e.length;this.setState((()=>({resetOrderTransaction:{status:n?"success":"info",title:n?"Reordered ".concat(1===t.results.length?"Document":"Documents"):"Reordering failed",closable:!0}})))}},this.state={showIncrements:!1,resetOrderTransaction:{}}}render(){var e,t,n,r,i,o;const s=null==(t=null==(e=null==this?void 0:this.props)?void 0:e.options)?void 0:t.type;return s?g(q,{filter:null==(r=null==(n=null==this?void 0:this.props)?void 0:n.options)?void 0:r.filter,params:null==(o=null==(i=null==this?void 0:this.props)?void 0:i.options)?void 0:o.params,type:s,showIncrements:this.state.showIncrements,resetOrderTransaction:this.state.resetOrderTransaction}):null}}function J(e){var t,n;if(!(null==e?void 0:e.type)||!e.context||!e.S)throw new Error("\n type, context and S (StructureBuilder) must be provided.\n context and S are available when configuring structure.\n Example: orderableDocumentListDeskItem({type: 'category'})\n ");const{type:r,filter:i,params:o,title:s,icon:l,id:c,context:d,S:a}=e,{schema:h,getClient:g}=d,m=g({apiVersion:"2021-09-01"}),f=null!=s?s:"Orderable ".concat(r),y=null!=c?c:"orderable-".concat(r),v=null!=l?l:p,b=null!=(n=null==(t=h.get(r))?void 0:t.title)?n:r;return a.listItem().title(f).id(y).icon(v).child(Object.assign(a.documentTypeList(r).serialize(),{__preserveInstance:!0,key:y,type:"component",component:A,options:{type:r,filter:i,params:o,client:m},menuItems:[a.menuItem().title("Create new ".concat(b)).intent({type:"create",params:{type:r}}).serialize(),a.menuItem().title("Reset Order").icon(u).action("resetOrder").serialize(),a.menuItem().title("Toggle Increments").icon(p).action("showIncrements").serialize()]})).serialize()}export{z as orderRankField,N as orderRankOrdering,J as orderableDocumentListDeskItem};//# sourceMappingURL=index.esm.js.map
|
package/lib/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/fields/orderRankField.ts","../src/helpers/constants.ts","../src/helpers/initialRank.ts","../src/fields/orderRankOrdering.ts","../src/OrderableContext.ts","../src/Document.tsx","../src/helpers/reorderDocuments.ts","../src/helpers/client.ts","../src/DraggableList.tsx","../src/Feedback.tsx","../src/DocumentListQuery.tsx","../src/DocumentListWrapper.tsx","../src/OrderableDocumentList.tsx","../src/helpers/resetOrder.ts","../src/desk-structure/orderableDocumentListDeskItem.ts"],"sourcesContent":["import {type ConfigContext, defineField} from 'sanity'\nimport {ORDER_FIELD_NAME} from '../helpers/constants'\nimport initialRank from '../helpers/initialRank'\n\nexport type SchemaContext = Omit<ConfigContext, 'schema' | 'currentUser' | 'client'>\n\nexport interface RankFieldConfig {\n type: string\n}\n\nexport const orderRankField = (config: RankFieldConfig) => {\n if (!config?.type) {\n throw new Error(\n `\n type must be provided.\n Example: orderRankField({type: 'category'})\n `\n )\n }\n\n const {type} = config\n return defineField({\n title: 'Order Rank',\n readOnly: true,\n hidden: true,\n ...config,\n name: ORDER_FIELD_NAME,\n type: 'string',\n initialValue: async (p, {getClient}) => {\n const lastDocOrderRank = await getClient({apiVersion: '2021-09-01'}).fetch(\n `*[_type == $type]|order(@[$order] desc)[0][$order]`,\n {type, order: ORDER_FIELD_NAME}\n )\n return initialRank(lastDocOrderRank)\n },\n })\n}\n","export const ORDER_FIELD_NAME = `orderRank` as const\n","import {LexoRank} from 'lexorank'\n\n// Use in initial value field by passing in the rank value of the last document\n// If not value passed, generate a sensibly low rank\nexport default function initialRank(lastRankValue = ``): string {\n const lastRank = lastRankValue ? LexoRank.parse(lastRankValue) : LexoRank.min()\n const nextRank = lastRank.genNext().genNext()\n\n return (nextRank as any).value\n}\n","import {ORDER_FIELD_NAME} from '../helpers/constants'\n\nexport const orderRankOrdering = {\n title: 'Ordered',\n name: 'ordered',\n by: [{field: ORDER_FIELD_NAME, direction: 'asc'}],\n}\n","import React from 'react'\n\nexport interface OrderableContextValue {\n showIncrements?: boolean\n}\n\nexport const OrderableContext = React.createContext<OrderableContextValue>({})\n","import React, {useContext} from 'react'\nimport {ChevronDownIcon, ChevronUpIcon, DragHandleIcon} from '@sanity/icons'\nimport {Box, Button, Flex, Text} from '@sanity/ui'\n\nimport {useSchema, SanityDocument, SchemaType, Preview} from 'sanity'\nimport {OrderableContext} from './OrderableContext'\n\nexport interface DocumentProps {\n doc: SanityDocument\n entities: SanityDocument[]\n handleSelect: (docId: string, index: number, event: MouseEvent) => void\n increment: (index: number, nextIndex: number, docId: string, entities: SanityDocument[]) => void\n index: number\n isFirst: boolean\n isLast: boolean\n}\n\nexport default function Document({\n doc,\n increment,\n entities,\n handleSelect,\n index,\n isFirst,\n isLast,\n}: DocumentProps) {\n const {showIncrements} = useContext(OrderableContext)\n const schema = useSchema()\n return (\n <Flex align=\"center\">\n <Box paddingX={3} style={{flexShrink: 0}}>\n <Text size={4}>\n <DragHandleIcon />\n </Text>\n </Box>\n {showIncrements && (\n <Flex style={{flexShrink: 0}} align=\"center\" gap={1} paddingRight={1}>\n <Button\n padding={2}\n mode=\"ghost\"\n onClick={() => increment(index, index + -1, doc._id, entities)}\n disabled={isFirst}\n icon={ChevronUpIcon}\n />\n <Button\n padding={2}\n mode=\"ghost\"\n disabled={isLast}\n onClick={() => increment(index, index + 1, doc._id, entities)}\n icon={ChevronDownIcon}\n />\n </Flex>\n )}\n <Button\n style={{width: `100%`}}\n padding={2}\n mode=\"bleed\"\n onClick={(e) => handleSelect(doc._id, index, e.nativeEvent)}\n >\n <Flex flex={1} align=\"center\">\n <Box flex={1}>\n <Preview\n layout=\"default\"\n value={doc}\n schemaType={schema.get(doc._type) as SchemaType}\n />\n </Box>\n </Flex>\n </Button>\n </Flex>\n )\n}\n","import {LexoRank} from 'lexorank'\nimport type {PatchOperations, SanityDocument} from 'sanity'\nimport {ORDER_FIELD_NAME} from './constants'\n\nexport interface MaifestArgs {\n entities: SanityDocument[]\n selectedItems: SanityDocument[]\n isMovingUp: boolean\n curIndex: number\n nextIndex: number\n prevIndex: number\n}\n\nexport interface ReorderArgs {\n entities: SanityDocument[]\n selectedIds: string[]\n source: any\n destination: any\n debug?: boolean\n}\n\nfunction lexicographicalSort(a: {[ORDER_FIELD_NAME]: string}, b: {[ORDER_FIELD_NAME]: string}) {\n if (a[ORDER_FIELD_NAME] < b[ORDER_FIELD_NAME]) {\n return -1\n }\n if (a[ORDER_FIELD_NAME] > b[ORDER_FIELD_NAME]) {\n return 1\n }\n return 0\n}\n\nexport const reorderDocuments = ({\n entities,\n selectedIds,\n source,\n destination,\n debug = false,\n}: ReorderArgs) => {\n const startIndex = source.index\n const endIndex = destination.index\n const isMovingUp = startIndex > endIndex\n const selectedItems = entities.filter((item) => selectedIds.includes(item._id))\n const message = [\n `Moved`,\n selectedItems.length === 1 ? `1 Document` : `${selectedItems.length} Documents`,\n isMovingUp ? `up` : `down`,\n `from position`,\n `${startIndex + 1} to ${endIndex + 1}`,\n ].join(' ')\n\n const {all, selected} = entities.reduce(\n (acc, cur, curIndex) => {\n // Selected items get spread in below, so skip them here\n if (selectedIds.includes(cur._id)) {\n return {all: acc.all, selected: acc.selected}\n }\n\n // Drop seleced items in\n if (curIndex === endIndex) {\n const prevIndex = curIndex - 1\n const prevRank = entities[prevIndex]?.[ORDER_FIELD_NAME]\n ? LexoRank.parse(entities[prevIndex]?.[ORDER_FIELD_NAME] as string)\n : LexoRank.min()\n\n const curRank = LexoRank.parse(entities[curIndex][ORDER_FIELD_NAME] as string)\n\n const nextIndex = curIndex + 1\n const nextRank = entities[nextIndex]?.[ORDER_FIELD_NAME]\n ? LexoRank.parse(entities[nextIndex]?.[ORDER_FIELD_NAME] as string)\n : LexoRank.max()\n\n let betweenRank = isMovingUp ? prevRank.between(curRank) : curRank.between(nextRank)\n\n // For each selected item, assign a new orderRank between now and next\n for (let selectedIndex = 0; selectedIndex < selectedItems.length; selectedIndex += 1) {\n selectedItems[selectedIndex][ORDER_FIELD_NAME] = (betweenRank as any).value as string\n betweenRank = isMovingUp ? betweenRank.between(curRank) : betweenRank.between(nextRank)\n }\n\n return {\n // The `all` array gets sorted by order field later anyway\n // so that this probably isn't necessary ¯\\_(ツ)_/¯\n all: isMovingUp\n ? [...acc.all, ...selectedItems, cur]\n : [...acc.all, cur, ...selectedItems],\n selected: selectedItems,\n }\n }\n\n return {all: [...acc.all, cur], selected: acc.selected}\n },\n {all: [] as SanityDocument[], selected: [] as SanityDocument[]}\n )\n\n const patches: [string, PatchOperations][] = selected.map((doc) => {\n return [\n doc._id,\n {\n set: {\n [ORDER_FIELD_NAME]: doc[ORDER_FIELD_NAME],\n },\n },\n ]\n })\n\n // Safety-check to make sure everything is in order\n const allSorted = (all as unknown as {[ORDER_FIELD_NAME]: string}[]).sort(lexicographicalSort)\n\n return {newOrder: allSorted, patches, message}\n}\n","import {useClient} from 'sanity'\n\nexport function useSanityClient() {\n return useClient({apiVersion: '2021-09-01'})\n}\n","import React, {useEffect, useState, useMemo, useCallback, CSSProperties} from 'react'\nimport {DragDropContext, Draggable, Droppable, type DropResult} from 'react-beautiful-dnd'\nimport {Box, Card, useToast} from '@sanity/ui'\nimport {usePaneRouter} from 'sanity/desk'\nimport type {SanityDocument, PatchOperations} from 'sanity'\nimport Document from './Document'\nimport {reorderDocuments} from './helpers/reorderDocuments'\nimport {ORDER_FIELD_NAME} from './helpers/constants'\nimport {useSanityClient} from './helpers/client'\n\nconst getItemStyle = (\n draggableStyle: CSSProperties | undefined,\n itemIsUpdating: boolean\n): CSSProperties => ({\n userSelect: 'none',\n transition: `opacity 500ms ease-in-out`,\n opacity: itemIsUpdating ? 0.2 : 1,\n pointerEvents: itemIsUpdating ? `none` : undefined,\n ...draggableStyle,\n})\n\nconst cardTone = (settings: ListSetting) => {\n const {isDuplicate, isGhosting, isDragging, isSelected} = settings\n\n if (isGhosting) return `transparent`\n if (isDragging || isSelected) return `primary`\n if (isDuplicate) return `caution`\n\n return undefined\n}\n\ninterface ListSetting {\n isDuplicate: boolean\n isGhosting: boolean\n isDragging: boolean\n isSelected: boolean\n}\n\nexport interface DraggableListProps {\n data: SanityDocument[]\n type: string\n listIsUpdating: boolean\n setListIsUpdating: (val: boolean) => void\n}\n\nexport default function DraggableList({\n data,\n type,\n listIsUpdating,\n setListIsUpdating,\n}: DraggableListProps) {\n const toast = useToast()\n const router = usePaneRouter()\n const {navigateIntent} = router\n\n // Maintains local state order before transaction completes\n const [orderedData, setOrderedData] = useState<SanityDocument[]>(data)\n\n // Update local state when documents change from an outside source\n useEffect(() => {\n if (!listIsUpdating) setOrderedData(data)\n /* eslint-disable-next-line react-hooks/exhaustive-deps */\n }, [data])\n\n const [draggingId, setDraggingId] = useState(``)\n const [selectedIds, setSelectedIds] = useState<string[]>([])\n\n const clearSelected = useCallback(() => setSelectedIds([]), [setSelectedIds])\n\n const handleSelect = useCallback(\n (clickedId: string, index: number, nativeEvent: MouseEvent) => {\n const isSelected = selectedIds.includes(clickedId)\n const selectMultiple = nativeEvent.shiftKey\n const isUsingWindows = navigator.appVersion.indexOf('Win') !== -1\n const selectAdditional = isUsingWindows ? nativeEvent.ctrlKey : nativeEvent.metaKey\n\n let updatedIds = []\n\n // No modifier keys pressed during click:\n // - update selected to just this one\n // - open document\n if (!selectMultiple && !selectAdditional) {\n navigateIntent('edit', {id: clickedId, type})\n return setSelectedIds([clickedId])\n }\n\n // Shift key was held, add id's between last selected and this one\n // ...before adding this one\n if (selectMultiple && !isSelected) {\n const lastSelectedId = selectedIds[selectedIds.length - 1]\n const lastSelectedIndex = orderedData.findIndex((item) => item._id === lastSelectedId)\n\n const firstSelected = index < lastSelectedIndex ? index : lastSelectedIndex\n const lastSelected = index > lastSelectedIndex ? index : lastSelectedIndex\n\n const betweenIds = orderedData\n .filter((item, itemIndex) => itemIndex > firstSelected && itemIndex < lastSelected)\n .map((item) => item._id)\n\n updatedIds = [...selectedIds, ...betweenIds, clickedId]\n } else if (isSelected) {\n // Toggle off a single id\n updatedIds = selectedIds.filter((id) => id !== clickedId)\n } else {\n // Toggle on a single id\n updatedIds = [...selectedIds, clickedId]\n }\n\n return setSelectedIds(updatedIds)\n },\n [setSelectedIds, navigateIntent, orderedData, selectedIds, type]\n )\n\n const client = useSanityClient()\n\n const transactPatches = useCallback(\n async (patches: [string, PatchOperations][], message: string) => {\n const transaction = client.transaction()\n\n patches.forEach(([docId, ops]) => transaction.patch(docId, ops))\n\n await transaction\n .commit()\n .then((updated) => {\n clearSelected()\n setDraggingId(``)\n setListIsUpdating(false)\n toast.push({\n title: `${\n updated.results.length === 1 ? `1 Document` : `${updated.results.length} Documents`\n } Reordered`,\n status: `success`,\n description: message,\n })\n })\n .catch(() => {\n setDraggingId(``)\n setListIsUpdating(false)\n toast.push({\n title: `Reordering failed`,\n status: `error`,\n })\n })\n },\n [client, setDraggingId, clearSelected, setListIsUpdating, toast]\n )\n\n const handleDragEnd = useCallback(\n (result: DropResult | undefined, entities: SanityDocument[]) => {\n setDraggingId(``)\n\n const {source, destination, draggableId} = result ?? {}\n\n // Don't do anything if nothing changed\n if (source?.index === destination?.index) return\n\n // Don't do anything if we don't have the entitites\n if (!entities?.length || !draggableId) return\n\n // A document can be dragged without being one-of-many-selected\n const effectedIds = selectedIds?.length ? selectedIds : [draggableId]\n\n // Don't do anything if we don't have ids to effect\n if (!effectedIds?.length) return\n\n // Update state to update styles + prevent data refetching\n setListIsUpdating(true)\n setSelectedIds(effectedIds)\n\n const {newOrder, patches, message} = reorderDocuments({\n entities,\n selectedIds: effectedIds,\n source,\n destination,\n })\n\n // Update local state\n if (newOrder?.length) {\n setOrderedData(newOrder as any)\n }\n\n // Transact new order patches\n if (patches?.length) {\n transactPatches(patches, message)\n }\n },\n [selectedIds, setDraggingId, setSelectedIds, transactPatches, setListIsUpdating]\n )\n\n const handleDragStart = useCallback(\n (start: {draggableId: string}) => {\n const id = start.draggableId\n const selected = selectedIds.includes(id)\n\n // if dragging an item that is not selected - unselect all items\n if (!selected) clearSelected()\n\n setDraggingId(id)\n },\n [selectedIds, clearSelected, setDraggingId]\n )\n\n // Move one document up or down one place, by fake invoking the drag function\n const incrementIndex = useCallback(\n (shiftFrom: number, shiftTo: number, id: string, entities: SanityDocument[]) => {\n const result = {\n draggableId: id,\n source: {index: shiftFrom},\n destination: {index: shiftTo},\n }\n\n return handleDragEnd(result as DropResult, entities)\n },\n [handleDragEnd]\n )\n\n const onWindowKeyDown = useCallback(\n (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n clearSelected()\n }\n },\n [clearSelected]\n )\n\n useEffect(() => {\n window.addEventListener('keydown', onWindowKeyDown)\n\n return () => {\n window.removeEventListener('keydown', onWindowKeyDown)\n }\n }, [onWindowKeyDown])\n\n // Find all items with duplicate order field\n const duplicateOrders = useMemo(() => {\n if (!orderedData.length) return []\n\n const orderField = orderedData.map((item) => item[ORDER_FIELD_NAME])\n\n return orderField.filter((item, index) => orderField.indexOf(item) !== index)\n }, [orderedData])\n\n const onDragEnd = useCallback(\n (result: DropResult) => handleDragEnd(result, orderedData),\n [orderedData, handleDragEnd]\n )\n\n return (\n <DragDropContext onDragStart={handleDragStart} onDragEnd={onDragEnd}>\n <Droppable droppableId=\"documentSortZone\">\n {(provided) => (\n <div {...provided.droppableProps} ref={provided.innerRef}>\n {orderedData.map((item, index) => (\n <Draggable\n key={`${item._id}-${item[ORDER_FIELD_NAME]}`}\n draggableId={item._id}\n index={index}\n // onClick={(event) => handleDraggableClick(event, provided, snapshot)}\n >\n {(innerProvided, innerSnapshot) => {\n const isSelected = selectedIds.includes(item._id)\n const isDragging = innerSnapshot.isDragging\n const isGhosting = Boolean(!isDragging && draggingId && isSelected)\n const isUpdating = listIsUpdating && isSelected\n const isDisabled = Boolean(!item[ORDER_FIELD_NAME])\n const isDuplicate = duplicateOrders.includes(item[ORDER_FIELD_NAME])\n const tone = cardTone({isDuplicate, isGhosting, isDragging, isSelected})\n\n return (\n <div\n ref={innerProvided.innerRef}\n {...innerProvided.draggableProps}\n {...innerProvided.dragHandleProps}\n style={\n isDisabled\n ? {opacity: 0.2, pointerEvents: `none`}\n : getItemStyle(innerProvided.draggableProps.style, isUpdating)\n }\n >\n <Box paddingBottom={1}>\n <Card tone={tone} shadow={isDragging ? 2 : undefined} radius={2}>\n <Document\n doc={item}\n entities={orderedData}\n handleSelect={handleSelect}\n increment={incrementIndex}\n index={index}\n isFirst={index === 0}\n isLast={index === orderedData.length - 1}\n />\n </Card>\n </Box>\n </div>\n )\n }}\n </Draggable>\n ))}\n {provided.placeholder}\n </div>\n )}\n </Droppable>\n </DragDropContext>\n )\n}\n","import React, {PropsWithChildren} from 'react'\nimport {Box, Card, Text} from '@sanity/ui'\n\nexport default function Feedback({children}: PropsWithChildren<{}>) {\n return (\n <Box padding={3}>\n <Card padding={4} radius={2} shadow={1} tone=\"caution\">\n <Text>{children}</Text>\n </Card>\n </Box>\n )\n}\n","import React, {useEffect, useMemo, useState} from 'react'\nimport {Box, Flex, Spinner, Stack} from '@sanity/ui'\n\nimport type {SanityDocument} from 'sanity'\nimport DraggableList from './DraggableList'\nimport {ORDER_FIELD_NAME} from './helpers/constants'\nimport Feedback from './Feedback'\nimport {useSanityClient} from './helpers/client'\n\nexport interface DocumentListQueryProps {\n type: string\n filter?: string\n params?: Record<string, unknown>\n}\n\n//rxjs Subscription does not seem to comply with sanity client subscribe anymore\ntype ClientSubscription = ReturnType<\n ReturnType<ReturnType<typeof useSanityClient>['listen']>['subscribe']\n>\n\nconst DEFAULT_PARAMS = {}\n\nexport default function DocumentListQuery({\n type,\n filter,\n params = DEFAULT_PARAMS,\n}: DocumentListQueryProps) {\n const [isLoading, setIsLoading] = useState(true)\n const [listIsUpdating, setListIsUpdating] = useState(false)\n const [data, setData] = useState<SanityDocument[]>([])\n\n const client = useSanityClient()\n\n useEffect(() => {\n const query = `*[_type == $type ${filter ? `&& ${filter}` : ''}]|order(@[$order] asc){\n _id, _type, ${ORDER_FIELD_NAME}\n }`\n const queryParams = Object.assign(params, {type, order: ORDER_FIELD_NAME})\n let subscription: ClientSubscription | undefined\n\n // eslint-disable-next-line require-await\n const fetchData = async () => {\n client.fetch<SanityDocument[]>(query, queryParams).then((documents) => {\n // Remove published document from list if draft also exists\n const filteredDocuments = documents.reduce((acc, cur) => {\n if (!cur._id.startsWith(`drafts.`)) {\n // eslint-disable-next-line max-nested-callbacks\n const alsoHasDraft = documents.some((doc) => doc._id === `drafts.${cur._id}`)\n\n return alsoHasDraft ? acc : [...acc, cur]\n }\n\n return [...acc, cur]\n }, [] as SanityDocument[])\n\n setData(filteredDocuments)\n\n if (isLoading) {\n setIsLoading(false)\n }\n })\n }\n\n const prepareData = async () => {\n setIsLoading(true)\n\n await fetchData()\n\n if (!subscription) {\n subscription = client.listen(query, queryParams).subscribe(() => fetchData())\n }\n }\n\n // Get data but only if a document isn't being patched or we don't yet have data\n if (!listIsUpdating && !data.length) {\n prepareData()\n }\n\n return () => subscription?.unsubscribe()\n /* eslint-disable-next-line react-hooks/exhaustive-deps */\n }, [type])\n\n const unorderedDataCount = useMemo(\n () => (data.length ? data.filter((doc) => !doc[ORDER_FIELD_NAME]).length : 0),\n [data]\n )\n\n if (isLoading)\n return (\n <Flex style={{width: `100%`, height: `100%`}} align=\"center\" justify=\"center\">\n <Spinner />\n </Flex>\n )\n\n return (\n <Stack space={1} style={{overflow: `scroll`, height: `100%`}}>\n {unorderedDataCount > 0 && (\n <Feedback>\n {unorderedDataCount}/{data.length} Documents have no Order. Select{' '}\n <strong>Reset Order</strong> from the Menu above to fix.\n </Feedback>\n )}\n <Box padding={1}>\n <DraggableList\n data={data}\n type={type}\n listIsUpdating={listIsUpdating}\n setListIsUpdating={setListIsUpdating}\n />\n </Box>\n </Stack>\n )\n}\n","import React, {useEffect, useMemo} from 'react'\nimport {useToast} from '@sanity/ui'\n\nimport {useSchema} from 'sanity'\nimport type {ToastParams} from '@sanity/ui'\nimport DocumentListQuery from './DocumentListQuery'\nimport {OrderableContext} from './OrderableContext'\n\nimport {ORDER_FIELD_NAME} from './helpers/constants'\nimport Feedback from './Feedback'\n\nexport interface DocumentListWrapperProps {\n showIncrements: boolean\n type: string\n resetOrderTransaction: ToastParams\n filter?: string\n params?: Record<string, unknown>\n}\n\n// 1. Validate first that the schema has been configured for ordering\n// 2. Setup context for showIncrements\nexport default function DocumentListWrapper({\n type,\n showIncrements,\n resetOrderTransaction,\n filter,\n params,\n}: DocumentListWrapperProps) {\n const toast = useToast()\n const schema = useSchema()\n\n useEffect(() => {\n if (resetOrderTransaction?.title && resetOrderTransaction?.status) {\n toast.push(resetOrderTransaction)\n }\n }, [resetOrderTransaction, toast])\n\n const schemaIsInvalid = useMemo(() => {\n // Option not passed\n if (!type) {\n return (\n <>\n No <code>type</code> was configured\n </>\n )\n }\n\n const typeSchema = schema.get(type)\n\n // Schema not found\n if (!typeSchema) {\n return (\n <>\n Schema <code>{type}</code> not found\n </>\n )\n }\n\n // Schema lacks an order field\n if (\n !('fields' in typeSchema) ||\n !typeSchema.fields.some((field) => field?.name === ORDER_FIELD_NAME)\n ) {\n return (\n <>\n Schema <code>{type}</code> must have an <code>{ORDER_FIELD_NAME}</code> field of type{' '}\n <code>string</code>\n </>\n )\n }\n\n // Schema's order field is not a string\n if (\n 'fields' in typeSchema &&\n typeSchema.fields.some(\n (field) => field?.name === ORDER_FIELD_NAME && field?.type?.name !== 'string'\n )\n ) {\n return (\n <>\n <code>{ORDER_FIELD_NAME}</code> field on Schema <code>{type}</code> must be{' '}\n <code>string</code> type\n </>\n )\n }\n\n return ''\n }, [type, schema])\n\n if (schemaIsInvalid) {\n return <Feedback>{schemaIsInvalid}</Feedback>\n }\n\n return (\n <OrderableContext.Provider value={{showIncrements}}>\n <DocumentListQuery type={type} filter={filter} params={params} />\n </OrderableContext.Provider>\n )\n}\n","import React, {Component} from 'react'\n\nimport {SanityClient} from '@sanity/client'\nimport type {ToastParams} from '@sanity/ui'\nimport DocumentListWrapper from './DocumentListWrapper'\nimport {resetOrder} from './helpers/resetOrder'\n\nexport interface OrderableDocumentListProps {\n options: {\n type: string\n client: SanityClient,\n filter?: string,\n params?: Record<string, unknown>\n }\n}\n\ninterface State {\n showIncrements: boolean\n resetOrderTransaction: ToastParams\n}\n\n// Must use a Class Component here so the actionHandlers can be called\nexport default class OrderableDocumentList extends Component<OrderableDocumentListProps, State> {\n constructor(props: OrderableDocumentListProps) {\n super(props)\n this.state = {\n showIncrements: false,\n resetOrderTransaction: {},\n }\n }\n\n actionHandlers = {\n showIncrements: () => {\n this.setState((state) => ({\n showIncrements: !state.showIncrements,\n }))\n },\n\n resetOrder: async () => {\n this.setState(() => ({\n resetOrderTransaction: {\n status: `info`,\n title: `Reordering started...`,\n closable: true,\n },\n }))\n\n const update = await resetOrder(this.props.options.type, this.props.options.client)\n\n const reorderWasSuccessful = update?.results?.length\n\n this.setState(() => ({\n resetOrderTransaction: {\n status: reorderWasSuccessful ? `success` : `info`,\n title: reorderWasSuccessful\n ? `Reordered ${update.results.length === 1 ? `Document` : `Documents`}`\n : `Reordering failed`,\n closable: true,\n },\n }))\n },\n }\n\n render() {\n const type = this?.props?.options?.type\n if (!type) {\n return null\n }\n return (\n <DocumentListWrapper\n filter={this?.props?.options?.filter}\n params={this?.props?.options?.params}\n type={type}\n showIncrements={this.state.showIncrements}\n resetOrderTransaction={this.state.resetOrderTransaction}\n />\n )\n }\n}\n","import {LexoRank} from 'lexorank'\nimport {SanityClient} from '@sanity/client'\nimport {ORDER_FIELD_NAME} from './constants'\n// Function to wipe and re-do ordering with LexoRank\n// Will at least attempt to start with the current order\nexport async function resetOrder(type = ``, client: SanityClient) {\n const query = `*[_type == $type]|order(@[$order] asc)._id`\n const queryParams = {type, order: ORDER_FIELD_NAME}\n const documents = await client.fetch(query, queryParams)\n\n if (!documents.length) {\n return null\n }\n\n const transaction = client.transaction()\n let aLexoRank = LexoRank.min()\n\n for (let index = 0; index < documents.length; index += 1) {\n // Generate next rank before even the first document so there's room to move!\n aLexoRank = aLexoRank.genNext().genNext()\n\n transaction.patch(documents[index], {\n set: {[ORDER_FIELD_NAME]: (aLexoRank as any).value as string},\n })\n }\n\n return transaction\n .commit()\n .then((update) => update)\n .catch((err) => err)\n}\n","import {GenerateIcon, SortIcon} from '@sanity/icons'\nimport type {ConfigContext} from 'sanity'\n\nimport {ComponentType} from 'react'\nimport {StructureBuilder} from 'sanity/desk'\nimport OrderableDocumentList from '../OrderableDocumentList'\n\nexport interface OrderableListConfig {\n type: string\n id?: string\n title?: string\n icon?: ComponentType\n params?: Record<string, unknown>\n filter?: string\n context: ConfigContext\n S: StructureBuilder\n}\n\nexport function orderableDocumentListDeskItem(config: OrderableListConfig) {\n if (!config?.type || !config.context || !config.S) {\n throw new Error(`\n type, context and S (StructureBuilder) must be provided.\n context and S are available when configuring structure.\n Example: orderableDocumentListDeskItem({type: 'category'})\n `)\n }\n\n const {type, filter, params, title, icon, id, context, S} = config\n const {schema, getClient} = context\n const client = getClient({apiVersion: '2021-09-01'})\n\n const listTitle = title ?? `Orderable ${type}`\n const listId = id ?? `orderable-${type}`\n const listIcon = icon ?? SortIcon\n const typeTitle = schema.get(type)?.title ?? type\n\n return S.listItem()\n .title(listTitle)\n .id(listId)\n .icon(listIcon)\n .child(\n Object.assign(S.documentTypeList(type).serialize(), {\n // Prevents the component from re-rendering when switching documents\n __preserveInstance: true,\n // Prevents the component from NOT re-rendering when switching listItems\n key: listId,\n\n type: 'component',\n component: OrderableDocumentList,\n options: {type, filter, params, client},\n menuItems: [\n S.menuItem()\n .title(`Create new ${typeTitle}`)\n .intent({type: 'create', params: {type}})\n .serialize(),\n S.menuItem().title(`Reset Order`).icon(GenerateIcon).action(`resetOrder`).serialize(),\n S.menuItem().title(`Show Increments`).icon(SortIcon).action(`showIncrements`).serialize(),\n ],\n })\n )\n .serialize()\n}\n"],"names":["orderRankField","config","type","Error","defineField","_objectSpread","title","readOnly","hidden","name","initialValue","async","p","_ref","getClient","lastRankValue","lastRank","LexoRank","parse","min","genNext","value","initialRank","apiVersion","fetch","order","orderRankOrdering","by","field","direction","OrderableContext","React","createContext","Document","_ref2","doc","increment","entities","handleSelect","index","isFirst","isLast","showIncrements","useContext","schema","useSchema","jsxs","Flex","align","children","jsx","Box","paddingX","style","flexShrink","Text","size","DragHandleIcon","gap","paddingRight","Button","padding","mode","onClick","_id","disabled","icon","ChevronUpIcon","ChevronDownIcon","width","e","nativeEvent","flex","Preview","layout","schemaType","get","_type","lexicographicalSort","a","b","useSanityClient","useClient","DraggableList","_ref4","data","listIsUpdating","setListIsUpdating","toast","useToast","router","usePaneRouter","navigateIntent","orderedData","setOrderedData","useState","useEffect","draggingId","setDraggingId","selectedIds","setSelectedIds","clearSelected","useCallback","clickedId","isSelected","includes","selectMultiple","shiftKey","selectAdditional","navigator","appVersion","indexOf","ctrlKey","metaKey","updatedIds","id","lastSelectedId","length","lastSelectedIndex","findIndex","item","firstSelected","lastSelected","betweenIds","filter","itemIndex","map","client","transactPatches","patches","message","transaction","forEach","_ref5","docId","ops","patch","commit","then","updated","push","results","concat","status","description","catch","handleDragEnd","result","source","destination","draggableId","effectedIds","newOrder","_ref3","debug","startIndex","endIndex","isMovingUp","selectedItems","join","all","selected","reduce","acc","cur","curIndex","_a","_b","_c","_d","prevIndex","prevRank","curRank","nextIndex","nextRank","max","betweenRank","between","selectedIndex","set","orderRank","sort","reorderDocuments","handleDragStart","start","incrementIndex","shiftFrom","shiftTo","onWindowKeyDown","event","key","window","addEventListener","removeEventListener","duplicateOrders","useMemo","orderField","onDragEnd","DragDropContext","onDragStart","Droppable","droppableId","provided","droppableProps","ref","innerRef","Draggable","innerProvided","innerSnapshot","isDragging","isGhosting","Boolean","isUpdating","isDisabled","tone","settings","isDuplicate","cardTone","draggableProps","dragHandleProps","opacity","pointerEvents","draggableStyle","itemIsUpdating","userSelect","transition","paddingBottom","Card","shadow","radius","placeholder","Feedback","_ref6","DEFAULT_PARAMS","DocumentListQuery","_ref7","params","isLoading","setIsLoading","setData","query","ORDER_FIELD_NAME","queryParams","Object","assign","subscription","fetchData","documents","filteredDocuments","startsWith","some","listen","subscribe","prepareData","unsubscribe","unorderedDataCount","height","justify","Spinner","Stack","space","overflow","DocumentListWrapper","_ref8","resetOrderTransaction","schemaIsInvalid","Fragment","typeSchema","fields","Provider","OrderableDocumentList","Component","constructor","props","super","this","actionHandlers","setState","state","resetOrder","closable","update","arguments","undefined","aLexoRank","err","options","reorderWasSuccessful","render","_e","_f","orderableDocumentListDeskItem","context","S","listTitle","listId","listIcon","SortIcon","typeTitle","listItem","child","documentTypeList","serialize","__preserveInstance","component","menuItems","menuItem","intent","GenerateIcon","action"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/lib/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
"use strict";function e(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 t(t){for(var r=1;r<arguments.length;r++){var i=null!=arguments[r]?arguments[r]:{};r%2?e(Object(i),!0).forEach((function(e){n(t,e,i[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(i)):e(Object(i)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(i,e))}))}return t}function n(e,t,n){return 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 r=require("sanity"),i=require("lexorank"),s=require("@sanity/icons"),o=require("react/jsx-runtime"),a=require("react"),l=require("@sanity/ui"),d=require("react-beautiful-dnd"),c=require("sanity/desk");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}const p={title:"Ordered",name:"ordered",by:[{field:"orderRank",direction:"asc"}]},h=u(a).default.createContext({});function g(e){let{doc:t,increment:n,entities:i,handleSelect:d,index:c,isFirst:u,isLast:p}=e;const{showIncrements:g}=a.useContext(h),f=r.useSchema();return o.jsxs(l.Flex,{align:"center",children:[o.jsx(l.Box,{paddingX:3,style:{flexShrink:0},children:o.jsx(l.Text,{size:4,children:o.jsx(s.DragHandleIcon,{})})}),g&&o.jsxs(l.Flex,{style:{flexShrink:0},align:"center",gap:1,paddingRight:1,children:[o.jsx(l.Button,{padding:2,mode:"ghost",onClick:()=>n(c,c+-1,t._id,i),disabled:u,icon:s.ChevronUpIcon}),o.jsx(l.Button,{padding:2,mode:"ghost",disabled:p,onClick:()=>n(c,c+1,t._id,i),icon:s.ChevronDownIcon})]}),o.jsx(l.Button,{style:{width:"100%"},padding:2,mode:"bleed",onClick:e=>d(t._id,c,e.nativeEvent),children:o.jsx(l.Flex,{flex:1,align:"center",children:o.jsx(l.Box,{flex:1,children:o.jsx(r.Preview,{layout:"default",value:t,schemaType:f.get(t._type)})})})})]})}function f(e,t){return e.orderRank<t.orderRank?-1:e.orderRank>t.orderRank?1:0}function m(){return r.useClient({apiVersion:"2021-09-01"})}function x(e){let{data:n,type:r,listIsUpdating:s,setListIsUpdating:u}=e;const p=l.useToast(),h=c.usePaneRouter(),{navigateIntent:x}=h,[y,v]=a.useState(n);a.useEffect((()=>{s||v(n)}),[n]);const[b,j]=a.useState(""),[k,R]=a.useState([]),w=a.useCallback((()=>R([])),[R]),O=a.useCallback(((e,t,n)=>{const i=k.includes(e),s=n.shiftKey,o=-1!==navigator.appVersion.indexOf("Win")?n.ctrlKey:n.metaKey;let a=[];if(!s&&!o)return x("edit",{id:e,type:r}),R([e]);if(s&&!i){const n=k[k.length-1],r=y.findIndex((e=>e._id===n)),i=t<r?t:r,s=t>r?t:r,o=y.filter(((e,t)=>t>i&&t<s)).map((e=>e._id));a=[...k,...o,e]}else a=i?k.filter((t=>t!==e)):[...k,e];return R(a)}),[R,x,y,k,r]),I=m(),S=a.useCallback((async(e,t)=>{const n=I.transaction();e.forEach((e=>{let[t,r]=e;return n.patch(t,r)})),await n.commit().then((e=>{w(),j(""),u(!1),p.push({title:"".concat(1===e.results.length?"1 Document":"".concat(e.results.length," Documents")," Reordered"),status:"success",description:t})})).catch((()=>{j(""),u(!1),p.push({title:"Reordering failed",status:"error"})}))}),[I,j,w,u,p]),D=a.useCallback(((e,t)=>{j("");const{source:n,destination:r,draggableId:s}=null!=e?e:{};if((null==n?void 0:n.index)===(null==r?void 0:r.index))return;if(!(null==t?void 0:t.length)||!s)return;const o=(null==k?void 0:k.length)?k:[s];if(!(null==o?void 0:o.length))return;u(!0),R(o);const{newOrder:a,patches:l,message:d}=(e=>{let{entities:t,selectedIds:n,source:r,destination:s,debug:o=!1}=e;const a=r.index,l=s.index,d=a>l,c=t.filter((e=>n.includes(e._id))),u=["Moved",1===c.length?"1 Document":"".concat(c.length," Documents"),d?"up":"down","from position","".concat(a+1," to ").concat(l+1)].join(" "),{all:p,selected:h}=t.reduce(((e,r,s)=>{var o,a,u,p;if(n.includes(r._id))return{all:e.all,selected:e.selected};if(s===l){const n=s-1,l=(null==(o=t[n])?void 0:o.orderRank)?i.LexoRank.parse(null==(a=t[n])?void 0:a.orderRank):i.LexoRank.min(),h=i.LexoRank.parse(t[s].orderRank),g=s+1,f=(null==(u=t[g])?void 0:u.orderRank)?i.LexoRank.parse(null==(p=t[g])?void 0:p.orderRank):i.LexoRank.max();let m=d?l.between(h):h.between(f);for(let e=0;e<c.length;e+=1)c[e].orderRank=m.value,m=d?m.between(h):m.between(f);return{all:d?[...e.all,...c,r]:[...e.all,r,...c],selected:c}}return{all:[...e.all,r],selected:e.selected}}),{all:[],selected:[]}),g=h.map((e=>[e._id,{set:{orderRank:e.orderRank}}]));return{newOrder:p.sort(f),patches:g,message:u}})({entities:t,selectedIds:o,source:n,destination:r});(null==a?void 0:a.length)&&v(a),(null==l?void 0:l.length)&&S(l,d)}),[k,j,R,S,u]),_=a.useCallback((e=>{const t=e.draggableId;k.includes(t)||w(),j(t)}),[k,w,j]),C=a.useCallback(((e,t,n,r)=>D({draggableId:n,source:{index:e},destination:{index:t}},r)),[D]),E=a.useCallback((e=>{"Escape"===e.key&&w()}),[w]);a.useEffect((()=>(window.addEventListener("keydown",E),()=>{window.removeEventListener("keydown",E)})),[E]);const L=a.useMemo((()=>{if(!y.length)return[];const e=y.map((e=>e.orderRank));return e.filter(((t,n)=>e.indexOf(t)!==n))}),[y]),P=a.useCallback((e=>D(e,y)),[y,D]);return o.jsx(d.DragDropContext,{onDragStart:_,onDragEnd:P,children:o.jsx(d.Droppable,{droppableId:"documentSortZone",children:e=>o.jsxs("div",t(t({},e.droppableProps),{},{ref:e.innerRef,children:[y.map(((e,n)=>o.jsx(d.Draggable,{draggableId:e._id,index:n,children:(r,i)=>{const a=k.includes(e._id),d=i.isDragging,c=Boolean(!d&&b&&a),u=s&&a,p=Boolean(!e.orderRank),h=(e=>{const{isDuplicate:t,isGhosting:n,isDragging:r,isSelected:i}=e;return n?"transparent":r||i?"primary":t?"caution":void 0})({isDuplicate:L.includes(e.orderRank),isGhosting:c,isDragging:d,isSelected:a});return o.jsx("div",t(t(t({ref:r.innerRef},r.draggableProps),r.dragHandleProps),{},{style:p?{opacity:.2,pointerEvents:"none"}:(f=r.draggableProps.style,m=u,t({userSelect:"none",transition:"opacity 500ms ease-in-out",opacity:m?.2:1,pointerEvents:m?"none":void 0},f)),children:o.jsx(l.Box,{paddingBottom:1,children:o.jsx(l.Card,{tone:h,shadow:d?2:void 0,radius:2,children:o.jsx(g,{doc:e,entities:y,handleSelect:O,increment:C,index:n,isFirst:0===n,isLast:n===y.length-1})})})}));var f,m}},"".concat(e._id,"-").concat(e.orderRank)))),e.placeholder]}))})})}function y(e){let{children:t}=e;return o.jsx(l.Box,{padding:3,children:o.jsx(l.Card,{padding:4,radius:2,shadow:1,tone:"caution",children:o.jsx(l.Text,{children:t})})})}const v={};function b(e){let{type:t,filter:n,params:r=v}=e;const[i,s]=a.useState(!0),[d,c]=a.useState(!1),[u,p]=a.useState([]),h=m();a.useEffect((()=>{const e="*[_type == $type ".concat(n?"&& ".concat(n):"","]|order(@[$order] asc){\n _id, _type, ").concat("orderRank","\n }"),o=Object.assign(r,{type:t,order:"orderRank"});let a;const l=async()=>{h.fetch(e,o).then((e=>{const t=e.reduce(((t,n)=>{if(!n._id.startsWith("drafts.")){return e.some((e=>e._id==="drafts.".concat(n._id)))?t:[...t,n]}return[...t,n]}),[]);p(t),i&&s(!1)}))};return d||u.length||(async()=>{s(!0),await l(),a||(a=h.listen(e,o).subscribe((()=>l())))})(),()=>null==a?void 0:a.unsubscribe()}),[t]);const g=a.useMemo((()=>u.length?u.filter((e=>!e.orderRank)).length:0),[u]);return i?o.jsx(l.Flex,{style:{width:"100%",height:"100%"},align:"center",justify:"center",children:o.jsx(l.Spinner,{})}):o.jsxs(l.Stack,{space:1,style:{overflow:"scroll",height:"100%"},children:[g>0&&o.jsxs(y,{children:[g,"/",u.length," Documents have no Order. Select"," ",o.jsx("strong",{children:"Reset Order"})," from the Menu above to fix."]}),o.jsx(l.Box,{padding:1,children:o.jsx(x,{data:u,type:t,listIsUpdating:d,setListIsUpdating:c})})]})}function j(e){let{type:t,showIncrements:n,resetOrderTransaction:i,filter:s,params:d}=e;const c=l.useToast(),u=r.useSchema();a.useEffect((()=>{(null==i?void 0:i.title)&&(null==i?void 0:i.status)&&c.push(i)}),[i,c]);const p=a.useMemo((()=>{if(!t)return o.jsxs(o.Fragment,{children:["No ",o.jsx("code",{children:"type"})," was configured"]});const e=u.get(t);return e?"fields"in e&&e.fields.some((e=>"orderRank"===(null==e?void 0:e.name)))?"fields"in e&&e.fields.some((e=>{var t;return"orderRank"===(null==e?void 0:e.name)&&"string"!==(null==(t=null==e?void 0:e.type)?void 0:t.name)}))?o.jsxs(o.Fragment,{children:[o.jsx("code",{children:"orderRank"})," field on Schema ",o.jsx("code",{children:t})," must be"," ",o.jsx("code",{children:"string"})," type"]}):"":o.jsxs(o.Fragment,{children:["Schema ",o.jsx("code",{children:t})," must have an ",o.jsx("code",{children:"orderRank"})," field of type"," ",o.jsx("code",{children:"string"})]}):o.jsxs(o.Fragment,{children:["Schema ",o.jsx("code",{children:t})," not found"]})}),[t,u]);return p?o.jsx(y,{children:p}):o.jsx(h.Provider,{value:{showIncrements:n},children:o.jsx(b,{type:t,filter:s,params:d})})}class k extends a.Component{constructor(e){super(e),this.actionHandlers={showIncrements:()=>{this.setState((e=>({showIncrements:!e.showIncrements})))},resetOrder:async()=>{var e;this.setState((()=>({resetOrderTransaction:{status:"info",title:"Reordering started...",closable:!0}})));const t=await async function(){let e=arguments.length>1?arguments[1]:void 0;const t="*[_type == $type]|order(@[$order] asc)._id",n={type:arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",order:"orderRank"},r=await e.fetch(t,n);if(!r.length)return null;const s=e.transaction();let o=i.LexoRank.min();for(let e=0;e<r.length;e+=1)o=o.genNext().genNext(),s.patch(r[e],{set:{orderRank:o.value}});return s.commit().then((e=>e)).catch((e=>e))}(this.props.options.type,this.props.options.client),n=null==(e=null==t?void 0:t.results)?void 0:e.length;this.setState((()=>({resetOrderTransaction:{status:n?"success":"info",title:n?"Reordered ".concat(1===t.results.length?"Document":"Documents"):"Reordering failed",closable:!0}})))}},this.state={showIncrements:!1,resetOrderTransaction:{}}}render(){var e,t,n,r,i,s;const a=null==(t=null==(e=null==this?void 0:this.props)?void 0:e.options)?void 0:t.type;return a?o.jsx(j,{filter:null==(r=null==(n=null==this?void 0:this.props)?void 0:n.options)?void 0:r.filter,params:null==(s=null==(i=null==this?void 0:this.props)?void 0:i.options)?void 0:s.params,type:a,showIncrements:this.state.showIncrements,resetOrderTransaction:this.state.resetOrderTransaction}):null}}exports.orderRankField=e=>{if(!(null==e?void 0:e.type))throw new Error("\n type must be provided.\n Example: orderRankField({type: 'category'})\n ");const{type:n}=e;return r.defineField(t(t({title:"Order Rank",readOnly:!0,hidden:!0},e),{},{name:"orderRank",type:"string",initialValue:async(e,t)=>{let{getClient:r}=t;return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";const t=e?i.LexoRank.parse(e):i.LexoRank.min();return t.genNext().genNext().value}(await r({apiVersion:"2021-09-01"}).fetch("*[_type == $type]|order(@[$order] desc)[0][$order]",{type:n,order:"orderRank"}))}}))},exports.orderRankOrdering=p,exports.orderableDocumentListDeskItem=function(e){var t,n;if(!(null==e?void 0:e.type)||!e.context||!e.S)throw new Error("\n type, context and S (StructureBuilder) must be provided.\n context and S are available when configuring structure.\n Example: orderableDocumentListDeskItem({type: 'category'})\n ");const{type:r,filter:i,params:o,title:a,icon:l,id:d,context:c,S:u}=e,{schema:p,getClient:h}=c,g=h({apiVersion:"2021-09-01"}),f=null!=a?a:"Orderable ".concat(r),m=null!=d?d:"orderable-".concat(r),x=null!=l?l:s.SortIcon,y=null!=(n=null==(t=p.get(r))?void 0:t.title)?n:r;return u.listItem().title(f).id(m).icon(x).child(Object.assign(u.documentTypeList(r).serialize(),{__preserveInstance:!0,key:m,type:"component",component:k,options:{type:r,filter:i,params:o,client:g},menuItems:[u.menuItem().title("Create new ".concat(y)).intent({type:"create",params:{type:r}}).serialize(),u.menuItem().title("Reset Order").icon(s.GenerateIcon).action("resetOrder").serialize(),u.menuItem().title("Show Increments").icon(s.SortIcon).action("showIncrements").serialize()]})).serialize()};
|
|
2
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
"use strict";function e(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 t(t){for(var r=1;r<arguments.length;r++){var i=null!=arguments[r]?arguments[r]:{};r%2?e(Object(i),!0).forEach((function(e){n(t,e,i[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(i)):e(Object(i)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(i,e))}))}return t}function n(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 r=require("sanity"),i=require("lexorank"),s=require("@sanity/icons"),o=require("react/jsx-runtime"),l=require("react"),a=require("@sanity/ui"),c=require("@hello-pangea/dnd"),d=require("sanity/desk");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}const p="orderRank";const h={title:"Ordered",name:"ordered",by:[{field:p,direction:"asc"}]},g=u(l).default.createContext({});function f(e){let{doc:t,increment:n,entities:i,handleSelect:c,index:d,isFirst:u,isLast:p}=e;const{showIncrements:h}=l.useContext(g),f=r.useSchema();return o.jsxs(a.Flex,{align:"center",children:[o.jsx(a.Box,{paddingX:3,style:{flexShrink:0},children:o.jsx(a.Text,{size:4,children:o.jsx(s.DragHandleIcon,{})})}),h&&o.jsxs(a.Flex,{style:{flexShrink:0},align:"center",gap:1,paddingRight:1,children:[o.jsx(a.Button,{padding:2,mode:"ghost",onClick:()=>n(d,d+-1,t._id,i),disabled:u,icon:s.ChevronUpIcon}),o.jsx(a.Button,{padding:2,mode:"ghost",disabled:p,onClick:()=>n(d,d+1,t._id,i),icon:s.ChevronDownIcon})]}),o.jsx(a.Button,{style:{width:"100%"},padding:2,mode:"bleed",onClick:e=>c(t._id,d,e.nativeEvent),children:o.jsx(a.Flex,{flex:1,align:"center",children:o.jsx(a.Card,{tone:"default",children:o.jsx(r.Preview,{layout:"default",value:t,schemaType:f.get(t._type)})})})})]})}function m(e,t){return e[p]&&t[p]?e[p]<t[p]?-1:e[p]>t[p]?1:0:0}const x=e=>{let{entities:t,selectedIds:n,source:r,destination:s}=e;const o=r.index,l=s.index,a=o>l,c=t.filter((e=>n.includes(e._id))),d=["Moved",1===c.length?"1 Document":"".concat(c.length," Documents"),a?"up":"down","from position","".concat(o+1," to ").concat(l+1)].join(" "),{all:u,selected:h}=t.reduce(((e,r,s)=>{var o,d,u,h;if(n.includes(r._id))return{all:e.all,selected:e.selected};if(s===l){const n=s-1,l=(null==(o=t[n])?void 0:o[p])?i.LexoRank.parse(null==(d=t[n])?void 0:d[p]):i.LexoRank.min(),g=i.LexoRank.parse(t[s][p]),f=s+1,m=(null==(u=t[f])?void 0:u[p])?i.LexoRank.parse(null==(h=t[f])?void 0:h[p]):i.LexoRank.max();let x=a?l.between(g):g.between(m);for(let e=0;e<c.length;e+=1)c[e][p]=x.toString(),x=a?x.between(g):x.between(m);return{all:a?[...e.all,...c,r]:[...e.all,r,...c],selected:c}}return{all:[...e.all,r],selected:e.selected}}),{all:[],selected:[]}),g=h.map((e=>[e._id,{set:{[p]:e[p]}}]));return{newOrder:u.sort(m),patches:g,message:d}};function y(){return r.useClient({apiVersion:"2021-09-01"})}const v=(e,n)=>t({userSelect:"none",transition:"opacity 500ms ease-in-out",opacity:n?.2:1,pointerEvents:n?"none":void 0},e),b=e=>{const{isDuplicate:t,isGhosting:n,isDragging:r,isSelected:i}=e;return n?"transparent":r||i?"primary":t?"caution":void 0};function j(e){let{data:n,type:r,listIsUpdating:i,setListIsUpdating:s}=e;const u=a.useToast(),h=d.usePaneRouter(),{navigateIntent:g}=h,[m,j]=l.useState(n);l.useEffect((()=>{i||j(n)}),[n]);const[w,O]=l.useState(""),[S,I]=l.useState([]),k=l.useCallback((()=>I([])),[I]),D=l.useCallback(((e,t,n)=>{const i=S.includes(e),s=n.shiftKey,o=-1!==navigator.appVersion.indexOf("Win")?n.ctrlKey:n.metaKey;let l=[];if(!s&&!o)return g("edit",{id:e,type:r}),I([e]);if(s&&!i){const n=S[S.length-1],r=m.findIndex((e=>e._id===n)),i=t<r?t:r,s=t>r?t:r,o=m.filter(((e,t)=>t>i&&t<s)).map((e=>e._id));l=[...S,...o,e]}else l=i?S.filter((t=>t!==e)):[...S,e];return I(l)}),[I,g,m,S,r]),_=y(),C=l.useCallback((async(e,t)=>{const n=_.transaction();e.forEach((e=>{let[t,r]=e;return n.patch(t,r)})),await n.commit().then((e=>{k(),O(""),s(!1),u.push({title:"".concat(1===e.results.length?"1 Document":"".concat(e.results.length," Documents")," Reordered"),status:"success",description:t})})).catch((()=>{O(""),s(!1),u.push({title:"Reordering failed",status:"error"})}))}),[_,O,k,s,u]),R=l.useCallback(((e,t)=>{O("");const{source:n,destination:r,draggableId:i}=null!=e?e:{};if((null==n?void 0:n.index)===(null==r?void 0:r.index))return;if(!(null==t?void 0:t.length)||!i)return;const o=(null==S?void 0:S.length)?S:[i];if(!(null==o?void 0:o.length))return;s(!0),I(o);const{newOrder:l,patches:a,message:c}=x({entities:t,selectedIds:o,source:n,destination:r});(null==l?void 0:l.length)&&j(l),(null==a?void 0:a.length)&&C(a,c)}),[S,O,I,C,s]),E=l.useCallback((e=>{const t=e.draggableId;S.includes(t)||k(),O(t)}),[S,k,O]),P=l.useCallback(((e,t,n,r)=>R({draggableId:n,source:{index:e},destination:{index:t}},r)),[R]),L=l.useCallback((e=>{"Escape"===e.key&&k()}),[k]);l.useEffect((()=>(window.addEventListener("keydown",L),()=>{window.removeEventListener("keydown",L)})),[L]);const T=l.useMemo((()=>{if(!m.length)return[];const e=m.map((e=>e[p]));return e.filter(((t,n)=>e.indexOf(t)!==n))}),[m]),F=l.useCallback((e=>R(e,m)),[m,R]);return o.jsx(c.DragDropContext,{onDragStart:E,onDragEnd:F,children:o.jsx(c.Droppable,{droppableId:"documentSortZone",children:e=>o.jsxs("div",t(t({},e.droppableProps),{},{ref:e.innerRef,children:[m.map(((e,n)=>o.jsx(c.Draggable,{draggableId:e._id,index:n,children:(r,s)=>{const l=S.includes(e._id),c=s.isDragging,d=Boolean(!c&&w&&l),u=i&&l,h=Boolean(!e[p]),g=T.includes(e[p]),x=b({isDuplicate:g,isGhosting:d,isDragging:c,isSelected:l});return o.jsx("div",t(t(t({ref:r.innerRef},r.draggableProps),r.dragHandleProps),{},{style:h?{opacity:.2,pointerEvents:"none"}:v(r.draggableProps.style,u),children:o.jsx(a.Box,{paddingBottom:1,children:o.jsx(a.Card,{tone:x,shadow:c?2:void 0,radius:2,children:o.jsx(f,{doc:e,entities:m,handleSelect:D,increment:P,index:n,isFirst:0===n,isLast:n===m.length-1})})})}))}},"".concat(e._id,"-").concat(e[p])))),e.placeholder]}))})})}function w(e){let{children:t}=e;return o.jsx(a.Box,{padding:3,children:o.jsx(a.Card,{padding:4,radius:2,shadow:1,tone:"caution",children:o.jsx(a.Text,{children:t})})})}const O={};function S(e){let{type:t,filter:n,params:r=O}=e;const[i,s]=l.useState(!0),[c,d]=l.useState(!1),[u,h]=l.useState([]),g=y();l.useEffect((()=>{const e="*[_type == $type ".concat(n?"&& ".concat(n):"","]|order(@[$order] asc){\n _id, _type, ").concat(p,"\n }"),o=Object.assign(r,{type:t,order:p});let l;const a=async()=>{g.fetch(e,o).then((e=>{const t=e.reduce(((t,n)=>{if(!n._id.startsWith("drafts.")){return e.some((e=>e._id==="drafts.".concat(n._id)))?t:[...t,n]}return[...t,n]}),[]);h(t),i&&s(!1)}))};return c||u.length||(async()=>{s(!0),await a(),l||(l=g.listen(e,o).subscribe((()=>a())))})(),()=>null==l?void 0:l.unsubscribe()}),[t]);const f=l.useMemo((()=>u.length?u.filter((e=>!e[p])).length:0),[u]);return i?o.jsx(a.Flex,{style:{width:"100%",height:"100%"},align:"center",justify:"center",children:o.jsx(a.Spinner,{})}):o.jsxs(a.Stack,{space:1,style:{overflow:"auto",height:"100%"},children:[f>0&&o.jsxs(w,{children:[f,"/",u.length," Documents have no Order. Select"," ",o.jsx("strong",{children:"Reset Order"})," from the Menu above to fix."]}),o.jsx(a.Box,{padding:1,children:o.jsx(j,{data:u,type:t,listIsUpdating:c,setListIsUpdating:d})})]})}function I(e){let{type:t,showIncrements:n,resetOrderTransaction:i,filter:s,params:c}=e;const d=a.useToast(),u=r.useSchema();l.useEffect((()=>{(null==i?void 0:i.title)&&(null==i?void 0:i.status)&&d.push(i)}),[i,d]);const h=l.useMemo((()=>{if(!t)return o.jsxs(o.Fragment,{children:["No ",o.jsx("code",{children:"type"})," was configured"]});const e=u.get(t);return e?"fields"in e&&e.fields.some((e=>(null==e?void 0:e.name)===p))?"fields"in e&&e.fields.some((e=>{var t;return(null==e?void 0:e.name)===p&&"string"!==(null==(t=null==e?void 0:e.type)?void 0:t.name)}))?o.jsxs(o.Fragment,{children:[o.jsx("code",{children:p})," field on Schema ",o.jsx("code",{children:t})," must be"," ",o.jsx("code",{children:"string"})," type"]}):"":o.jsxs(o.Fragment,{children:["Schema ",o.jsx("code",{children:t})," must have an ",o.jsx("code",{children:p})," field of type"," ",o.jsx("code",{children:"string"})]}):o.jsxs(o.Fragment,{children:["Schema ",o.jsx("code",{children:t})," not found"]})}),[t,u]);return h?o.jsx(w,{children:h}):o.jsx(g.Provider,{value:{showIncrements:n},children:o.jsx(S,{type:t,filter:s,params:c})})}class k extends l.Component{constructor(e){super(e),this.actionHandlers={showIncrements:()=>{this.setState((e=>({showIncrements:!e.showIncrements})))},resetOrder:async()=>{var e;this.setState((()=>({resetOrderTransaction:{status:"info",title:"Reordering started...",closable:!0}})));const t=await async function(){let e=arguments.length>1?arguments[1]:void 0;const t={type:arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",order:p},n=await e.fetch("*[_type == $type]|order(@[$order] asc)._id",t);if(!n.length)return null;const r=e.transaction();let s=i.LexoRank.min();for(let e=0;e<n.length;e+=1)s=s.genNext().genNext(),r.patch(n[e],{set:{[p]:s.toString()}});return r.commit().then((e=>e)).catch((e=>e))}(this.props.options.type,this.props.options.client),n=null==(e=null==t?void 0:t.results)?void 0:e.length;this.setState((()=>({resetOrderTransaction:{status:n?"success":"info",title:n?"Reordered ".concat(1===t.results.length?"Document":"Documents"):"Reordering failed",closable:!0}})))}},this.state={showIncrements:!1,resetOrderTransaction:{}}}render(){var e,t,n,r,i,s;const l=null==(t=null==(e=null==this?void 0:this.props)?void 0:e.options)?void 0:t.type;return l?o.jsx(I,{filter:null==(r=null==(n=null==this?void 0:this.props)?void 0:n.options)?void 0:r.filter,params:null==(s=null==(i=null==this?void 0:this.props)?void 0:i.options)?void 0:s.params,type:l,showIncrements:this.state.showIncrements,resetOrderTransaction:this.state.resetOrderTransaction}):null}}exports.orderRankField=e=>{if(!(null==e?void 0:e.type))throw new Error("\n type must be provided.\n Example: orderRankField({type: 'category'})\n ");const{type:n}=e;return r.defineField(t(t({title:"Order Rank",readOnly:!0,hidden:!0},e),{},{name:p,type:"string",initialValue:async(e,t)=>{let{getClient:r}=t;return function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";return(e?i.LexoRank.parse(e):i.LexoRank.min()).genNext().genNext().toString()}(await r({apiVersion:"2021-09-01"}).fetch("*[_type == $type]|order(@[$order] desc)[0][$order]",{type:n,order:p}))}}))},exports.orderRankOrdering=h,exports.orderableDocumentListDeskItem=function(e){var t,n;if(!(null==e?void 0:e.type)||!e.context||!e.S)throw new Error("\n type, context and S (StructureBuilder) must be provided.\n context and S are available when configuring structure.\n Example: orderableDocumentListDeskItem({type: 'category'})\n ");const{type:r,filter:i,params:o,title:l,icon:a,id:c,context:d,S:u}=e,{schema:p,getClient:h}=d,g=h({apiVersion:"2021-09-01"}),f=null!=l?l:"Orderable ".concat(r),m=null!=c?c:"orderable-".concat(r),x=null!=a?a:s.SortIcon,y=null!=(n=null==(t=p.get(r))?void 0:t.title)?n:r;return u.listItem().title(f).id(m).icon(x).child(Object.assign(u.documentTypeList(r).serialize(),{__preserveInstance:!0,key:m,type:"component",component:k,options:{type:r,filter:i,params:o,client:g},menuItems:[u.menuItem().title("Create new ".concat(y)).intent({type:"create",params:{type:r}}).serialize(),u.menuItem().title("Reset Order").icon(s.GenerateIcon).action("resetOrder").serialize(),u.menuItem().title("Toggle Increments").icon(s.SortIcon).action("showIncrements").serialize()]})).serialize()};//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/fields/orderRankField.ts","../src/fields/orderRankOrdering.ts","../src/helpers/constants.ts","../src/OrderableContext.ts","../src/Document.tsx","../src/helpers/reorderDocuments.ts","../src/helpers/client.ts","../src/DraggableList.tsx","../src/Feedback.tsx","../src/DocumentListQuery.tsx","../src/DocumentListWrapper.tsx","../src/OrderableDocumentList.tsx","../src/helpers/resetOrder.ts","../src/helpers/initialRank.ts","../src/desk-structure/orderableDocumentListDeskItem.ts"],"sourcesContent":["import {type ConfigContext, defineField} from 'sanity'\nimport {ORDER_FIELD_NAME} from '../helpers/constants'\nimport initialRank from '../helpers/initialRank'\n\nexport type SchemaContext = Omit<ConfigContext, 'schema' | 'currentUser' | 'client'>\n\nexport interface RankFieldConfig {\n type: string\n}\n\nexport const orderRankField = (config: RankFieldConfig) => {\n if (!config?.type) {\n throw new Error(\n `\n type must be provided.\n Example: orderRankField({type: 'category'})\n `\n )\n }\n\n const {type} = config\n return defineField({\n title: 'Order Rank',\n readOnly: true,\n hidden: true,\n ...config,\n name: ORDER_FIELD_NAME,\n type: 'string',\n initialValue: async (p, {getClient}) => {\n const lastDocOrderRank = await getClient({apiVersion: '2021-09-01'}).fetch(\n `*[_type == $type]|order(@[$order] desc)[0][$order]`,\n {type, order: ORDER_FIELD_NAME}\n )\n return initialRank(lastDocOrderRank)\n },\n })\n}\n","import {ORDER_FIELD_NAME} from '../helpers/constants'\n\nexport const orderRankOrdering = {\n title: 'Ordered',\n name: 'ordered',\n by: [{field: ORDER_FIELD_NAME, direction: 'asc'}],\n}\n","export const ORDER_FIELD_NAME = `orderRank` as const\n","import React from 'react'\n\nexport interface OrderableContextValue {\n showIncrements?: boolean\n}\n\nexport const OrderableContext = React.createContext<OrderableContextValue>({})\n","import React, {useContext} from 'react'\nimport {ChevronDownIcon, ChevronUpIcon, DragHandleIcon} from '@sanity/icons'\nimport {Box, Button, Flex, Text} from '@sanity/ui'\n\nimport {useSchema, SanityDocument, SchemaType, Preview} from 'sanity'\nimport {OrderableContext} from './OrderableContext'\n\nexport interface DocumentProps {\n doc: SanityDocument\n entities: SanityDocument[]\n handleSelect: (docId: string, index: number, event: MouseEvent) => void\n increment: (index: number, nextIndex: number, docId: string, entities: SanityDocument[]) => void\n index: number\n isFirst: boolean\n isLast: boolean\n}\n\nexport default function Document({\n doc,\n increment,\n entities,\n handleSelect,\n index,\n isFirst,\n isLast,\n}: DocumentProps) {\n const {showIncrements} = useContext(OrderableContext)\n const schema = useSchema()\n return (\n <Flex align=\"center\">\n <Box paddingX={3} style={{flexShrink: 0}}>\n <Text size={4}>\n <DragHandleIcon />\n </Text>\n </Box>\n {showIncrements && (\n <Flex style={{flexShrink: 0}} align=\"center\" gap={1} paddingRight={1}>\n <Button\n padding={2}\n mode=\"ghost\"\n onClick={() => increment(index, index + -1, doc._id, entities)}\n disabled={isFirst}\n icon={ChevronUpIcon}\n />\n <Button\n padding={2}\n mode=\"ghost\"\n disabled={isLast}\n onClick={() => increment(index, index + 1, doc._id, entities)}\n icon={ChevronDownIcon}\n />\n </Flex>\n )}\n <Button\n style={{width: `100%`}}\n padding={2}\n mode=\"bleed\"\n onClick={(e) => handleSelect(doc._id, index, e.nativeEvent)}\n >\n <Flex flex={1} align=\"center\">\n <Box flex={1}>\n <Preview\n layout=\"default\"\n value={doc}\n schemaType={schema.get(doc._type) as SchemaType}\n />\n </Box>\n </Flex>\n </Button>\n </Flex>\n )\n}\n","import {LexoRank} from 'lexorank'\nimport type {PatchOperations, SanityDocument} from 'sanity'\nimport {ORDER_FIELD_NAME} from './constants'\n\nexport interface MaifestArgs {\n entities: SanityDocument[]\n selectedItems: SanityDocument[]\n isMovingUp: boolean\n curIndex: number\n nextIndex: number\n prevIndex: number\n}\n\nexport interface ReorderArgs {\n entities: SanityDocument[]\n selectedIds: string[]\n source: any\n destination: any\n debug?: boolean\n}\n\nfunction lexicographicalSort(a: {[ORDER_FIELD_NAME]: string}, b: {[ORDER_FIELD_NAME]: string}) {\n if (a[ORDER_FIELD_NAME] < b[ORDER_FIELD_NAME]) {\n return -1\n }\n if (a[ORDER_FIELD_NAME] > b[ORDER_FIELD_NAME]) {\n return 1\n }\n return 0\n}\n\nexport const reorderDocuments = ({\n entities,\n selectedIds,\n source,\n destination,\n debug = false,\n}: ReorderArgs) => {\n const startIndex = source.index\n const endIndex = destination.index\n const isMovingUp = startIndex > endIndex\n const selectedItems = entities.filter((item) => selectedIds.includes(item._id))\n const message = [\n `Moved`,\n selectedItems.length === 1 ? `1 Document` : `${selectedItems.length} Documents`,\n isMovingUp ? `up` : `down`,\n `from position`,\n `${startIndex + 1} to ${endIndex + 1}`,\n ].join(' ')\n\n const {all, selected} = entities.reduce(\n (acc, cur, curIndex) => {\n // Selected items get spread in below, so skip them here\n if (selectedIds.includes(cur._id)) {\n return {all: acc.all, selected: acc.selected}\n }\n\n // Drop seleced items in\n if (curIndex === endIndex) {\n const prevIndex = curIndex - 1\n const prevRank = entities[prevIndex]?.[ORDER_FIELD_NAME]\n ? LexoRank.parse(entities[prevIndex]?.[ORDER_FIELD_NAME] as string)\n : LexoRank.min()\n\n const curRank = LexoRank.parse(entities[curIndex][ORDER_FIELD_NAME] as string)\n\n const nextIndex = curIndex + 1\n const nextRank = entities[nextIndex]?.[ORDER_FIELD_NAME]\n ? LexoRank.parse(entities[nextIndex]?.[ORDER_FIELD_NAME] as string)\n : LexoRank.max()\n\n let betweenRank = isMovingUp ? prevRank.between(curRank) : curRank.between(nextRank)\n\n // For each selected item, assign a new orderRank between now and next\n for (let selectedIndex = 0; selectedIndex < selectedItems.length; selectedIndex += 1) {\n selectedItems[selectedIndex][ORDER_FIELD_NAME] = (betweenRank as any).value as string\n betweenRank = isMovingUp ? betweenRank.between(curRank) : betweenRank.between(nextRank)\n }\n\n return {\n // The `all` array gets sorted by order field later anyway\n // so that this probably isn't necessary ¯\\_(ツ)_/¯\n all: isMovingUp\n ? [...acc.all, ...selectedItems, cur]\n : [...acc.all, cur, ...selectedItems],\n selected: selectedItems,\n }\n }\n\n return {all: [...acc.all, cur], selected: acc.selected}\n },\n {all: [] as SanityDocument[], selected: [] as SanityDocument[]}\n )\n\n const patches: [string, PatchOperations][] = selected.map((doc) => {\n return [\n doc._id,\n {\n set: {\n [ORDER_FIELD_NAME]: doc[ORDER_FIELD_NAME],\n },\n },\n ]\n })\n\n // Safety-check to make sure everything is in order\n const allSorted = (all as unknown as {[ORDER_FIELD_NAME]: string}[]).sort(lexicographicalSort)\n\n return {newOrder: allSorted, patches, message}\n}\n","import {useClient} from 'sanity'\n\nexport function useSanityClient() {\n return useClient({apiVersion: '2021-09-01'})\n}\n","import React, {useEffect, useState, useMemo, useCallback, CSSProperties} from 'react'\nimport {DragDropContext, Draggable, Droppable, type DropResult} from 'react-beautiful-dnd'\nimport {Box, Card, useToast} from '@sanity/ui'\nimport {usePaneRouter} from 'sanity/desk'\nimport type {SanityDocument, PatchOperations} from 'sanity'\nimport Document from './Document'\nimport {reorderDocuments} from './helpers/reorderDocuments'\nimport {ORDER_FIELD_NAME} from './helpers/constants'\nimport {useSanityClient} from './helpers/client'\n\nconst getItemStyle = (\n draggableStyle: CSSProperties | undefined,\n itemIsUpdating: boolean\n): CSSProperties => ({\n userSelect: 'none',\n transition: `opacity 500ms ease-in-out`,\n opacity: itemIsUpdating ? 0.2 : 1,\n pointerEvents: itemIsUpdating ? `none` : undefined,\n ...draggableStyle,\n})\n\nconst cardTone = (settings: ListSetting) => {\n const {isDuplicate, isGhosting, isDragging, isSelected} = settings\n\n if (isGhosting) return `transparent`\n if (isDragging || isSelected) return `primary`\n if (isDuplicate) return `caution`\n\n return undefined\n}\n\ninterface ListSetting {\n isDuplicate: boolean\n isGhosting: boolean\n isDragging: boolean\n isSelected: boolean\n}\n\nexport interface DraggableListProps {\n data: SanityDocument[]\n type: string\n listIsUpdating: boolean\n setListIsUpdating: (val: boolean) => void\n}\n\nexport default function DraggableList({\n data,\n type,\n listIsUpdating,\n setListIsUpdating,\n}: DraggableListProps) {\n const toast = useToast()\n const router = usePaneRouter()\n const {navigateIntent} = router\n\n // Maintains local state order before transaction completes\n const [orderedData, setOrderedData] = useState<SanityDocument[]>(data)\n\n // Update local state when documents change from an outside source\n useEffect(() => {\n if (!listIsUpdating) setOrderedData(data)\n /* eslint-disable-next-line react-hooks/exhaustive-deps */\n }, [data])\n\n const [draggingId, setDraggingId] = useState(``)\n const [selectedIds, setSelectedIds] = useState<string[]>([])\n\n const clearSelected = useCallback(() => setSelectedIds([]), [setSelectedIds])\n\n const handleSelect = useCallback(\n (clickedId: string, index: number, nativeEvent: MouseEvent) => {\n const isSelected = selectedIds.includes(clickedId)\n const selectMultiple = nativeEvent.shiftKey\n const isUsingWindows = navigator.appVersion.indexOf('Win') !== -1\n const selectAdditional = isUsingWindows ? nativeEvent.ctrlKey : nativeEvent.metaKey\n\n let updatedIds = []\n\n // No modifier keys pressed during click:\n // - update selected to just this one\n // - open document\n if (!selectMultiple && !selectAdditional) {\n navigateIntent('edit', {id: clickedId, type})\n return setSelectedIds([clickedId])\n }\n\n // Shift key was held, add id's between last selected and this one\n // ...before adding this one\n if (selectMultiple && !isSelected) {\n const lastSelectedId = selectedIds[selectedIds.length - 1]\n const lastSelectedIndex = orderedData.findIndex((item) => item._id === lastSelectedId)\n\n const firstSelected = index < lastSelectedIndex ? index : lastSelectedIndex\n const lastSelected = index > lastSelectedIndex ? index : lastSelectedIndex\n\n const betweenIds = orderedData\n .filter((item, itemIndex) => itemIndex > firstSelected && itemIndex < lastSelected)\n .map((item) => item._id)\n\n updatedIds = [...selectedIds, ...betweenIds, clickedId]\n } else if (isSelected) {\n // Toggle off a single id\n updatedIds = selectedIds.filter((id) => id !== clickedId)\n } else {\n // Toggle on a single id\n updatedIds = [...selectedIds, clickedId]\n }\n\n return setSelectedIds(updatedIds)\n },\n [setSelectedIds, navigateIntent, orderedData, selectedIds, type]\n )\n\n const client = useSanityClient()\n\n const transactPatches = useCallback(\n async (patches: [string, PatchOperations][], message: string) => {\n const transaction = client.transaction()\n\n patches.forEach(([docId, ops]) => transaction.patch(docId, ops))\n\n await transaction\n .commit()\n .then((updated) => {\n clearSelected()\n setDraggingId(``)\n setListIsUpdating(false)\n toast.push({\n title: `${\n updated.results.length === 1 ? `1 Document` : `${updated.results.length} Documents`\n } Reordered`,\n status: `success`,\n description: message,\n })\n })\n .catch(() => {\n setDraggingId(``)\n setListIsUpdating(false)\n toast.push({\n title: `Reordering failed`,\n status: `error`,\n })\n })\n },\n [client, setDraggingId, clearSelected, setListIsUpdating, toast]\n )\n\n const handleDragEnd = useCallback(\n (result: DropResult | undefined, entities: SanityDocument[]) => {\n setDraggingId(``)\n\n const {source, destination, draggableId} = result ?? {}\n\n // Don't do anything if nothing changed\n if (source?.index === destination?.index) return\n\n // Don't do anything if we don't have the entitites\n if (!entities?.length || !draggableId) return\n\n // A document can be dragged without being one-of-many-selected\n const effectedIds = selectedIds?.length ? selectedIds : [draggableId]\n\n // Don't do anything if we don't have ids to effect\n if (!effectedIds?.length) return\n\n // Update state to update styles + prevent data refetching\n setListIsUpdating(true)\n setSelectedIds(effectedIds)\n\n const {newOrder, patches, message} = reorderDocuments({\n entities,\n selectedIds: effectedIds,\n source,\n destination,\n })\n\n // Update local state\n if (newOrder?.length) {\n setOrderedData(newOrder as any)\n }\n\n // Transact new order patches\n if (patches?.length) {\n transactPatches(patches, message)\n }\n },\n [selectedIds, setDraggingId, setSelectedIds, transactPatches, setListIsUpdating]\n )\n\n const handleDragStart = useCallback(\n (start: {draggableId: string}) => {\n const id = start.draggableId\n const selected = selectedIds.includes(id)\n\n // if dragging an item that is not selected - unselect all items\n if (!selected) clearSelected()\n\n setDraggingId(id)\n },\n [selectedIds, clearSelected, setDraggingId]\n )\n\n // Move one document up or down one place, by fake invoking the drag function\n const incrementIndex = useCallback(\n (shiftFrom: number, shiftTo: number, id: string, entities: SanityDocument[]) => {\n const result = {\n draggableId: id,\n source: {index: shiftFrom},\n destination: {index: shiftTo},\n }\n\n return handleDragEnd(result as DropResult, entities)\n },\n [handleDragEnd]\n )\n\n const onWindowKeyDown = useCallback(\n (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n clearSelected()\n }\n },\n [clearSelected]\n )\n\n useEffect(() => {\n window.addEventListener('keydown', onWindowKeyDown)\n\n return () => {\n window.removeEventListener('keydown', onWindowKeyDown)\n }\n }, [onWindowKeyDown])\n\n // Find all items with duplicate order field\n const duplicateOrders = useMemo(() => {\n if (!orderedData.length) return []\n\n const orderField = orderedData.map((item) => item[ORDER_FIELD_NAME])\n\n return orderField.filter((item, index) => orderField.indexOf(item) !== index)\n }, [orderedData])\n\n const onDragEnd = useCallback(\n (result: DropResult) => handleDragEnd(result, orderedData),\n [orderedData, handleDragEnd]\n )\n\n return (\n <DragDropContext onDragStart={handleDragStart} onDragEnd={onDragEnd}>\n <Droppable droppableId=\"documentSortZone\">\n {(provided) => (\n <div {...provided.droppableProps} ref={provided.innerRef}>\n {orderedData.map((item, index) => (\n <Draggable\n key={`${item._id}-${item[ORDER_FIELD_NAME]}`}\n draggableId={item._id}\n index={index}\n // onClick={(event) => handleDraggableClick(event, provided, snapshot)}\n >\n {(innerProvided, innerSnapshot) => {\n const isSelected = selectedIds.includes(item._id)\n const isDragging = innerSnapshot.isDragging\n const isGhosting = Boolean(!isDragging && draggingId && isSelected)\n const isUpdating = listIsUpdating && isSelected\n const isDisabled = Boolean(!item[ORDER_FIELD_NAME])\n const isDuplicate = duplicateOrders.includes(item[ORDER_FIELD_NAME])\n const tone = cardTone({isDuplicate, isGhosting, isDragging, isSelected})\n\n return (\n <div\n ref={innerProvided.innerRef}\n {...innerProvided.draggableProps}\n {...innerProvided.dragHandleProps}\n style={\n isDisabled\n ? {opacity: 0.2, pointerEvents: `none`}\n : getItemStyle(innerProvided.draggableProps.style, isUpdating)\n }\n >\n <Box paddingBottom={1}>\n <Card tone={tone} shadow={isDragging ? 2 : undefined} radius={2}>\n <Document\n doc={item}\n entities={orderedData}\n handleSelect={handleSelect}\n increment={incrementIndex}\n index={index}\n isFirst={index === 0}\n isLast={index === orderedData.length - 1}\n />\n </Card>\n </Box>\n </div>\n )\n }}\n </Draggable>\n ))}\n {provided.placeholder}\n </div>\n )}\n </Droppable>\n </DragDropContext>\n )\n}\n","import React, {PropsWithChildren} from 'react'\nimport {Box, Card, Text} from '@sanity/ui'\n\nexport default function Feedback({children}: PropsWithChildren<{}>) {\n return (\n <Box padding={3}>\n <Card padding={4} radius={2} shadow={1} tone=\"caution\">\n <Text>{children}</Text>\n </Card>\n </Box>\n )\n}\n","import React, {useEffect, useMemo, useState} from 'react'\nimport {Box, Flex, Spinner, Stack} from '@sanity/ui'\n\nimport type {SanityDocument} from 'sanity'\nimport DraggableList from './DraggableList'\nimport {ORDER_FIELD_NAME} from './helpers/constants'\nimport Feedback from './Feedback'\nimport {useSanityClient} from './helpers/client'\n\nexport interface DocumentListQueryProps {\n type: string\n filter?: string\n params?: Record<string, unknown>\n}\n\n//rxjs Subscription does not seem to comply with sanity client subscribe anymore\ntype ClientSubscription = ReturnType<\n ReturnType<ReturnType<typeof useSanityClient>['listen']>['subscribe']\n>\n\nconst DEFAULT_PARAMS = {}\n\nexport default function DocumentListQuery({\n type,\n filter,\n params = DEFAULT_PARAMS,\n}: DocumentListQueryProps) {\n const [isLoading, setIsLoading] = useState(true)\n const [listIsUpdating, setListIsUpdating] = useState(false)\n const [data, setData] = useState<SanityDocument[]>([])\n\n const client = useSanityClient()\n\n useEffect(() => {\n const query = `*[_type == $type ${filter ? `&& ${filter}` : ''}]|order(@[$order] asc){\n _id, _type, ${ORDER_FIELD_NAME}\n }`\n const queryParams = Object.assign(params, {type, order: ORDER_FIELD_NAME})\n let subscription: ClientSubscription | undefined\n\n // eslint-disable-next-line require-await\n const fetchData = async () => {\n client.fetch<SanityDocument[]>(query, queryParams).then((documents) => {\n // Remove published document from list if draft also exists\n const filteredDocuments = documents.reduce((acc, cur) => {\n if (!cur._id.startsWith(`drafts.`)) {\n // eslint-disable-next-line max-nested-callbacks\n const alsoHasDraft = documents.some((doc) => doc._id === `drafts.${cur._id}`)\n\n return alsoHasDraft ? acc : [...acc, cur]\n }\n\n return [...acc, cur]\n }, [] as SanityDocument[])\n\n setData(filteredDocuments)\n\n if (isLoading) {\n setIsLoading(false)\n }\n })\n }\n\n const prepareData = async () => {\n setIsLoading(true)\n\n await fetchData()\n\n if (!subscription) {\n subscription = client.listen(query, queryParams).subscribe(() => fetchData())\n }\n }\n\n // Get data but only if a document isn't being patched or we don't yet have data\n if (!listIsUpdating && !data.length) {\n prepareData()\n }\n\n return () => subscription?.unsubscribe()\n /* eslint-disable-next-line react-hooks/exhaustive-deps */\n }, [type])\n\n const unorderedDataCount = useMemo(\n () => (data.length ? data.filter((doc) => !doc[ORDER_FIELD_NAME]).length : 0),\n [data]\n )\n\n if (isLoading)\n return (\n <Flex style={{width: `100%`, height: `100%`}} align=\"center\" justify=\"center\">\n <Spinner />\n </Flex>\n )\n\n return (\n <Stack space={1} style={{overflow: `scroll`, height: `100%`}}>\n {unorderedDataCount > 0 && (\n <Feedback>\n {unorderedDataCount}/{data.length} Documents have no Order. Select{' '}\n <strong>Reset Order</strong> from the Menu above to fix.\n </Feedback>\n )}\n <Box padding={1}>\n <DraggableList\n data={data}\n type={type}\n listIsUpdating={listIsUpdating}\n setListIsUpdating={setListIsUpdating}\n />\n </Box>\n </Stack>\n )\n}\n","import React, {useEffect, useMemo} from 'react'\nimport {useToast} from '@sanity/ui'\n\nimport {useSchema} from 'sanity'\nimport type {ToastParams} from '@sanity/ui'\nimport DocumentListQuery from './DocumentListQuery'\nimport {OrderableContext} from './OrderableContext'\n\nimport {ORDER_FIELD_NAME} from './helpers/constants'\nimport Feedback from './Feedback'\n\nexport interface DocumentListWrapperProps {\n showIncrements: boolean\n type: string\n resetOrderTransaction: ToastParams\n filter?: string\n params?: Record<string, unknown>\n}\n\n// 1. Validate first that the schema has been configured for ordering\n// 2. Setup context for showIncrements\nexport default function DocumentListWrapper({\n type,\n showIncrements,\n resetOrderTransaction,\n filter,\n params,\n}: DocumentListWrapperProps) {\n const toast = useToast()\n const schema = useSchema()\n\n useEffect(() => {\n if (resetOrderTransaction?.title && resetOrderTransaction?.status) {\n toast.push(resetOrderTransaction)\n }\n }, [resetOrderTransaction, toast])\n\n const schemaIsInvalid = useMemo(() => {\n // Option not passed\n if (!type) {\n return (\n <>\n No <code>type</code> was configured\n </>\n )\n }\n\n const typeSchema = schema.get(type)\n\n // Schema not found\n if (!typeSchema) {\n return (\n <>\n Schema <code>{type}</code> not found\n </>\n )\n }\n\n // Schema lacks an order field\n if (\n !('fields' in typeSchema) ||\n !typeSchema.fields.some((field) => field?.name === ORDER_FIELD_NAME)\n ) {\n return (\n <>\n Schema <code>{type}</code> must have an <code>{ORDER_FIELD_NAME}</code> field of type{' '}\n <code>string</code>\n </>\n )\n }\n\n // Schema's order field is not a string\n if (\n 'fields' in typeSchema &&\n typeSchema.fields.some(\n (field) => field?.name === ORDER_FIELD_NAME && field?.type?.name !== 'string'\n )\n ) {\n return (\n <>\n <code>{ORDER_FIELD_NAME}</code> field on Schema <code>{type}</code> must be{' '}\n <code>string</code> type\n </>\n )\n }\n\n return ''\n }, [type, schema])\n\n if (schemaIsInvalid) {\n return <Feedback>{schemaIsInvalid}</Feedback>\n }\n\n return (\n <OrderableContext.Provider value={{showIncrements}}>\n <DocumentListQuery type={type} filter={filter} params={params} />\n </OrderableContext.Provider>\n )\n}\n","import React, {Component} from 'react'\n\nimport {SanityClient} from '@sanity/client'\nimport type {ToastParams} from '@sanity/ui'\nimport DocumentListWrapper from './DocumentListWrapper'\nimport {resetOrder} from './helpers/resetOrder'\n\nexport interface OrderableDocumentListProps {\n options: {\n type: string\n client: SanityClient,\n filter?: string,\n params?: Record<string, unknown>\n }\n}\n\ninterface State {\n showIncrements: boolean\n resetOrderTransaction: ToastParams\n}\n\n// Must use a Class Component here so the actionHandlers can be called\nexport default class OrderableDocumentList extends Component<OrderableDocumentListProps, State> {\n constructor(props: OrderableDocumentListProps) {\n super(props)\n this.state = {\n showIncrements: false,\n resetOrderTransaction: {},\n }\n }\n\n actionHandlers = {\n showIncrements: () => {\n this.setState((state) => ({\n showIncrements: !state.showIncrements,\n }))\n },\n\n resetOrder: async () => {\n this.setState(() => ({\n resetOrderTransaction: {\n status: `info`,\n title: `Reordering started...`,\n closable: true,\n },\n }))\n\n const update = await resetOrder(this.props.options.type, this.props.options.client)\n\n const reorderWasSuccessful = update?.results?.length\n\n this.setState(() => ({\n resetOrderTransaction: {\n status: reorderWasSuccessful ? `success` : `info`,\n title: reorderWasSuccessful\n ? `Reordered ${update.results.length === 1 ? `Document` : `Documents`}`\n : `Reordering failed`,\n closable: true,\n },\n }))\n },\n }\n\n render() {\n const type = this?.props?.options?.type\n if (!type) {\n return null\n }\n return (\n <DocumentListWrapper\n filter={this?.props?.options?.filter}\n params={this?.props?.options?.params}\n type={type}\n showIncrements={this.state.showIncrements}\n resetOrderTransaction={this.state.resetOrderTransaction}\n />\n )\n }\n}\n","import {LexoRank} from 'lexorank'\nimport {SanityClient} from '@sanity/client'\nimport {ORDER_FIELD_NAME} from './constants'\n// Function to wipe and re-do ordering with LexoRank\n// Will at least attempt to start with the current order\nexport async function resetOrder(type = ``, client: SanityClient) {\n const query = `*[_type == $type]|order(@[$order] asc)._id`\n const queryParams = {type, order: ORDER_FIELD_NAME}\n const documents = await client.fetch(query, queryParams)\n\n if (!documents.length) {\n return null\n }\n\n const transaction = client.transaction()\n let aLexoRank = LexoRank.min()\n\n for (let index = 0; index < documents.length; index += 1) {\n // Generate next rank before even the first document so there's room to move!\n aLexoRank = aLexoRank.genNext().genNext()\n\n transaction.patch(documents[index], {\n set: {[ORDER_FIELD_NAME]: (aLexoRank as any).value as string},\n })\n }\n\n return transaction\n .commit()\n .then((update) => update)\n .catch((err) => err)\n}\n","import {LexoRank} from 'lexorank'\n\n// Use in initial value field by passing in the rank value of the last document\n// If not value passed, generate a sensibly low rank\nexport default function initialRank(lastRankValue = ``): string {\n const lastRank = lastRankValue ? LexoRank.parse(lastRankValue) : LexoRank.min()\n const nextRank = lastRank.genNext().genNext()\n\n return (nextRank as any).value\n}\n","import {GenerateIcon, SortIcon} from '@sanity/icons'\nimport type {ConfigContext} from 'sanity'\n\nimport {ComponentType} from 'react'\nimport {StructureBuilder} from 'sanity/desk'\nimport OrderableDocumentList from '../OrderableDocumentList'\n\nexport interface OrderableListConfig {\n type: string\n id?: string\n title?: string\n icon?: ComponentType\n params?: Record<string, unknown>\n filter?: string\n context: ConfigContext\n S: StructureBuilder\n}\n\nexport function orderableDocumentListDeskItem(config: OrderableListConfig) {\n if (!config?.type || !config.context || !config.S) {\n throw new Error(`\n type, context and S (StructureBuilder) must be provided.\n context and S are available when configuring structure.\n Example: orderableDocumentListDeskItem({type: 'category'})\n `)\n }\n\n const {type, filter, params, title, icon, id, context, S} = config\n const {schema, getClient} = context\n const client = getClient({apiVersion: '2021-09-01'})\n\n const listTitle = title ?? `Orderable ${type}`\n const listId = id ?? `orderable-${type}`\n const listIcon = icon ?? SortIcon\n const typeTitle = schema.get(type)?.title ?? type\n\n return S.listItem()\n .title(listTitle)\n .id(listId)\n .icon(listIcon)\n .child(\n Object.assign(S.documentTypeList(type).serialize(), {\n // Prevents the component from re-rendering when switching documents\n __preserveInstance: true,\n // Prevents the component from NOT re-rendering when switching listItems\n key: listId,\n\n type: 'component',\n component: OrderableDocumentList,\n options: {type, filter, params, client},\n menuItems: [\n S.menuItem()\n .title(`Create new ${typeTitle}`)\n .intent({type: 'create', params: {type}})\n .serialize(),\n S.menuItem().title(`Reset Order`).icon(GenerateIcon).action(`resetOrder`).serialize(),\n S.menuItem().title(`Show Increments`).icon(SortIcon).action(`showIncrements`).serialize(),\n ],\n })\n )\n .serialize()\n}\n"],"names":["orderRankOrdering","title","name","by","field","direction","OrderableContext","React","createContext","Document","_ref2","doc","increment","entities","handleSelect","index","isFirst","isLast","showIncrements","useContext","schema","useSchema","jsxs","Flex","align","children","jsx","Box","paddingX","style","flexShrink","Text","size","DragHandleIcon","gap","paddingRight","Button","padding","mode","onClick","_id","disabled","icon","ChevronUpIcon","ChevronDownIcon","width","e","nativeEvent","flex","Preview","layout","value","schemaType","get","_type","lexicographicalSort","a","b","useSanityClient","useClient","apiVersion","DraggableList","_ref4","data","type","listIsUpdating","setListIsUpdating","toast","useToast","router","usePaneRouter","navigateIntent","orderedData","setOrderedData","useState","useEffect","draggingId","setDraggingId","selectedIds","setSelectedIds","clearSelected","useCallback","clickedId","isSelected","includes","selectMultiple","shiftKey","selectAdditional","navigator","appVersion","indexOf","ctrlKey","metaKey","updatedIds","id","lastSelectedId","length","lastSelectedIndex","findIndex","item","firstSelected","lastSelected","betweenIds","filter","itemIndex","map","client","transactPatches","async","patches","message","transaction","forEach","_ref5","docId","ops","patch","commit","then","updated","push","results","concat","status","description","catch","handleDragEnd","result","source","destination","draggableId","effectedIds","newOrder","_ref3","debug","startIndex","endIndex","isMovingUp","selectedItems","join","all","selected","reduce","acc","cur","curIndex","_a","_b","_c","_d","prevIndex","prevRank","LexoRank","parse","min","curRank","nextIndex","nextRank","max","betweenRank","between","selectedIndex","set","orderRank","sort","reorderDocuments","handleDragStart","start","incrementIndex","shiftFrom","shiftTo","onWindowKeyDown","event","key","window","addEventListener","removeEventListener","duplicateOrders","useMemo","orderField","onDragEnd","DragDropContext","onDragStart","Droppable","droppableId","provided","_objectSpread","droppableProps","ref","innerRef","Draggable","innerProvided","innerSnapshot","isDragging","isGhosting","Boolean","isUpdating","isDisabled","tone","settings","isDuplicate","cardTone","draggableProps","dragHandleProps","opacity","pointerEvents","draggableStyle","itemIsUpdating","userSelect","transition","paddingBottom","Card","shadow","radius","placeholder","Feedback","_ref6","DEFAULT_PARAMS","DocumentListQuery","_ref7","params","isLoading","setIsLoading","setData","query","ORDER_FIELD_NAME","queryParams","Object","assign","order","subscription","fetchData","fetch","documents","filteredDocuments","startsWith","some","listen","subscribe","prepareData","unsubscribe","unorderedDataCount","height","justify","Spinner","Stack","space","overflow","DocumentListWrapper","_ref8","resetOrderTransaction","schemaIsInvalid","Fragment","typeSchema","fields","Provider","OrderableDocumentList","Component","constructor","props","super","this","actionHandlers","setState","state","resetOrder","closable","update","arguments","undefined","aLexoRank","genNext","err","options","reorderWasSuccessful","render","_e","_f","config","Error","defineField","readOnly","hidden","initialValue","p","_ref","getClient","lastRankValue","lastRank","initialRank","context","S","listTitle","listId","listIcon","SortIcon","typeTitle","listItem","child","documentTypeList","serialize","__preserveInstance","component","menuItems","menuItem","intent","GenerateIcon","action"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/lib/src/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {ComponentType} from 'react'
|
|
|
2
2
|
import type {ConfigContext} from 'sanity'
|
|
3
3
|
import {FieldDefinitionBase} from 'sanity'
|
|
4
4
|
import {ListItem} from 'sanity/desk'
|
|
5
|
+
import {SortOrdering} from 'sanity'
|
|
5
6
|
import {StringDefinition} from 'sanity'
|
|
6
7
|
import {StructureBuilder} from 'sanity/desk'
|
|
7
8
|
import {WidenInitialValue} from 'sanity'
|
|
@@ -28,14 +29,7 @@ export declare const orderRankField: (config: RankFieldConfig) => {
|
|
|
28
29
|
WidenValidation &
|
|
29
30
|
WidenInitialValue
|
|
30
31
|
|
|
31
|
-
export declare const orderRankOrdering:
|
|
32
|
-
title: string
|
|
33
|
-
name: string
|
|
34
|
-
by: {
|
|
35
|
-
field: 'orderRank'
|
|
36
|
-
direction: string
|
|
37
|
-
}[]
|
|
38
|
-
}
|
|
32
|
+
export declare const orderRankOrdering: SortOrdering
|
|
39
33
|
|
|
40
34
|
export declare interface RankFieldConfig {
|
|
41
35
|
type: string
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/orderable-document-list",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Drag-and-drop Document Ordering without leaving the Editing surface",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -55,12 +55,12 @@
|
|
|
55
55
|
}
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
+
"@hello-pangea/dnd": "^16.2.0",
|
|
58
59
|
"@sanity/icons": "^2.0.0",
|
|
59
60
|
"@sanity/incompatible-plugin": "^1.0.4",
|
|
60
61
|
"@sanity/ui": "^1.0.0",
|
|
61
62
|
"lexorank": "^1.0.4",
|
|
62
|
-
"prop-types": "^15.8.1"
|
|
63
|
-
"react-beautiful-dnd": "^13.1.0"
|
|
63
|
+
"prop-types": "^15.8.1"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@commitlint/cli": "^17.2.0",
|
|
@@ -68,7 +68,6 @@
|
|
|
68
68
|
"@sanity/pkg-utils": "^1.17.2",
|
|
69
69
|
"@sanity/plugin-kit": "^2.1.4",
|
|
70
70
|
"@sanity/semantic-release-preset": "^2.0.2",
|
|
71
|
-
"@types/react-beautiful-dnd": "^13.1.2",
|
|
72
71
|
"@typescript-eslint/eslint-plugin": "^5.42.0",
|
|
73
72
|
"@typescript-eslint/parser": "^5.42.0",
|
|
74
73
|
"autoprefixer": "^10.3.6",
|
package/src/Document.tsx
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import React, {useContext} from 'react'
|
|
2
2
|
import {ChevronDownIcon, ChevronUpIcon, DragHandleIcon} from '@sanity/icons'
|
|
3
|
-
import {Box, Button, Flex, Text} from '@sanity/ui'
|
|
3
|
+
import {Box, Button, Card, Flex, Text} from '@sanity/ui'
|
|
4
|
+
import {useSchema, SchemaType, Preview} from 'sanity'
|
|
4
5
|
|
|
5
|
-
import {useSchema, SanityDocument, SchemaType, Preview} from 'sanity'
|
|
6
6
|
import {OrderableContext} from './OrderableContext'
|
|
7
|
+
import {SanityDocumentWithOrder} from './types'
|
|
7
8
|
|
|
8
9
|
export interface DocumentProps {
|
|
9
|
-
doc:
|
|
10
|
-
entities:
|
|
10
|
+
doc: SanityDocumentWithOrder
|
|
11
|
+
entities: SanityDocumentWithOrder[]
|
|
11
12
|
handleSelect: (docId: string, index: number, event: MouseEvent) => void
|
|
12
|
-
increment: (
|
|
13
|
+
increment: (
|
|
14
|
+
index: number,
|
|
15
|
+
nextIndex: number,
|
|
16
|
+
docId: string,
|
|
17
|
+
entities: SanityDocumentWithOrder[]
|
|
18
|
+
) => void
|
|
13
19
|
index: number
|
|
14
20
|
isFirst: boolean
|
|
15
21
|
isLast: boolean
|
|
@@ -58,13 +64,13 @@ export default function Document({
|
|
|
58
64
|
onClick={(e) => handleSelect(doc._id, index, e.nativeEvent)}
|
|
59
65
|
>
|
|
60
66
|
<Flex flex={1} align="center">
|
|
61
|
-
<
|
|
67
|
+
<Card tone="default">
|
|
62
68
|
<Preview
|
|
63
69
|
layout="default"
|
|
64
70
|
value={doc}
|
|
65
71
|
schemaType={schema.get(doc._type) as SchemaType}
|
|
66
72
|
/>
|
|
67
|
-
</
|
|
73
|
+
</Card>
|
|
68
74
|
</Flex>
|
|
69
75
|
</Button>
|
|
70
76
|
</Flex>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React, {useEffect, useMemo, useState} from 'react'
|
|
2
2
|
import {Box, Flex, Spinner, Stack} from '@sanity/ui'
|
|
3
3
|
|
|
4
|
-
import type {SanityDocument} from 'sanity'
|
|
5
4
|
import DraggableList from './DraggableList'
|
|
6
5
|
import {ORDER_FIELD_NAME} from './helpers/constants'
|
|
7
6
|
import Feedback from './Feedback'
|
|
8
7
|
import {useSanityClient} from './helpers/client'
|
|
8
|
+
import { SanityDocumentWithOrder } from './types'
|
|
9
9
|
|
|
10
10
|
export interface DocumentListQueryProps {
|
|
11
11
|
type: string
|
|
@@ -27,7 +27,7 @@ export default function DocumentListQuery({
|
|
|
27
27
|
}: DocumentListQueryProps) {
|
|
28
28
|
const [isLoading, setIsLoading] = useState(true)
|
|
29
29
|
const [listIsUpdating, setListIsUpdating] = useState(false)
|
|
30
|
-
const [data, setData] = useState<
|
|
30
|
+
const [data, setData] = useState<SanityDocumentWithOrder[]>([])
|
|
31
31
|
|
|
32
32
|
const client = useSanityClient()
|
|
33
33
|
|
|
@@ -40,9 +40,9 @@ export default function DocumentListQuery({
|
|
|
40
40
|
|
|
41
41
|
// eslint-disable-next-line require-await
|
|
42
42
|
const fetchData = async () => {
|
|
43
|
-
client.fetch<
|
|
43
|
+
client.fetch<SanityDocumentWithOrder[]>(query, queryParams).then((documents) => {
|
|
44
44
|
// Remove published document from list if draft also exists
|
|
45
|
-
const filteredDocuments = documents.reduce((acc, cur) => {
|
|
45
|
+
const filteredDocuments = documents.reduce<SanityDocumentWithOrder[]>((acc, cur) => {
|
|
46
46
|
if (!cur._id.startsWith(`drafts.`)) {
|
|
47
47
|
// eslint-disable-next-line max-nested-callbacks
|
|
48
48
|
const alsoHasDraft = documents.some((doc) => doc._id === `drafts.${cur._id}`)
|
|
@@ -51,7 +51,7 @@ export default function DocumentListQuery({
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
return [...acc, cur]
|
|
54
|
-
}, []
|
|
54
|
+
}, [])
|
|
55
55
|
|
|
56
56
|
setData(filteredDocuments)
|
|
57
57
|
|
|
@@ -93,7 +93,7 @@ export default function DocumentListQuery({
|
|
|
93
93
|
)
|
|
94
94
|
|
|
95
95
|
return (
|
|
96
|
-
<Stack space={1} style={{overflow: `
|
|
96
|
+
<Stack space={1} style={{overflow: `auto`, height: `100%`}}>
|
|
97
97
|
{unorderedDataCount > 0 && (
|
|
98
98
|
<Feedback>
|
|
99
99
|
{unorderedDataCount}/{data.length} Documents have no Order. Select{' '}
|
package/src/DraggableList.tsx
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import React, {useEffect, useState, useMemo, useCallback, CSSProperties} from 'react'
|
|
2
|
-
import {DragDropContext, Draggable, Droppable, type DropResult} from '
|
|
2
|
+
import {DragDropContext, Draggable, Droppable, type DropResult} from '@hello-pangea/dnd'
|
|
3
3
|
import {Box, Card, useToast} from '@sanity/ui'
|
|
4
4
|
import {usePaneRouter} from 'sanity/desk'
|
|
5
|
-
import type {
|
|
5
|
+
import type {PatchOperations} from 'sanity'
|
|
6
|
+
|
|
6
7
|
import Document from './Document'
|
|
7
8
|
import {reorderDocuments} from './helpers/reorderDocuments'
|
|
8
9
|
import {ORDER_FIELD_NAME} from './helpers/constants'
|
|
9
10
|
import {useSanityClient} from './helpers/client'
|
|
11
|
+
import { SanityDocumentWithOrder } from './types'
|
|
10
12
|
|
|
11
13
|
const getItemStyle = (
|
|
12
14
|
draggableStyle: CSSProperties | undefined,
|
|
@@ -37,7 +39,7 @@ interface ListSetting {
|
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
export interface DraggableListProps {
|
|
40
|
-
data:
|
|
42
|
+
data: SanityDocumentWithOrder[]
|
|
41
43
|
type: string
|
|
42
44
|
listIsUpdating: boolean
|
|
43
45
|
setListIsUpdating: (val: boolean) => void
|
|
@@ -54,7 +56,7 @@ export default function DraggableList({
|
|
|
54
56
|
const {navigateIntent} = router
|
|
55
57
|
|
|
56
58
|
// Maintains local state order before transaction completes
|
|
57
|
-
const [orderedData, setOrderedData] = useState<
|
|
59
|
+
const [orderedData, setOrderedData] = useState<SanityDocumentWithOrder[]>(data)
|
|
58
60
|
|
|
59
61
|
// Update local state when documents change from an outside source
|
|
60
62
|
useEffect(() => {
|
|
@@ -146,7 +148,7 @@ export default function DraggableList({
|
|
|
146
148
|
)
|
|
147
149
|
|
|
148
150
|
const handleDragEnd = useCallback(
|
|
149
|
-
(result: DropResult | undefined, entities:
|
|
151
|
+
(result: DropResult | undefined, entities: SanityDocumentWithOrder[]) => {
|
|
150
152
|
setDraggingId(``)
|
|
151
153
|
|
|
152
154
|
const {source, destination, draggableId} = result ?? {}
|
|
@@ -176,7 +178,7 @@ export default function DraggableList({
|
|
|
176
178
|
|
|
177
179
|
// Update local state
|
|
178
180
|
if (newOrder?.length) {
|
|
179
|
-
setOrderedData(newOrder
|
|
181
|
+
setOrderedData(newOrder)
|
|
180
182
|
}
|
|
181
183
|
|
|
182
184
|
// Transact new order patches
|
|
@@ -202,7 +204,7 @@ export default function DraggableList({
|
|
|
202
204
|
|
|
203
205
|
// Move one document up or down one place, by fake invoking the drag function
|
|
204
206
|
const incrementIndex = useCallback(
|
|
205
|
-
(shiftFrom: number, shiftTo: number, id: string, entities:
|
|
207
|
+
(shiftFrom: number, shiftTo: number, id: string, entities: SanityDocumentWithOrder[]) => {
|
|
206
208
|
const result = {
|
|
207
209
|
draggableId: id,
|
|
208
210
|
source: {index: shiftFrom},
|
|
@@ -54,7 +54,7 @@ export function orderableDocumentListDeskItem(config: OrderableListConfig) {
|
|
|
54
54
|
.intent({type: 'create', params: {type}})
|
|
55
55
|
.serialize(),
|
|
56
56
|
S.menuItem().title(`Reset Order`).icon(GenerateIcon).action(`resetOrder`).serialize(),
|
|
57
|
-
S.menuItem().title(`
|
|
57
|
+
S.menuItem().title(`Toggle Increments`).icon(SortIcon).action(`showIncrements`).serialize(),
|
|
58
58
|
],
|
|
59
59
|
})
|
|
60
60
|
)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { SortOrdering } from 'sanity'
|
|
1
2
|
import {ORDER_FIELD_NAME} from '../helpers/constants'
|
|
2
3
|
|
|
3
|
-
export const orderRankOrdering = {
|
|
4
|
+
export const orderRankOrdering: SortOrdering = {
|
|
4
5
|
title: 'Ordered',
|
|
5
6
|
name: 'ordered',
|
|
6
7
|
by: [{field: ORDER_FIELD_NAME, direction: 'asc'}],
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import {LexoRank} from 'lexorank'
|
|
2
|
-
import type {PatchOperations
|
|
2
|
+
import type {PatchOperations} from 'sanity'
|
|
3
|
+
|
|
4
|
+
import { SanityDocumentWithOrder } from '../types'
|
|
3
5
|
import {ORDER_FIELD_NAME} from './constants'
|
|
4
6
|
|
|
5
7
|
export interface MaifestArgs {
|
|
6
|
-
entities:
|
|
7
|
-
selectedItems:
|
|
8
|
+
entities: SanityDocumentWithOrder[]
|
|
9
|
+
selectedItems: SanityDocumentWithOrder[]
|
|
8
10
|
isMovingUp: boolean
|
|
9
11
|
curIndex: number
|
|
10
12
|
nextIndex: number
|
|
@@ -12,18 +14,18 @@ export interface MaifestArgs {
|
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
export interface ReorderArgs {
|
|
15
|
-
entities:
|
|
17
|
+
entities: SanityDocumentWithOrder[]
|
|
16
18
|
selectedIds: string[]
|
|
17
19
|
source: any
|
|
18
20
|
destination: any
|
|
19
|
-
debug?: boolean
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
function lexicographicalSort(a:
|
|
23
|
-
if (a[ORDER_FIELD_NAME]
|
|
23
|
+
function lexicographicalSort(a: SanityDocumentWithOrder, b: SanityDocumentWithOrder) {
|
|
24
|
+
if (!a[ORDER_FIELD_NAME] || !b[ORDER_FIELD_NAME]) {
|
|
25
|
+
return 0
|
|
26
|
+
} else if (a[ORDER_FIELD_NAME] < b[ORDER_FIELD_NAME]) {
|
|
24
27
|
return -1
|
|
25
|
-
}
|
|
26
|
-
if (a[ORDER_FIELD_NAME] > b[ORDER_FIELD_NAME]) {
|
|
28
|
+
} else if (a[ORDER_FIELD_NAME] > b[ORDER_FIELD_NAME]) {
|
|
27
29
|
return 1
|
|
28
30
|
}
|
|
29
31
|
return 0
|
|
@@ -34,7 +36,6 @@ export const reorderDocuments = ({
|
|
|
34
36
|
selectedIds,
|
|
35
37
|
source,
|
|
36
38
|
destination,
|
|
37
|
-
debug = false,
|
|
38
39
|
}: ReorderArgs) => {
|
|
39
40
|
const startIndex = source.index
|
|
40
41
|
const endIndex = destination.index
|
|
@@ -48,14 +49,17 @@ export const reorderDocuments = ({
|
|
|
48
49
|
`${startIndex + 1} to ${endIndex + 1}`,
|
|
49
50
|
].join(' ')
|
|
50
51
|
|
|
51
|
-
const {all, selected} = entities.reduce
|
|
52
|
+
const {all, selected} = entities.reduce<{
|
|
53
|
+
all: SanityDocumentWithOrder[]
|
|
54
|
+
selected: SanityDocumentWithOrder[]
|
|
55
|
+
}>(
|
|
52
56
|
(acc, cur, curIndex) => {
|
|
53
57
|
// Selected items get spread in below, so skip them here
|
|
54
58
|
if (selectedIds.includes(cur._id)) {
|
|
55
59
|
return {all: acc.all, selected: acc.selected}
|
|
56
60
|
}
|
|
57
61
|
|
|
58
|
-
// Drop
|
|
62
|
+
// Drop selected items in
|
|
59
63
|
if (curIndex === endIndex) {
|
|
60
64
|
const prevIndex = curIndex - 1
|
|
61
65
|
const prevRank = entities[prevIndex]?.[ORDER_FIELD_NAME]
|
|
@@ -73,7 +77,7 @@ export const reorderDocuments = ({
|
|
|
73
77
|
|
|
74
78
|
// For each selected item, assign a new orderRank between now and next
|
|
75
79
|
for (let selectedIndex = 0; selectedIndex < selectedItems.length; selectedIndex += 1) {
|
|
76
|
-
selectedItems[selectedIndex][ORDER_FIELD_NAME] = (
|
|
80
|
+
selectedItems[selectedIndex][ORDER_FIELD_NAME] = betweenRank.toString()
|
|
77
81
|
betweenRank = isMovingUp ? betweenRank.between(curRank) : betweenRank.between(nextRank)
|
|
78
82
|
}
|
|
79
83
|
|
|
@@ -89,7 +93,7 @@ export const reorderDocuments = ({
|
|
|
89
93
|
|
|
90
94
|
return {all: [...acc.all, cur], selected: acc.selected}
|
|
91
95
|
},
|
|
92
|
-
{all: []
|
|
96
|
+
{all: [], selected: []}
|
|
93
97
|
)
|
|
94
98
|
|
|
95
99
|
const patches: [string, PatchOperations][] = selected.map((doc) => {
|
|
@@ -104,7 +108,7 @@ export const reorderDocuments = ({
|
|
|
104
108
|
})
|
|
105
109
|
|
|
106
110
|
// Safety-check to make sure everything is in order
|
|
107
|
-
const allSorted =
|
|
111
|
+
const allSorted = all.sort(lexicographicalSort)
|
|
108
112
|
|
|
109
113
|
return {newOrder: allSorted, patches, message}
|
|
110
114
|
}
|
|
@@ -20,7 +20,7 @@ export async function resetOrder(type = ``, client: SanityClient) {
|
|
|
20
20
|
aLexoRank = aLexoRank.genNext().genNext()
|
|
21
21
|
|
|
22
22
|
transaction.patch(documents[index], {
|
|
23
|
-
set: {[ORDER_FIELD_NAME]: (
|
|
23
|
+
set: {[ORDER_FIELD_NAME]: aLexoRank.toString()},
|
|
24
24
|
})
|
|
25
25
|
}
|
|
26
26
|
|