@cntrl-site/components 1.0.12-alpha.2 → 1.0.12-alpha.3

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.
Files changed (3) hide show
  1. package/dist/index.js +2541 -2541
  2. package/dist/index.mjs +2542 -2542
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4662,2545 +4662,2545 @@ a.${e}-list-item {
4662
4662
  overflow-wrap: anywhere;
4663
4663
  word-break: break-word;
4664
4664
  }
4665
- `}const Pt=["AColumn","BColumnWidth","CColumnWidth","DColumnWidth","EColumnWidth"],eo=["AColumn","BColumn","CColumn","DColumn","EColumn"],vt="cutLabel",Pn=[...eo,vt],to=["A","B","C","D","E"];function Ai(e){return`${e}ColumnVerticalAlign`}const Xc=["Top","Center","Bottom"];function Zc(e){const t=String(e??"Top").trim();return t.toLowerCase().startsWith("baseline")?!1:t==="Top"||t==="Center"||t==="Bottom"}function Jc(e){const t=String(e??"").trim();if(!t.toLowerCase().startsWith("baseline"))return null;const n=t.slice(-1).toUpperCase();return to.includes(n)?n:null}function Ri(e,t,n){const r=Jc(e);return r?r===t?!1:Zc(n[Ai(r)]):!0}function Rr(e){const t=String(e??"Top").trim();if(t.toLowerCase().startsWith("baseline")){const n=t.slice(-1).toUpperCase();return to.includes(n)?{kind:"baseline",anchorLetter:n}:{kind:"top"}}return t==="Center"?{kind:"center"}:t==="Bottom"?{kind:"bottom"}:{kind:"top"}}function Qc(e,t,n){if(Ii(e,t,n))return Rr(e);const r=Rr(e);return r.kind==="baseline"?{kind:"top"}:r}function Ii(e,t,n){return Ri(e,n,t)?Rr(e).kind==="baseline":!1}function ed(e){if(e.type==="B")return null;const t={};let n=!1;for(const r of to){const o=Ai(r),s=e[o];Ri(s,r,e)||(t[o]="Top",n=!0)}return n?t:null}function td(e){return e==="center"?{marginTop:"auto",marginBottom:"auto"}:e==="bottom"?{marginTop:"auto"}:{}}function nd(e,t){const n=document.createElement("i");n.className=t,n.setAttribute("aria-hidden","true"),e.prepend(n);const{top:r}=e.getBoundingClientRect(),{bottom:o}=n.getBoundingClientRect(),s=o-r;return n.remove(),s}function br(e,t,n,r){const o=e.titleEl;if(!o)return 0;const s=o.closest(`.${n}`);if(!s)return 0;const i=nd(o,r);if(e.kind==="baseline")return o.getBoundingClientRect().top-t+i;const a=s.getBoundingClientRect(),c=o.getBoundingClientRect().height;let u=0;return e.kind==="center"?u=(a.height-c)/2:e.kind==="bottom"&&(u=a.height-c),a.top-t+u+i}function rd(e,t,n){const r=e.getBoundingClientRect().height;return r<=0?0:(t.forEach(o=>{const s=o.querySelector(`.${n}`);s&&(s.style.minHeight=`${r}px`,s.style.height=`${r}px`)}),e.offsetHeight,r)}function od(e,t){return!e||!t?(e&&(e.style.transform=""),0):(e.style.transform=`translateY(${t}px)`,t)}const id={AColumn:"AColumn",BColumnWidth:"BColumn",CColumnWidth:"CColumn",DColumnWidth:"DColumn",EColumnWidth:"EColumn"},ad=["textFontFamily","textFontSettings","textFontSize","textLineHeight","textLetterSpacing","textWordSpacing","textTextAppearance"];function we(e,t){return`${e}${t.replace(/^text/,"Text")}`}function Zn(e,t){const n=r=>{const o=we(t,r),s=e[o];return s!==void 0?s:e[r]};return{textFontFamily:n("textFontFamily")??"Arial",textFontSettings:n("textFontSettings")??{fontWeight:400,fontStyle:"normal"},textFontSize:n("textFontSize"),textLineHeight:n("textLineHeight"),textLetterSpacing:n("textLetterSpacing")??0,textWordSpacing:n("textWordSpacing")??0,textTextAppearance:n("textTextAppearance"),textColor:e.textColor}}function Ho(e,t){var r,o;const n={fontSettings:{fontFamily:e.textFontFamily,fontWeight:((r=e.textFontSettings)==null?void 0:r.fontWeight)??400,fontStyle:((o=e.textFontSettings)==null?void 0:o.fontStyle)??"normal"},fontSize:e.textFontSize??.01,lineHeight:e.textLineHeight,letterSpacing:e.textLetterSpacing,wordSpacing:e.textWordSpacing,textAppearance:e.textTextAppearance,color:e.textColor??"#767676"};return yt(Je(n,t))}function Oo(e,t,n,r){const o=Zn(e,t),s=o.textFontSize??.01,i=o.textLineHeight;return i!==void 0&&i<s?`${n} ${r}`:n}function Bo(e,t,n,r){const o=Zn(e,t),s=o.textFontSize??.01,i=o.textLineHeight;return i===void 0||i>=s?{}:{[`--${n}-title-leading-gap`]:T.scalingValue((s-i)/2,r)}}function sd(e,t){const n={};let r=!1;for(const o of ad)if(e[o]!==t[o]&&e[o]!==void 0){r=!0;for(const s of Pn)Object.assign(n,{[we(s,o)]:e[o]})}return r?n:null}const nt=["AColumnWidth","BColumnWidth","CColumnWidth","DColumnWidth","EColumnWidth"],Zt=["AColumnPaddingLeft","BColumnPaddingLeft","CColumnPaddingLeft","DColumnPaddingLeft","EColumnPaddingLeft"],Jt=["AColumnPaddingRight","BColumnPaddingRight","CColumnPaddingRight","DColumnPaddingRight","EColumnPaddingRight"],Qt=["AColumnPaddingBottom","BColumnPaddingBottom","CColumnPaddingBottom","DColumnPaddingBottom","EColumnPaddingBottom"],ld={textColor:"text-color",backgroundColor:"background-color",dividerColor:"divider-color",textHoverColor:"text-hover-color",backgroundHoverColor:"background-hover-color",dividerHoverColor:"divider-hover-color"},cd=["hover","focus","filled","success","error"],Vo=.004,ln=.004,no=50,bn=1440,xn=no/bn;function Wi(e){const t=typeof e=="number"&&e>0?e:bn;return no/t}function dd(e){let t=e??null;for(;t;){const n=t.style.getPropertyValue("--cntrl-article-width").trim();if(n){const o=parseFloat(n);if(Number.isFinite(o)&&o>0)return o}const r=getComputedStyle(t).getPropertyValue("--cntrl-article-width").trim();if(r){const o=parseFloat(r);if(Number.isFinite(o)&&o>0)return o}t=t.parentElement}return bn}const Fi={AColumnWidth:.02,BColumnWidth:.02,CColumnWidth:.02,DColumnWidth:.02,EColumnWidth:.02};function jn(e){const t=typeof e.wrapperWidth=="number"?e.wrapperWidth:1;return Math.max(0,t)}function ud(e,t=1){const n=t/e;return Object.fromEntries(nt.map(r=>[r,n]))}function pd(){return Object.fromEntries([...Zt.map(e=>[e,0]),...Jt.map(e=>[e,0])])}function md(){return Object.fromEntries(Qt.map(e=>[e,0]))}function Nn(e){return Object.fromEntries(nt.map(t=>[t,typeof e[t]=="number"?e[t]:Fi[t]]))}function ki(e,t,n){const r=e-xn,o=t+n;if(o<=0||o<=r)return{paddingLeft:t,paddingRight:n};if(r<=0)return{paddingLeft:0,paddingRight:0};const s=r/o;return{paddingLeft:t*s,paddingRight:n*s}}function Kn(e,t,n){const r=ro(e,t,n);if(e<=0)return[];const o=r.slice(0,e-1).reduce((s,i)=>s+i,0);return[...r.slice(0,e-1),Math.max(0,t-o)]}function gd(e,t,n){const r={};for(let o=0;o<e;o+=1){const s=Zt[o],i=Jt[o],a=typeof n[s]=="number"?n[s]:0,c=typeof n[i]=="number"?n[i]:0,u=ki(t[o]??0,a,c);u.paddingLeft!==a&&(r[s]=u.paddingLeft),u.paddingRight!==c&&(r[i]=u.paddingRight)}return r}function ro(e,t,n){if(e<=0)return[];const r=nt.slice(0,e).map(u=>n[u]);if(e===1)return r;const o=r.slice(0,e-1),i=o.reduce((u,d)=>u+d,0)+xn;if(t>=i)return r;const a=[...o];let c=i-t;for(let u=a.length-1;u>=0&&c>0;u-=1){const d=a[u]-xn;if(d<=0)continue;const $=Math.min(c,d);a[u]-=$,c-=$}return[...a,r[e-1]]}function hd(e,t,n){if(e<=1)return{};const r=ro(e,t,n),o={};for(let s=0;s<e-1;s+=1){const i=nt[s];r[s]!==n[i]&&(o[i]=r[s])}return o}function Do(e){return Array.isArray(e.columnsOrder)&&e.columnsOrder.length>0?e.columnsOrder:[...Pt]}function fd(e,t){return e.length!==t.length?!1:e.every((n,r)=>n===t[r])}function yd(e,t,n,r){const o=Math.min(r,e.length,nt.length),s={};for(let i=0;i<o;i+=1){const a=e[i],c=t.indexOf(a);if(c===-1)continue;const u=nt[c],d=Zt[c],$=Jt[c],h=Qt[c],f=nt[i],m=Zt[i],g=Jt[i],C=Qt[i],y=n[u],x=n[d],P=n[$],L=n[h];typeof y=="number"&&(s[f]=y),typeof x=="number"&&(s[m]=x),typeof P=="number"&&(s[g]=P),typeof L=="number"&&(s[C]=L)}return s}function vd(e,t,n){const r=sd(e,t);r&&(e={...e,...r});const o=ed(e);o&&(e={...e,...o});const s=Wi(n==null?void 0:n.designWidth),i=e.columns,a=t.columns,c=jn(e),u=jn(t),d=e.type==="B"||e.type===void 0&&t.type==="B",$=typeof i=="number"?i:typeof a=="number"?a:Pt.length,h=L=>{if(d)return L;const _=Nn({...t,...L}),E=jn(L),v=Kn($,E,_),S=gd($,v,{...t,...L});return Object.keys(S).length===0?L:{...L,...S}};if(typeof i=="number"&&i!==a){const L={...e,...ud(i,c),...pd()};if(d)for(const _ of Qt)typeof t[_]=="number"&&(L[_]=t[_]);else Object.assign(L,md());return L}const f=Do(e),m=Do(t);if(!fd(f,m))return h({...e,...yd(f,m,t,$)});if(c<u&&typeof $=="number"&&!d){const L=Nn({...t,...e});return h({...e,...hd($,c,L)})}if(d){const L=typeof e.textPaddingLR=="number"?e.textPaddingLR:0,_=Math.max(0,(c-s)/2);return L>_?{...e,textPaddingLR:_}:e}const g=Nn({...t,...e}),C=Kn($,u,Nn(t)),x=Kn($,c,g).some((L,_)=>L<(C[_]??L)),P=nt.some(L=>{const _=e[L],E=t[L];return typeof _=="number"&&typeof E=="number"&&_!==E});return x||P?h(e):e}function bd(e,t,n,r){const o=t.slice(0,e).reduce((i,a)=>i+a,0),s=n.slice(e+1,t.length-1).reduce((i,a)=>i+a,0);return Math.max(xn,r-o-s-xn)}function xd(e,t){return Math.random()*(t-e)+e}function Cd(e){return Object.fromEntries(nt.map(t=>[t,typeof e[t]=="number"?e[t]:Fi[t]]))}function xr(e,t,n=0){return Object.fromEntries(t.map(r=>[r,typeof e[r]=="number"?e[r]:n]))}function Sd(e,t,n,r,o,s){return e.slice(0,t).map((i,a)=>{const c=Zt[a],u=Jt[a],d=Qt[a];return{key:i,textPrefix:id[i],widthKey:nt[a],width:n[nt[a]],paddingLeftKey:c,paddingRightKey:u,paddingBottomKey:d,paddingLeft:r[c],paddingRight:o[u],paddingBottom:s[d]}})}function wd({settings:e,content:t,isEditor:n,isPreviewMode:r,activeEvent:o,layoutId:s,onUpdateSettings:i}){const{prefix:a}=T.useScopedStyles(),c=!!(n&&r),{columns:u,type:d,wrapperWidth:$,entriesCount:h,cellMinHeight:f,dividerWidth:m,showVisibility:g,cut:C,showCut:y,cutCellMinHeight:x,cutLabel:P,imageSize:L,imageOnHover:_,entryHoverEffect:E,rowPaddingTop:v,rowPaddingBottom:S,rowPaddingTopB:F,columnsOrder:V,textPaddingLR:A,textColor:O,textFontFamily:D,textFontSettings:j,textFontSize:U,textLineHeight:w,textLetterSpacing:N,textWordSpacing:k,textTextAppearance:M,backgroundColor:R,dividerColor:B,textHoverColor:te,backgroundHoverColor:ue,dividerHoverColor:ie}=e,[me,H]=p.useState(void 0),[Q,G]=p.useState(null),Y=_==="On",oe=(C??0)>0,W=d==="B",ne=p.useRef(null),[I,b]=p.useState(bn),z=Wi(I),q=Math.max(0,(($??0)-z)/2),J=Math.min(A??0,q),se=Math.max(J,ln),le=(($??0)+z)/2;p.useLayoutEffect(()=>{if(!n){b(bn);return}const ge=()=>{b(dd(ne.current))};ge();const xe=ne.current;if(!xe)return;const Se=new ResizeObserver(ge);Se.observe(xe);let Re=xe;for(;Re&&!Re.style.getPropertyValue("--cntrl-article-width");)Re=Re.parentElement;return Re&&Se.observe(Re),()=>Se.disconnect()},[n,s]),p.useEffect(()=>{H(void 0)},[C,y,t,h]);const ce=T.buildColorVars(a,{textColor:O,backgroundColor:R,dividerColor:B,textHoverColor:te,backgroundHoverColor:ue,dividerHoverColor:ie},ld,cd),he=o&&o!=="default"?`${a}-state-${o}`:"",ee=`${E==="Default"?`${a}-entry-hover-default`:E==="Blinds"?`${a}-entry-hover-blinds`:""} ${he}`.trim(),Z=(g==null?void 0:g[0])??!1,de=(g==null?void 0:g[1])??!1,re=p.useRef(e),pe=p.useRef(s);p.useEffect(()=>{if(!i||!n){re.current=e,pe.current=s;return}if(pe.current!==s){re.current=e,pe.current=s;return}const ge=re.current,xe=vd(e,ge,{designWidth:I});re.current=e,xe!==e&&i(xe)},[e,i,n,s,I]);const ve=p.useMemo(()=>Cd(e),[e.AColumnWidth,e.BColumnWidth,e.CColumnWidth,e.DColumnWidth,e.EColumnWidth]),Pe=p.useMemo(()=>xr(e,Zt),[e.AColumnPaddingLeft,e.BColumnPaddingLeft,e.CColumnPaddingLeft,e.DColumnPaddingLeft,e.EColumnPaddingLeft]),Ke=p.useMemo(()=>xr(e,Jt),[e.AColumnPaddingRight,e.BColumnPaddingRight,e.CColumnPaddingRight,e.DColumnPaddingRight,e.EColumnPaddingRight]),Ge=p.useMemo(()=>xr(e,Qt),[e.AColumnPaddingBottom,e.BColumnPaddingBottom,e.CColumnPaddingBottom,e.DColumnPaddingBottom,e.EColumnPaddingBottom]),$e=p.useMemo(()=>Array.isArray(V)&&V.length>0?V:[...Pt],[V]),Ae=p.useMemo(()=>Sd($e,u,ve,Pe,Ke,Ge),[$e,u,ve,Pe,Ke,Ge]),Me=jn(e),Ie=p.useMemo(()=>nt.slice(0,u).map(ge=>ve[ge]),[u,ve]),Ve=p.useMemo(()=>ro(u,Me,ve),[u,Me,ve]),ye=p.useMemo(()=>Kn(u,Me,ve),[u,Me,ve]),ke=p.useMemo(()=>Ae.map((ge,xe)=>ki(ye[xe]??0,ge.paddingLeft,ge.paddingRight)),[Ae,ye]),He=p.useMemo(()=>{const ge=h===0?1/0:h;return(t??[]).slice(0,ge).map((Se,Re)=>({id:Re,cells:Object.fromEntries(Pt.map(Xe=>[Xe,Se[Xe]??""])),image:Se.image,link:Se.link}))},[t,h]),Oe=oe?me??C:He.length,De=p.useMemo(()=>oe?He.slice(0,Oe):He,[He,oe,Oe]),Qe=oe&&Oe<He.length,Ct=De.length>1||Qe,lt=[Z?`${a}-divider-top`:"",de||Ct?`${a}-divider-bottom`:""].filter(Boolean).join(" "),dr=()=>{const ge=me??C;if(!y){H(He.length);return}H(Math.min(ge+y,He.length))},Ee=ge=>T.scalingValue(ge,n??!1),An=W?F??0:v??0,rn=S??0,on=f??0,ur=W?"rowPaddingTopB":"rowPaddingTop",be=Ae[0],Ye=Ae[Ae.length-1],ze=ke[0],Ne=ke[ke.length-1],St=be&&ze?Math.max(ze.paddingLeft,ln):0,oo=Ye&&Ne?Math.max(Ne.paddingRight,ln):0,Ni=Me,io=ge=>{const xe=ne.current;if(!xe)return{x:0,y:0};const Se=xe.getBoundingClientRect();return{x:ge.clientX-Se.left+No,y:ge.clientY-Se.top+No}},Hi=(ge,xe)=>{if(!Y)return;const Se=ge.image;if(!(Se!=null&&Se.url)){G(null);return}const{x:Re,y:Xe}=io(xe),ct=(L==null?void 0:L.min)??80,Te=(L==null?void 0:L.max)??320,Be=(Q==null?void 0:Q.rowId)===ge.id?Q.widthPx:xd(ct,Te);G({rowId:ge.id,url:Se.url,objectFit:Se.objectFit??"cover",widthPx:Be,x:Re,y:Xe})},Oi=ge=>{if(!Y||!Q)return;const{x:xe,y:Se}=io(ge);G(Re=>!Re||Re.x===xe&&Re.y===Se?Re:{...Re,x:xe,y:Se})},Bi=()=>{G(null)},ao=p.useMemo(()=>!W&&eo.some(ge=>{const xe=ge.charAt(0),Se=e[`${ge}VerticalAlign`];return Ii(Se,e,xe)}),[W,e,e.AColumnVerticalAlign,e.BColumnVerticalAlign,e.CColumnVerticalAlign,e.DColumnVerticalAlign,e.EColumnVerticalAlign]);return p.useLayoutEffect(()=>{var ct;const ge=ne.current;if(!ge)return;const xe=()=>{ge.querySelectorAll("[data-list-col]").forEach(Te=>{Te.style.transform="";const Be=Te.querySelector(`.${a}-list-col`);Be&&(Be.style.minHeight="",Be.style.height="");const ot=Te.querySelector(`.${a}-list-col-title`);ot&&(ot.style.transform="")})};if(W||!ao){xe();return}const Se=()=>{ge.querySelectorAll("[data-list-row]").forEach(Te=>{const Be=Array.from(Te.querySelectorAll("[data-list-col]"));Be.forEach(Le=>{Le.style.transform="";const Ze=Le.querySelector(`.${a}-list-col`);Ze&&(Ze.style.minHeight="",Ze.style.height="");const Ue=Le.querySelector(`.${a}-list-col-title`);Ue&&(Ue.style.transform="")}),rd(Te,Be,`${a}-list-col`),Te.offsetHeight;const ot=Te.getBoundingClientRect().top,wt=`${a}-baseline-probe`,Wt=new Map,an=Be.map(Le=>{const Ze=Le.querySelector(`.${a}-list-col-title`),Ue={el:Le,titleEl:Ze,letter:Le.getAttribute("data-col-letter")??"",kind:Le.getAttribute("data-valign")??"top",anchor:Le.getAttribute("data-valign-anchor")};return Wt.set(Ue.letter,Ue),Ue}),sn=new Map,Rn=(Le,Ze)=>{const Ue=sn.get(Le.letter);if(Ue!==void 0)return Ue;const so=Le.anchor?Wt.get(Le.anchor):void 0;if(Le.kind!=="baseline"||!so||Ze.has(Le.letter)){const co=br(Le,ot,`${a}-list-col`,wt);return sn.set(Le.letter,co),co}Ze.add(Le.letter);const Vi=Rn(so,Ze);Ze.delete(Le.letter);const Di=br(Le,ot,`${a}-list-col`,wt),zi=Vi-Di;od(Le.titleEl,zi);const lo=br(Le,ot,`${a}-list-col`,wt);return sn.set(Le.letter,lo),lo};an.forEach(Le=>Rn(Le,new Set))})};Se();const Re=new ResizeObserver(()=>Se());Re.observe(ge);let Xe=!1;return typeof document<"u"&&((ct=document.fonts)!=null&&ct.ready)&&document.fonts.ready.then(()=>{Xe||Se()}),()=>{Xe=!0,Re.disconnect(),xe()}},[ao,W,e,t,I,De,ye]),l.jsxs(l.Fragment,{children:[l.jsx("style",{dangerouslySetInnerHTML:{__html:Yc(a)}}),l.jsx("div",{style:ce,children:l.jsxs("div",{ref:ne,className:`${a}-wrapper ${ee}${lt?` ${lt}`:""}${W?` ${a}-type-b`:""}`.trim(),style:{width:T.scalingValue($??0,n)},onMouseMove:Y?Oi:void 0,onMouseLeave:Y?Bi:void 0,children:[l.jsxs("div",{style:{width:"100%"},children:[De.map((ge,xe)=>{var ct;const Se=(((ct=ge.link)==null?void 0:ct.length)??0)>0,Re=Se?"a":"div",Xe=qc(xe,De.length,Z,de,Qe,m??0,n??!1);return l.jsxs(Re,{className:`${a}-list-item${Se?` ${a}-list-item-has-link`:""}`,...Se?{href:ge.link,target:"_blank"}:{},style:Xe,onMouseEnter:Y?Te=>Hi(ge,Te):void 0,children:[(An>0||c)&&l.jsx("div",{...c?{"data-controls":ur,"data-controls-axis":"y","data-controls-min":"0"}:{},className:`${a}-row-padding-handle`,style:{height:Ee(An)}}),l.jsx("div",{className:`${a}-list-cols-row${W?"":` ${a}-list-cols-row-h`}`,...W?{}:{"data-list-row":""},style:W?void 0:{minHeight:Ee(on)},children:Ae.map((Te,Be)=>{const ot=Be===Ae.length-1,wt=ke[Be],Wt=Te.paddingBottom,an=Uc(ge.cells[Te.key]),sn=W&&an&&(Wt>0||c),Rn=W?{minHeight:Ee(on)}:ot?{}:{width:Ee(ye[Be])},Le=W?{paddingLeft:Ee(J),paddingRight:Ee(J)}:{paddingLeft:Ee(wt.paddingLeft),paddingRight:Ee(wt.paddingRight)},Ze=Te.textPrefix.charAt(0),Ue=W?{kind:"top"}:Qc(e[`${Te.textPrefix}VerticalAlign`],e,Ze);return l.jsxs("div",{...W?{}:{"data-list-col":"","data-col-letter":Ze,"data-valign":Ue.kind,...Ue.kind==="baseline"?{"data-valign-anchor":Ue.anchorLetter}:{}},children:[l.jsx("div",{className:`${a}-list-col${ot?` ${a}-list-col-last`:""}`,style:{...Le,...Rn},"data-test":Te.width,children:l.jsx("span",{className:Oo(e,Te.textPrefix,`${a}-list-col-title`,`${a}-text-tight-leading`),style:{...Ho(Zn(e,Te.textPrefix),n),...Bo(e,Te.textPrefix,a,n),...W?{}:td(Ue.kind)},children:ge.cells[Te.key]??null})}),sn&&l.jsx("div",{...c?{"data-controls":Te.paddingBottomKey,"data-controls-axis":"y","data-controls-min":"0"}:{},className:`${a}-row-padding-handle`,style:{height:Ee(Wt)}})]},Te.key)})}),!W&&(rn>0||c)&&l.jsx("div",{...c?{"data-controls":"rowPaddingBottom","data-controls-axis":"y","data-controls-min":"0"}:{},className:`${a}-row-padding-handle`,style:{height:Ee(rn)}})]},ge.id)}),Qe&&l.jsx("button",{type:"button",className:`${a}-cut-item`,style:{minHeight:Ee(x??0),...Gc(de,m??0,n??!1)},onClick:dr,children:l.jsx("div",{className:`${a}-list-cols-row`,style:W?{paddingLeft:Ee(J),paddingRight:Ee(J)}:{justifyContent:"center"},children:l.jsx("span",{className:Oo(e,vt,`${a}-cut-label`,`${a}-text-tight-leading`),style:{...Ho(Zn(e,vt),n),...Bo(e,vt,a,n)},children:P})})})]}),c&&!W&&be&&Ye&&l.jsxs("div",{style:{position:"absolute",inset:0,pointerEvents:"none"},children:[l.jsx("div",{"data-controls":be.paddingLeftKey,"data-controls-axis":"x","data-controls-variant":"column-padding","data-controls-min":"0","data-controls-max-fraction":String(ye[0]-((ze==null?void 0:ze.paddingRight)??0)),"data-controls-static-handle":"",className:`${a}-padding-control-handle`,style:{position:"absolute",top:0,left:0,width:Ee(St),height:"100%",pointerEvents:"auto",zIndex:2}}),l.jsx("div",{"data-controls":Ye.paddingRightKey,"data-controls-axis":"x","data-controls-variant":"column-padding","data-controls-reverse":"","data-controls-min":"0","data-controls-max-fraction":String(ye[Ae.length-1]-((Ne==null?void 0:Ne.paddingLeft)??0)),"data-controls-static-handle":"",className:`${a}-padding-control-handle`,style:{position:"absolute",top:0,left:Ee(Ni-oo),width:Ee(oo),height:"100%",pointerEvents:"auto",zIndex:2}})]},"column-edge-padding-handles"),c&&!W&&Ae.slice(0,-1).map((ge,xe)=>{const Se=Ae[xe+1],Re=bd(xe,Ve,Ie,Me),Xe=Ve.slice(0,xe+1).reduce((Wt,an)=>Wt+an,0),ct=ke[xe],Te=ke[xe+1],Be=Math.max(ct.paddingRight,ln),ot=Math.max(Te.paddingLeft,ln),wt=Xe-Vo/2;return l.jsxs("div",{style:{position:"absolute",inset:0,pointerEvents:"none"},children:[l.jsx("div",{"data-controls":ge.paddingRightKey,"data-controls-axis":"x","data-controls-variant":"column-padding","data-controls-reverse":"","data-controls-min":"0","data-controls-max-fraction":String(ye[xe]-ct.paddingLeft),"data-controls-static-handle":"",className:`${a}-padding-control-handle`,style:{position:"absolute",top:0,left:Ee(Xe-Be),width:Ee(Be),height:"100%",pointerEvents:"auto",zIndex:2}}),l.jsx("div",{"data-controls":ge.widthKey,"data-controls-axis":"x","data-controls-min":String(no),"data-controls-max-fraction":String(Re),"data-controls-variant":"column-width",className:`${a}-col-resize-handle`,style:{position:"absolute",top:"0px",left:Ee(wt),width:Ee(Vo),height:"calc(100%)",pointerEvents:"auto",zIndex:4}}),l.jsx("div",{"data-controls":Se.paddingLeftKey,"data-controls-axis":"x","data-controls-variant":"column-padding","data-controls-min":"0","data-controls-max-fraction":String(ye[xe+1]-Te.paddingRight),"data-controls-static-handle":"",className:`${a}-padding-control-handle`,style:{position:"absolute",top:0,left:Ee(Xe),width:Ee(ot),height:"100%",pointerEvents:"auto",zIndex:2}})]},`${ge.widthKey}-junction`)}),c&&W&&l.jsxs("div",{style:{position:"absolute",inset:0,pointerEvents:"none"},children:[l.jsx("div",{"data-controls":"textPaddingLR","data-controls-paired":"","data-controls-axis":"x","data-controls-min":"0","data-controls-max-fraction":String(le),"data-controls-static-handle":"",className:`${a}-text-padding-lr-handle`,style:{position:"absolute",top:0,left:0,width:Ee(se),height:"100%",pointerEvents:"auto",zIndex:2}}),l.jsx("div",{"data-controls":"textPaddingLR","data-controls-paired":"","data-controls-axis":"x","data-controls-reverse":"","data-controls-min":"0","data-controls-max-fraction":String(le),"data-controls-static-handle":"",className:`${a}-text-padding-lr-handle`,style:{position:"absolute",top:0,left:Ee(Math.max(se,Me-se)),width:Ee(se),height:"100%",pointerEvents:"auto",zIndex:2}})]},"text-padding-lr-handles"),Y&&Q&&l.jsx("img",{className:`${a}-hover-image`,src:Q.url,alt:"",style:{width:zn(Q.widthPx),objectFit:Q.objectFit,left:Q.x,top:Q.y}})]})})]})}const $d=`import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';\r
4666
- import { CommonComponentProps } from '../props';\r
4667
- import { buildColorVars, scalingValue, useScopedStyles } from '../utils/index';\r
4668
- import { omitTextColors, TextStyles, textStylesToCss } from '../utils/textStylesToCss';\r
4669
- \r
4670
- type ListFontSettings = { fontWeight: number; fontStyle: string };\r
4671
- \r
4672
- type ListColumnPrefix = 'AColumn' | 'BColumn' | 'CColumn' | 'DColumn' | 'EColumn';\r
4673
- \r
4674
- type ListColumnTextStyleOverrides = {\r
4675
- AColumnVerticalAlign?: string;\r
4676
- AColumnTextFontFamily?: string;\r
4677
- AColumnTextFontSettings?: ListFontSettings;\r
4678
- AColumnTextFontSize?: number;\r
4679
- AColumnTextLineHeight?: number;\r
4680
- AColumnTextLetterSpacing?: number;\r
4681
- AColumnTextWordSpacing?: number;\r
4682
- AColumnTextTextAppearance?: TextStyles['textAppearance'];\r
4683
- BColumnVerticalAlign?: string;\r
4684
- BColumnTextFontFamily?: string;\r
4685
- BColumnTextFontSettings?: ListFontSettings;\r
4686
- BColumnTextFontSize?: number;\r
4687
- BColumnTextLineHeight?: number;\r
4688
- BColumnTextLetterSpacing?: number;\r
4689
- BColumnTextWordSpacing?: number;\r
4690
- BColumnTextTextAppearance?: TextStyles['textAppearance'];\r
4691
- CColumnVerticalAlign?: string;\r
4692
- CColumnTextFontFamily?: string;\r
4693
- CColumnTextFontSettings?: ListFontSettings;\r
4694
- CColumnTextFontSize?: number;\r
4695
- CColumnTextLineHeight?: number;\r
4696
- CColumnTextLetterSpacing?: number;\r
4697
- CColumnTextWordSpacing?: number;\r
4698
- CColumnTextTextAppearance?: TextStyles['textAppearance'];\r
4699
- DColumnVerticalAlign?: string;\r
4700
- DColumnTextFontFamily?: string;\r
4701
- DColumnTextFontSettings?: ListFontSettings;\r
4702
- DColumnTextFontSize?: number;\r
4703
- DColumnTextLineHeight?: number;\r
4704
- DColumnTextLetterSpacing?: number;\r
4705
- DColumnTextWordSpacing?: number;\r
4706
- DColumnTextTextAppearance?: TextStyles['textAppearance'];\r
4707
- EColumnVerticalAlign?: string;\r
4708
- EColumnTextFontFamily?: string;\r
4709
- EColumnTextFontSettings?: ListFontSettings;\r
4710
- EColumnTextFontSize?: number;\r
4711
- EColumnTextLineHeight?: number;\r
4712
- EColumnTextLetterSpacing?: number;\r
4713
- EColumnTextWordSpacing?: number;\r
4714
- EColumnTextTextAppearance?: TextStyles['textAppearance'];\r
4715
- cutLabelTextFontFamily?: string;\r
4716
- cutLabelTextFontSettings?: ListFontSettings;\r
4717
- cutLabelTextFontSize?: number;\r
4718
- cutLabelTextLineHeight?: number;\r
4719
- cutLabelTextLetterSpacing?: number;\r
4720
- cutLabelTextWordSpacing?: number;\r
4721
- cutLabelTextTextAppearance?: TextStyles['textAppearance'];\r
4722
- };\r
4723
- \r
4724
- export type ListColumnVerticalAlignKey = \`\${ListColumnPrefix}VerticalAlign\`;\r
4725
- \r
4726
- type ListColumnVerticalAlignUpdates = {\r
4727
- AColumnVerticalAlign?: string;\r
4728
- BColumnVerticalAlign?: string;\r
4729
- CColumnVerticalAlign?: string;\r
4730
- DColumnVerticalAlign?: string;\r
4731
- EColumnVerticalAlign?: string;\r
4732
- };\r
4733
- \r
4734
- type ListColumnTextStyleSyncUpdates = {\r
4735
- AColumnTextFontFamily?: string;\r
4736
- AColumnTextFontSettings?: ListFontSettings;\r
4737
- AColumnTextFontSize?: number;\r
4738
- AColumnTextLineHeight?: number;\r
4739
- AColumnTextLetterSpacing?: number;\r
4740
- AColumnTextWordSpacing?: number;\r
4741
- AColumnTextTextAppearance?: TextStyles['textAppearance'];\r
4742
- BColumnTextFontFamily?: string;\r
4743
- BColumnTextFontSettings?: ListFontSettings;\r
4744
- BColumnTextFontSize?: number;\r
4745
- BColumnTextLineHeight?: number;\r
4746
- BColumnTextLetterSpacing?: number;\r
4747
- BColumnTextWordSpacing?: number;\r
4748
- BColumnTextTextAppearance?: TextStyles['textAppearance'];\r
4749
- CColumnTextFontFamily?: string;\r
4750
- CColumnTextFontSettings?: ListFontSettings;\r
4751
- CColumnTextFontSize?: number;\r
4752
- CColumnTextLineHeight?: number;\r
4753
- CColumnTextLetterSpacing?: number;\r
4754
- CColumnTextWordSpacing?: number;\r
4755
- CColumnTextTextAppearance?: TextStyles['textAppearance'];\r
4756
- DColumnTextFontFamily?: string;\r
4757
- DColumnTextFontSettings?: ListFontSettings;\r
4758
- DColumnTextFontSize?: number;\r
4759
- DColumnTextLineHeight?: number;\r
4760
- DColumnTextLetterSpacing?: number;\r
4761
- DColumnTextWordSpacing?: number;\r
4762
- DColumnTextTextAppearance?: TextStyles['textAppearance'];\r
4763
- EColumnTextFontFamily?: string;\r
4764
- EColumnTextFontSettings?: ListFontSettings;\r
4765
- EColumnTextFontSize?: number;\r
4766
- EColumnTextLineHeight?: number;\r
4767
- EColumnTextLetterSpacing?: number;\r
4768
- EColumnTextWordSpacing?: number;\r
4769
- EColumnTextTextAppearance?: TextStyles['textAppearance'];\r
4770
- cutLabelTextFontFamily?: string;\r
4771
- cutLabelTextFontSettings?: ListFontSettings;\r
4772
- cutLabelTextFontSize?: number;\r
4773
- cutLabelTextLineHeight?: number;\r
4774
- cutLabelTextLetterSpacing?: number;\r
4775
- cutLabelTextWordSpacing?: number;\r
4776
- cutLabelTextTextAppearance?: TextStyles['textAppearance'];\r
4777
- };\r
4778
- \r
4779
- export type ListSettings = {\r
4780
- columns: number;\r
4781
- type: 'A' | 'B';\r
4782
- wrapperWidth: number;\r
4783
- entriesCount: number;\r
4784
- cellMinHeight: number;\r
4785
- imageOnHover: 'On' | 'Off';\r
4786
- imageSize?: { min: number; max: number };\r
4787
- dividerWidth: number;\r
4788
- showVisibility: boolean[];\r
4789
- cut: number;\r
4790
- showCut: number;\r
4791
- cutCellMinHeight: number;\r
4792
- cutLabel: string;\r
4793
- entryHoverEffect: 'None' | 'Default' | 'Blinds';\r
4794
- rowPaddingTop: number;\r
4795
- rowPaddingBottom: number;\r
4796
- rowPaddingTopB: number;\r
4797
- AColumnWidth: number;\r
4798
- AColumnPaddingLeft: number;\r
4799
- AColumnPaddingRight: number;\r
4800
- AColumnPaddingBottom: number;\r
4801
- BColumnWidth: number;\r
4802
- BColumnPaddingLeft: number;\r
4803
- BColumnPaddingRight: number;\r
4804
- BColumnPaddingBottom: number;\r
4805
- CColumnWidth: number;\r
4806
- CColumnPaddingLeft: number;\r
4807
- CColumnPaddingRight: number;\r
4808
- CColumnPaddingBottom: number;\r
4809
- DColumnWidth: number;\r
4810
- DColumnPaddingLeft: number;\r
4811
- DColumnPaddingRight: number;\r
4812
- DColumnPaddingBottom: number;\r
4813
- EColumnWidth: number;\r
4814
- EColumnPaddingLeft: number;\r
4815
- EColumnPaddingRight: number;\r
4816
- EColumnPaddingBottom: number;\r
4817
- columnsOrder?: string[];\r
4818
- textPaddingLR?: number;\r
4819
- textColor: string;\r
4820
- textFontFamily: string;\r
4821
- textFontSettings?: ListFontSettings;\r
4822
- textFontSize?: number;\r
4823
- textLineHeight?: number;\r
4824
- textLetterSpacing?: number;\r
4825
- textWordSpacing?: number;\r
4826
- textTextAppearance?: TextStyles['textAppearance'];\r
4827
- backgroundColor: string;\r
4828
- dividerColor: string;\r
4829
- textHoverColor: string;\r
4830
- backgroundHoverColor: string;\r
4831
- dividerHoverColor: string;\r
4832
- } & ListColumnTextStyleOverrides;\r
4833
- \r
4834
- type ListContentItem = {\r
4835
- AColumn?: string;\r
4836
- BColumnWidth?: string;\r
4837
- CColumnWidth?: string;\r
4838
- DColumnWidth?: string;\r
4839
- EColumnWidth?: string;\r
4840
- image?: {\r
4841
- objectFit?: 'cover' | 'contain';\r
4842
- url: string;\r
4843
- name: string;\r
4844
- };\r
4845
- link?: string;\r
4846
- };\r
4847
- \r
4848
- type ListItemRow = {\r
4849
- id: string | number;\r
4850
- cells: Record<string, React.ReactNode>;\r
4851
- image?: ListContentItem['image'];\r
4852
- link?: string;\r
4853
- };\r
4854
- \r
4855
- type HoverImageState = {\r
4856
- rowId: string | number;\r
4857
- url: string;\r
4858
- objectFit: 'cover' | 'contain';\r
4859
- widthPx: number;\r
4860
- x: number;\r
4861
- y: number;\r
4862
- };\r
4863
- \r
4864
- type ListProps = {\r
4865
- layoutId?: string;\r
4866
- settings: ListSettings;\r
4867
- content?: ListContentItem[];\r
4868
- isEditor?: boolean;\r
4869
- isPreviewMode?: boolean;\r
4870
- activeEvent: string | undefined;\r
4871
- onUpdateSettings?: (settings: ListSettings) => void;\r
4872
- } & CommonComponentProps;\r
4873
- \r
4874
- function sv(px: number): string {\r
4875
- return \`calc(var(--cntrl-article-width, 100vw) * \${px / 1440})\`;\r
4876
- }\r
4877
- \r
4878
- function hasListColumnText(value: React.ReactNode): boolean {\r
4879
- return String(value ?? '').trim().length > 0;\r
4880
- }\r
4881
- \r
4882
- function getEntryDividerWidths(\r
4883
- rowIdx: number,\r
4884
- rowCount: number,\r
4885
- showDividerTop: boolean,\r
4886
- showDividerBottom: boolean,\r
4887
- hasCutItem: boolean,\r
4888
- dividerWidth: number,\r
4889
- isEditor: boolean,\r
4890
- ): { borderTopWidth: string; borderBottomWidth: string } {\r
4891
- const scaledDividerWidth = scalingValue(dividerWidth, isEditor);\r
4892
- const none = scalingValue(0, isEditor);\r
4893
- \r
4894
- const isFirst = rowIdx === 0;\r
4895
- const isLastEntry = rowIdx === rowCount - 1 && !hasCutItem;\r
4896
- \r
4897
- const borderTopWidth = isFirst && showDividerTop ? scaledDividerWidth : none;\r
4898
- const borderBottomWidth = !isLastEntry || showDividerBottom ? scaledDividerWidth : none;\r
4899
- \r
4900
- return { borderTopWidth, borderBottomWidth };\r
4901
- }\r
4902
- \r
4903
- function getCutItemDividerWidths(\r
4904
- showDividerBottom: boolean,\r
4905
- dividerWidth: number,\r
4906
- isEditor: boolean,\r
4907
- ): { borderTopWidth: string; borderBottomWidth: string } {\r
4908
- const scaledDividerWidth = scalingValue(dividerWidth, isEditor);\r
4909
- const none = scalingValue(0, isEditor);\r
4910
- \r
4911
- return {\r
4912
- borderTopWidth: none,\r
4913
- borderBottomWidth: showDividerBottom ? scaledDividerWidth : none,\r
4914
- };\r
4915
- }\r
4916
- \r
4917
- const HOVER_IMAGE_CURSOR_OFFSET = 10;\r
4918
- \r
4919
- function getCSS(P: string): string {\r
4920
- return \`\r
4921
- .\${P}-wrapper {\r
4922
- display: grid;\r
4923
- align-items: start;\r
4924
- min-height: \${sv(48)};\r
4925
- position: relative;\r
4926
- overflow: visible;\r
4927
- box-sizing: border-box;\r
4928
- }\r
4929
- \r
4930
- .\${P}-hover-image {\r
4931
- position: absolute;\r
4932
- left: 0;\r
4933
- top: 0;\r
4934
- z-index: 10;\r
4935
- pointer-events: none;\r
4936
- display: block;\r
4937
- height: auto;\r
4938
- }\r
4939
- \r
4940
- .\${P}-list-item {\r
4941
- display: flex;\r
4942
- flex-direction: column;\r
4943
- align-items: stretch;\r
4944
- width: 100%;\r
4945
- overflow: visible;\r
4946
- position: relative;\r
4947
- box-sizing: content-box;\r
4948
- user-select: none;\r
4949
- background: var(--\${P}-background-color);\r
4950
- }\r
4951
- \r
4952
- .\${P}-wrapper.\${P}-divider-top .\${P}-list-item {\r
4953
- border-top-style: solid;\r
4954
- border-top-color: var(--\${P}-divider-color);\r
4955
- }\r
4956
- \r
4957
- .\${P}-wrapper.\${P}-divider-bottom .\${P}-list-item {\r
4958
- border-bottom-style: solid;\r
4959
- border-bottom-color: var(--\${P}-divider-color);\r
4960
- }\r
4961
- \r
4962
- .\${P}-list-cols-row {\r
4963
- display: flex;\r
4964
- align-items: start;\r
4965
- width: 100%;\r
4966
- box-sizing: border-box;\r
4967
- }\r
4968
- \r
4969
- .\${P}-list-cols-row-h {\r
4970
- align-items: stretch;\r
4971
- }\r
4972
- \r
4973
- .\${P}-list-cols-row-h [data-list-col] {\r
4974
- display: grid;\r
4975
- grid-template-rows: minmax(0, 1fr);\r
4976
- align-self: stretch;\r
4977
- min-height: min-content;\r
4978
- }\r
4979
- \r
4980
- .\${P}-list-cols-row-h .\${P}-list-col {\r
4981
- display: flex;\r
4982
- flex-direction: column;\r
4983
- align-items: flex-start;\r
4984
- justify-content: flex-start;\r
4985
- width: 100%;\r
4986
- min-height: 0;\r
4987
- }\r
4988
- \r
4989
- .\${P}-list-cols-row-h .\${P}-list-col-title {\r
4990
- display: block;\r
4991
- flex: 0 0 auto;\r
4992
- align-self: stretch;\r
4993
- }\r
4994
- \r
4995
- .\${P}-text-tight-leading {\r
4996
- display: block;\r
4997
- flex-shrink: 0;\r
4998
- padding-top: var(--\${P}-title-leading-gap, 0);\r
4999
- padding-bottom: var(--\${P}-title-leading-gap, 0);\r
5000
- }\r
5001
- \r
5002
- .\${P}-wrapper.\${P}-type-b .\${P}-list-cols-row {\r
5003
- flex-direction: column;\r
5004
- align-items: stretch;\r
5005
- }\r
5006
- \r
5007
- .\${P}-wrapper.\${P}-type-b .\${P}-list-col {\r
5008
- width: 100%;\r
5009
- min-width: 0;\r
5010
- flex-direction: column;\r
5011
- justify-content: flex-start;\r
5012
- align-items: flex-start;\r
5013
- min-height: min-content;\r
5014
- }\r
5015
- \r
5016
- .\${P}-wrapper.\${P}-type-b .\${P}-list-col-title {\r
5017
- display: block;\r
5018
- flex: 0 0 auto;\r
5019
- align-self: stretch;\r
5020
- text-align: center;\r
5021
- }\r
5022
- \r
5023
- .\${P}-wrapper.\${P}-type-b .\${P}-cut-item .\${P}-list-cols-row {\r
5024
- flex-direction: row;\r
5025
- align-items: center;\r
5026
- justify-content: center;\r
5027
- }\r
5028
- \r
5029
- .\${P}-wrapper.\${P}-type-b .\${P}-cut-label {\r
5030
- text-align: center;\r
5031
- width: 100%;\r
5032
- box-sizing: border-box;\r
5033
- }\r
5034
- \r
5035
- .\${P}-wrapper.\${P}-type-b .\${P}-list-col-last {\r
5036
- flex: 0 0 auto;\r
5037
- min-width: 0;\r
5038
- }\r
5039
- \r
5040
- a.\${P}-list-item {\r
5041
- text-decoration: none;\r
5042
- color: inherit;\r
5043
- cursor: pointer;\r
5044
- }\r
5045
- \r
5046
- .\${P}-list-col {\r
5047
- flex-shrink: 0;\r
5048
- overflow: visible;\r
5049
- box-sizing: border-box;\r
5050
- min-width: \${sv(50)};\r
5051
- position: relative;\r
5052
- display: flex;\r
5053
- align-items: flex-start;\r
5054
- }\r
5055
- \r
5056
- .\${P}-list-col-last {\r
5057
- flex: 1 1 auto;\r
5058
- min-width: \${sv(50)};\r
5059
- }\r
5060
- \r
5061
- .\${P}-list-col-title {\r
5062
- color: var(--\${P}-text-color);\r
5063
- white-space: pre-wrap;\r
5064
- overflow-wrap: anywhere;\r
5065
- word-break: break-word;\r
5066
- flex: 1;\r
5067
- min-width: 0;\r
5068
- width: 100%;\r
5069
- box-sizing: border-box;\r
5070
- }\r
5071
- \r
5072
- .\${P}-baseline-probe {\r
5073
- display: inline-block;\r
5074
- width: 0;\r
5075
- height: 0;\r
5076
- overflow: hidden;\r
5077
- vertical-align: baseline;\r
5078
- }\r
5079
- \r
5080
- .\${P}-col-resize-handle,\r
5081
- .\${P}-padding-control-handle {\r
5082
- background: transparent;\r
5083
- }\r
5084
- \r
5085
- .\${P}-row-padding-handle {\r
5086
- position: relative;\r
5087
- z-index: 2;\r
5088
- width: 100%;\r
5089
- flex-shrink: 0;\r
5090
- background: transparent;\r
5091
- }\r
5092
- \r
5093
- .\${P}-row-padding-handle::before {\r
5094
- content: "";\r
5095
- position: absolute;\r
5096
- top: 0;\r
5097
- left: 0;\r
5098
- width: 100%;\r
5099
- height: 100%;\r
5100
- min-height: 20px;\r
5101
- pointer-events: auto;\r
5102
- z-index: 10;\r
5103
- }\r
5104
- \r
5105
- .\${P}-col-resize-handle::after {\r
5106
- content: '';\r
5107
- position: absolute;\r
5108
- top: 0;\r
5109
- left: 50%;\r
5110
- transform: translateX(-50%);\r
5111
- width: 2px;\r
5112
- height: 100%;\r
5113
- background: #FF5C02;\r
5114
- pointer-events: none;\r
5115
- }\r
5116
- \r
5117
- .\${P}-wrapper.\${P}-type-b .\${P}-col-resize-handle::after {\r
5118
- top: 50%;\r
5119
- left: 0;\r
5120
- transform: translateY(-50%);\r
5121
- width: 100%;\r
5122
- height: 2px;\r
5123
- }\r
5124
- \r
5125
- .\${P}-padding-control-handle::after {\r
5126
- content: '';\r
5127
- position: absolute;\r
5128
- top: 50%;\r
5129
- left: 50%;\r
5130
- transform: translate(-50%, -50%);\r
5131
- width: 4px;\r
5132
- height: 12px;\r
5133
- background: #FF5C02;\r
5134
- border: 1px solid #FFFFFF;\r
5135
- border-radius: 5px;\r
5136
- pointer-events: none;\r
5137
- box-sizing: border-box;\r
5138
- }\r
5139
- \r
5140
- .\${P}-wrapper.\${P}-type-b .\${P}-padding-control-handle::after {\r
5141
- width: 12px;\r
5142
- height: 4px;\r
5143
- }\r
5144
- \r
5145
- .\${P}-text-padding-lr-handle {\r
5146
- background: transparent;\r
5147
- }\r
5148
- \r
5149
- .\${P}-text-padding-lr-handle::after {\r
5150
- content: '';\r
5151
- position: absolute;\r
5152
- top: 50%;\r
5153
- left: 50%;\r
5154
- transform: translate(-50%, -50%);\r
5155
- width: 4px;\r
5156
- height: 12px;\r
5157
- background: #FF5C02;\r
5158
- border: 1px solid #FFFFFF;\r
5159
- border-radius: 5px;\r
5160
- pointer-events: none;\r
5161
- box-sizing: border-box;\r
5162
- }\r
5163
- \r
5164
- .\${P}-wrapper.\${P}-entry-hover-default .\${P}-list-item-has-link,\r
5165
- .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-list-item-has-link,\r
5166
- .\${P}-wrapper.\${P}-entry-hover-default .\${P}-cut-item,\r
5167
- .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-cut-item {\r
5168
- transition: background-color 250ms, border-color 250ms;\r
5169
- }\r
5170
- \r
5171
- .\${P}-wrapper.\${P}-entry-hover-default .\${P}-list-item-has-link .\${P}-list-col-title,\r
5172
- .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-list-item-has-link .\${P}-list-col-title,\r
5173
- .\${P}-wrapper.\${P}-entry-hover-default .\${P}-cut-label,\r
5174
- .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-cut-label {\r
5175
- transition: color 250ms;\r
5176
- }\r
5177
- \r
5178
- .\${P}-wrapper.\${P}-entry-hover-default .\${P}-list-item-has-link:hover,\r
5179
- .\${P}-wrapper.\${P}-entry-hover-default.\${P}-state-hover .\${P}-list-item-has-link,\r
5180
- .\${P}-wrapper.\${P}-entry-hover-default .\${P}-cut-item:hover,\r
5181
- .\${P}-wrapper.\${P}-entry-hover-default.\${P}-state-hover .\${P}-cut-item {\r
5182
- background: var(--\${P}-background-hover-color);\r
5183
- }\r
5184
- \r
5185
- .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-default .\${P}-list-item-has-link:hover,\r
5186
- .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-default .\${P}-list-item:has(+ .\${P}-list-item-has-link:hover),\r
5187
- .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-default .\${P}-list-item:has(+ .\${P}-cut-item:hover),\r
5188
- .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-default.\${P}-state-hover .\${P}-list-item-has-link,\r
5189
- .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-default .\${P}-cut-item:hover,\r
5190
- .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-default.\${P}-state-hover .\${P}-cut-item,\r
5191
- .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-blinds .\${P}-list-item-has-link:hover,\r
5192
- .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-blinds .\${P}-list-item:has(+ .\${P}-list-item-has-link:hover),\r
5193
- .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-blinds .\${P}-list-item:has(+ .\${P}-cut-item:hover),\r
5194
- .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-blinds.\${P}-state-hover .\${P}-list-item-has-link,\r
5195
- .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-blinds .\${P}-cut-item:hover,\r
5196
- .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-blinds.\${P}-state-hover .\${P}-cut-item {\r
5197
- border-bottom-color: var(--\${P}-divider-hover-color);\r
5198
- }\r
5199
- \r
5200
- .\${P}-wrapper.\${P}-divider-top:not(.\${P}-divider-bottom).\${P}-entry-hover-default .\${P}-list-item-has-link:hover:first-child,\r
5201
- .\${P}-wrapper.\${P}-divider-top:not(.\${P}-divider-bottom).\${P}-entry-hover-default.\${P}-state-hover .\${P}-list-item-has-link:first-child,\r
5202
- .\${P}-wrapper.\${P}-divider-top:not(.\${P}-divider-bottom).\${P}-entry-hover-blinds .\${P}-list-item-has-link:hover:first-child,\r
5203
- .\${P}-wrapper.\${P}-divider-top:not(.\${P}-divider-bottom).\${P}-entry-hover-blinds.\${P}-state-hover .\${P}-list-item-has-link:first-child {\r
5204
- border-top-color: var(--\${P}-divider-hover-color);\r
5205
- }\r
5206
- \r
5207
- .\${P}-wrapper.\${P}-divider-top.\${P}-divider-bottom.\${P}-entry-hover-default .\${P}-list-item-has-link:hover:first-child,\r
5208
- .\${P}-wrapper.\${P}-divider-top.\${P}-divider-bottom.\${P}-entry-hover-default.\${P}-state-hover .\${P}-list-item-has-link:first-child,\r
5209
- .\${P}-wrapper.\${P}-divider-top.\${P}-divider-bottom.\${P}-entry-hover-blinds .\${P}-list-item-has-link:hover:first-child,\r
5210
- .\${P}-wrapper.\${P}-divider-top.\${P}-divider-bottom.\${P}-entry-hover-blinds.\${P}-state-hover .\${P}-list-item-has-link:first-child {\r
5211
- border-top-color: var(--\${P}-divider-hover-color);\r
5212
- }\r
5213
- \r
5214
- .\${P}-wrapper.\${P}-entry-hover-default .\${P}-list-item-has-link:hover .\${P}-list-col-title,\r
5215
- .\${P}-wrapper.\${P}-entry-hover-default.\${P}-state-hover .\${P}-list-item-has-link .\${P}-list-col-title,\r
5216
- .\${P}-wrapper.\${P}-entry-hover-default .\${P}-cut-item:hover .\${P}-cut-label,\r
5217
- .\${P}-wrapper.\${P}-entry-hover-default.\${P}-state-hover .\${P}-cut-item .\${P}-cut-label,\r
5218
- .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-list-item-has-link:hover .\${P}-list-col-title,\r
5219
- .\${P}-wrapper.\${P}-entry-hover-blinds.\${P}-state-hover .\${P}-list-item-has-link .\${P}-list-col-title,\r
5220
- .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-cut-item:hover .\${P}-cut-label,\r
5221
- .\${P}-wrapper.\${P}-entry-hover-blinds.\${P}-state-hover .\${P}-cut-item .\${P}-cut-label {\r
5222
- color: var(--\${P}-text-hover-color);\r
5223
- }\r
5224
- \r
5225
- .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-list-item-has-link::before,\r
5226
- .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-cut-item::before {\r
5227
- content: '';\r
5228
- position: absolute;\r
5229
- inset: 0;\r
5230
- background: var(--\${P}-background-hover-color);\r
5231
- transform: scaleY(0);\r
5232
- transform-origin: center center;\r
5233
- transition: transform 250ms;\r
5234
- z-index: 0;\r
5235
- pointer-events: none;\r
5236
- }\r
5237
- \r
5238
- .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-list-col,\r
5239
- .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-cut-label {\r
5240
- position: relative;\r
5241
- z-index: 1;\r
5242
- }\r
5243
- \r
5244
- .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-list-item-has-link:hover::before,\r
5245
- .\${P}-wrapper.\${P}-entry-hover-blinds.\${P}-state-hover .\${P}-list-item-has-link::before,\r
5246
- .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-cut-item:hover::before,\r
5247
- .\${P}-wrapper.\${P}-entry-hover-blinds.\${P}-state-hover .\${P}-cut-item::before {\r
5248
- transform: scaleY(1);\r
5249
- }\r
5250
- \r
5251
- .\${P}-cut-item {\r
5252
- display: flex;\r
5253
- align-items: center;\r
5254
- justify-content: center;\r
5255
- width: 100%;\r
5256
- overflow: visible;\r
5257
- position: relative;\r
5258
- z-index: 3;\r
5259
- box-sizing: border-box;\r
5260
- user-select: none;\r
5261
- background: var(--\${P}-background-color);\r
5262
- cursor: pointer;\r
5263
- padding: 0;\r
5264
- border: none;\r
5265
- font: inherit;\r
5266
- text-align: inherit;\r
5267
- appearance: none;\r
5268
- -webkit-appearance: none;\r
5269
- }\r
5270
- \r
5271
- .\${P}-cut-item .\${P}-list-cols-row {\r
5272
- flex: 1;\r
5273
- min-height: 100%;\r
5274
- align-items: center;\r
5275
- }\r
5276
- \r
5277
- .\${P}-wrapper.\${P}-divider-bottom .\${P}-cut-item {\r
5278
- border-bottom-style: solid;\r
5279
- border-bottom-color: var(--\${P}-divider-color);\r
5280
- }\r
5281
- \r
5282
- .\${P}-cut-label {\r
5283
- display: block;\r
5284
- position: relative;\r
5285
- z-index: 1;\r
5286
- margin: 0;\r
5287
- color: var(--\${P}-text-color);\r
5288
- white-space: pre-wrap;\r
5289
- overflow-wrap: anywhere;\r
5290
- word-break: break-word;\r
5291
- }\r
5292
- \`;\r
5293
- }\r
5294
- \r
5295
- export const COLUMN_CONTENT_KEYS = [\r
5296
- 'AColumn',\r
5297
- 'BColumnWidth',\r
5298
- 'CColumnWidth',\r
5299
- 'DColumnWidth',\r
5300
- 'EColumnWidth',\r
5301
- ] as const;\r
5302
- \r
5303
- export const COLUMN_TEXT_PREFIXES = [\r
5304
- 'AColumn',\r
5305
- 'BColumn',\r
5306
- 'CColumn',\r
5307
- 'DColumn',\r
5308
- 'EColumn',\r
5309
- ] as const;\r
5310
- \r
5311
- export const CUT_LABEL_TEXT_PREFIX = 'cutLabel' as const;\r
5312
- \r
5313
- export const LIST_TEXT_STYLE_PREFIXES = [\r
5314
- ...COLUMN_TEXT_PREFIXES,\r
5315
- CUT_LABEL_TEXT_PREFIX,\r
5316
- ] as const;\r
5317
- \r
5318
- export type ListTextStylePrefix = typeof LIST_TEXT_STYLE_PREFIXES[number];\r
5319
- \r
5320
- export const LIST_COLUMN_LETTERS = ['A', 'B', 'C', 'D', 'E'] as const;\r
5321
- \r
5322
- export function getListColumnVerticalAlignSettingKey(columnLetter: string): string {\r
5323
- return \`\${columnLetter}ColumnVerticalAlign\`;\r
5324
- }\r
5325
- \r
5326
- export const COLUMN_VALIGN_BASIC_OPTIONS = ['Top', 'Center', 'Bottom'] as const;\r
5327
- \r
5328
- export function isBaselineAnchorColumnVerticalAlign(value: string | undefined): boolean {\r
5329
- const raw = String(value ?? 'Top').trim();\r
5330
- if (raw.toLowerCase().startsWith('baseline')) {\r
5331
- return false;\r
5332
- }\r
5333
- return raw === 'Top' || raw === 'Center' || raw === 'Bottom';\r
5334
- }\r
5335
- \r
5336
- export function parseBaselineAnchorLetter(value: string | undefined): string | null {\r
5337
- const raw = String(value ?? '').trim();\r
5338
- if (!raw.toLowerCase().startsWith('baseline')) {\r
5339
- return null;\r
5340
- }\r
5341
- const anchorLetter = raw.slice(-1).toUpperCase();\r
5342
- return LIST_COLUMN_LETTERS.includes(anchorLetter as typeof LIST_COLUMN_LETTERS[number])\r
5343
- ? anchorLetter\r
5344
- : null;\r
5345
- }\r
5346
- \r
5347
- export function isValidColumnBaselineVAlign(\r
5348
- value: string | undefined,\r
5349
- forColumnLetter: string,\r
5350
- settings: ListSettings,\r
5351
- ): boolean {\r
5352
- const anchorLetter = parseBaselineAnchorLetter(value);\r
5353
- if (!anchorLetter) {\r
5354
- return true;\r
5355
- }\r
5356
- if (anchorLetter === forColumnLetter) {\r
5357
- return false;\r
5358
- }\r
5359
- return isBaselineAnchorColumnVerticalAlign(settings[getListColumnVerticalAlignSettingKey(anchorLetter) as ListColumnVerticalAlignKey]);\r
5360
- }\r
5361
- \r
5362
- export function getColumnVerticalAlignOptionsForLetter(\r
5363
- columnLetter: string,\r
5364
- settings: ListSettings,\r
5365
- ): string[] {\r
5366
- const baselineOptions = LIST_COLUMN_LETTERS\r
5367
- .filter((letter) => letter !== columnLetter)\r
5368
- .filter((letter) => isBaselineAnchorColumnVerticalAlign(settings[getListColumnVerticalAlignSettingKey(letter) as ListColumnVerticalAlignKey]))\r
5369
- .map((letter) => \`Baseline \${letter}\`);\r
5370
- \r
5371
- return [...COLUMN_VALIGN_BASIC_OPTIONS, ...baselineOptions];\r
5372
- }\r
5373
- \r
5374
- type ColumnVerticalAlign =\r
5375
- | { kind: 'top' | 'center' | 'bottom' }\r
5376
- | { kind: 'baseline'; anchorLetter: string };\r
5377
- \r
5378
- function parseColumnVerticalAlign(value: string | undefined): ColumnVerticalAlign {\r
5379
- const raw = String(value ?? 'Top').trim();\r
5380
- if (raw.toLowerCase().startsWith('baseline')) {\r
5381
- const anchorLetter = raw.slice(-1).toUpperCase();\r
5382
- if (LIST_COLUMN_LETTERS.includes(anchorLetter as typeof LIST_COLUMN_LETTERS[number])) {\r
5383
- return { kind: 'baseline', anchorLetter };\r
5384
- }\r
5385
- return { kind: 'top' };\r
5386
- }\r
5387
- if (raw === 'Center') return { kind: 'center' };\r
5388
- if (raw === 'Bottom') return { kind: 'bottom' };\r
5389
- return { kind: 'top' };\r
5390
- }\r
5391
- \r
5392
- function resolveColumnVerticalAlign(\r
5393
- value: string | undefined,\r
5394
- settings: ListSettings,\r
5395
- columnLetter: string,\r
5396
- ): ColumnVerticalAlign {\r
5397
- if (isActiveBaselineVAlign(value, settings, columnLetter)) {\r
5398
- return parseColumnVerticalAlign(value);\r
5399
- }\r
5400
- \r
5401
- const parsed = parseColumnVerticalAlign(value);\r
5402
- if (parsed.kind === 'baseline') {\r
5403
- return { kind: 'top' };\r
5404
- }\r
5405
- \r
5406
- return parsed;\r
5407
- }\r
5408
- \r
5409
- function isActiveBaselineVAlign(\r
5410
- value: string | undefined,\r
5411
- settings: ListSettings,\r
5412
- forColumnLetter: string,\r
5413
- ): boolean {\r
5414
- if (!isValidColumnBaselineVAlign(value, forColumnLetter, settings)) {\r
5415
- return false;\r
5416
- }\r
5417
- return parseColumnVerticalAlign(value).kind === 'baseline';\r
5418
- }\r
5419
- \r
5420
- function getListColumnVerticalAlignSanitizeUpdates(\r
5421
- settings: ListSettings,\r
5422
- ): ListColumnVerticalAlignUpdates | null {\r
5423
- if (settings.type === 'B') {\r
5424
- return null;\r
5425
- }\r
5426
- \r
5427
- const updates: ListColumnVerticalAlignUpdates = {};\r
5428
- let hasUpdates = false;\r
5429
- \r
5430
- for (const letter of LIST_COLUMN_LETTERS) {\r
5431
- const key = getListColumnVerticalAlignSettingKey(letter) as ListColumnVerticalAlignKey;\r
5432
- const value = settings[key];\r
5433
- if (!isValidColumnBaselineVAlign(value, letter, settings)) {\r
5434
- updates[key] = 'Top';\r
5435
- hasUpdates = true;\r
5436
- }\r
5437
- }\r
5438
- \r
5439
- return hasUpdates ? updates : null;\r
5440
- }\r
5441
- \r
5442
- function vAlignToTitleStyle(\r
5443
- kind: ColumnVerticalAlign['kind'],\r
5444
- ): React.CSSProperties {\r
5445
- if (kind === 'center') {\r
5446
- return { marginTop: 'auto', marginBottom: 'auto' };\r
5447
- }\r
5448
- if (kind === 'bottom') {\r
5449
- return { marginTop: 'auto' };\r
5450
- }\r
5451
- return {};\r
5452
- }\r
5453
- \r
5454
- function getFirstLineBaselineOffsetInTitle(\r
5455
- titleEl: HTMLElement,\r
5456
- probeClassName: string,\r
5457
- ): number {\r
5458
- const probe = document.createElement('i');\r
5459
- probe.className = probeClassName;\r
5460
- probe.setAttribute('aria-hidden', 'true');\r
5461
- titleEl.prepend(probe);\r
5462
- \r
5463
- const { top: titleTop } = titleEl.getBoundingClientRect();\r
5464
- const { bottom: probeBottom } = probe.getBoundingClientRect();\r
5465
- const baselineOffset = probeBottom - titleTop;\r
5466
- probe.remove();\r
5467
- \r
5468
- return baselineOffset;\r
5469
- }\r
5470
- \r
5471
- function measureColumnFirstLineBaselineOffset(\r
5472
- info: {\r
5473
- titleEl: HTMLElement | null;\r
5474
- kind: string;\r
5475
- },\r
5476
- rowTop: number,\r
5477
- listColClassName: string,\r
5478
- probeClassName: string,\r
5479
- ): number {\r
5480
- const titleEl = info.titleEl;\r
5481
- if (!titleEl) return 0;\r
5482
- \r
5483
- const listCol = titleEl.closest<HTMLElement>(\`.\${listColClassName}\`);\r
5484
- if (!listCol) return 0;\r
5485
- \r
5486
- const baselineInTitle = getFirstLineBaselineOffsetInTitle(titleEl, probeClassName);\r
5487
- \r
5488
- if (info.kind === 'baseline') {\r
5489
- return titleEl.getBoundingClientRect().top - rowTop + baselineInTitle;\r
5490
- }\r
5491
- \r
5492
- const listColRect = listCol.getBoundingClientRect();\r
5493
- const titleHeight = titleEl.getBoundingClientRect().height;\r
5494
- let valignOffset = 0;\r
5495
- \r
5496
- if (info.kind === 'center') {\r
5497
- valignOffset = (listColRect.height - titleHeight) / 2;\r
5498
- } else if (info.kind === 'bottom') {\r
5499
- valignOffset = listColRect.height - titleHeight;\r
5500
- }\r
5501
- \r
5502
- return (listColRect.top - rowTop) + valignOffset + baselineInTitle;\r
5503
- }\r
5504
- \r
5505
- function syncRowListColHeights(\r
5506
- rowEl: HTMLElement,\r
5507
- cols: HTMLElement[],\r
5508
- listColClassName: string,\r
5509
- ): number {\r
5510
- const rowHeight = rowEl.getBoundingClientRect().height;\r
5511
- if (rowHeight <= 0) {\r
5512
- return 0;\r
5513
- }\r
5514
- \r
5515
- cols.forEach((colEl) => {\r
5516
- const listCol = colEl.querySelector<HTMLElement>(\`.\${listColClassName}\`);\r
5517
- if (listCol) {\r
5518
- listCol.style.minHeight = \`\${rowHeight}px\`;\r
5519
- listCol.style.height = \`\${rowHeight}px\`;\r
5520
- }\r
5521
- });\r
5522
- \r
5523
- void rowEl.offsetHeight;\r
5524
- return rowHeight;\r
5525
- }\r
5526
- \r
5527
- function applyBaselineTitleShift(titleEl: HTMLElement | null, shift: number): number {\r
5528
- if (!titleEl || !shift) {\r
5529
- if (titleEl) {\r
5530
- titleEl.style.transform = '';\r
5531
- }\r
5532
- return 0;\r
5533
- }\r
5534
- \r
5535
- titleEl.style.transform = \`translateY(\${shift}px)\`;\r
5536
- return shift;\r
5537
- }\r
5538
- \r
5539
- const COLUMN_CONTENT_KEY_TO_TEXT_PREFIX: Record<\r
5540
- typeof COLUMN_CONTENT_KEYS[number],\r
5541
- typeof COLUMN_TEXT_PREFIXES[number]\r
5542
- > = {\r
5543
- AColumn: 'AColumn',\r
5544
- BColumnWidth: 'BColumn',\r
5545
- CColumnWidth: 'CColumn',\r
5546
- DColumnWidth: 'DColumn',\r
5547
- EColumnWidth: 'EColumn',\r
5548
- };\r
5549
- \r
5550
- export const LIST_GLOBAL_TEXT_STYLE_KEYS = [\r
5551
- 'textFontFamily',\r
5552
- 'textFontSettings',\r
5553
- 'textFontSize',\r
5554
- 'textLineHeight',\r
5555
- 'textLetterSpacing',\r
5556
- 'textWordSpacing',\r
5557
- 'textTextAppearance',\r
5558
- ] as const;\r
5559
- \r
5560
- export type ListGlobalTextStyleKey = typeof LIST_GLOBAL_TEXT_STYLE_KEYS[number];\r
5561
- \r
5562
- export function getListColumnTextSettingKey(\r
5563
- prefix: ListTextStylePrefix,\r
5564
- globalKey: ListGlobalTextStyleKey,\r
5565
- ): string {\r
5566
- return \`\${prefix}\${globalKey.replace(/^text/, 'Text')}\`;\r
5567
- }\r
5568
- \r
5569
- type ListTextStyleFields = {\r
5570
- textFontFamily?: string;\r
5571
- textFontSettings?: { fontWeight: number; fontStyle: string };\r
5572
- textFontSize?: number;\r
5573
- textLineHeight?: number;\r
5574
- textLetterSpacing?: number;\r
5575
- textWordSpacing?: number;\r
5576
- textTextAppearance?: TextStyles['textAppearance'];\r
5577
- textColor?: string;\r
5578
- };\r
5579
- \r
5580
- type ResolvedListTextFields = {\r
5581
- textFontFamily: string;\r
5582
- textFontSettings: { fontWeight: number; fontStyle: string };\r
5583
- textFontSize?: number;\r
5584
- textLineHeight?: number;\r
5585
- textLetterSpacing: number;\r
5586
- textWordSpacing: number;\r
5587
- textTextAppearance?: TextStyles['textAppearance'];\r
5588
- textColor?: string;\r
5589
- };\r
5590
- \r
5591
- function resolveListGlobalTextFields(\r
5592
- settings: ListTextStyleFields,\r
5593
- ): ResolvedListTextFields {\r
5594
- return {\r
5595
- textFontFamily: settings.textFontFamily ?? 'Arial',\r
5596
- textFontSettings: settings.textFontSettings ?? {\r
5597
- fontWeight: 400,\r
5598
- fontStyle: 'normal',\r
5599
- },\r
5600
- textFontSize: settings.textFontSize,\r
5601
- textLineHeight: settings.textLineHeight,\r
5602
- textLetterSpacing: settings.textLetterSpacing ?? 0,\r
5603
- textWordSpacing: settings.textWordSpacing ?? 0,\r
5604
- textTextAppearance: settings.textTextAppearance,\r
5605
- textColor: settings.textColor,\r
5606
- };\r
5607
- }\r
5608
- \r
5609
- function resolveListColumnTextFields(\r
5610
- settings: ListSettings,\r
5611
- textPrefix: ListTextStylePrefix,\r
5612
- ): ResolvedListTextFields {\r
5613
- const read = <K extends ListGlobalTextStyleKey>(globalKey: K) => {\r
5614
- const columnKey = getListColumnTextSettingKey(textPrefix, globalKey);\r
5615
- const columnValue = settings[columnKey as keyof ListSettings];\r
5616
- if (columnValue !== undefined) {\r
5617
- return columnValue as ListTextStyleFields[K];\r
5618
- }\r
5619
- return settings[globalKey];\r
5620
- };\r
5621
- \r
5622
- return {\r
5623
- textFontFamily: (read('textFontFamily') as string | undefined) ?? 'Arial',\r
5624
- textFontSettings: (read('textFontSettings') as ListTextStyleFields['textFontSettings']) ?? {\r
5625
- fontWeight: 400,\r
5626
- fontStyle: 'normal',\r
5627
- },\r
5628
- textFontSize: read('textFontSize') as number | undefined,\r
5629
- textLineHeight: read('textLineHeight') as number | undefined,\r
5630
- textLetterSpacing: (read('textLetterSpacing') as number | undefined) ?? 0,\r
5631
- textWordSpacing: (read('textWordSpacing') as number | undefined) ?? 0,\r
5632
- textTextAppearance: read('textTextAppearance') as ListTextStyleFields['textTextAppearance'],\r
5633
- textColor: settings.textColor,\r
5634
- };\r
5635
- }\r
5636
- \r
5637
- function listColumnTextFieldsToCss(\r
5638
- fields: ResolvedListTextFields,\r
5639
- isEditor?: boolean,\r
5640
- ): React.CSSProperties {\r
5641
- const resolvedTextStyle: TextStyles = {\r
5642
- fontSettings: {\r
5643
- fontFamily: fields.textFontFamily,\r
5644
- fontWeight: fields.textFontSettings?.fontWeight ?? 400,\r
5645
- fontStyle: fields.textFontSettings?.fontStyle ?? 'normal',\r
5646
- },\r
5647
- fontSize: fields.textFontSize ?? 0.01,\r
5648
- lineHeight: fields.textLineHeight,\r
5649
- letterSpacing: fields.textLetterSpacing,\r
5650
- wordSpacing: fields.textWordSpacing,\r
5651
- textAppearance: fields.textTextAppearance,\r
5652
- color: fields.textColor ?? '#767676',\r
5653
- };\r
5654
- \r
5655
- return omitTextColors(textStylesToCss(resolvedTextStyle, isEditor));\r
5656
- }\r
5657
- \r
5658
- function getListColumnTitleClassName(\r
5659
- settings: ListSettings,\r
5660
- prefix: ListTextStylePrefix,\r
5661
- baseClassName: string,\r
5662
- tightLeadingClassName: string,\r
5663
- ): string {\r
5664
- const fields = resolveListColumnTextFields(settings, prefix);\r
5665
- const fontSize = fields.textFontSize ?? 0.01;\r
5666
- const lineHeight = fields.textLineHeight;\r
5667
- const needsTightLeading = lineHeight !== undefined && lineHeight < fontSize;\r
5668
- \r
5669
- return needsTightLeading\r
5670
- ? \`\${baseClassName} \${tightLeadingClassName}\`\r
5671
- : baseClassName;\r
5672
- }\r
5673
- \r
5674
- function getListColumnTitleVars(\r
5675
- settings: ListSettings,\r
5676
- prefix: ListTextStylePrefix,\r
5677
- titleVarPrefix: string,\r
5678
- isEditor?: boolean,\r
5679
- ): React.CSSProperties {\r
5680
- const fields = resolveListColumnTextFields(settings, prefix);\r
5681
- const fontSize = fields.textFontSize ?? 0.01;\r
5682
- const lineHeight = fields.textLineHeight;\r
5683
- \r
5684
- if (lineHeight === undefined || lineHeight >= fontSize) {\r
5685
- return {};\r
5686
- }\r
5687
- \r
5688
- return {\r
5689
- [\`--\${titleVarPrefix}-title-leading-gap\`]: scalingValue((fontSize - lineHeight) / 2, isEditor),\r
5690
- } as React.CSSProperties;\r
5691
- }\r
5692
- \r
5693
- function getListGlobalTextSyncUpdates(\r
5694
- nextSettings: ListSettings,\r
5695
- prevSettings: ListSettings,\r
5696
- ): ListColumnTextStyleSyncUpdates | null {\r
5697
- const updates: ListColumnTextStyleSyncUpdates = {};\r
5698
- let hasChanges = false;\r
5699
- \r
5700
- for (const globalKey of LIST_GLOBAL_TEXT_STYLE_KEYS) {\r
5701
- if (nextSettings[globalKey] === prevSettings[globalKey]) {\r
5702
- continue;\r
5703
- }\r
5704
- if (nextSettings[globalKey] === undefined) {\r
5705
- continue;\r
5706
- }\r
5707
- \r
5708
- hasChanges = true;\r
5709
- for (const prefix of LIST_TEXT_STYLE_PREFIXES) {\r
5710
- Object.assign(updates, {\r
5711
- [getListColumnTextSettingKey(prefix, globalKey)]: nextSettings[globalKey],\r
5712
- });\r
5713
- }\r
5714
- }\r
5715
- \r
5716
- return hasChanges ? updates : null;\r
5717
- }\r
5718
- \r
5719
- const COLUMN_WIDTH_KEYS = [\r
5720
- 'AColumnWidth',\r
5721
- 'BColumnWidth',\r
5722
- 'CColumnWidth',\r
5723
- 'DColumnWidth',\r
5724
- 'EColumnWidth',\r
5725
- ] as const;\r
5726
- \r
5727
- const COLUMN_PADDING_LEFT_KEYS = [\r
5728
- 'AColumnPaddingLeft',\r
5729
- 'BColumnPaddingLeft',\r
5730
- 'CColumnPaddingLeft',\r
5731
- 'DColumnPaddingLeft',\r
5732
- 'EColumnPaddingLeft',\r
5733
- ] as const;\r
5734
- \r
5735
- const COLUMN_PADDING_RIGHT_KEYS = [\r
5736
- 'AColumnPaddingRight',\r
5737
- 'BColumnPaddingRight',\r
5738
- 'CColumnPaddingRight',\r
5739
- 'DColumnPaddingRight',\r
5740
- 'EColumnPaddingRight',\r
5741
- ] as const;\r
5742
- \r
5743
- const COLUMN_PADDING_BOTTOM_KEYS = [\r
5744
- 'AColumnPaddingBottom',\r
5745
- 'BColumnPaddingBottom',\r
5746
- 'CColumnPaddingBottom',\r
5747
- 'DColumnPaddingBottom',\r
5748
- 'EColumnPaddingBottom',\r
5749
- ] as const;\r
5750
- \r
5751
- type ColumnWidthKey = typeof COLUMN_WIDTH_KEYS[number];\r
5752
- type ColumnPaddingLeftKey = typeof COLUMN_PADDING_LEFT_KEYS[number];\r
5753
- type ColumnPaddingRightKey = typeof COLUMN_PADDING_RIGHT_KEYS[number];\r
5754
- type ColumnPaddingBottomKey = typeof COLUMN_PADDING_BOTTOM_KEYS[number];\r
5755
- \r
5756
- type ListColumnPaddingUpdates = {\r
5757
- AColumnPaddingLeft?: number;\r
5758
- AColumnPaddingRight?: number;\r
5759
- BColumnPaddingLeft?: number;\r
5760
- BColumnPaddingRight?: number;\r
5761
- CColumnPaddingLeft?: number;\r
5762
- CColumnPaddingRight?: number;\r
5763
- DColumnPaddingLeft?: number;\r
5764
- DColumnPaddingRight?: number;\r
5765
- EColumnPaddingLeft?: number;\r
5766
- EColumnPaddingRight?: number;\r
5767
- };\r
5768
- \r
5769
- type ListColumnWidthUpdates = {\r
5770
- AColumnWidth?: number;\r
5771
- BColumnWidth?: number;\r
5772
- CColumnWidth?: number;\r
5773
- DColumnWidth?: number;\r
5774
- EColumnWidth?: number;\r
5775
- };\r
5776
- \r
5777
- type ListItemColumn = {\r
5778
- key: string;\r
5779
- textPrefix: typeof COLUMN_TEXT_PREFIXES[number];\r
5780
- widthKey: ColumnWidthKey;\r
5781
- paddingLeftKey: ColumnPaddingLeftKey;\r
5782
- paddingRightKey: ColumnPaddingRightKey;\r
5783
- paddingBottomKey: ColumnPaddingBottomKey;\r
5784
- width: number;\r
5785
- paddingLeft: number;\r
5786
- paddingRight: number;\r
5787
- paddingBottom: number;\r
5788
- };\r
5789
- \r
5790
- type ColorKeys =\r
5791
- | 'textColor'\r
5792
- | 'backgroundColor'\r
5793
- | 'dividerColor'\r
5794
- | 'textHoverColor'\r
5795
- | 'backgroundHoverColor'\r
5796
- | 'dividerHoverColor';\r
5797
- \r
5798
- const COLOR_VAR_MAP: Record<ColorKeys, string> = {\r
5799
- textColor: 'text-color',\r
5800
- backgroundColor: 'background-color',\r
5801
- dividerColor: 'divider-color',\r
5802
- textHoverColor: 'text-hover-color',\r
5803
- backgroundHoverColor: 'background-hover-color',\r
5804
- dividerHoverColor: 'divider-hover-color',\r
5805
- };\r
5806
- \r
5807
- const STATE_KEYS = ['hover', 'focus', 'filled', 'success', 'error'] as const;\r
5808
- \r
5809
- const COL_RESIZE_HANDLE_WIDTH = 0.004;\r
5810
- const COL_PADDING_HANDLE_WIDTH = 0.004;\r
5811
- const MIN_COLUMN_WIDTH_PX = 50;\r
5812
- const ARTICLE_DESIGN_WIDTH = 1440;\r
5813
- const MIN_COLUMN_WIDTH = MIN_COLUMN_WIDTH_PX / ARTICLE_DESIGN_WIDTH;\r
5814
- \r
5815
- export function getListMinColumnWidth(designWidthPx?: number): number {\r
5816
- const designWidth = typeof designWidthPx === 'number' && designWidthPx > 0\r
5817
- ? designWidthPx\r
5818
- : ARTICLE_DESIGN_WIDTH;\r
5819
- \r
5820
- return MIN_COLUMN_WIDTH_PX / designWidth;\r
5821
- }\r
5822
- \r
5823
- function getEditorDesignWidth(element: HTMLElement | null | undefined): number {\r
5824
- let el = element ?? null;\r
5825
- \r
5826
- while (el) {\r
5827
- const inline = el.style.getPropertyValue('--cntrl-article-width').trim();\r
5828
- if (inline) {\r
5829
- const px = parseFloat(inline);\r
5830
- if (Number.isFinite(px) && px > 0) {\r
5831
- return px;\r
5832
- }\r
5833
- }\r
5834
- \r
5835
- const computed = getComputedStyle(el).getPropertyValue('--cntrl-article-width').trim();\r
5836
- if (computed) {\r
5837
- const px = parseFloat(computed);\r
5838
- if (Number.isFinite(px) && px > 0) {\r
5839
- return px;\r
5840
- }\r
5841
- }\r
5842
- \r
5843
- el = el.parentElement;\r
5844
- }\r
5845
- \r
5846
- return ARTICLE_DESIGN_WIDTH;\r
5847
- }\r
5848
- \r
5849
- const DEFAULT_COLUMN_WIDTHS: Record<ColumnWidthKey, number> = {\r
5850
- AColumnWidth: 0.02,\r
5851
- BColumnWidth: 0.02,\r
5852
- CColumnWidth: 0.02,\r
5853
- DColumnWidth: 0.02,\r
5854
- EColumnWidth: 0.02,\r
5855
- };\r
5856
- \r
5857
- export function getListEffectiveContentWidth(\r
5858
- settings: ListSettings,\r
5859
- ): number {\r
5860
- const wrapperWidth = typeof settings.wrapperWidth === 'number' ? settings.wrapperWidth : 1;\r
5861
- \r
5862
- return Math.max(0, wrapperWidth);\r
5863
- }\r
5864
- \r
5865
- export function getEqualListColumnWidthUpdates(\r
5866
- columns: number,\r
5867
- contentWidth: number = 1,\r
5868
- ): Record<ColumnWidthKey, number> {\r
5869
- const equalColumnWidth = contentWidth / columns;\r
5870
- return Object.fromEntries(\r
5871
- COLUMN_WIDTH_KEYS.map((key) => [key, equalColumnWidth]),\r
5872
- ) as Record<ColumnWidthKey, number>;\r
5873
- }\r
5874
- \r
5875
- function getResetListColumnPaddingUpdates(): Record<\r
5876
- ColumnPaddingLeftKey | ColumnPaddingRightKey,\r
5877
- number\r
5878
- > {\r
5879
- return Object.fromEntries([\r
5880
- ...COLUMN_PADDING_LEFT_KEYS.map((key) => [key, 0]),\r
5881
- ...COLUMN_PADDING_RIGHT_KEYS.map((key) => [key, 0]),\r
5882
- ]) as Record<ColumnPaddingLeftKey | ColumnPaddingRightKey, number>;\r
5883
- }\r
5884
- \r
5885
- function getResetListColumnPaddingBottomUpdates(): Record<ColumnPaddingBottomKey, number> {\r
5886
- return Object.fromEntries(\r
5887
- COLUMN_PADDING_BOTTOM_KEYS.map((key) => [key, 0]),\r
5888
- ) as Record<ColumnPaddingBottomKey, number>;\r
5889
- }\r
5890
- \r
5891
- function getStoredColumnWidths(\r
5892
- settings: ListSettings,\r
5893
- ): Record<ColumnWidthKey, number> {\r
5894
- return Object.fromEntries(\r
5895
- COLUMN_WIDTH_KEYS.map((key) => [\r
5896
- key,\r
5897
- typeof settings[key] === 'number'\r
5898
- ? settings[key] as number\r
5899
- : DEFAULT_COLUMN_WIDTHS[key],\r
5900
- ]),\r
5901
- ) as Record<ColumnWidthKey, number>;\r
5902
- }\r
5903
- \r
5904
- export function resolveListColumnPadding(\r
5905
- columnWidth: number,\r
5906
- paddingLeft: number,\r
5907
- paddingRight: number,\r
5908
- ): { paddingLeft: number; paddingRight: number } {\r
5909
- const maxTotalPadding = columnWidth - MIN_COLUMN_WIDTH;\r
5910
- const totalPadding = paddingLeft + paddingRight;\r
5911
- \r
5912
- if (totalPadding <= 0 || totalPadding <= maxTotalPadding) {\r
5913
- return { paddingLeft, paddingRight };\r
5914
- }\r
5915
- \r
5916
- if (maxTotalPadding <= 0) {\r
5917
- return { paddingLeft: 0, paddingRight: 0 };\r
5918
- }\r
5919
- \r
5920
- const scale = maxTotalPadding / totalPadding;\r
5921
- \r
5922
- return {\r
5923
- paddingLeft: paddingLeft * scale,\r
5924
- paddingRight: paddingRight * scale,\r
5925
- };\r
5926
- }\r
5927
- \r
5928
- export function getEffectiveListColumnWidths(\r
5929
- columns: number,\r
5930
- wrapperWidth: number,\r
5931
- storedWidths: Record<ColumnWidthKey, number>,\r
5932
- ): number[] {\r
5933
- const resolvedWidths = resolveListColumnWidths(columns, wrapperWidth, storedWidths);\r
5934
- \r
5935
- if (columns <= 0) {\r
5936
- return [];\r
5937
- }\r
5938
- \r
5939
- const sumFixed = resolvedWidths.slice(0, columns - 1).reduce((sum, width) => sum + width, 0);\r
5940
- \r
5941
- return [\r
5942
- ...resolvedWidths.slice(0, columns - 1),\r
5943
- Math.max(0, wrapperWidth - sumFixed),\r
5944
- ];\r
5945
- }\r
5946
- \r
5947
- function getListColumnPaddingUpdates(\r
5948
- columns: number,\r
5949
- effectiveWidths: number[],\r
5950
- settings: ListSettings,\r
5951
- ): ListColumnPaddingUpdates {\r
5952
- const updates: ListColumnPaddingUpdates = {};\r
5953
- \r
5954
- for (let index = 0; index < columns; index += 1) {\r
5955
- const paddingLeftKey = COLUMN_PADDING_LEFT_KEYS[index];\r
5956
- const paddingRightKey = COLUMN_PADDING_RIGHT_KEYS[index];\r
5957
- const storedPaddingLeft = typeof settings[paddingLeftKey] === 'number'\r
5958
- ? settings[paddingLeftKey] as number\r
5959
- : 0;\r
5960
- const storedPaddingRight = typeof settings[paddingRightKey] === 'number'\r
5961
- ? settings[paddingRightKey] as number\r
5962
- : 0;\r
5963
- const resolvedPadding = resolveListColumnPadding(\r
5964
- effectiveWidths[index] ?? 0,\r
5965
- storedPaddingLeft,\r
5966
- storedPaddingRight,\r
5967
- );\r
5968
- \r
5969
- if (resolvedPadding.paddingLeft !== storedPaddingLeft) {\r
5970
- updates[paddingLeftKey] = resolvedPadding.paddingLeft;\r
5971
- }\r
5972
- \r
5973
- if (resolvedPadding.paddingRight !== storedPaddingRight) {\r
5974
- updates[paddingRightKey] = resolvedPadding.paddingRight;\r
5975
- }\r
5976
- }\r
5977
- \r
5978
- return updates;\r
5979
- }\r
5980
- \r
5981
- export function resolveListColumnWidths(\r
5982
- columns: number,\r
5983
- wrapperWidth: number,\r
5984
- storedWidths: Record<ColumnWidthKey, number>,\r
5985
- ): number[] {\r
5986
- if (columns <= 0) {\r
5987
- return [];\r
5988
- }\r
5989
- \r
5990
- const widths = COLUMN_WIDTH_KEYS.slice(0, columns).map(\r
5991
- (key) => storedWidths[key],\r
5992
- );\r
5993
- \r
5994
- if (columns === 1) {\r
5995
- return widths;\r
5996
- }\r
5997
- \r
5998
- const fixedWidths = widths.slice(0, columns - 1);\r
5999
- const fixedSum = fixedWidths.reduce((sum, width) => sum + width, 0);\r
6000
- const minTotalWidth = fixedSum + MIN_COLUMN_WIDTH;\r
6001
- \r
6002
- if (wrapperWidth >= minTotalWidth) {\r
6003
- return widths;\r
6004
- }\r
6005
- \r
6006
- const resolvedFixedWidths = [...fixedWidths];\r
6007
- let overflow = minTotalWidth - wrapperWidth;\r
6008
- \r
6009
- for (let index = resolvedFixedWidths.length - 1; index >= 0 && overflow > 0; index -= 1) {\r
6010
- const shrinkable = resolvedFixedWidths[index] - MIN_COLUMN_WIDTH;\r
6011
- if (shrinkable <= 0) {\r
6012
- continue;\r
6013
- }\r
6014
- \r
6015
- const shrinkAmount = Math.min(overflow, shrinkable);\r
6016
- resolvedFixedWidths[index] -= shrinkAmount;\r
6017
- overflow -= shrinkAmount;\r
6018
- }\r
6019
- \r
6020
- return [...resolvedFixedWidths, widths[columns - 1]];\r
6021
- }\r
6022
- \r
6023
- function getListColumnWidthUpdatesForWrapperWidth(\r
6024
- columns: number,\r
6025
- wrapperWidth: number,\r
6026
- storedWidths: Record<ColumnWidthKey, number>,\r
6027
- ): ListColumnWidthUpdates {\r
6028
- if (columns <= 1) {\r
6029
- return {};\r
6030
- }\r
6031
- \r
6032
- const resolvedWidths = resolveListColumnWidths(columns, wrapperWidth, storedWidths);\r
6033
- const updates: ListColumnWidthUpdates = {};\r
6034
- \r
6035
- for (let index = 0; index < columns - 1; index += 1) {\r
6036
- const key = COLUMN_WIDTH_KEYS[index];\r
6037
- if (resolvedWidths[index] !== storedWidths[key]) {\r
6038
- updates[key] = resolvedWidths[index];\r
6039
- }\r
6040
- }\r
6041
- \r
6042
- return updates;\r
6043
- }\r
6044
- \r
6045
- function getColumnsOrder(settings: ListSettings): string[] {\r
6046
- if (Array.isArray(settings.columnsOrder) && settings.columnsOrder.length > 0) {\r
6047
- return settings.columnsOrder as string[];\r
6048
- }\r
6049
- \r
6050
- return [...COLUMN_CONTENT_KEYS];\r
6051
- }\r
6052
- \r
6053
- function areStringArraysEqual(left: string[], right: string[]): boolean {\r
6054
- if (left.length !== right.length) {\r
6055
- return false;\r
6056
- }\r
6057
- \r
6058
- return left.every((value, index) => value === right[index]);\r
6059
- }\r
6060
- \r
6061
- function getColumnLayoutUpdatesForOrderChange(\r
6062
- nextOrder: string[],\r
6063
- prevOrder: string[],\r
6064
- prevSettings: ListSettings,\r
6065
- columns: number,\r
6066
- ): Record<string, number> {\r
6067
- const count = Math.min(columns, nextOrder.length, COLUMN_WIDTH_KEYS.length);\r
6068
- const updates: Record<string, number> = {};\r
6069
- \r
6070
- for (let index = 0; index < count; index += 1) {\r
6071
- const contentKey = nextOrder[index];\r
6072
- const prevSlotIndex = prevOrder.indexOf(contentKey);\r
6073
- \r
6074
- if (prevSlotIndex === -1) {\r
6075
- continue;\r
6076
- }\r
6077
- \r
6078
- const prevWidthKey = COLUMN_WIDTH_KEYS[prevSlotIndex];\r
6079
- const prevPaddingLeftKey = COLUMN_PADDING_LEFT_KEYS[prevSlotIndex];\r
6080
- const prevPaddingRightKey = COLUMN_PADDING_RIGHT_KEYS[prevSlotIndex];\r
6081
- const prevPaddingBottomKey = COLUMN_PADDING_BOTTOM_KEYS[prevSlotIndex];\r
6082
- const widthKey = COLUMN_WIDTH_KEYS[index];\r
6083
- const paddingLeftKey = COLUMN_PADDING_LEFT_KEYS[index];\r
6084
- const paddingRightKey = COLUMN_PADDING_RIGHT_KEYS[index];\r
6085
- const paddingBottomKey = COLUMN_PADDING_BOTTOM_KEYS[index];\r
6086
- \r
6087
- const prevWidth = prevSettings[prevWidthKey];\r
6088
- const prevPaddingLeft = prevSettings[prevPaddingLeftKey];\r
6089
- const prevPaddingRight = prevSettings[prevPaddingRightKey];\r
6090
- const prevPaddingBottom = prevSettings[prevPaddingBottomKey];\r
6091
- \r
6092
- if (typeof prevWidth === 'number') {\r
6093
- updates[widthKey] = prevWidth;\r
6094
- }\r
6095
- \r
6096
- if (typeof prevPaddingLeft === 'number') {\r
6097
- updates[paddingLeftKey] = prevPaddingLeft;\r
6098
- }\r
6099
- \r
6100
- if (typeof prevPaddingRight === 'number') {\r
6101
- updates[paddingRightKey] = prevPaddingRight;\r
6102
- }\r
6103
- \r
6104
- if (typeof prevPaddingBottom === 'number') {\r
6105
- updates[paddingBottomKey] = prevPaddingBottom;\r
6106
- }\r
6107
- }\r
6108
- \r
6109
- return updates;\r
6110
- }\r
6111
- \r
6112
- export function applyListSettingsChange(\r
6113
- nextSettings: ListSettings,\r
6114
- prevSettings: ListSettings,\r
6115
- options?: { designWidth?: number },\r
6116
- ): ListSettings {\r
6117
- const textSyncUpdates = getListGlobalTextSyncUpdates(nextSettings, prevSettings);\r
6118
- if (textSyncUpdates) {\r
6119
- nextSettings = { ...nextSettings, ...textSyncUpdates };\r
6120
- }\r
6121
- \r
6122
- const valignSanitizeUpdates = getListColumnVerticalAlignSanitizeUpdates(nextSettings);\r
6123
- if (valignSanitizeUpdates) {\r
6124
- nextSettings = { ...nextSettings, ...valignSanitizeUpdates };\r
6125
- }\r
6126
- \r
6127
- const minColumnWidth = getListMinColumnWidth(options?.designWidth);\r
6128
- const nextColumns = nextSettings.columns;\r
6129
- const prevColumns = prevSettings.columns;\r
6130
- const nextContentWidth = getListEffectiveContentWidth(nextSettings);\r
6131
- const prevContentWidth = getListEffectiveContentWidth(prevSettings);\r
6132
- const isVerticalLayout = nextSettings.type === 'B'\r
6133
- || (nextSettings.type === undefined && prevSettings.type === 'B');\r
6134
- const columns =\r
6135
- typeof nextColumns === 'number'\r
6136
- ? nextColumns\r
6137
- : typeof prevColumns === 'number'\r
6138
- ? prevColumns\r
6139
- : COLUMN_CONTENT_KEYS.length;\r
6140
- \r
6141
- const withColumnPaddingUpdates = (\r
6142
- settings: ListSettings,\r
6143
- ): ListSettings => {\r
6144
- if (isVerticalLayout) {\r
6145
- return settings;\r
6146
- }\r
6147
- \r
6148
- const storedWidths = getStoredColumnWidths({ ...prevSettings, ...settings });\r
6149
- const contentWidth = getListEffectiveContentWidth(settings);\r
6150
- const effectiveWidths = getEffectiveListColumnWidths(columns, contentWidth, storedWidths);\r
6151
- const paddingUpdates = getListColumnPaddingUpdates(columns, effectiveWidths, {\r
6152
- ...prevSettings,\r
6153
- ...settings,\r
6154
- });\r
6155
- \r
6156
- if (Object.keys(paddingUpdates).length === 0) {\r
6157
- return settings;\r
6158
- }\r
6159
- \r
6160
- return {\r
6161
- ...settings,\r
6162
- ...paddingUpdates,\r
6163
- };\r
6164
- };\r
6165
- \r
6166
- if (typeof nextColumns === 'number' && nextColumns !== prevColumns) {\r
6167
- const updates: ListSettings = {\r
6168
- ...nextSettings,\r
6169
- ...getEqualListColumnWidthUpdates(nextColumns, nextContentWidth),\r
6170
- ...getResetListColumnPaddingUpdates(),\r
6171
- };\r
6172
- \r
6173
- if (isVerticalLayout) {\r
6174
- for (const key of COLUMN_PADDING_BOTTOM_KEYS) {\r
6175
- if (typeof prevSettings[key] === 'number') {\r
6176
- updates[key] = prevSettings[key];\r
6177
- }\r
6178
- }\r
6179
- } else {\r
6180
- Object.assign(updates, getResetListColumnPaddingBottomUpdates());\r
6181
- }\r
6182
- \r
6183
- return updates;\r
6184
- }\r
6185
- \r
6186
- const nextOrder = getColumnsOrder(nextSettings);\r
6187
- const prevOrder = getColumnsOrder(prevSettings);\r
6188
- \r
6189
- if (!areStringArraysEqual(nextOrder, prevOrder)) {\r
6190
- return withColumnPaddingUpdates({\r
6191
- ...nextSettings,\r
6192
- ...getColumnLayoutUpdatesForOrderChange(nextOrder, prevOrder, prevSettings, columns),\r
6193
- });\r
6194
- }\r
6195
- \r
6196
- if (nextContentWidth < prevContentWidth) {\r
6197
- if (typeof columns === 'number' && !isVerticalLayout) {\r
6198
- const storedWidths = getStoredColumnWidths({ ...prevSettings, ...nextSettings });\r
6199
- \r
6200
- return withColumnPaddingUpdates({\r
6201
- ...nextSettings,\r
6202
- ...getListColumnWidthUpdatesForWrapperWidth(columns, nextContentWidth, storedWidths),\r
6203
- });\r
6204
- }\r
6205
- }\r
6206
- \r
6207
- if (isVerticalLayout) {\r
6208
- const storedTextPaddingLR = typeof nextSettings.textPaddingLR === 'number'\r
6209
- ? nextSettings.textPaddingLR as number\r
6210
- : 0;\r
6211
- const maxAllowedPadding = Math.max(0, (nextContentWidth - minColumnWidth) / 2);\r
6212
- \r
6213
- if (storedTextPaddingLR > maxAllowedPadding) {\r
6214
- return { ...nextSettings, textPaddingLR: maxAllowedPadding };\r
6215
- }\r
6216
- \r
6217
- return nextSettings;\r
6218
- }\r
6219
- \r
6220
- const storedWidths = getStoredColumnWidths({ ...prevSettings, ...nextSettings });\r
6221
- const prevEffectiveWidths = getEffectiveListColumnWidths(\r
6222
- columns,\r
6223
- prevContentWidth,\r
6224
- getStoredColumnWidths(prevSettings),\r
6225
- );\r
6226
- const nextEffectiveWidths = getEffectiveListColumnWidths(\r
6227
- columns,\r
6228
- nextContentWidth,\r
6229
- storedWidths,\r
6230
- );\r
6231
- const columnWidthDecreased = nextEffectiveWidths.some(\r
6232
- (width, index) => width < (prevEffectiveWidths[index] ?? width),\r
6233
- );\r
6234
- const columnWidthSettingChanged = COLUMN_WIDTH_KEYS.some((key) => {\r
6235
- const nextWidth = nextSettings[key];\r
6236
- const prevWidth = prevSettings[key];\r
6237
- \r
6238
- return typeof nextWidth === 'number'\r
6239
- && typeof prevWidth === 'number'\r
6240
- && nextWidth !== prevWidth;\r
6241
- });\r
6242
- \r
6243
- if (columnWidthDecreased || columnWidthSettingChanged) {\r
6244
- return withColumnPaddingUpdates(nextSettings);\r
6245
- }\r
6246
- \r
6247
- return nextSettings;\r
6248
- }\r
6249
- \r
6250
- function getColumnMaxWidth(\r
6251
- columnIndex: number,\r
6252
- resolvedWidths: number[],\r
6253
- storedWidths: number[],\r
6254
- wrapperWidth: number,\r
6255
- ): number {\r
6256
- const leftWidth = resolvedWidths\r
6257
- .slice(0, columnIndex)\r
6258
- .reduce((sum, width) => sum + width, 0);\r
6259
- const rightPreferredWidth = storedWidths\r
6260
- .slice(columnIndex + 1, resolvedWidths.length - 1)\r
6261
- .reduce((sum, width) => sum + width, 0);\r
6262
- \r
6263
- return Math.max(\r
6264
- MIN_COLUMN_WIDTH,\r
6265
- wrapperWidth - leftWidth - rightPreferredWidth - MIN_COLUMN_WIDTH,\r
6266
- );\r
6267
- }\r
6268
- \r
6269
- function randomBetween(min: number, max: number): number {\r
6270
- return Math.random() * (max - min) + min;\r
6271
- }\r
6272
- \r
6273
- function getColumnWidthsFromSettings(\r
6274
- settings: ListSettings,\r
6275
- ): Record<ColumnWidthKey, number> {\r
6276
- return Object.fromEntries(\r
6277
- COLUMN_WIDTH_KEYS.map((key) => [\r
6278
- key,\r
6279
- typeof settings[key] === 'number' ? settings[key] as number : DEFAULT_COLUMN_WIDTHS[key],\r
6280
- ]),\r
6281
- ) as Record<ColumnWidthKey, number>;\r
6282
- }\r
6283
- \r
6284
- function getNumericSettingValues<K extends ColumnPaddingLeftKey | ColumnPaddingRightKey | ColumnPaddingBottomKey>(\r
6285
- settings: ListSettings,\r
6286
- keys: readonly K[],\r
6287
- fallback = 0,\r
6288
- ): Record<K, number> {\r
6289
- return Object.fromEntries(\r
6290
- keys.map((key) => [\r
6291
- key,\r
6292
- typeof settings[key] === 'number' ? settings[key] as number : fallback,\r
6293
- ]),\r
6294
- ) as Record<K, number>;\r
6295
- }\r
6296
- \r
6297
- function buildListColumns(\r
6298
- columnContentOrder: readonly typeof COLUMN_CONTENT_KEYS[number][],\r
6299
- columns: number,\r
6300
- columnWidthByKey: Record<ColumnWidthKey, number>,\r
6301
- columnPaddingLeftByKey: Record<ColumnPaddingLeftKey, number>,\r
6302
- columnPaddingRightByKey: Record<ColumnPaddingRightKey, number>,\r
6303
- columnPaddingBottomByKey: Record<ColumnPaddingBottomKey, number>,\r
6304
- ): ListItemColumn[] {\r
6305
- return columnContentOrder.slice(0, columns).map((key, index) => {\r
6306
- const paddingLeftKey = COLUMN_PADDING_LEFT_KEYS[index];\r
6307
- const paddingRightKey = COLUMN_PADDING_RIGHT_KEYS[index];\r
6308
- const paddingBottomKey = COLUMN_PADDING_BOTTOM_KEYS[index];\r
6309
- \r
6310
- return {\r
6311
- key,\r
6312
- textPrefix: COLUMN_CONTENT_KEY_TO_TEXT_PREFIX[key],\r
6313
- widthKey: COLUMN_WIDTH_KEYS[index],\r
6314
- width: columnWidthByKey[COLUMN_WIDTH_KEYS[index]],\r
6315
- paddingLeftKey,\r
6316
- paddingRightKey,\r
6317
- paddingBottomKey,\r
6318
- paddingLeft: columnPaddingLeftByKey[paddingLeftKey],\r
6319
- paddingRight: columnPaddingRightByKey[paddingRightKey],\r
6320
- paddingBottom: columnPaddingBottomByKey[paddingBottomKey],\r
6321
- };\r
6322
- });\r
6323
- }\r
6324
- \r
6325
- export function List({ settings, content, isEditor, isPreviewMode, activeEvent, layoutId, onUpdateSettings }: ListProps) {\r
6326
- const { prefix: P } = useScopedStyles();\r
6327
- const showControls = Boolean(isEditor && isPreviewMode);\r
6328
- const {\r
6329
- columns,\r
6330
- type,\r
6331
- wrapperWidth,\r
6332
- entriesCount,\r
6333
- cellMinHeight,\r
6334
- dividerWidth,\r
6335
- showVisibility,\r
6336
- cut,\r
6337
- showCut,\r
6338
- cutCellMinHeight,\r
6339
- cutLabel,\r
6340
- imageSize,\r
6341
- imageOnHover,\r
6342
- entryHoverEffect,\r
6343
- rowPaddingTop,\r
6344
- rowPaddingBottom,\r
6345
- rowPaddingTopB,\r
6346
- columnsOrder,\r
6347
- textPaddingLR,\r
6348
- textColor,\r
6349
- textFontFamily,\r
6350
- textFontSettings,\r
6351
- textFontSize,\r
6352
- textLineHeight,\r
6353
- textLetterSpacing,\r
6354
- textWordSpacing,\r
6355
- textTextAppearance,\r
6356
- backgroundColor,\r
6357
- dividerColor,\r
6358
- textHoverColor,\r
6359
- backgroundHoverColor,\r
6360
- dividerHoverColor,\r
6361
- } = settings;\r
6362
- \r
6363
- const [visibleRowCount, setVisibleRowCount] = useState<number | undefined>(undefined);\r
6364
- const [hoverImage, setHoverImage] = useState<HoverImageState | null>(null);\r
6365
- const showHoverImage = imageOnHover === 'On';\r
6366
- const cutEnabled = (cut ?? 0) > 0;\r
6367
- const isVerticalLayout = type === 'B';\r
6368
- const containerRef = useRef<HTMLDivElement>(null);\r
6369
- const [designWidth, setDesignWidth] = useState(ARTICLE_DESIGN_WIDTH);\r
6370
- const minColumnWidth = getListMinColumnWidth(designWidth);\r
6371
- \r
6372
- const storedTextPaddingLRMax = Math.max(0, ((wrapperWidth ?? 0) - minColumnWidth) / 2);\r
6373
- const effectiveTextPaddingLR = Math.min(textPaddingLR ?? 0, storedTextPaddingLRMax);\r
6374
- const textPaddingLRHandleWidth = Math.max(effectiveTextPaddingLR, COL_PADDING_HANDLE_WIDTH);\r
6375
- const textPaddingLRMaxFraction = ((wrapperWidth ?? 0) + minColumnWidth) / 2;\r
6376
- \r
6377
- useLayoutEffect(() => {\r
6378
- if (!isEditor) {\r
6379
- setDesignWidth(ARTICLE_DESIGN_WIDTH);\r
6380
- return;\r
6381
- }\r
6382
- \r
6383
- const syncDesignWidth = () => {\r
6384
- setDesignWidth(getEditorDesignWidth(containerRef.current));\r
6385
- };\r
6386
- \r
6387
- syncDesignWidth();\r
6388
- \r
6389
- const observed = containerRef.current;\r
6390
- if (!observed) {\r
6391
- return;\r
6392
- }\r
6393
- \r
6394
- const observer = new ResizeObserver(syncDesignWidth);\r
6395
- observer.observe(observed);\r
6396
- \r
6397
- let pageEl: HTMLElement | null = observed;\r
6398
- while (pageEl && !pageEl.style.getPropertyValue('--cntrl-article-width')) {\r
6399
- pageEl = pageEl.parentElement;\r
6400
- }\r
6401
- if (pageEl) {\r
6402
- observer.observe(pageEl);\r
6403
- }\r
6404
- \r
6405
- return () => observer.disconnect();\r
6406
- }, [isEditor, layoutId]);\r
6407
- \r
6408
- useEffect(() => {\r
6409
- setVisibleRowCount(undefined);\r
6410
- }, [cut, showCut, content, entriesCount]);\r
6411
- \r
6412
- const colorVars = buildColorVars(P, {\r
6413
- textColor,\r
6414
- backgroundColor,\r
6415
- dividerColor,\r
6416
- textHoverColor,\r
6417
- backgroundHoverColor,\r
6418
- dividerHoverColor\r
6419
- }, COLOR_VAR_MAP, STATE_KEYS);\r
6420
- \r
6421
- const stateClass = activeEvent && activeEvent !== 'default' ? \`\${P}-state-\${activeEvent}\` : '';\r
6422
- const entryHoverClass =\r
6423
- entryHoverEffect === 'Default'\r
6424
- ? \`\${P}-entry-hover-default\`\r
6425
- : entryHoverEffect === 'Blinds'\r
6426
- ? \`\${P}-entry-hover-blinds\`\r
6427
- : '';\r
6428
- const wrapperStateClasses = \`\${entryHoverClass} \${stateClass}\`.trim();\r
6429
- const showDividerTop = showVisibility?.[0] ?? false;\r
6430
- const showDividerBottom = showVisibility?.[1] ?? false;\r
6431
- \r
6432
- const prevSettingsRef = useRef(settings);\r
6433
- const prevLayoutIdRef = useRef(layoutId);\r
6434
- \r
6435
- useEffect(() => {\r
6436
- if (!onUpdateSettings || !isEditor) {\r
6437
- prevSettingsRef.current = settings;\r
6438
- prevLayoutIdRef.current = layoutId;\r
6439
- return;\r
6440
- }\r
6441
- \r
6442
- if (prevLayoutIdRef.current !== layoutId) {\r
6443
- prevSettingsRef.current = settings;\r
6444
- prevLayoutIdRef.current = layoutId;\r
6445
- return;\r
6446
- }\r
6447
- \r
6448
- const prevSettings = prevSettingsRef.current;\r
6449
- const updatedSettings = applyListSettingsChange(\r
6450
- settings,\r
6451
- prevSettings,\r
6452
- { designWidth },\r
6453
- );\r
6454
- \r
6455
- prevSettingsRef.current = settings;\r
6456
- \r
6457
- if (updatedSettings === settings) {\r
6458
- return;\r
6459
- }\r
6460
- \r
6461
- onUpdateSettings(updatedSettings);\r
6462
- }, [settings, onUpdateSettings, isEditor, layoutId, designWidth]);\r
6463
- \r
6464
- const columnWidthByKey = useMemo(\r
6465
- () => getColumnWidthsFromSettings(settings),\r
6466
- [\r
6467
- settings.AColumnWidth,\r
6468
- settings.BColumnWidth,\r
6469
- settings.CColumnWidth,\r
6470
- settings.DColumnWidth,\r
6471
- settings.EColumnWidth,\r
6472
- ],\r
6473
- );\r
6474
- \r
6475
- const columnPaddingLeftByKey = useMemo(\r
6476
- () => getNumericSettingValues(settings, COLUMN_PADDING_LEFT_KEYS),\r
6477
- [\r
6478
- settings.AColumnPaddingLeft,\r
6479
- settings.BColumnPaddingLeft,\r
6480
- settings.CColumnPaddingLeft,\r
6481
- settings.DColumnPaddingLeft,\r
6482
- settings.EColumnPaddingLeft,\r
6483
- ],\r
6484
- );\r
6485
- \r
6486
- const columnPaddingRightByKey = useMemo(\r
6487
- () => getNumericSettingValues(settings, COLUMN_PADDING_RIGHT_KEYS),\r
6488
- [\r
6489
- settings.AColumnPaddingRight,\r
6490
- settings.BColumnPaddingRight,\r
6491
- settings.CColumnPaddingRight,\r
6492
- settings.DColumnPaddingRight,\r
6493
- settings.EColumnPaddingRight,\r
6494
- ],\r
6495
- );\r
6496
- \r
6497
- const columnPaddingBottomByKey = useMemo(\r
6498
- () => getNumericSettingValues(settings, COLUMN_PADDING_BOTTOM_KEYS),\r
6499
- [\r
6500
- settings.AColumnPaddingBottom,\r
6501
- settings.BColumnPaddingBottom,\r
6502
- settings.CColumnPaddingBottom,\r
6503
- settings.DColumnPaddingBottom,\r
6504
- settings.EColumnPaddingBottom,\r
6505
- ],\r
6506
- );\r
6507
- \r
6508
- const columnContentOrder = useMemo((): typeof COLUMN_CONTENT_KEYS[number][] => {\r
6509
- if (Array.isArray(columnsOrder) && columnsOrder.length > 0) {\r
6510
- return columnsOrder as typeof COLUMN_CONTENT_KEYS[number][];\r
6511
- }\r
6512
- return [...COLUMN_CONTENT_KEYS];\r
6513
- }, [columnsOrder]);\r
6514
- \r
6515
- const listColumns = useMemo(\r
6516
- () => buildListColumns(\r
6517
- columnContentOrder,\r
6518
- columns,\r
6519
- columnWidthByKey,\r
6520
- columnPaddingLeftByKey,\r
6521
- columnPaddingRightByKey,\r
6522
- columnPaddingBottomByKey,\r
6523
- ),\r
6524
- [columnContentOrder, columns, columnWidthByKey, columnPaddingLeftByKey, columnPaddingRightByKey, columnPaddingBottomByKey],\r
6525
- );\r
6526
- \r
6527
- const resolvedContentWidth = getListEffectiveContentWidth(settings);\r
6528
- \r
6529
- const storedColumnWidths = useMemo(\r
6530
- () => COLUMN_WIDTH_KEYS.slice(0, columns).map((key) => columnWidthByKey[key]),\r
6531
- [columns, columnWidthByKey],\r
6532
- );\r
6533
- \r
6534
- const resolvedColumnWidths = useMemo(\r
6535
- () => resolveListColumnWidths(columns, resolvedContentWidth, columnWidthByKey),\r
6536
- [columns, resolvedContentWidth, columnWidthByKey],\r
6537
- );\r
6538
- \r
6539
- const effectiveColumnWidths = useMemo(\r
6540
- () => getEffectiveListColumnWidths(columns, resolvedContentWidth, columnWidthByKey),\r
6541
- [columns, resolvedContentWidth, columnWidthByKey],\r
6542
- );\r
6543
- \r
6544
- const effectiveColumnPaddings = useMemo(\r
6545
- () =>\r
6546
- listColumns.map((col, index) =>\r
6547
- resolveListColumnPadding(\r
6548
- effectiveColumnWidths[index] ?? 0,\r
6549
- col.paddingLeft,\r
6550
- col.paddingRight,\r
6551
- )),\r
6552
- [listColumns, effectiveColumnWidths],\r
6553
- );\r
6554
- \r
6555
- const allRows: ListItemRow[] = useMemo(() => {\r
6556
- const resEntriesCount = entriesCount === 0 ? Infinity : entriesCount;\r
6557
- const items = (content ?? []).slice(0, resEntriesCount);\r
6558
- \r
6559
- return items.map((item, index) => ({\r
6560
- id: index,\r
6561
- cells: Object.fromEntries(\r
6562
- COLUMN_CONTENT_KEYS.map((key) => [key, item[key] ?? ''])\r
6563
- ),\r
6564
- image: item.image,\r
6565
- link: item.link,\r
6566
- }));\r
6567
- }, [content, entriesCount]);\r
6568
- \r
6569
- const effectiveVisibleCount = cutEnabled\r
6570
- ? (visibleRowCount ?? cut)\r
6571
- : allRows.length;\r
6572
- \r
6573
- const visibleRows = useMemo(() => {\r
6574
- if (cutEnabled) {\r
6575
- return allRows.slice(0, effectiveVisibleCount);\r
6576
- }\r
6577
- return allRows;\r
6578
- }, [allRows, cutEnabled, effectiveVisibleCount]);\r
6579
- \r
6580
- const showCutLabel = cutEnabled && effectiveVisibleCount < allRows.length;\r
6581
- \r
6582
- const hasBetweenItemDividers = visibleRows.length > 1 || showCutLabel;\r
6583
- const dividerClassNames = [\r
6584
- showDividerTop ? \`\${P}-divider-top\` : '',\r
6585
- showDividerBottom || hasBetweenItemDividers ? \`\${P}-divider-bottom\` : '',\r
6586
- ].filter(Boolean).join(' ');\r
6587
- \r
6588
- const handleShowMore = () => {\r
6589
- const currentVisible = visibleRowCount ?? cut;\r
6590
- if (!showCut) {\r
6591
- setVisibleRowCount(allRows.length);\r
6592
- return;\r
6593
- }\r
6594
- setVisibleRowCount(Math.min(currentVisible + showCut, allRows.length));\r
6595
- };\r
6596
- \r
6597
- const scaled = (v: number) => scalingValue(v, isEditor ?? false);\r
6598
- const resolvedRowPaddingTop = isVerticalLayout\r
6599
- ? (rowPaddingTopB ?? 0)\r
6600
- : (rowPaddingTop ?? 0);\r
6601
- const resolvedRowPaddingBottom = rowPaddingBottom ?? 0;\r
6602
- const resolvedCellMinHeight = cellMinHeight ?? 0;\r
6603
- const rowPaddingTopControlKey = isVerticalLayout ? 'rowPaddingTopB' : 'rowPaddingTop';\r
6604
- const firstColumn = listColumns[0];\r
6605
- const lastColumn = listColumns[listColumns.length - 1];\r
6606
- const firstColumnEffectivePadding = effectiveColumnPaddings[0];\r
6607
- const lastColumnEffectivePadding = effectiveColumnPaddings[effectiveColumnPaddings.length - 1];\r
6608
- const firstColumnPaddingLeftWidth = firstColumn && firstColumnEffectivePadding\r
6609
- ? Math.max(firstColumnEffectivePadding.paddingLeft, COL_PADDING_HANDLE_WIDTH)\r
6610
- : 0;\r
6611
- const lastColumnPaddingRightWidth = lastColumn && lastColumnEffectivePadding\r
6612
- ? Math.max(lastColumnEffectivePadding.paddingRight, COL_PADDING_HANDLE_WIDTH)\r
6613
- : 0;\r
6614
- const columnsRightEdge = resolvedContentWidth;\r
6615
- \r
6616
- const getHoverImagePosition = (event: React.MouseEvent) => {\r
6617
- const container = containerRef.current;\r
6618
- if (!container) {\r
6619
- return { x: 0, y: 0 };\r
6620
- }\r
6621
- \r
6622
- const rect = container.getBoundingClientRect();\r
6623
- return {\r
6624
- x: event.clientX - rect.left + HOVER_IMAGE_CURSOR_OFFSET,\r
6625
- y: event.clientY - rect.top + HOVER_IMAGE_CURSOR_OFFSET,\r
6626
- };\r
6627
- };\r
6628
- \r
6629
- const handleRowMouseEnter = (row: ListItemRow, event: React.MouseEvent) => {\r
6630
- if (!showHoverImage) return;\r
6631
- \r
6632
- const image = row.image;\r
6633
- if (!image?.url) {\r
6634
- setHoverImage(null);\r
6635
- return;\r
6636
- }\r
6637
- \r
6638
- const { x, y } = getHoverImagePosition(event);\r
6639
- const minWidth = imageSize?.min ?? 80;\r
6640
- const maxWidth = imageSize?.max ?? 320;\r
6641
- const widthPx = hoverImage?.rowId === row.id\r
6642
- ? hoverImage.widthPx\r
6643
- : randomBetween(minWidth, maxWidth);\r
6644
- \r
6645
- setHoverImage({\r
6646
- rowId: row.id,\r
6647
- url: image.url,\r
6648
- objectFit: image.objectFit ?? 'cover',\r
6649
- widthPx,\r
6650
- x,\r
6651
- y,\r
6652
- });\r
6653
- };\r
6654
- \r
6655
- const handleWrapperMouseMove = (event: React.MouseEvent) => {\r
6656
- if (!showHoverImage || !hoverImage) return;\r
6657
- \r
6658
- const { x, y } = getHoverImagePosition(event);\r
6659
- setHoverImage((prev) => {\r
6660
- if (!prev) return prev;\r
6661
- if (prev.x === x && prev.y === y) return prev;\r
6662
- return { ...prev, x, y };\r
6663
- });\r
6664
- };\r
6665
- \r
6666
- const handleWrapperMouseLeave = () => {\r
6667
- setHoverImage(null);\r
6668
- };\r
6669
- \r
6670
- const hasBaselineColumn = useMemo(\r
6671
- () =>\r
6672
- !isVerticalLayout &&\r
6673
- COLUMN_TEXT_PREFIXES.some((prefix) => {\r
6674
- const columnLetter = prefix.charAt(0);\r
6675
- const valign = settings[\`\${prefix}VerticalAlign\` as ListColumnVerticalAlignKey];\r
6676
- return isActiveBaselineVAlign(valign, settings, columnLetter);\r
6677
- }),\r
6678
- [\r
6679
- isVerticalLayout,\r
6680
- settings,\r
6681
- settings.AColumnVerticalAlign,\r
6682
- settings.BColumnVerticalAlign,\r
6683
- settings.CColumnVerticalAlign,\r
6684
- settings.DColumnVerticalAlign,\r
6685
- settings.EColumnVerticalAlign,\r
6686
- ],\r
6687
- );\r
6688
- \r
6689
- useLayoutEffect(() => {\r
6690
- const container = containerRef.current;\r
6691
- if (!container) return;\r
6692
- \r
6693
- const clearBaselineStyles = () => {\r
6694
- container.querySelectorAll<HTMLElement>('[data-list-col]').forEach((el) => {\r
6695
- el.style.transform = '';\r
6696
- const listCol = el.querySelector<HTMLElement>(\`.\${P}-list-col\`);\r
6697
- if (listCol) {\r
6698
- listCol.style.minHeight = '';\r
6699
- listCol.style.height = '';\r
6700
- }\r
6701
- const title = el.querySelector<HTMLElement>(\`.\${P}-list-col-title\`);\r
6702
- if (title) {\r
6703
- title.style.transform = '';\r
6704
- }\r
6705
- });\r
6706
- };\r
6707
- \r
6708
- if (isVerticalLayout || !hasBaselineColumn) {\r
6709
- clearBaselineStyles();\r
6710
- return;\r
6711
- }\r
6712
- \r
6713
- const applyBaselines = () => {\r
6714
- container.querySelectorAll<HTMLElement>('[data-list-row]').forEach((rowEl) => {\r
6715
- const cols = Array.from(rowEl.querySelectorAll<HTMLElement>('[data-list-col]'));\r
6716
- cols.forEach((el) => {\r
6717
- el.style.transform = '';\r
6718
- const listCol = el.querySelector<HTMLElement>(\`.\${P}-list-col\`);\r
6719
- if (listCol) {\r
6720
- listCol.style.minHeight = '';\r
6721
- listCol.style.height = '';\r
6722
- }\r
6723
- const title = el.querySelector<HTMLElement>(\`.\${P}-list-col-title\`);\r
6724
- if (title) {\r
6725
- title.style.transform = '';\r
6726
- }\r
6727
- });\r
6728
- \r
6729
- syncRowListColHeights(rowEl, cols, \`\${P}-list-col\`);\r
6730
- void rowEl.offsetHeight;\r
6731
- const rowTop = rowEl.getBoundingClientRect().top;\r
6732
- \r
6733
- type ColInfo = {\r
6734
- el: HTMLElement;\r
6735
- titleEl: HTMLElement | null;\r
6736
- letter: string;\r
6737
- kind: string;\r
6738
- anchor: string | null;\r
6739
- };\r
6740
- \r
6741
- const probeClassName = \`\${P}-baseline-probe\`;\r
6742
- const byLetter = new Map<string, ColInfo>();\r
6743
- const infos: ColInfo[] = cols.map((el) => {\r
6744
- const titleEl = el.querySelector<HTMLElement>(\`.\${P}-list-col-title\`);\r
6745
- const info: ColInfo = {\r
6746
- el,\r
6747
- titleEl,\r
6748
- letter: el.getAttribute('data-col-letter') ?? '',\r
6749
- kind: el.getAttribute('data-valign') ?? 'top',\r
6750
- anchor: el.getAttribute('data-valign-anchor'),\r
6751
- };\r
6752
- byLetter.set(info.letter, info);\r
6753
- return info;\r
6754
- });\r
6755
- \r
6756
- const finalBaseline = new Map<string, number>();\r
6757
- const resolve = (info: ColInfo, stack: Set<string>): number => {\r
6758
- const cached = finalBaseline.get(info.letter);\r
6759
- if (cached !== undefined) return cached;\r
6760
- \r
6761
- const anchor = info.anchor ? byLetter.get(info.anchor) : undefined;\r
6762
- if (info.kind !== 'baseline' || !anchor || stack.has(info.letter)) {\r
6763
- const baseline = measureColumnFirstLineBaselineOffset(\r
6764
- info,\r
6765
- rowTop,\r
6766
- \`\${P}-list-col\`,\r
6767
- probeClassName,\r
6768
- );\r
6769
- finalBaseline.set(info.letter, baseline);\r
6770
- return baseline;\r
6771
- }\r
6772
- \r
6773
- stack.add(info.letter);\r
6774
- const anchorBaseline = resolve(anchor, stack);\r
6775
- stack.delete(info.letter);\r
6776
- \r
6777
- const followerNatural = measureColumnFirstLineBaselineOffset(\r
6778
- info,\r
6779
- rowTop,\r
6780
- \`\${P}-list-col\`,\r
6781
- probeClassName,\r
6782
- );\r
6783
- const shift = anchorBaseline - followerNatural;\r
6784
- applyBaselineTitleShift(info.titleEl, shift);\r
6785
- \r
6786
- const result = measureColumnFirstLineBaselineOffset(\r
6787
- info,\r
6788
- rowTop,\r
6789
- \`\${P}-list-col\`,\r
6790
- probeClassName,\r
6791
- );\r
6792
- finalBaseline.set(info.letter, result);\r
6793
- return result;\r
6794
- };\r
6795
- \r
6796
- infos.forEach((info) => resolve(info, new Set<string>()));\r
6797
- });\r
6798
- };\r
6799
- \r
6800
- applyBaselines();\r
6801
- \r
6802
- const observer = new ResizeObserver(() => applyBaselines());\r
6803
- observer.observe(container);\r
6804
- \r
6805
- let cancelled = false;\r
6806
- if (typeof document !== 'undefined' && document.fonts?.ready) {\r
6807
- document.fonts.ready.then(() => {\r
6808
- if (!cancelled) applyBaselines();\r
6809
- });\r
6810
- }\r
6811
- \r
6812
- return () => {\r
6813
- cancelled = true;\r
6814
- observer.disconnect();\r
6815
- clearBaselineStyles();\r
6816
- };\r
6817
- }, [\r
6818
- hasBaselineColumn,\r
6819
- isVerticalLayout,\r
6820
- settings,\r
6821
- content,\r
6822
- designWidth,\r
6823
- visibleRows,\r
6824
- effectiveColumnWidths,\r
6825
- ]);\r
6826
- \r
6827
- return (\r
6828
- <>\r
6829
- <style dangerouslySetInnerHTML={{ __html: getCSS(P) }} />\r
6830
- <div style={colorVars}>\r
6831
- <div\r
6832
- ref={containerRef}\r
6833
- className={\`\${P}-wrapper \${wrapperStateClasses}\${dividerClassNames ? \` \${dividerClassNames}\` : ''}\${isVerticalLayout ? \` \${P}-type-b\` : ''}\`.trim()}\r
6834
- style={{\r
6835
- width: scalingValue(wrapperWidth ?? 0, isEditor),\r
6836
- }}\r
6837
- onMouseMove={showHoverImage ? handleWrapperMouseMove : undefined}\r
6838
- onMouseLeave={showHoverImage ? handleWrapperMouseLeave : undefined}\r
6839
- >\r
6840
- <div style={{ width: '100%' }}>\r
6841
- {visibleRows.map((row, rowIdx) => {\r
6842
- const hasLink = (row.link?.length ?? 0) > 0;\r
6843
- const RowElement = hasLink ? 'a' : 'div';\r
6844
- const rowStyle = getEntryDividerWidths(\r
6845
- rowIdx,\r
6846
- visibleRows.length,\r
6847
- showDividerTop,\r
6848
- showDividerBottom,\r
6849
- showCutLabel,\r
6850
- dividerWidth ?? 0,\r
6851
- isEditor ?? false,\r
6852
- );\r
6853
- \r
6854
- return (\r
6855
- <RowElement\r
6856
- key={row.id}\r
6857
- className={\`\${P}-list-item\${hasLink ? \` \${P}-list-item-has-link\` : ''}\`}\r
6858
- {...(hasLink ? { href: row.link, target: '_blank' } : {})}\r
6859
- style={rowStyle}\r
6860
- onMouseEnter={showHoverImage ? (event) => handleRowMouseEnter(row, event) : undefined}\r
6861
- >\r
6862
- {(resolvedRowPaddingTop > 0 || showControls) && (\r
6863
- <div\r
6864
- {...(showControls ? {\r
6865
- 'data-controls': rowPaddingTopControlKey,\r
6866
- 'data-controls-axis': 'y',\r
6867
- 'data-controls-min': '0',\r
6868
- } : {})}\r
6869
- className={\`\${P}-row-padding-handle\`}\r
6870
- style={{ height: scaled(resolvedRowPaddingTop) }}\r
6871
- />\r
6872
- )}\r
6873
- <div\r
6874
- className={\`\${P}-list-cols-row\${isVerticalLayout ? '' : \` \${P}-list-cols-row-h\`}\`}\r
6875
- {...(isVerticalLayout ? {} : { 'data-list-row': '' })}\r
6876
- style={isVerticalLayout ? undefined : { minHeight: scaled(resolvedCellMinHeight) }}\r
6877
- >\r
6878
- {listColumns.map((col, colIndex) => {\r
6879
- const isLastColumn = colIndex === listColumns.length - 1;\r
6880
- const effectivePadding = effectiveColumnPaddings[colIndex];\r
6881
- const columnPaddingBottom = col.paddingBottom;\r
6882
- const hasColumnText = hasListColumnText(row.cells[col.key]);\r
6883
- const showColumnPaddingBottom = isVerticalLayout\r
6884
- && hasColumnText\r
6885
- && (columnPaddingBottom > 0 || showControls);\r
6886
- const columnSizeStyle = isVerticalLayout\r
6887
- ? { minHeight: scaled(resolvedCellMinHeight) }\r
6888
- : (isLastColumn ? {} : { width: scaled(effectiveColumnWidths[colIndex]) });\r
6889
- const columnPaddingStyle = isVerticalLayout\r
6890
- ? {\r
6891
- paddingLeft: scaled(effectiveTextPaddingLR),\r
6892
- paddingRight: scaled(effectiveTextPaddingLR),\r
6893
- }\r
6894
- : {\r
6895
- paddingLeft: scaled(effectivePadding.paddingLeft),\r
6896
- paddingRight: scaled(effectivePadding.paddingRight),\r
6897
- };\r
6898
- const columnLetter = col.textPrefix.charAt(0);\r
6899
- const vAlign = isVerticalLayout\r
6900
- ? { kind: 'top' as const }\r
6901
- : resolveColumnVerticalAlign(\r
6902
- settings[\`\${col.textPrefix}VerticalAlign\` as ListColumnVerticalAlignKey],\r
6903
- settings,\r
6904
- columnLetter,\r
6905
- );\r
6906
- \r
6907
- return (\r
6908
- <div\r
6909
- key={col.key}\r
6910
- {...(isVerticalLayout\r
6911
- ? {}\r
6912
- : {\r
6913
- 'data-list-col': '',\r
6914
- 'data-col-letter': columnLetter,\r
6915
- 'data-valign': vAlign.kind,\r
6916
- ...(vAlign.kind === 'baseline'\r
6917
- ? { 'data-valign-anchor': vAlign.anchorLetter }\r
6918
- : {}),\r
6919
- })}\r
6920
- >\r
6921
- <div\r
6922
- className={\`\${P}-list-col\${isLastColumn ? \` \${P}-list-col-last\` : ''}\`}\r
6923
- style={{\r
6924
- ...columnPaddingStyle,\r
6925
- ...columnSizeStyle,\r
6926
- }}\r
6927
- data-test={col.width}\r
6928
- >\r
6929
- <span\r
6930
- className={getListColumnTitleClassName(\r
6931
- settings,\r
6932
- col.textPrefix,\r
6933
- \`\${P}-list-col-title\`,\r
6934
- \`\${P}-text-tight-leading\`,\r
6935
- )}\r
6936
- style={{\r
6937
- ...listColumnTextFieldsToCss(resolveListColumnTextFields(settings, col.textPrefix), isEditor),\r
6938
- ...getListColumnTitleVars(settings, col.textPrefix, P, isEditor),\r
6939
- ...(!isVerticalLayout ? vAlignToTitleStyle(vAlign.kind) : {}),\r
6940
- }}\r
6941
- >\r
6942
- {row.cells[col.key] ?? null}\r
6943
- </span>\r
6944
- </div>\r
6945
- {showColumnPaddingBottom && (\r
6946
- <div\r
6947
- {...(showControls ? {\r
6948
- 'data-controls': col.paddingBottomKey,\r
6949
- 'data-controls-axis': 'y',\r
6950
- 'data-controls-min': '0',\r
6951
- } : {})}\r
6952
- className={\`\${P}-row-padding-handle\`}\r
6953
- style={{ height: scaled(columnPaddingBottom) }}\r
6954
- />\r
6955
- )}\r
6956
- </div>\r
6957
- );\r
6958
- })}\r
6959
- </div>\r
6960
- {!isVerticalLayout && (resolvedRowPaddingBottom > 0 || showControls) && (\r
6961
- <div\r
6962
- {...(showControls ? {\r
6963
- 'data-controls': 'rowPaddingBottom',\r
6964
- 'data-controls-axis': 'y',\r
6965
- 'data-controls-min': '0',\r
6966
- } : {})}\r
6967
- className={\`\${P}-row-padding-handle\`}\r
6968
- style={{ height: scaled(resolvedRowPaddingBottom) }}\r
6969
- />\r
6970
- )}\r
6971
- </RowElement>\r
6972
- );\r
6973
- })}\r
6974
- {showCutLabel && (\r
6975
- <button\r
6976
- type="button"\r
6977
- className={\`\${P}-cut-item\`}\r
6978
- style={{\r
6979
- minHeight: scaled(cutCellMinHeight ?? 0),\r
6980
- ...getCutItemDividerWidths(\r
6981
- showDividerBottom,\r
6982
- dividerWidth ?? 0,\r
6983
- isEditor ?? false,\r
6984
- ),\r
6985
- }}\r
6986
- onClick={handleShowMore}\r
6987
- >\r
6988
- <div\r
6989
- className={\`\${P}-list-cols-row\`}\r
6990
- style={\r
6991
- isVerticalLayout\r
6992
- ? {\r
6993
- paddingLeft: scaled(effectiveTextPaddingLR),\r
6994
- paddingRight: scaled(effectiveTextPaddingLR),\r
6995
- }\r
6996
- : { justifyContent: 'center' }\r
6997
- }\r
6998
- >\r
6999
- <span\r
7000
- className={getListColumnTitleClassName(\r
7001
- settings,\r
7002
- CUT_LABEL_TEXT_PREFIX,\r
7003
- \`\${P}-cut-label\`,\r
7004
- \`\${P}-text-tight-leading\`,\r
7005
- )}\r
7006
- style={{\r
7007
- ...listColumnTextFieldsToCss(resolveListColumnTextFields(settings, CUT_LABEL_TEXT_PREFIX), isEditor),\r
7008
- ...getListColumnTitleVars(settings, CUT_LABEL_TEXT_PREFIX, P, isEditor),\r
7009
- }}\r
7010
- >\r
7011
- {cutLabel}\r
7012
- </span>\r
7013
- </div>\r
7014
- </button>\r
7015
- )}\r
7016
- </div>\r
7017
- {showControls && !isVerticalLayout && firstColumn && lastColumn && (\r
7018
- <div key="column-edge-padding-handles" style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>\r
7019
- <div\r
7020
- data-controls={firstColumn.paddingLeftKey}\r
7021
- data-controls-axis="x"\r
7022
- data-controls-variant="column-padding"\r
7023
- data-controls-min="0"\r
7024
- data-controls-max-fraction={String(\r
7025
- effectiveColumnWidths[0] - (firstColumnEffectivePadding?.paddingRight ?? 0),\r
7026
- )}\r
7027
- data-controls-static-handle=""\r
7028
- className={\`\${P}-padding-control-handle\`}\r
7029
- style={{\r
7030
- position: 'absolute',\r
7031
- top: 0,\r
7032
- left: 0,\r
7033
- width: scaled(firstColumnPaddingLeftWidth),\r
7034
- height: '100%',\r
7035
- pointerEvents: 'auto',\r
7036
- zIndex: 2,\r
7037
- }}\r
7038
- />\r
7039
- <div\r
7040
- data-controls={lastColumn.paddingRightKey}\r
7041
- data-controls-axis="x"\r
7042
- data-controls-variant="column-padding"\r
7043
- data-controls-reverse=""\r
7044
- data-controls-min="0"\r
7045
- data-controls-max-fraction={String(\r
7046
- effectiveColumnWidths[listColumns.length - 1]\r
7047
- - (lastColumnEffectivePadding?.paddingLeft ?? 0),\r
7048
- )}\r
7049
- data-controls-static-handle=""\r
7050
- className={\`\${P}-padding-control-handle\`}\r
7051
- style={{\r
7052
- position: 'absolute',\r
7053
- top: 0,\r
7054
- left: scaled(columnsRightEdge - lastColumnPaddingRightWidth),\r
7055
- width: scaled(lastColumnPaddingRightWidth),\r
7056
- height: '100%',\r
7057
- pointerEvents: 'auto',\r
7058
- zIndex: 2,\r
7059
- }}\r
7060
- />\r
7061
- </div>\r
7062
- )}\r
7063
- {showControls && !isVerticalLayout && listColumns.slice(0, -1).map((col, colIndex) => {\r
7064
- const nextCol = listColumns[colIndex + 1];\r
7065
- const maxColumnWidth = getColumnMaxWidth(\r
7066
- colIndex,\r
7067
- resolvedColumnWidths,\r
7068
- storedColumnWidths,\r
7069
- resolvedContentWidth,\r
7070
- );\r
7071
- const boundaryOffset = resolvedColumnWidths.slice(0, colIndex + 1).reduce((sum, width) => sum + width, 0);\r
7072
- const colEffectivePadding = effectiveColumnPaddings[colIndex];\r
7073
- const nextColEffectivePadding = effectiveColumnPaddings[colIndex + 1];\r
7074
- const paddingRightWidth = Math.max(\r
7075
- colEffectivePadding.paddingRight,\r
7076
- COL_PADDING_HANDLE_WIDTH,\r
7077
- );\r
7078
- const paddingLeftWidth = Math.max(\r
7079
- nextColEffectivePadding.paddingLeft,\r
7080
- COL_PADDING_HANDLE_WIDTH,\r
7081
- );\r
7082
- const columnWidthHandleOffset = boundaryOffset - COL_RESIZE_HANDLE_WIDTH / 2;\r
7083
- \r
7084
- return (\r
7085
- <div key={\`\${col.widthKey}-junction\`} style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>\r
7086
- <div\r
7087
- data-controls={col.paddingRightKey}\r
7088
- data-controls-axis="x"\r
7089
- data-controls-variant="column-padding"\r
7090
- data-controls-reverse=""\r
7091
- data-controls-min="0"\r
7092
- data-controls-max-fraction={String(\r
7093
- effectiveColumnWidths[colIndex] - colEffectivePadding.paddingLeft,\r
7094
- )}\r
7095
- data-controls-static-handle=""\r
7096
- className={\`\${P}-padding-control-handle\`}\r
7097
- style={{\r
7098
- position: 'absolute',\r
7099
- top: 0,\r
7100
- left: scaled(boundaryOffset - paddingRightWidth),\r
7101
- width: scaled(paddingRightWidth),\r
7102
- height: '100%',\r
7103
- pointerEvents: 'auto',\r
7104
- zIndex: 2,\r
7105
- }}\r
7106
- />\r
7107
- <div\r
7108
- data-controls={col.widthKey}\r
7109
- data-controls-axis="x"\r
7110
- data-controls-min={String(MIN_COLUMN_WIDTH_PX)}\r
7111
- data-controls-max-fraction={String(maxColumnWidth)}\r
7112
- data-controls-variant="column-width"\r
7113
- className={\`\${P}-col-resize-handle\`}\r
7114
- style={{\r
7115
- position: 'absolute',\r
7116
- top: '0px',\r
7117
- left: scaled(columnWidthHandleOffset),\r
7118
- width: scaled(COL_RESIZE_HANDLE_WIDTH),\r
7119
- height: 'calc(100%)',\r
7120
- pointerEvents: 'auto',\r
7121
- zIndex: 4,\r
7122
- }}\r
7123
- />\r
7124
- <div\r
7125
- data-controls={nextCol.paddingLeftKey}\r
7126
- data-controls-axis="x"\r
7127
- data-controls-variant="column-padding"\r
7128
- data-controls-min="0"\r
7129
- data-controls-max-fraction={String(\r
7130
- effectiveColumnWidths[colIndex + 1] - nextColEffectivePadding.paddingRight,\r
7131
- )}\r
7132
- data-controls-static-handle=""\r
7133
- className={\`\${P}-padding-control-handle\`}\r
7134
- style={{\r
7135
- position: 'absolute',\r
7136
- top: 0,\r
7137
- left: scaled(boundaryOffset),\r
7138
- width: scaled(paddingLeftWidth),\r
7139
- height: '100%',\r
7140
- pointerEvents: 'auto',\r
7141
- zIndex: 2,\r
7142
- }}\r
7143
- />\r
7144
- </div>\r
7145
- );\r
7146
- })}\r
7147
- {showControls && isVerticalLayout && (\r
7148
- <div key="text-padding-lr-handles" style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>\r
7149
- <div\r
7150
- data-controls="textPaddingLR"\r
7151
- data-controls-paired=""\r
7152
- data-controls-axis="x"\r
7153
- data-controls-min="0"\r
7154
- data-controls-max-fraction={String(textPaddingLRMaxFraction)}\r
7155
- data-controls-static-handle=""\r
7156
- className={\`\${P}-text-padding-lr-handle\`}\r
7157
- style={{\r
7158
- position: 'absolute',\r
7159
- top: 0,\r
7160
- left: 0,\r
7161
- width: scaled(textPaddingLRHandleWidth),\r
7162
- height: '100%',\r
7163
- pointerEvents: 'auto',\r
7164
- zIndex: 2,\r
7165
- }}\r
7166
- />\r
7167
- <div\r
7168
- data-controls="textPaddingLR"\r
7169
- data-controls-paired=""\r
7170
- data-controls-axis="x"\r
7171
- data-controls-reverse=""\r
7172
- data-controls-min="0"\r
7173
- data-controls-max-fraction={String(textPaddingLRMaxFraction)}\r
7174
- data-controls-static-handle=""\r
7175
- className={\`\${P}-text-padding-lr-handle\`}\r
7176
- style={{\r
7177
- position: 'absolute',\r
7178
- top: 0,\r
7179
- left: scaled(Math.max(textPaddingLRHandleWidth, resolvedContentWidth - textPaddingLRHandleWidth)),\r
7180
- width: scaled(textPaddingLRHandleWidth),\r
7181
- height: '100%',\r
7182
- pointerEvents: 'auto',\r
7183
- zIndex: 2,\r
7184
- }}\r
7185
- />\r
7186
- </div>\r
7187
- )}\r
7188
- {showHoverImage && hoverImage && (\r
7189
- <img\r
7190
- className={\`\${P}-hover-image\`}\r
7191
- src={hoverImage.url}\r
7192
- alt=""\r
7193
- style={{\r
7194
- width: sv(hoverImage.widthPx),\r
7195
- objectFit: hoverImage.objectFit,\r
7196
- left: hoverImage.x,\r
7197
- top: hoverImage.y,\r
7198
- }}\r
7199
- />\r
7200
- )}\r
7201
- </div>\r
7202
- </div>\r
7203
- </>\r
7204
- );\r
7205
- }\r
4665
+ `}const Pt=["AColumn","BColumnWidth","CColumnWidth","DColumnWidth","EColumnWidth"],eo=["AColumn","BColumn","CColumn","DColumn","EColumn"],vt="cutLabel",Pn=[...eo,vt],to=["A","B","C","D","E"];function Ai(e){return`${e}ColumnVerticalAlign`}const Xc=["Top","Center","Bottom"];function Zc(e){const t=String(e??"Top").trim();return t.toLowerCase().startsWith("baseline")?!1:t==="Top"||t==="Center"||t==="Bottom"}function Jc(e){const t=String(e??"").trim();if(!t.toLowerCase().startsWith("baseline"))return null;const n=t.slice(-1).toUpperCase();return to.includes(n)?n:null}function Ri(e,t,n){const r=Jc(e);return r?r===t?!1:Zc(n[Ai(r)]):!0}function Rr(e){const t=String(e??"Top").trim();if(t.toLowerCase().startsWith("baseline")){const n=t.slice(-1).toUpperCase();return to.includes(n)?{kind:"baseline",anchorLetter:n}:{kind:"top"}}return t==="Center"?{kind:"center"}:t==="Bottom"?{kind:"bottom"}:{kind:"top"}}function Qc(e,t,n){if(Ii(e,t,n))return Rr(e);const r=Rr(e);return r.kind==="baseline"?{kind:"top"}:r}function Ii(e,t,n){return Ri(e,n,t)?Rr(e).kind==="baseline":!1}function ed(e){if(e.type==="B")return null;const t={};let n=!1;for(const r of to){const o=Ai(r),s=e[o];Ri(s,r,e)||(t[o]="Top",n=!0)}return n?t:null}function td(e){return e==="center"?{marginTop:"auto",marginBottom:"auto"}:e==="bottom"?{marginTop:"auto"}:{}}function nd(e,t){const n=document.createElement("i");n.className=t,n.setAttribute("aria-hidden","true"),e.prepend(n);const{top:r}=e.getBoundingClientRect(),{bottom:o}=n.getBoundingClientRect(),s=o-r;return n.remove(),s}function br(e,t,n,r){const o=e.titleEl;if(!o)return 0;const s=o.closest(`.${n}`);if(!s)return 0;const i=nd(o,r);if(e.kind==="baseline")return o.getBoundingClientRect().top-t+i;const a=s.getBoundingClientRect(),c=o.getBoundingClientRect().height;let u=0;return e.kind==="center"?u=(a.height-c)/2:e.kind==="bottom"&&(u=a.height-c),a.top-t+u+i}function rd(e,t,n){const r=e.getBoundingClientRect().height;return r<=0?0:(t.forEach(o=>{const s=o.querySelector(`.${n}`);s&&(s.style.minHeight=`${r}px`,s.style.height=`${r}px`)}),e.offsetHeight,r)}function od(e,t){return!e||!t?(e&&(e.style.transform=""),0):(e.style.transform=`translateY(${t}px)`,t)}const id={AColumn:"AColumn",BColumnWidth:"BColumn",CColumnWidth:"CColumn",DColumnWidth:"DColumn",EColumnWidth:"EColumn"},ad=["textFontFamily","textFontSettings","textFontSize","textLineHeight","textLetterSpacing","textWordSpacing","textTextAppearance"];function we(e,t){return`${e}${t.replace(/^text/,"Text")}`}function Zn(e,t){const n=r=>{const o=we(t,r),s=e[o];return s!==void 0?s:e[r]};return{textFontFamily:n("textFontFamily")??"Arial",textFontSettings:n("textFontSettings")??{fontWeight:400,fontStyle:"normal"},textFontSize:n("textFontSize"),textLineHeight:n("textLineHeight"),textLetterSpacing:n("textLetterSpacing")??0,textWordSpacing:n("textWordSpacing")??0,textTextAppearance:n("textTextAppearance"),textColor:e.textColor}}function Ho(e,t){var r,o;const n={fontSettings:{fontFamily:e.textFontFamily,fontWeight:((r=e.textFontSettings)==null?void 0:r.fontWeight)??400,fontStyle:((o=e.textFontSettings)==null?void 0:o.fontStyle)??"normal"},fontSize:e.textFontSize??.01,lineHeight:e.textLineHeight,letterSpacing:e.textLetterSpacing,wordSpacing:e.textWordSpacing,textAppearance:e.textTextAppearance,color:e.textColor??"#767676"};return yt(Je(n,t))}function Oo(e,t,n,r){const o=Zn(e,t),s=o.textFontSize??.01,i=o.textLineHeight;return i!==void 0&&i<s?`${n} ${r}`:n}function Bo(e,t,n,r){const o=Zn(e,t),s=o.textFontSize??.01,i=o.textLineHeight;return i===void 0||i>=s?{}:{[`--${n}-title-leading-gap`]:T.scalingValue((s-i)/2,r)}}function sd(e,t){const n={};let r=!1;for(const o of ad)if(e[o]!==t[o]&&e[o]!==void 0){r=!0;for(const s of Pn)Object.assign(n,{[we(s,o)]:e[o]})}return r?n:null}const nt=["AColumnWidth","BColumnWidth","CColumnWidth","DColumnWidth","EColumnWidth"],Zt=["AColumnPaddingLeft","BColumnPaddingLeft","CColumnPaddingLeft","DColumnPaddingLeft","EColumnPaddingLeft"],Jt=["AColumnPaddingRight","BColumnPaddingRight","CColumnPaddingRight","DColumnPaddingRight","EColumnPaddingRight"],Qt=["AColumnPaddingBottom","BColumnPaddingBottom","CColumnPaddingBottom","DColumnPaddingBottom","EColumnPaddingBottom"],ld={textColor:"text-color",backgroundColor:"background-color",dividerColor:"divider-color",textHoverColor:"text-hover-color",backgroundHoverColor:"background-hover-color",dividerHoverColor:"divider-hover-color"},cd=["hover","focus","filled","success","error"],Vo=.004,ln=.004,no=50,bn=1440,xn=no/bn;function Wi(e){const t=typeof e=="number"&&e>0?e:bn;return no/t}function dd(e){let t=e??null;for(;t;){const n=t.style.getPropertyValue("--cntrl-article-width").trim();if(n){const o=parseFloat(n);if(Number.isFinite(o)&&o>0)return o}const r=getComputedStyle(t).getPropertyValue("--cntrl-article-width").trim();if(r){const o=parseFloat(r);if(Number.isFinite(o)&&o>0)return o}t=t.parentElement}return bn}const Fi={AColumnWidth:.02,BColumnWidth:.02,CColumnWidth:.02,DColumnWidth:.02,EColumnWidth:.02};function jn(e){const t=typeof e.wrapperWidth=="number"?e.wrapperWidth:1;return Math.max(0,t)}function ud(e,t=1){const n=t/e;return Object.fromEntries(nt.map(r=>[r,n]))}function pd(){return Object.fromEntries([...Zt.map(e=>[e,0]),...Jt.map(e=>[e,0])])}function md(){return Object.fromEntries(Qt.map(e=>[e,0]))}function Nn(e){return Object.fromEntries(nt.map(t=>[t,typeof e[t]=="number"?e[t]:Fi[t]]))}function ki(e,t,n){const r=e-xn,o=t+n;if(o<=0||o<=r)return{paddingLeft:t,paddingRight:n};if(r<=0)return{paddingLeft:0,paddingRight:0};const s=r/o;return{paddingLeft:t*s,paddingRight:n*s}}function Kn(e,t,n){const r=ro(e,t,n);if(e<=0)return[];const o=r.slice(0,e-1).reduce((s,i)=>s+i,0);return[...r.slice(0,e-1),Math.max(0,t-o)]}function gd(e,t,n){const r={};for(let o=0;o<e;o+=1){const s=Zt[o],i=Jt[o],a=typeof n[s]=="number"?n[s]:0,c=typeof n[i]=="number"?n[i]:0,u=ki(t[o]??0,a,c);u.paddingLeft!==a&&(r[s]=u.paddingLeft),u.paddingRight!==c&&(r[i]=u.paddingRight)}return r}function ro(e,t,n){if(e<=0)return[];const r=nt.slice(0,e).map(u=>n[u]);if(e===1)return r;const o=r.slice(0,e-1),i=o.reduce((u,d)=>u+d,0)+xn;if(t>=i)return r;const a=[...o];let c=i-t;for(let u=a.length-1;u>=0&&c>0;u-=1){const d=a[u]-xn;if(d<=0)continue;const $=Math.min(c,d);a[u]-=$,c-=$}return[...a,r[e-1]]}function hd(e,t,n){if(e<=1)return{};const r=ro(e,t,n),o={};for(let s=0;s<e-1;s+=1){const i=nt[s];r[s]!==n[i]&&(o[i]=r[s])}return o}function Do(e){return Array.isArray(e.columnsOrder)&&e.columnsOrder.length>0?e.columnsOrder:[...Pt]}function fd(e,t){return e.length!==t.length?!1:e.every((n,r)=>n===t[r])}function yd(e,t,n,r){const o=Math.min(r,e.length,nt.length),s={};for(let i=0;i<o;i+=1){const a=e[i],c=t.indexOf(a);if(c===-1)continue;const u=nt[c],d=Zt[c],$=Jt[c],h=Qt[c],f=nt[i],m=Zt[i],g=Jt[i],C=Qt[i],y=n[u],x=n[d],P=n[$],L=n[h];typeof y=="number"&&(s[f]=y),typeof x=="number"&&(s[m]=x),typeof P=="number"&&(s[g]=P),typeof L=="number"&&(s[C]=L)}return s}function vd(e,t,n){const r=sd(e,t);r&&(e={...e,...r});const o=ed(e);o&&(e={...e,...o});const s=Wi(n==null?void 0:n.designWidth),i=e.columns,a=t.columns,c=jn(e),u=jn(t),d=e.type==="B"||e.type===void 0&&t.type==="B",$=typeof i=="number"?i:typeof a=="number"?a:Pt.length,h=L=>{if(d)return L;const _=Nn({...t,...L}),E=jn(L),v=Kn($,E,_),S=gd($,v,{...t,...L});return Object.keys(S).length===0?L:{...L,...S}};if(typeof i=="number"&&i!==a){const L={...e,...ud(i,c),...pd()};if(d)for(const _ of Qt)typeof t[_]=="number"&&(L[_]=t[_]);else Object.assign(L,md());return L}const f=Do(e),m=Do(t);if(!fd(f,m))return h({...e,...yd(f,m,t,$)});if(c<u&&typeof $=="number"&&!d){const L=Nn({...t,...e});return h({...e,...hd($,c,L)})}if(d){const L=typeof e.textPaddingLR=="number"?e.textPaddingLR:0,_=Math.max(0,(c-s)/2);return L>_?{...e,textPaddingLR:_}:e}const g=Nn({...t,...e}),C=Kn($,u,Nn(t)),x=Kn($,c,g).some((L,_)=>L<(C[_]??L)),P=nt.some(L=>{const _=e[L],E=t[L];return typeof _=="number"&&typeof E=="number"&&_!==E});return x||P?h(e):e}function bd(e,t,n,r){const o=t.slice(0,e).reduce((i,a)=>i+a,0),s=n.slice(e+1,t.length-1).reduce((i,a)=>i+a,0);return Math.max(xn,r-o-s-xn)}function xd(e,t){return Math.random()*(t-e)+e}function Cd(e){return Object.fromEntries(nt.map(t=>[t,typeof e[t]=="number"?e[t]:Fi[t]]))}function xr(e,t,n=0){return Object.fromEntries(t.map(r=>[r,typeof e[r]=="number"?e[r]:n]))}function Sd(e,t,n,r,o,s){return e.slice(0,t).map((i,a)=>{const c=Zt[a],u=Jt[a],d=Qt[a];return{key:i,textPrefix:id[i],widthKey:nt[a],width:n[nt[a]],paddingLeftKey:c,paddingRightKey:u,paddingBottomKey:d,paddingLeft:r[c],paddingRight:o[u],paddingBottom:s[d]}})}function wd({settings:e,content:t,isEditor:n,isPreviewMode:r,activeEvent:o,layoutId:s,onUpdateSettings:i}){const{prefix:a}=T.useScopedStyles(),c=!!(n&&r),{columns:u,type:d,wrapperWidth:$,entriesCount:h,cellMinHeight:f,dividerWidth:m,showVisibility:g,cut:C,showCut:y,cutCellMinHeight:x,cutLabel:P,imageSize:L,imageOnHover:_,entryHoverEffect:E,rowPaddingTop:v,rowPaddingBottom:S,rowPaddingTopB:F,columnsOrder:V,textPaddingLR:A,textColor:O,textFontFamily:D,textFontSettings:j,textFontSize:U,textLineHeight:w,textLetterSpacing:N,textWordSpacing:k,textTextAppearance:M,backgroundColor:R,dividerColor:B,textHoverColor:te,backgroundHoverColor:ue,dividerHoverColor:ie}=e,[me,H]=p.useState(void 0),[Q,G]=p.useState(null),Y=_==="On"&&(!n||r),oe=(C??0)>0,W=d==="B",ne=p.useRef(null),[I,b]=p.useState(bn),z=Wi(I),q=Math.max(0,(($??0)-z)/2),J=Math.min(A??0,q),se=Math.max(J,ln),le=(($??0)+z)/2;p.useLayoutEffect(()=>{if(!n){b(bn);return}const ge=()=>{b(dd(ne.current))};ge();const xe=ne.current;if(!xe)return;const Se=new ResizeObserver(ge);Se.observe(xe);let Re=xe;for(;Re&&!Re.style.getPropertyValue("--cntrl-article-width");)Re=Re.parentElement;return Re&&Se.observe(Re),()=>Se.disconnect()},[n,s]),p.useEffect(()=>{H(void 0)},[C,y,t,h]);const ce=T.buildColorVars(a,{textColor:O,backgroundColor:R,dividerColor:B,textHoverColor:te,backgroundHoverColor:ue,dividerHoverColor:ie},ld,cd),he=o&&o!=="default"?`${a}-state-${o}`:"",ee=`${E==="Default"?`${a}-entry-hover-default`:E==="Blinds"?`${a}-entry-hover-blinds`:""} ${he}`.trim(),Z=(g==null?void 0:g[0])??!1,de=(g==null?void 0:g[1])??!1,re=p.useRef(e),pe=p.useRef(s);p.useEffect(()=>{if(!i||!n){re.current=e,pe.current=s;return}if(pe.current!==s){re.current=e,pe.current=s;return}const ge=re.current,xe=vd(e,ge,{designWidth:I});re.current=e,xe!==e&&i(xe)},[e,i,n,s,I]);const ve=p.useMemo(()=>Cd(e),[e.AColumnWidth,e.BColumnWidth,e.CColumnWidth,e.DColumnWidth,e.EColumnWidth]),Pe=p.useMemo(()=>xr(e,Zt),[e.AColumnPaddingLeft,e.BColumnPaddingLeft,e.CColumnPaddingLeft,e.DColumnPaddingLeft,e.EColumnPaddingLeft]),Ke=p.useMemo(()=>xr(e,Jt),[e.AColumnPaddingRight,e.BColumnPaddingRight,e.CColumnPaddingRight,e.DColumnPaddingRight,e.EColumnPaddingRight]),Ge=p.useMemo(()=>xr(e,Qt),[e.AColumnPaddingBottom,e.BColumnPaddingBottom,e.CColumnPaddingBottom,e.DColumnPaddingBottom,e.EColumnPaddingBottom]),$e=p.useMemo(()=>Array.isArray(V)&&V.length>0?V:[...Pt],[V]),Ae=p.useMemo(()=>Sd($e,u,ve,Pe,Ke,Ge),[$e,u,ve,Pe,Ke,Ge]),Me=jn(e),Ie=p.useMemo(()=>nt.slice(0,u).map(ge=>ve[ge]),[u,ve]),Ve=p.useMemo(()=>ro(u,Me,ve),[u,Me,ve]),ye=p.useMemo(()=>Kn(u,Me,ve),[u,Me,ve]),ke=p.useMemo(()=>Ae.map((ge,xe)=>ki(ye[xe]??0,ge.paddingLeft,ge.paddingRight)),[Ae,ye]),He=p.useMemo(()=>{const ge=h===0?1/0:h;return(t??[]).slice(0,ge).map((Se,Re)=>({id:Re,cells:Object.fromEntries(Pt.map(Xe=>[Xe,Se[Xe]??""])),image:Se.image,link:Se.link}))},[t,h]),Oe=oe?me??C:He.length,De=p.useMemo(()=>oe?He.slice(0,Oe):He,[He,oe,Oe]),Qe=oe&&Oe<He.length,Ct=De.length>1||Qe,lt=[Z?`${a}-divider-top`:"",de||Ct?`${a}-divider-bottom`:""].filter(Boolean).join(" "),dr=()=>{const ge=me??C;if(!y){H(He.length);return}H(Math.min(ge+y,He.length))},Ee=ge=>T.scalingValue(ge,n??!1),An=W?F??0:v??0,rn=S??0,on=f??0,ur=W?"rowPaddingTopB":"rowPaddingTop",be=Ae[0],Ye=Ae[Ae.length-1],ze=ke[0],Ne=ke[ke.length-1],St=be&&ze?Math.max(ze.paddingLeft,ln):0,oo=Ye&&Ne?Math.max(Ne.paddingRight,ln):0,Ni=Me,io=ge=>{const xe=ne.current;if(!xe)return{x:0,y:0};const Se=xe.getBoundingClientRect();return{x:ge.clientX-Se.left+No,y:ge.clientY-Se.top+No}},Hi=(ge,xe)=>{if(!Y)return;const Se=ge.image;if(!(Se!=null&&Se.url)){G(null);return}const{x:Re,y:Xe}=io(xe),ct=(L==null?void 0:L.min)??80,Te=(L==null?void 0:L.max)??320,Be=(Q==null?void 0:Q.rowId)===ge.id?Q.widthPx:xd(ct,Te);G({rowId:ge.id,url:Se.url,objectFit:Se.objectFit??"cover",widthPx:Be,x:Re,y:Xe})},Oi=ge=>{if(!Y||!Q)return;const{x:xe,y:Se}=io(ge);G(Re=>!Re||Re.x===xe&&Re.y===Se?Re:{...Re,x:xe,y:Se})},Bi=()=>{G(null)},ao=p.useMemo(()=>!W&&eo.some(ge=>{const xe=ge.charAt(0),Se=e[`${ge}VerticalAlign`];return Ii(Se,e,xe)}),[W,e,e.AColumnVerticalAlign,e.BColumnVerticalAlign,e.CColumnVerticalAlign,e.DColumnVerticalAlign,e.EColumnVerticalAlign]);return p.useLayoutEffect(()=>{var ct;const ge=ne.current;if(!ge)return;const xe=()=>{ge.querySelectorAll("[data-list-col]").forEach(Te=>{Te.style.transform="";const Be=Te.querySelector(`.${a}-list-col`);Be&&(Be.style.minHeight="",Be.style.height="");const ot=Te.querySelector(`.${a}-list-col-title`);ot&&(ot.style.transform="")})};if(W||!ao){xe();return}const Se=()=>{ge.querySelectorAll("[data-list-row]").forEach(Te=>{const Be=Array.from(Te.querySelectorAll("[data-list-col]"));Be.forEach(Le=>{Le.style.transform="";const Ze=Le.querySelector(`.${a}-list-col`);Ze&&(Ze.style.minHeight="",Ze.style.height="");const Ue=Le.querySelector(`.${a}-list-col-title`);Ue&&(Ue.style.transform="")}),rd(Te,Be,`${a}-list-col`),Te.offsetHeight;const ot=Te.getBoundingClientRect().top,wt=`${a}-baseline-probe`,Wt=new Map,an=Be.map(Le=>{const Ze=Le.querySelector(`.${a}-list-col-title`),Ue={el:Le,titleEl:Ze,letter:Le.getAttribute("data-col-letter")??"",kind:Le.getAttribute("data-valign")??"top",anchor:Le.getAttribute("data-valign-anchor")};return Wt.set(Ue.letter,Ue),Ue}),sn=new Map,Rn=(Le,Ze)=>{const Ue=sn.get(Le.letter);if(Ue!==void 0)return Ue;const so=Le.anchor?Wt.get(Le.anchor):void 0;if(Le.kind!=="baseline"||!so||Ze.has(Le.letter)){const co=br(Le,ot,`${a}-list-col`,wt);return sn.set(Le.letter,co),co}Ze.add(Le.letter);const Vi=Rn(so,Ze);Ze.delete(Le.letter);const Di=br(Le,ot,`${a}-list-col`,wt),zi=Vi-Di;od(Le.titleEl,zi);const lo=br(Le,ot,`${a}-list-col`,wt);return sn.set(Le.letter,lo),lo};an.forEach(Le=>Rn(Le,new Set))})};Se();const Re=new ResizeObserver(()=>Se());Re.observe(ge);let Xe=!1;return typeof document<"u"&&((ct=document.fonts)!=null&&ct.ready)&&document.fonts.ready.then(()=>{Xe||Se()}),()=>{Xe=!0,Re.disconnect(),xe()}},[ao,W,e,t,I,De,ye]),l.jsxs(l.Fragment,{children:[l.jsx("style",{dangerouslySetInnerHTML:{__html:Yc(a)}}),l.jsx("div",{style:ce,children:l.jsxs("div",{ref:ne,className:`${a}-wrapper ${ee}${lt?` ${lt}`:""}${W?` ${a}-type-b`:""}`.trim(),style:{width:T.scalingValue($??0,n)},onMouseMove:Y?Oi:void 0,onMouseLeave:Y?Bi:void 0,children:[l.jsxs("div",{style:{width:"100%"},children:[De.map((ge,xe)=>{var ct;const Se=(((ct=ge.link)==null?void 0:ct.length)??0)>0,Re=Se?"a":"div",Xe=qc(xe,De.length,Z,de,Qe,m??0,n??!1);return l.jsxs(Re,{className:`${a}-list-item${Se?` ${a}-list-item-has-link`:""}`,...Se?{href:ge.link,target:"_blank"}:{},style:Xe,onMouseEnter:Y?Te=>Hi(ge,Te):void 0,children:[(An>0||c)&&l.jsx("div",{...c?{"data-controls":ur,"data-controls-axis":"y","data-controls-min":"0"}:{},className:`${a}-row-padding-handle`,style:{height:Ee(An)}}),l.jsx("div",{className:`${a}-list-cols-row${W?"":` ${a}-list-cols-row-h`}`,...W?{}:{"data-list-row":""},style:W?void 0:{minHeight:Ee(on)},children:Ae.map((Te,Be)=>{const ot=Be===Ae.length-1,wt=ke[Be],Wt=Te.paddingBottom,an=Uc(ge.cells[Te.key]),sn=W&&an&&(Wt>0||c),Rn=W?{minHeight:Ee(on)}:ot?{}:{width:Ee(ye[Be])},Le=W?{paddingLeft:Ee(J),paddingRight:Ee(J)}:{paddingLeft:Ee(wt.paddingLeft),paddingRight:Ee(wt.paddingRight)},Ze=Te.textPrefix.charAt(0),Ue=W?{kind:"top"}:Qc(e[`${Te.textPrefix}VerticalAlign`],e,Ze);return l.jsxs("div",{...W?{}:{"data-list-col":"","data-col-letter":Ze,"data-valign":Ue.kind,...Ue.kind==="baseline"?{"data-valign-anchor":Ue.anchorLetter}:{}},children:[l.jsx("div",{className:`${a}-list-col${ot?` ${a}-list-col-last`:""}`,style:{...Le,...Rn},"data-test":Te.width,children:l.jsx("span",{className:Oo(e,Te.textPrefix,`${a}-list-col-title`,`${a}-text-tight-leading`),style:{...Ho(Zn(e,Te.textPrefix),n),...Bo(e,Te.textPrefix,a,n),...W?{}:td(Ue.kind)},children:ge.cells[Te.key]??null})}),sn&&l.jsx("div",{...c?{"data-controls":Te.paddingBottomKey,"data-controls-axis":"y","data-controls-min":"0"}:{},className:`${a}-row-padding-handle`,style:{height:Ee(Wt)}})]},Te.key)})}),!W&&(rn>0||c)&&l.jsx("div",{...c?{"data-controls":"rowPaddingBottom","data-controls-axis":"y","data-controls-min":"0"}:{},className:`${a}-row-padding-handle`,style:{height:Ee(rn)}})]},ge.id)}),Qe&&l.jsx("button",{type:"button",className:`${a}-cut-item`,style:{minHeight:Ee(x??0),...Gc(de,m??0,n??!1)},onClick:dr,children:l.jsx("div",{className:`${a}-list-cols-row`,style:W?{paddingLeft:Ee(J),paddingRight:Ee(J)}:{justifyContent:"center"},children:l.jsx("span",{className:Oo(e,vt,`${a}-cut-label`,`${a}-text-tight-leading`),style:{...Ho(Zn(e,vt),n),...Bo(e,vt,a,n)},children:P})})})]}),c&&!W&&be&&Ye&&l.jsxs("div",{style:{position:"absolute",inset:0,pointerEvents:"none"},children:[l.jsx("div",{"data-controls":be.paddingLeftKey,"data-controls-axis":"x","data-controls-variant":"column-padding","data-controls-min":"0","data-controls-max-fraction":String(ye[0]-((ze==null?void 0:ze.paddingRight)??0)),"data-controls-static-handle":"",className:`${a}-padding-control-handle`,style:{position:"absolute",top:0,left:0,width:Ee(St),height:"100%",pointerEvents:"auto",zIndex:2}}),l.jsx("div",{"data-controls":Ye.paddingRightKey,"data-controls-axis":"x","data-controls-variant":"column-padding","data-controls-reverse":"","data-controls-min":"0","data-controls-max-fraction":String(ye[Ae.length-1]-((Ne==null?void 0:Ne.paddingLeft)??0)),"data-controls-static-handle":"",className:`${a}-padding-control-handle`,style:{position:"absolute",top:0,left:Ee(Ni-oo),width:Ee(oo),height:"100%",pointerEvents:"auto",zIndex:2}})]},"column-edge-padding-handles"),c&&!W&&Ae.slice(0,-1).map((ge,xe)=>{const Se=Ae[xe+1],Re=bd(xe,Ve,Ie,Me),Xe=Ve.slice(0,xe+1).reduce((Wt,an)=>Wt+an,0),ct=ke[xe],Te=ke[xe+1],Be=Math.max(ct.paddingRight,ln),ot=Math.max(Te.paddingLeft,ln),wt=Xe-Vo/2;return l.jsxs("div",{style:{position:"absolute",inset:0,pointerEvents:"none"},children:[l.jsx("div",{"data-controls":ge.paddingRightKey,"data-controls-axis":"x","data-controls-variant":"column-padding","data-controls-reverse":"","data-controls-min":"0","data-controls-max-fraction":String(ye[xe]-ct.paddingLeft),"data-controls-static-handle":"",className:`${a}-padding-control-handle`,style:{position:"absolute",top:0,left:Ee(Xe-Be),width:Ee(Be),height:"100%",pointerEvents:"auto",zIndex:2}}),l.jsx("div",{"data-controls":ge.widthKey,"data-controls-axis":"x","data-controls-min":String(no),"data-controls-max-fraction":String(Re),"data-controls-variant":"column-width",className:`${a}-col-resize-handle`,style:{position:"absolute",top:"0px",left:Ee(wt),width:Ee(Vo),height:"calc(100%)",pointerEvents:"auto",zIndex:4}}),l.jsx("div",{"data-controls":Se.paddingLeftKey,"data-controls-axis":"x","data-controls-variant":"column-padding","data-controls-min":"0","data-controls-max-fraction":String(ye[xe+1]-Te.paddingRight),"data-controls-static-handle":"",className:`${a}-padding-control-handle`,style:{position:"absolute",top:0,left:Ee(Xe),width:Ee(ot),height:"100%",pointerEvents:"auto",zIndex:2}})]},`${ge.widthKey}-junction`)}),c&&W&&l.jsxs("div",{style:{position:"absolute",inset:0,pointerEvents:"none"},children:[l.jsx("div",{"data-controls":"textPaddingLR","data-controls-paired":"","data-controls-axis":"x","data-controls-min":"0","data-controls-max-fraction":String(le),"data-controls-static-handle":"",className:`${a}-text-padding-lr-handle`,style:{position:"absolute",top:0,left:0,width:Ee(se),height:"100%",pointerEvents:"auto",zIndex:2}}),l.jsx("div",{"data-controls":"textPaddingLR","data-controls-paired":"","data-controls-axis":"x","data-controls-reverse":"","data-controls-min":"0","data-controls-max-fraction":String(le),"data-controls-static-handle":"",className:`${a}-text-padding-lr-handle`,style:{position:"absolute",top:0,left:Ee(Math.max(se,Me-se)),width:Ee(se),height:"100%",pointerEvents:"auto",zIndex:2}})]},"text-padding-lr-handles"),Y&&Q&&l.jsx("img",{className:`${a}-hover-image`,src:Q.url,alt:"",style:{width:zn(Q.widthPx),objectFit:Q.objectFit,left:Q.x,top:Q.y}})]})})]})}const $d=`import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
4666
+ import { CommonComponentProps } from '../props';
4667
+ import { buildColorVars, scalingValue, useScopedStyles } from '../utils/index';
4668
+ import { omitTextColors, TextStyles, textStylesToCss } from '../utils/textStylesToCss';
4669
+
4670
+ type ListFontSettings = { fontWeight: number; fontStyle: string };
4671
+
4672
+ type ListColumnPrefix = 'AColumn' | 'BColumn' | 'CColumn' | 'DColumn' | 'EColumn';
4673
+
4674
+ type ListColumnTextStyleOverrides = {
4675
+ AColumnVerticalAlign?: string;
4676
+ AColumnTextFontFamily?: string;
4677
+ AColumnTextFontSettings?: ListFontSettings;
4678
+ AColumnTextFontSize?: number;
4679
+ AColumnTextLineHeight?: number;
4680
+ AColumnTextLetterSpacing?: number;
4681
+ AColumnTextWordSpacing?: number;
4682
+ AColumnTextTextAppearance?: TextStyles['textAppearance'];
4683
+ BColumnVerticalAlign?: string;
4684
+ BColumnTextFontFamily?: string;
4685
+ BColumnTextFontSettings?: ListFontSettings;
4686
+ BColumnTextFontSize?: number;
4687
+ BColumnTextLineHeight?: number;
4688
+ BColumnTextLetterSpacing?: number;
4689
+ BColumnTextWordSpacing?: number;
4690
+ BColumnTextTextAppearance?: TextStyles['textAppearance'];
4691
+ CColumnVerticalAlign?: string;
4692
+ CColumnTextFontFamily?: string;
4693
+ CColumnTextFontSettings?: ListFontSettings;
4694
+ CColumnTextFontSize?: number;
4695
+ CColumnTextLineHeight?: number;
4696
+ CColumnTextLetterSpacing?: number;
4697
+ CColumnTextWordSpacing?: number;
4698
+ CColumnTextTextAppearance?: TextStyles['textAppearance'];
4699
+ DColumnVerticalAlign?: string;
4700
+ DColumnTextFontFamily?: string;
4701
+ DColumnTextFontSettings?: ListFontSettings;
4702
+ DColumnTextFontSize?: number;
4703
+ DColumnTextLineHeight?: number;
4704
+ DColumnTextLetterSpacing?: number;
4705
+ DColumnTextWordSpacing?: number;
4706
+ DColumnTextTextAppearance?: TextStyles['textAppearance'];
4707
+ EColumnVerticalAlign?: string;
4708
+ EColumnTextFontFamily?: string;
4709
+ EColumnTextFontSettings?: ListFontSettings;
4710
+ EColumnTextFontSize?: number;
4711
+ EColumnTextLineHeight?: number;
4712
+ EColumnTextLetterSpacing?: number;
4713
+ EColumnTextWordSpacing?: number;
4714
+ EColumnTextTextAppearance?: TextStyles['textAppearance'];
4715
+ cutLabelTextFontFamily?: string;
4716
+ cutLabelTextFontSettings?: ListFontSettings;
4717
+ cutLabelTextFontSize?: number;
4718
+ cutLabelTextLineHeight?: number;
4719
+ cutLabelTextLetterSpacing?: number;
4720
+ cutLabelTextWordSpacing?: number;
4721
+ cutLabelTextTextAppearance?: TextStyles['textAppearance'];
4722
+ };
4723
+
4724
+ export type ListColumnVerticalAlignKey = \`\${ListColumnPrefix}VerticalAlign\`;
4725
+
4726
+ type ListColumnVerticalAlignUpdates = {
4727
+ AColumnVerticalAlign?: string;
4728
+ BColumnVerticalAlign?: string;
4729
+ CColumnVerticalAlign?: string;
4730
+ DColumnVerticalAlign?: string;
4731
+ EColumnVerticalAlign?: string;
4732
+ };
4733
+
4734
+ type ListColumnTextStyleSyncUpdates = {
4735
+ AColumnTextFontFamily?: string;
4736
+ AColumnTextFontSettings?: ListFontSettings;
4737
+ AColumnTextFontSize?: number;
4738
+ AColumnTextLineHeight?: number;
4739
+ AColumnTextLetterSpacing?: number;
4740
+ AColumnTextWordSpacing?: number;
4741
+ AColumnTextTextAppearance?: TextStyles['textAppearance'];
4742
+ BColumnTextFontFamily?: string;
4743
+ BColumnTextFontSettings?: ListFontSettings;
4744
+ BColumnTextFontSize?: number;
4745
+ BColumnTextLineHeight?: number;
4746
+ BColumnTextLetterSpacing?: number;
4747
+ BColumnTextWordSpacing?: number;
4748
+ BColumnTextTextAppearance?: TextStyles['textAppearance'];
4749
+ CColumnTextFontFamily?: string;
4750
+ CColumnTextFontSettings?: ListFontSettings;
4751
+ CColumnTextFontSize?: number;
4752
+ CColumnTextLineHeight?: number;
4753
+ CColumnTextLetterSpacing?: number;
4754
+ CColumnTextWordSpacing?: number;
4755
+ CColumnTextTextAppearance?: TextStyles['textAppearance'];
4756
+ DColumnTextFontFamily?: string;
4757
+ DColumnTextFontSettings?: ListFontSettings;
4758
+ DColumnTextFontSize?: number;
4759
+ DColumnTextLineHeight?: number;
4760
+ DColumnTextLetterSpacing?: number;
4761
+ DColumnTextWordSpacing?: number;
4762
+ DColumnTextTextAppearance?: TextStyles['textAppearance'];
4763
+ EColumnTextFontFamily?: string;
4764
+ EColumnTextFontSettings?: ListFontSettings;
4765
+ EColumnTextFontSize?: number;
4766
+ EColumnTextLineHeight?: number;
4767
+ EColumnTextLetterSpacing?: number;
4768
+ EColumnTextWordSpacing?: number;
4769
+ EColumnTextTextAppearance?: TextStyles['textAppearance'];
4770
+ cutLabelTextFontFamily?: string;
4771
+ cutLabelTextFontSettings?: ListFontSettings;
4772
+ cutLabelTextFontSize?: number;
4773
+ cutLabelTextLineHeight?: number;
4774
+ cutLabelTextLetterSpacing?: number;
4775
+ cutLabelTextWordSpacing?: number;
4776
+ cutLabelTextTextAppearance?: TextStyles['textAppearance'];
4777
+ };
4778
+
4779
+ export type ListSettings = {
4780
+ columns: number;
4781
+ type: 'A' | 'B';
4782
+ wrapperWidth: number;
4783
+ entriesCount: number;
4784
+ cellMinHeight: number;
4785
+ imageOnHover: 'On' | 'Off';
4786
+ imageSize?: { min: number; max: number };
4787
+ dividerWidth: number;
4788
+ showVisibility: boolean[];
4789
+ cut: number;
4790
+ showCut: number;
4791
+ cutCellMinHeight: number;
4792
+ cutLabel: string;
4793
+ entryHoverEffect: 'None' | 'Default' | 'Blinds';
4794
+ rowPaddingTop: number;
4795
+ rowPaddingBottom: number;
4796
+ rowPaddingTopB: number;
4797
+ AColumnWidth: number;
4798
+ AColumnPaddingLeft: number;
4799
+ AColumnPaddingRight: number;
4800
+ AColumnPaddingBottom: number;
4801
+ BColumnWidth: number;
4802
+ BColumnPaddingLeft: number;
4803
+ BColumnPaddingRight: number;
4804
+ BColumnPaddingBottom: number;
4805
+ CColumnWidth: number;
4806
+ CColumnPaddingLeft: number;
4807
+ CColumnPaddingRight: number;
4808
+ CColumnPaddingBottom: number;
4809
+ DColumnWidth: number;
4810
+ DColumnPaddingLeft: number;
4811
+ DColumnPaddingRight: number;
4812
+ DColumnPaddingBottom: number;
4813
+ EColumnWidth: number;
4814
+ EColumnPaddingLeft: number;
4815
+ EColumnPaddingRight: number;
4816
+ EColumnPaddingBottom: number;
4817
+ columnsOrder?: string[];
4818
+ textPaddingLR?: number;
4819
+ textColor: string;
4820
+ textFontFamily: string;
4821
+ textFontSettings?: ListFontSettings;
4822
+ textFontSize?: number;
4823
+ textLineHeight?: number;
4824
+ textLetterSpacing?: number;
4825
+ textWordSpacing?: number;
4826
+ textTextAppearance?: TextStyles['textAppearance'];
4827
+ backgroundColor: string;
4828
+ dividerColor: string;
4829
+ textHoverColor: string;
4830
+ backgroundHoverColor: string;
4831
+ dividerHoverColor: string;
4832
+ } & ListColumnTextStyleOverrides;
4833
+
4834
+ type ListContentItem = {
4835
+ AColumn?: string;
4836
+ BColumnWidth?: string;
4837
+ CColumnWidth?: string;
4838
+ DColumnWidth?: string;
4839
+ EColumnWidth?: string;
4840
+ image?: {
4841
+ objectFit?: 'cover' | 'contain';
4842
+ url: string;
4843
+ name: string;
4844
+ };
4845
+ link?: string;
4846
+ };
4847
+
4848
+ type ListItemRow = {
4849
+ id: string | number;
4850
+ cells: Record<string, React.ReactNode>;
4851
+ image?: ListContentItem['image'];
4852
+ link?: string;
4853
+ };
4854
+
4855
+ type HoverImageState = {
4856
+ rowId: string | number;
4857
+ url: string;
4858
+ objectFit: 'cover' | 'contain';
4859
+ widthPx: number;
4860
+ x: number;
4861
+ y: number;
4862
+ };
4863
+
4864
+ type ListProps = {
4865
+ layoutId?: string;
4866
+ settings: ListSettings;
4867
+ content?: ListContentItem[];
4868
+ isEditor?: boolean;
4869
+ isPreviewMode?: boolean;
4870
+ activeEvent: string | undefined;
4871
+ onUpdateSettings?: (settings: ListSettings) => void;
4872
+ } & CommonComponentProps;
4873
+
4874
+ function sv(px: number): string {
4875
+ return \`calc(var(--cntrl-article-width, 100vw) * \${px / 1440})\`;
4876
+ }
4877
+
4878
+ function hasListColumnText(value: React.ReactNode): boolean {
4879
+ return String(value ?? '').trim().length > 0;
4880
+ }
4881
+
4882
+ function getEntryDividerWidths(
4883
+ rowIdx: number,
4884
+ rowCount: number,
4885
+ showDividerTop: boolean,
4886
+ showDividerBottom: boolean,
4887
+ hasCutItem: boolean,
4888
+ dividerWidth: number,
4889
+ isEditor: boolean,
4890
+ ): { borderTopWidth: string; borderBottomWidth: string } {
4891
+ const scaledDividerWidth = scalingValue(dividerWidth, isEditor);
4892
+ const none = scalingValue(0, isEditor);
4893
+
4894
+ const isFirst = rowIdx === 0;
4895
+ const isLastEntry = rowIdx === rowCount - 1 && !hasCutItem;
4896
+
4897
+ const borderTopWidth = isFirst && showDividerTop ? scaledDividerWidth : none;
4898
+ const borderBottomWidth = !isLastEntry || showDividerBottom ? scaledDividerWidth : none;
4899
+
4900
+ return { borderTopWidth, borderBottomWidth };
4901
+ }
4902
+
4903
+ function getCutItemDividerWidths(
4904
+ showDividerBottom: boolean,
4905
+ dividerWidth: number,
4906
+ isEditor: boolean,
4907
+ ): { borderTopWidth: string; borderBottomWidth: string } {
4908
+ const scaledDividerWidth = scalingValue(dividerWidth, isEditor);
4909
+ const none = scalingValue(0, isEditor);
4910
+
4911
+ return {
4912
+ borderTopWidth: none,
4913
+ borderBottomWidth: showDividerBottom ? scaledDividerWidth : none,
4914
+ };
4915
+ }
4916
+
4917
+ const HOVER_IMAGE_CURSOR_OFFSET = 10;
4918
+
4919
+ function getCSS(P: string): string {
4920
+ return \`
4921
+ .\${P}-wrapper {
4922
+ display: grid;
4923
+ align-items: start;
4924
+ min-height: \${sv(48)};
4925
+ position: relative;
4926
+ overflow: visible;
4927
+ box-sizing: border-box;
4928
+ }
4929
+
4930
+ .\${P}-hover-image {
4931
+ position: absolute;
4932
+ left: 0;
4933
+ top: 0;
4934
+ z-index: 10;
4935
+ pointer-events: none;
4936
+ display: block;
4937
+ height: auto;
4938
+ }
4939
+
4940
+ .\${P}-list-item {
4941
+ display: flex;
4942
+ flex-direction: column;
4943
+ align-items: stretch;
4944
+ width: 100%;
4945
+ overflow: visible;
4946
+ position: relative;
4947
+ box-sizing: content-box;
4948
+ user-select: none;
4949
+ background: var(--\${P}-background-color);
4950
+ }
4951
+
4952
+ .\${P}-wrapper.\${P}-divider-top .\${P}-list-item {
4953
+ border-top-style: solid;
4954
+ border-top-color: var(--\${P}-divider-color);
4955
+ }
4956
+
4957
+ .\${P}-wrapper.\${P}-divider-bottom .\${P}-list-item {
4958
+ border-bottom-style: solid;
4959
+ border-bottom-color: var(--\${P}-divider-color);
4960
+ }
4961
+
4962
+ .\${P}-list-cols-row {
4963
+ display: flex;
4964
+ align-items: start;
4965
+ width: 100%;
4966
+ box-sizing: border-box;
4967
+ }
4968
+
4969
+ .\${P}-list-cols-row-h {
4970
+ align-items: stretch;
4971
+ }
4972
+
4973
+ .\${P}-list-cols-row-h [data-list-col] {
4974
+ display: grid;
4975
+ grid-template-rows: minmax(0, 1fr);
4976
+ align-self: stretch;
4977
+ min-height: min-content;
4978
+ }
4979
+
4980
+ .\${P}-list-cols-row-h .\${P}-list-col {
4981
+ display: flex;
4982
+ flex-direction: column;
4983
+ align-items: flex-start;
4984
+ justify-content: flex-start;
4985
+ width: 100%;
4986
+ min-height: 0;
4987
+ }
4988
+
4989
+ .\${P}-list-cols-row-h .\${P}-list-col-title {
4990
+ display: block;
4991
+ flex: 0 0 auto;
4992
+ align-self: stretch;
4993
+ }
4994
+
4995
+ .\${P}-text-tight-leading {
4996
+ display: block;
4997
+ flex-shrink: 0;
4998
+ padding-top: var(--\${P}-title-leading-gap, 0);
4999
+ padding-bottom: var(--\${P}-title-leading-gap, 0);
5000
+ }
5001
+
5002
+ .\${P}-wrapper.\${P}-type-b .\${P}-list-cols-row {
5003
+ flex-direction: column;
5004
+ align-items: stretch;
5005
+ }
5006
+
5007
+ .\${P}-wrapper.\${P}-type-b .\${P}-list-col {
5008
+ width: 100%;
5009
+ min-width: 0;
5010
+ flex-direction: column;
5011
+ justify-content: flex-start;
5012
+ align-items: flex-start;
5013
+ min-height: min-content;
5014
+ }
5015
+
5016
+ .\${P}-wrapper.\${P}-type-b .\${P}-list-col-title {
5017
+ display: block;
5018
+ flex: 0 0 auto;
5019
+ align-self: stretch;
5020
+ text-align: center;
5021
+ }
5022
+
5023
+ .\${P}-wrapper.\${P}-type-b .\${P}-cut-item .\${P}-list-cols-row {
5024
+ flex-direction: row;
5025
+ align-items: center;
5026
+ justify-content: center;
5027
+ }
5028
+
5029
+ .\${P}-wrapper.\${P}-type-b .\${P}-cut-label {
5030
+ text-align: center;
5031
+ width: 100%;
5032
+ box-sizing: border-box;
5033
+ }
5034
+
5035
+ .\${P}-wrapper.\${P}-type-b .\${P}-list-col-last {
5036
+ flex: 0 0 auto;
5037
+ min-width: 0;
5038
+ }
5039
+
5040
+ a.\${P}-list-item {
5041
+ text-decoration: none;
5042
+ color: inherit;
5043
+ cursor: pointer;
5044
+ }
5045
+
5046
+ .\${P}-list-col {
5047
+ flex-shrink: 0;
5048
+ overflow: visible;
5049
+ box-sizing: border-box;
5050
+ min-width: \${sv(50)};
5051
+ position: relative;
5052
+ display: flex;
5053
+ align-items: flex-start;
5054
+ }
5055
+
5056
+ .\${P}-list-col-last {
5057
+ flex: 1 1 auto;
5058
+ min-width: \${sv(50)};
5059
+ }
5060
+
5061
+ .\${P}-list-col-title {
5062
+ color: var(--\${P}-text-color);
5063
+ white-space: pre-wrap;
5064
+ overflow-wrap: anywhere;
5065
+ word-break: break-word;
5066
+ flex: 1;
5067
+ min-width: 0;
5068
+ width: 100%;
5069
+ box-sizing: border-box;
5070
+ }
5071
+
5072
+ .\${P}-baseline-probe {
5073
+ display: inline-block;
5074
+ width: 0;
5075
+ height: 0;
5076
+ overflow: hidden;
5077
+ vertical-align: baseline;
5078
+ }
5079
+
5080
+ .\${P}-col-resize-handle,
5081
+ .\${P}-padding-control-handle {
5082
+ background: transparent;
5083
+ }
5084
+
5085
+ .\${P}-row-padding-handle {
5086
+ position: relative;
5087
+ z-index: 2;
5088
+ width: 100%;
5089
+ flex-shrink: 0;
5090
+ background: transparent;
5091
+ }
5092
+
5093
+ .\${P}-row-padding-handle::before {
5094
+ content: "";
5095
+ position: absolute;
5096
+ top: 0;
5097
+ left: 0;
5098
+ width: 100%;
5099
+ height: 100%;
5100
+ min-height: 20px;
5101
+ pointer-events: auto;
5102
+ z-index: 10;
5103
+ }
5104
+
5105
+ .\${P}-col-resize-handle::after {
5106
+ content: '';
5107
+ position: absolute;
5108
+ top: 0;
5109
+ left: 50%;
5110
+ transform: translateX(-50%);
5111
+ width: 2px;
5112
+ height: 100%;
5113
+ background: #FF5C02;
5114
+ pointer-events: none;
5115
+ }
5116
+
5117
+ .\${P}-wrapper.\${P}-type-b .\${P}-col-resize-handle::after {
5118
+ top: 50%;
5119
+ left: 0;
5120
+ transform: translateY(-50%);
5121
+ width: 100%;
5122
+ height: 2px;
5123
+ }
5124
+
5125
+ .\${P}-padding-control-handle::after {
5126
+ content: '';
5127
+ position: absolute;
5128
+ top: 50%;
5129
+ left: 50%;
5130
+ transform: translate(-50%, -50%);
5131
+ width: 4px;
5132
+ height: 12px;
5133
+ background: #FF5C02;
5134
+ border: 1px solid #FFFFFF;
5135
+ border-radius: 5px;
5136
+ pointer-events: none;
5137
+ box-sizing: border-box;
5138
+ }
5139
+
5140
+ .\${P}-wrapper.\${P}-type-b .\${P}-padding-control-handle::after {
5141
+ width: 12px;
5142
+ height: 4px;
5143
+ }
5144
+
5145
+ .\${P}-text-padding-lr-handle {
5146
+ background: transparent;
5147
+ }
5148
+
5149
+ .\${P}-text-padding-lr-handle::after {
5150
+ content: '';
5151
+ position: absolute;
5152
+ top: 50%;
5153
+ left: 50%;
5154
+ transform: translate(-50%, -50%);
5155
+ width: 4px;
5156
+ height: 12px;
5157
+ background: #FF5C02;
5158
+ border: 1px solid #FFFFFF;
5159
+ border-radius: 5px;
5160
+ pointer-events: none;
5161
+ box-sizing: border-box;
5162
+ }
5163
+
5164
+ .\${P}-wrapper.\${P}-entry-hover-default .\${P}-list-item-has-link,
5165
+ .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-list-item-has-link,
5166
+ .\${P}-wrapper.\${P}-entry-hover-default .\${P}-cut-item,
5167
+ .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-cut-item {
5168
+ transition: background-color 250ms, border-color 250ms;
5169
+ }
5170
+
5171
+ .\${P}-wrapper.\${P}-entry-hover-default .\${P}-list-item-has-link .\${P}-list-col-title,
5172
+ .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-list-item-has-link .\${P}-list-col-title,
5173
+ .\${P}-wrapper.\${P}-entry-hover-default .\${P}-cut-label,
5174
+ .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-cut-label {
5175
+ transition: color 250ms;
5176
+ }
5177
+
5178
+ .\${P}-wrapper.\${P}-entry-hover-default .\${P}-list-item-has-link:hover,
5179
+ .\${P}-wrapper.\${P}-entry-hover-default.\${P}-state-hover .\${P}-list-item-has-link,
5180
+ .\${P}-wrapper.\${P}-entry-hover-default .\${P}-cut-item:hover,
5181
+ .\${P}-wrapper.\${P}-entry-hover-default.\${P}-state-hover .\${P}-cut-item {
5182
+ background: var(--\${P}-background-hover-color);
5183
+ }
5184
+
5185
+ .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-default .\${P}-list-item-has-link:hover,
5186
+ .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-default .\${P}-list-item:has(+ .\${P}-list-item-has-link:hover),
5187
+ .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-default .\${P}-list-item:has(+ .\${P}-cut-item:hover),
5188
+ .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-default.\${P}-state-hover .\${P}-list-item-has-link,
5189
+ .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-default .\${P}-cut-item:hover,
5190
+ .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-default.\${P}-state-hover .\${P}-cut-item,
5191
+ .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-blinds .\${P}-list-item-has-link:hover,
5192
+ .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-blinds .\${P}-list-item:has(+ .\${P}-list-item-has-link:hover),
5193
+ .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-blinds .\${P}-list-item:has(+ .\${P}-cut-item:hover),
5194
+ .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-blinds.\${P}-state-hover .\${P}-list-item-has-link,
5195
+ .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-blinds .\${P}-cut-item:hover,
5196
+ .\${P}-wrapper.\${P}-divider-bottom.\${P}-entry-hover-blinds.\${P}-state-hover .\${P}-cut-item {
5197
+ border-bottom-color: var(--\${P}-divider-hover-color);
5198
+ }
5199
+
5200
+ .\${P}-wrapper.\${P}-divider-top:not(.\${P}-divider-bottom).\${P}-entry-hover-default .\${P}-list-item-has-link:hover:first-child,
5201
+ .\${P}-wrapper.\${P}-divider-top:not(.\${P}-divider-bottom).\${P}-entry-hover-default.\${P}-state-hover .\${P}-list-item-has-link:first-child,
5202
+ .\${P}-wrapper.\${P}-divider-top:not(.\${P}-divider-bottom).\${P}-entry-hover-blinds .\${P}-list-item-has-link:hover:first-child,
5203
+ .\${P}-wrapper.\${P}-divider-top:not(.\${P}-divider-bottom).\${P}-entry-hover-blinds.\${P}-state-hover .\${P}-list-item-has-link:first-child {
5204
+ border-top-color: var(--\${P}-divider-hover-color);
5205
+ }
5206
+
5207
+ .\${P}-wrapper.\${P}-divider-top.\${P}-divider-bottom.\${P}-entry-hover-default .\${P}-list-item-has-link:hover:first-child,
5208
+ .\${P}-wrapper.\${P}-divider-top.\${P}-divider-bottom.\${P}-entry-hover-default.\${P}-state-hover .\${P}-list-item-has-link:first-child,
5209
+ .\${P}-wrapper.\${P}-divider-top.\${P}-divider-bottom.\${P}-entry-hover-blinds .\${P}-list-item-has-link:hover:first-child,
5210
+ .\${P}-wrapper.\${P}-divider-top.\${P}-divider-bottom.\${P}-entry-hover-blinds.\${P}-state-hover .\${P}-list-item-has-link:first-child {
5211
+ border-top-color: var(--\${P}-divider-hover-color);
5212
+ }
5213
+
5214
+ .\${P}-wrapper.\${P}-entry-hover-default .\${P}-list-item-has-link:hover .\${P}-list-col-title,
5215
+ .\${P}-wrapper.\${P}-entry-hover-default.\${P}-state-hover .\${P}-list-item-has-link .\${P}-list-col-title,
5216
+ .\${P}-wrapper.\${P}-entry-hover-default .\${P}-cut-item:hover .\${P}-cut-label,
5217
+ .\${P}-wrapper.\${P}-entry-hover-default.\${P}-state-hover .\${P}-cut-item .\${P}-cut-label,
5218
+ .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-list-item-has-link:hover .\${P}-list-col-title,
5219
+ .\${P}-wrapper.\${P}-entry-hover-blinds.\${P}-state-hover .\${P}-list-item-has-link .\${P}-list-col-title,
5220
+ .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-cut-item:hover .\${P}-cut-label,
5221
+ .\${P}-wrapper.\${P}-entry-hover-blinds.\${P}-state-hover .\${P}-cut-item .\${P}-cut-label {
5222
+ color: var(--\${P}-text-hover-color);
5223
+ }
5224
+
5225
+ .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-list-item-has-link::before,
5226
+ .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-cut-item::before {
5227
+ content: '';
5228
+ position: absolute;
5229
+ inset: 0;
5230
+ background: var(--\${P}-background-hover-color);
5231
+ transform: scaleY(0);
5232
+ transform-origin: center center;
5233
+ transition: transform 250ms;
5234
+ z-index: 0;
5235
+ pointer-events: none;
5236
+ }
5237
+
5238
+ .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-list-col,
5239
+ .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-cut-label {
5240
+ position: relative;
5241
+ z-index: 1;
5242
+ }
5243
+
5244
+ .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-list-item-has-link:hover::before,
5245
+ .\${P}-wrapper.\${P}-entry-hover-blinds.\${P}-state-hover .\${P}-list-item-has-link::before,
5246
+ .\${P}-wrapper.\${P}-entry-hover-blinds .\${P}-cut-item:hover::before,
5247
+ .\${P}-wrapper.\${P}-entry-hover-blinds.\${P}-state-hover .\${P}-cut-item::before {
5248
+ transform: scaleY(1);
5249
+ }
5250
+
5251
+ .\${P}-cut-item {
5252
+ display: flex;
5253
+ align-items: center;
5254
+ justify-content: center;
5255
+ width: 100%;
5256
+ overflow: visible;
5257
+ position: relative;
5258
+ z-index: 3;
5259
+ box-sizing: border-box;
5260
+ user-select: none;
5261
+ background: var(--\${P}-background-color);
5262
+ cursor: pointer;
5263
+ padding: 0;
5264
+ border: none;
5265
+ font: inherit;
5266
+ text-align: inherit;
5267
+ appearance: none;
5268
+ -webkit-appearance: none;
5269
+ }
5270
+
5271
+ .\${P}-cut-item .\${P}-list-cols-row {
5272
+ flex: 1;
5273
+ min-height: 100%;
5274
+ align-items: center;
5275
+ }
5276
+
5277
+ .\${P}-wrapper.\${P}-divider-bottom .\${P}-cut-item {
5278
+ border-bottom-style: solid;
5279
+ border-bottom-color: var(--\${P}-divider-color);
5280
+ }
5281
+
5282
+ .\${P}-cut-label {
5283
+ display: block;
5284
+ position: relative;
5285
+ z-index: 1;
5286
+ margin: 0;
5287
+ color: var(--\${P}-text-color);
5288
+ white-space: pre-wrap;
5289
+ overflow-wrap: anywhere;
5290
+ word-break: break-word;
5291
+ }
5292
+ \`;
5293
+ }
5294
+
5295
+ export const COLUMN_CONTENT_KEYS = [
5296
+ 'AColumn',
5297
+ 'BColumnWidth',
5298
+ 'CColumnWidth',
5299
+ 'DColumnWidth',
5300
+ 'EColumnWidth',
5301
+ ] as const;
5302
+
5303
+ export const COLUMN_TEXT_PREFIXES = [
5304
+ 'AColumn',
5305
+ 'BColumn',
5306
+ 'CColumn',
5307
+ 'DColumn',
5308
+ 'EColumn',
5309
+ ] as const;
5310
+
5311
+ export const CUT_LABEL_TEXT_PREFIX = 'cutLabel' as const;
5312
+
5313
+ export const LIST_TEXT_STYLE_PREFIXES = [
5314
+ ...COLUMN_TEXT_PREFIXES,
5315
+ CUT_LABEL_TEXT_PREFIX,
5316
+ ] as const;
5317
+
5318
+ export type ListTextStylePrefix = typeof LIST_TEXT_STYLE_PREFIXES[number];
5319
+
5320
+ export const LIST_COLUMN_LETTERS = ['A', 'B', 'C', 'D', 'E'] as const;
5321
+
5322
+ export function getListColumnVerticalAlignSettingKey(columnLetter: string): string {
5323
+ return \`\${columnLetter}ColumnVerticalAlign\`;
5324
+ }
5325
+
5326
+ export const COLUMN_VALIGN_BASIC_OPTIONS = ['Top', 'Center', 'Bottom'] as const;
5327
+
5328
+ export function isBaselineAnchorColumnVerticalAlign(value: string | undefined): boolean {
5329
+ const raw = String(value ?? 'Top').trim();
5330
+ if (raw.toLowerCase().startsWith('baseline')) {
5331
+ return false;
5332
+ }
5333
+ return raw === 'Top' || raw === 'Center' || raw === 'Bottom';
5334
+ }
5335
+
5336
+ export function parseBaselineAnchorLetter(value: string | undefined): string | null {
5337
+ const raw = String(value ?? '').trim();
5338
+ if (!raw.toLowerCase().startsWith('baseline')) {
5339
+ return null;
5340
+ }
5341
+ const anchorLetter = raw.slice(-1).toUpperCase();
5342
+ return LIST_COLUMN_LETTERS.includes(anchorLetter as typeof LIST_COLUMN_LETTERS[number])
5343
+ ? anchorLetter
5344
+ : null;
5345
+ }
5346
+
5347
+ export function isValidColumnBaselineVAlign(
5348
+ value: string | undefined,
5349
+ forColumnLetter: string,
5350
+ settings: ListSettings,
5351
+ ): boolean {
5352
+ const anchorLetter = parseBaselineAnchorLetter(value);
5353
+ if (!anchorLetter) {
5354
+ return true;
5355
+ }
5356
+ if (anchorLetter === forColumnLetter) {
5357
+ return false;
5358
+ }
5359
+ return isBaselineAnchorColumnVerticalAlign(settings[getListColumnVerticalAlignSettingKey(anchorLetter) as ListColumnVerticalAlignKey]);
5360
+ }
5361
+
5362
+ export function getColumnVerticalAlignOptionsForLetter(
5363
+ columnLetter: string,
5364
+ settings: ListSettings,
5365
+ ): string[] {
5366
+ const baselineOptions = LIST_COLUMN_LETTERS
5367
+ .filter((letter) => letter !== columnLetter)
5368
+ .filter((letter) => isBaselineAnchorColumnVerticalAlign(settings[getListColumnVerticalAlignSettingKey(letter) as ListColumnVerticalAlignKey]))
5369
+ .map((letter) => \`Baseline \${letter}\`);
5370
+
5371
+ return [...COLUMN_VALIGN_BASIC_OPTIONS, ...baselineOptions];
5372
+ }
5373
+
5374
+ type ColumnVerticalAlign =
5375
+ | { kind: 'top' | 'center' | 'bottom' }
5376
+ | { kind: 'baseline'; anchorLetter: string };
5377
+
5378
+ function parseColumnVerticalAlign(value: string | undefined): ColumnVerticalAlign {
5379
+ const raw = String(value ?? 'Top').trim();
5380
+ if (raw.toLowerCase().startsWith('baseline')) {
5381
+ const anchorLetter = raw.slice(-1).toUpperCase();
5382
+ if (LIST_COLUMN_LETTERS.includes(anchorLetter as typeof LIST_COLUMN_LETTERS[number])) {
5383
+ return { kind: 'baseline', anchorLetter };
5384
+ }
5385
+ return { kind: 'top' };
5386
+ }
5387
+ if (raw === 'Center') return { kind: 'center' };
5388
+ if (raw === 'Bottom') return { kind: 'bottom' };
5389
+ return { kind: 'top' };
5390
+ }
5391
+
5392
+ function resolveColumnVerticalAlign(
5393
+ value: string | undefined,
5394
+ settings: ListSettings,
5395
+ columnLetter: string,
5396
+ ): ColumnVerticalAlign {
5397
+ if (isActiveBaselineVAlign(value, settings, columnLetter)) {
5398
+ return parseColumnVerticalAlign(value);
5399
+ }
5400
+
5401
+ const parsed = parseColumnVerticalAlign(value);
5402
+ if (parsed.kind === 'baseline') {
5403
+ return { kind: 'top' };
5404
+ }
5405
+
5406
+ return parsed;
5407
+ }
5408
+
5409
+ function isActiveBaselineVAlign(
5410
+ value: string | undefined,
5411
+ settings: ListSettings,
5412
+ forColumnLetter: string,
5413
+ ): boolean {
5414
+ if (!isValidColumnBaselineVAlign(value, forColumnLetter, settings)) {
5415
+ return false;
5416
+ }
5417
+ return parseColumnVerticalAlign(value).kind === 'baseline';
5418
+ }
5419
+
5420
+ function getListColumnVerticalAlignSanitizeUpdates(
5421
+ settings: ListSettings,
5422
+ ): ListColumnVerticalAlignUpdates | null {
5423
+ if (settings.type === 'B') {
5424
+ return null;
5425
+ }
5426
+
5427
+ const updates: ListColumnVerticalAlignUpdates = {};
5428
+ let hasUpdates = false;
5429
+
5430
+ for (const letter of LIST_COLUMN_LETTERS) {
5431
+ const key = getListColumnVerticalAlignSettingKey(letter) as ListColumnVerticalAlignKey;
5432
+ const value = settings[key];
5433
+ if (!isValidColumnBaselineVAlign(value, letter, settings)) {
5434
+ updates[key] = 'Top';
5435
+ hasUpdates = true;
5436
+ }
5437
+ }
5438
+
5439
+ return hasUpdates ? updates : null;
5440
+ }
5441
+
5442
+ function vAlignToTitleStyle(
5443
+ kind: ColumnVerticalAlign['kind'],
5444
+ ): React.CSSProperties {
5445
+ if (kind === 'center') {
5446
+ return { marginTop: 'auto', marginBottom: 'auto' };
5447
+ }
5448
+ if (kind === 'bottom') {
5449
+ return { marginTop: 'auto' };
5450
+ }
5451
+ return {};
5452
+ }
5453
+
5454
+ function getFirstLineBaselineOffsetInTitle(
5455
+ titleEl: HTMLElement,
5456
+ probeClassName: string,
5457
+ ): number {
5458
+ const probe = document.createElement('i');
5459
+ probe.className = probeClassName;
5460
+ probe.setAttribute('aria-hidden', 'true');
5461
+ titleEl.prepend(probe);
5462
+
5463
+ const { top: titleTop } = titleEl.getBoundingClientRect();
5464
+ const { bottom: probeBottom } = probe.getBoundingClientRect();
5465
+ const baselineOffset = probeBottom - titleTop;
5466
+ probe.remove();
5467
+
5468
+ return baselineOffset;
5469
+ }
5470
+
5471
+ function measureColumnFirstLineBaselineOffset(
5472
+ info: {
5473
+ titleEl: HTMLElement | null;
5474
+ kind: string;
5475
+ },
5476
+ rowTop: number,
5477
+ listColClassName: string,
5478
+ probeClassName: string,
5479
+ ): number {
5480
+ const titleEl = info.titleEl;
5481
+ if (!titleEl) return 0;
5482
+
5483
+ const listCol = titleEl.closest<HTMLElement>(\`.\${listColClassName}\`);
5484
+ if (!listCol) return 0;
5485
+
5486
+ const baselineInTitle = getFirstLineBaselineOffsetInTitle(titleEl, probeClassName);
5487
+
5488
+ if (info.kind === 'baseline') {
5489
+ return titleEl.getBoundingClientRect().top - rowTop + baselineInTitle;
5490
+ }
5491
+
5492
+ const listColRect = listCol.getBoundingClientRect();
5493
+ const titleHeight = titleEl.getBoundingClientRect().height;
5494
+ let valignOffset = 0;
5495
+
5496
+ if (info.kind === 'center') {
5497
+ valignOffset = (listColRect.height - titleHeight) / 2;
5498
+ } else if (info.kind === 'bottom') {
5499
+ valignOffset = listColRect.height - titleHeight;
5500
+ }
5501
+
5502
+ return (listColRect.top - rowTop) + valignOffset + baselineInTitle;
5503
+ }
5504
+
5505
+ function syncRowListColHeights(
5506
+ rowEl: HTMLElement,
5507
+ cols: HTMLElement[],
5508
+ listColClassName: string,
5509
+ ): number {
5510
+ const rowHeight = rowEl.getBoundingClientRect().height;
5511
+ if (rowHeight <= 0) {
5512
+ return 0;
5513
+ }
5514
+
5515
+ cols.forEach((colEl) => {
5516
+ const listCol = colEl.querySelector<HTMLElement>(\`.\${listColClassName}\`);
5517
+ if (listCol) {
5518
+ listCol.style.minHeight = \`\${rowHeight}px\`;
5519
+ listCol.style.height = \`\${rowHeight}px\`;
5520
+ }
5521
+ });
5522
+
5523
+ void rowEl.offsetHeight;
5524
+ return rowHeight;
5525
+ }
5526
+
5527
+ function applyBaselineTitleShift(titleEl: HTMLElement | null, shift: number): number {
5528
+ if (!titleEl || !shift) {
5529
+ if (titleEl) {
5530
+ titleEl.style.transform = '';
5531
+ }
5532
+ return 0;
5533
+ }
5534
+
5535
+ titleEl.style.transform = \`translateY(\${shift}px)\`;
5536
+ return shift;
5537
+ }
5538
+
5539
+ const COLUMN_CONTENT_KEY_TO_TEXT_PREFIX: Record<
5540
+ typeof COLUMN_CONTENT_KEYS[number],
5541
+ typeof COLUMN_TEXT_PREFIXES[number]
5542
+ > = {
5543
+ AColumn: 'AColumn',
5544
+ BColumnWidth: 'BColumn',
5545
+ CColumnWidth: 'CColumn',
5546
+ DColumnWidth: 'DColumn',
5547
+ EColumnWidth: 'EColumn',
5548
+ };
5549
+
5550
+ export const LIST_GLOBAL_TEXT_STYLE_KEYS = [
5551
+ 'textFontFamily',
5552
+ 'textFontSettings',
5553
+ 'textFontSize',
5554
+ 'textLineHeight',
5555
+ 'textLetterSpacing',
5556
+ 'textWordSpacing',
5557
+ 'textTextAppearance',
5558
+ ] as const;
5559
+
5560
+ export type ListGlobalTextStyleKey = typeof LIST_GLOBAL_TEXT_STYLE_KEYS[number];
5561
+
5562
+ export function getListColumnTextSettingKey(
5563
+ prefix: ListTextStylePrefix,
5564
+ globalKey: ListGlobalTextStyleKey,
5565
+ ): string {
5566
+ return \`\${prefix}\${globalKey.replace(/^text/, 'Text')}\`;
5567
+ }
5568
+
5569
+ type ListTextStyleFields = {
5570
+ textFontFamily?: string;
5571
+ textFontSettings?: { fontWeight: number; fontStyle: string };
5572
+ textFontSize?: number;
5573
+ textLineHeight?: number;
5574
+ textLetterSpacing?: number;
5575
+ textWordSpacing?: number;
5576
+ textTextAppearance?: TextStyles['textAppearance'];
5577
+ textColor?: string;
5578
+ };
5579
+
5580
+ type ResolvedListTextFields = {
5581
+ textFontFamily: string;
5582
+ textFontSettings: { fontWeight: number; fontStyle: string };
5583
+ textFontSize?: number;
5584
+ textLineHeight?: number;
5585
+ textLetterSpacing: number;
5586
+ textWordSpacing: number;
5587
+ textTextAppearance?: TextStyles['textAppearance'];
5588
+ textColor?: string;
5589
+ };
5590
+
5591
+ function resolveListGlobalTextFields(
5592
+ settings: ListTextStyleFields,
5593
+ ): ResolvedListTextFields {
5594
+ return {
5595
+ textFontFamily: settings.textFontFamily ?? 'Arial',
5596
+ textFontSettings: settings.textFontSettings ?? {
5597
+ fontWeight: 400,
5598
+ fontStyle: 'normal',
5599
+ },
5600
+ textFontSize: settings.textFontSize,
5601
+ textLineHeight: settings.textLineHeight,
5602
+ textLetterSpacing: settings.textLetterSpacing ?? 0,
5603
+ textWordSpacing: settings.textWordSpacing ?? 0,
5604
+ textTextAppearance: settings.textTextAppearance,
5605
+ textColor: settings.textColor,
5606
+ };
5607
+ }
5608
+
5609
+ function resolveListColumnTextFields(
5610
+ settings: ListSettings,
5611
+ textPrefix: ListTextStylePrefix,
5612
+ ): ResolvedListTextFields {
5613
+ const read = <K extends ListGlobalTextStyleKey>(globalKey: K) => {
5614
+ const columnKey = getListColumnTextSettingKey(textPrefix, globalKey);
5615
+ const columnValue = settings[columnKey as keyof ListSettings];
5616
+ if (columnValue !== undefined) {
5617
+ return columnValue as ListTextStyleFields[K];
5618
+ }
5619
+ return settings[globalKey];
5620
+ };
5621
+
5622
+ return {
5623
+ textFontFamily: (read('textFontFamily') as string | undefined) ?? 'Arial',
5624
+ textFontSettings: (read('textFontSettings') as ListTextStyleFields['textFontSettings']) ?? {
5625
+ fontWeight: 400,
5626
+ fontStyle: 'normal',
5627
+ },
5628
+ textFontSize: read('textFontSize') as number | undefined,
5629
+ textLineHeight: read('textLineHeight') as number | undefined,
5630
+ textLetterSpacing: (read('textLetterSpacing') as number | undefined) ?? 0,
5631
+ textWordSpacing: (read('textWordSpacing') as number | undefined) ?? 0,
5632
+ textTextAppearance: read('textTextAppearance') as ListTextStyleFields['textTextAppearance'],
5633
+ textColor: settings.textColor,
5634
+ };
5635
+ }
5636
+
5637
+ function listColumnTextFieldsToCss(
5638
+ fields: ResolvedListTextFields,
5639
+ isEditor?: boolean,
5640
+ ): React.CSSProperties {
5641
+ const resolvedTextStyle: TextStyles = {
5642
+ fontSettings: {
5643
+ fontFamily: fields.textFontFamily,
5644
+ fontWeight: fields.textFontSettings?.fontWeight ?? 400,
5645
+ fontStyle: fields.textFontSettings?.fontStyle ?? 'normal',
5646
+ },
5647
+ fontSize: fields.textFontSize ?? 0.01,
5648
+ lineHeight: fields.textLineHeight,
5649
+ letterSpacing: fields.textLetterSpacing,
5650
+ wordSpacing: fields.textWordSpacing,
5651
+ textAppearance: fields.textTextAppearance,
5652
+ color: fields.textColor ?? '#767676',
5653
+ };
5654
+
5655
+ return omitTextColors(textStylesToCss(resolvedTextStyle, isEditor));
5656
+ }
5657
+
5658
+ function getListColumnTitleClassName(
5659
+ settings: ListSettings,
5660
+ prefix: ListTextStylePrefix,
5661
+ baseClassName: string,
5662
+ tightLeadingClassName: string,
5663
+ ): string {
5664
+ const fields = resolveListColumnTextFields(settings, prefix);
5665
+ const fontSize = fields.textFontSize ?? 0.01;
5666
+ const lineHeight = fields.textLineHeight;
5667
+ const needsTightLeading = lineHeight !== undefined && lineHeight < fontSize;
5668
+
5669
+ return needsTightLeading
5670
+ ? \`\${baseClassName} \${tightLeadingClassName}\`
5671
+ : baseClassName;
5672
+ }
5673
+
5674
+ function getListColumnTitleVars(
5675
+ settings: ListSettings,
5676
+ prefix: ListTextStylePrefix,
5677
+ titleVarPrefix: string,
5678
+ isEditor?: boolean,
5679
+ ): React.CSSProperties {
5680
+ const fields = resolveListColumnTextFields(settings, prefix);
5681
+ const fontSize = fields.textFontSize ?? 0.01;
5682
+ const lineHeight = fields.textLineHeight;
5683
+
5684
+ if (lineHeight === undefined || lineHeight >= fontSize) {
5685
+ return {};
5686
+ }
5687
+
5688
+ return {
5689
+ [\`--\${titleVarPrefix}-title-leading-gap\`]: scalingValue((fontSize - lineHeight) / 2, isEditor),
5690
+ } as React.CSSProperties;
5691
+ }
5692
+
5693
+ function getListGlobalTextSyncUpdates(
5694
+ nextSettings: ListSettings,
5695
+ prevSettings: ListSettings,
5696
+ ): ListColumnTextStyleSyncUpdates | null {
5697
+ const updates: ListColumnTextStyleSyncUpdates = {};
5698
+ let hasChanges = false;
5699
+
5700
+ for (const globalKey of LIST_GLOBAL_TEXT_STYLE_KEYS) {
5701
+ if (nextSettings[globalKey] === prevSettings[globalKey]) {
5702
+ continue;
5703
+ }
5704
+ if (nextSettings[globalKey] === undefined) {
5705
+ continue;
5706
+ }
5707
+
5708
+ hasChanges = true;
5709
+ for (const prefix of LIST_TEXT_STYLE_PREFIXES) {
5710
+ Object.assign(updates, {
5711
+ [getListColumnTextSettingKey(prefix, globalKey)]: nextSettings[globalKey],
5712
+ });
5713
+ }
5714
+ }
5715
+
5716
+ return hasChanges ? updates : null;
5717
+ }
5718
+
5719
+ const COLUMN_WIDTH_KEYS = [
5720
+ 'AColumnWidth',
5721
+ 'BColumnWidth',
5722
+ 'CColumnWidth',
5723
+ 'DColumnWidth',
5724
+ 'EColumnWidth',
5725
+ ] as const;
5726
+
5727
+ const COLUMN_PADDING_LEFT_KEYS = [
5728
+ 'AColumnPaddingLeft',
5729
+ 'BColumnPaddingLeft',
5730
+ 'CColumnPaddingLeft',
5731
+ 'DColumnPaddingLeft',
5732
+ 'EColumnPaddingLeft',
5733
+ ] as const;
5734
+
5735
+ const COLUMN_PADDING_RIGHT_KEYS = [
5736
+ 'AColumnPaddingRight',
5737
+ 'BColumnPaddingRight',
5738
+ 'CColumnPaddingRight',
5739
+ 'DColumnPaddingRight',
5740
+ 'EColumnPaddingRight',
5741
+ ] as const;
5742
+
5743
+ const COLUMN_PADDING_BOTTOM_KEYS = [
5744
+ 'AColumnPaddingBottom',
5745
+ 'BColumnPaddingBottom',
5746
+ 'CColumnPaddingBottom',
5747
+ 'DColumnPaddingBottom',
5748
+ 'EColumnPaddingBottom',
5749
+ ] as const;
5750
+
5751
+ type ColumnWidthKey = typeof COLUMN_WIDTH_KEYS[number];
5752
+ type ColumnPaddingLeftKey = typeof COLUMN_PADDING_LEFT_KEYS[number];
5753
+ type ColumnPaddingRightKey = typeof COLUMN_PADDING_RIGHT_KEYS[number];
5754
+ type ColumnPaddingBottomKey = typeof COLUMN_PADDING_BOTTOM_KEYS[number];
5755
+
5756
+ type ListColumnPaddingUpdates = {
5757
+ AColumnPaddingLeft?: number;
5758
+ AColumnPaddingRight?: number;
5759
+ BColumnPaddingLeft?: number;
5760
+ BColumnPaddingRight?: number;
5761
+ CColumnPaddingLeft?: number;
5762
+ CColumnPaddingRight?: number;
5763
+ DColumnPaddingLeft?: number;
5764
+ DColumnPaddingRight?: number;
5765
+ EColumnPaddingLeft?: number;
5766
+ EColumnPaddingRight?: number;
5767
+ };
5768
+
5769
+ type ListColumnWidthUpdates = {
5770
+ AColumnWidth?: number;
5771
+ BColumnWidth?: number;
5772
+ CColumnWidth?: number;
5773
+ DColumnWidth?: number;
5774
+ EColumnWidth?: number;
5775
+ };
5776
+
5777
+ type ListItemColumn = {
5778
+ key: string;
5779
+ textPrefix: typeof COLUMN_TEXT_PREFIXES[number];
5780
+ widthKey: ColumnWidthKey;
5781
+ paddingLeftKey: ColumnPaddingLeftKey;
5782
+ paddingRightKey: ColumnPaddingRightKey;
5783
+ paddingBottomKey: ColumnPaddingBottomKey;
5784
+ width: number;
5785
+ paddingLeft: number;
5786
+ paddingRight: number;
5787
+ paddingBottom: number;
5788
+ };
5789
+
5790
+ type ColorKeys =
5791
+ | 'textColor'
5792
+ | 'backgroundColor'
5793
+ | 'dividerColor'
5794
+ | 'textHoverColor'
5795
+ | 'backgroundHoverColor'
5796
+ | 'dividerHoverColor';
5797
+
5798
+ const COLOR_VAR_MAP: Record<ColorKeys, string> = {
5799
+ textColor: 'text-color',
5800
+ backgroundColor: 'background-color',
5801
+ dividerColor: 'divider-color',
5802
+ textHoverColor: 'text-hover-color',
5803
+ backgroundHoverColor: 'background-hover-color',
5804
+ dividerHoverColor: 'divider-hover-color',
5805
+ };
5806
+
5807
+ const STATE_KEYS = ['hover', 'focus', 'filled', 'success', 'error'] as const;
5808
+
5809
+ const COL_RESIZE_HANDLE_WIDTH = 0.004;
5810
+ const COL_PADDING_HANDLE_WIDTH = 0.004;
5811
+ const MIN_COLUMN_WIDTH_PX = 50;
5812
+ const ARTICLE_DESIGN_WIDTH = 1440;
5813
+ const MIN_COLUMN_WIDTH = MIN_COLUMN_WIDTH_PX / ARTICLE_DESIGN_WIDTH;
5814
+
5815
+ export function getListMinColumnWidth(designWidthPx?: number): number {
5816
+ const designWidth = typeof designWidthPx === 'number' && designWidthPx > 0
5817
+ ? designWidthPx
5818
+ : ARTICLE_DESIGN_WIDTH;
5819
+
5820
+ return MIN_COLUMN_WIDTH_PX / designWidth;
5821
+ }
5822
+
5823
+ function getEditorDesignWidth(element: HTMLElement | null | undefined): number {
5824
+ let el = element ?? null;
5825
+
5826
+ while (el) {
5827
+ const inline = el.style.getPropertyValue('--cntrl-article-width').trim();
5828
+ if (inline) {
5829
+ const px = parseFloat(inline);
5830
+ if (Number.isFinite(px) && px > 0) {
5831
+ return px;
5832
+ }
5833
+ }
5834
+
5835
+ const computed = getComputedStyle(el).getPropertyValue('--cntrl-article-width').trim();
5836
+ if (computed) {
5837
+ const px = parseFloat(computed);
5838
+ if (Number.isFinite(px) && px > 0) {
5839
+ return px;
5840
+ }
5841
+ }
5842
+
5843
+ el = el.parentElement;
5844
+ }
5845
+
5846
+ return ARTICLE_DESIGN_WIDTH;
5847
+ }
5848
+
5849
+ const DEFAULT_COLUMN_WIDTHS: Record<ColumnWidthKey, number> = {
5850
+ AColumnWidth: 0.02,
5851
+ BColumnWidth: 0.02,
5852
+ CColumnWidth: 0.02,
5853
+ DColumnWidth: 0.02,
5854
+ EColumnWidth: 0.02,
5855
+ };
5856
+
5857
+ export function getListEffectiveContentWidth(
5858
+ settings: ListSettings,
5859
+ ): number {
5860
+ const wrapperWidth = typeof settings.wrapperWidth === 'number' ? settings.wrapperWidth : 1;
5861
+
5862
+ return Math.max(0, wrapperWidth);
5863
+ }
5864
+
5865
+ export function getEqualListColumnWidthUpdates(
5866
+ columns: number,
5867
+ contentWidth: number = 1,
5868
+ ): Record<ColumnWidthKey, number> {
5869
+ const equalColumnWidth = contentWidth / columns;
5870
+ return Object.fromEntries(
5871
+ COLUMN_WIDTH_KEYS.map((key) => [key, equalColumnWidth]),
5872
+ ) as Record<ColumnWidthKey, number>;
5873
+ }
5874
+
5875
+ function getResetListColumnPaddingUpdates(): Record<
5876
+ ColumnPaddingLeftKey | ColumnPaddingRightKey,
5877
+ number
5878
+ > {
5879
+ return Object.fromEntries([
5880
+ ...COLUMN_PADDING_LEFT_KEYS.map((key) => [key, 0]),
5881
+ ...COLUMN_PADDING_RIGHT_KEYS.map((key) => [key, 0]),
5882
+ ]) as Record<ColumnPaddingLeftKey | ColumnPaddingRightKey, number>;
5883
+ }
5884
+
5885
+ function getResetListColumnPaddingBottomUpdates(): Record<ColumnPaddingBottomKey, number> {
5886
+ return Object.fromEntries(
5887
+ COLUMN_PADDING_BOTTOM_KEYS.map((key) => [key, 0]),
5888
+ ) as Record<ColumnPaddingBottomKey, number>;
5889
+ }
5890
+
5891
+ function getStoredColumnWidths(
5892
+ settings: ListSettings,
5893
+ ): Record<ColumnWidthKey, number> {
5894
+ return Object.fromEntries(
5895
+ COLUMN_WIDTH_KEYS.map((key) => [
5896
+ key,
5897
+ typeof settings[key] === 'number'
5898
+ ? settings[key] as number
5899
+ : DEFAULT_COLUMN_WIDTHS[key],
5900
+ ]),
5901
+ ) as Record<ColumnWidthKey, number>;
5902
+ }
5903
+
5904
+ export function resolveListColumnPadding(
5905
+ columnWidth: number,
5906
+ paddingLeft: number,
5907
+ paddingRight: number,
5908
+ ): { paddingLeft: number; paddingRight: number } {
5909
+ const maxTotalPadding = columnWidth - MIN_COLUMN_WIDTH;
5910
+ const totalPadding = paddingLeft + paddingRight;
5911
+
5912
+ if (totalPadding <= 0 || totalPadding <= maxTotalPadding) {
5913
+ return { paddingLeft, paddingRight };
5914
+ }
5915
+
5916
+ if (maxTotalPadding <= 0) {
5917
+ return { paddingLeft: 0, paddingRight: 0 };
5918
+ }
5919
+
5920
+ const scale = maxTotalPadding / totalPadding;
5921
+
5922
+ return {
5923
+ paddingLeft: paddingLeft * scale,
5924
+ paddingRight: paddingRight * scale,
5925
+ };
5926
+ }
5927
+
5928
+ export function getEffectiveListColumnWidths(
5929
+ columns: number,
5930
+ wrapperWidth: number,
5931
+ storedWidths: Record<ColumnWidthKey, number>,
5932
+ ): number[] {
5933
+ const resolvedWidths = resolveListColumnWidths(columns, wrapperWidth, storedWidths);
5934
+
5935
+ if (columns <= 0) {
5936
+ return [];
5937
+ }
5938
+
5939
+ const sumFixed = resolvedWidths.slice(0, columns - 1).reduce((sum, width) => sum + width, 0);
5940
+
5941
+ return [
5942
+ ...resolvedWidths.slice(0, columns - 1),
5943
+ Math.max(0, wrapperWidth - sumFixed),
5944
+ ];
5945
+ }
5946
+
5947
+ function getListColumnPaddingUpdates(
5948
+ columns: number,
5949
+ effectiveWidths: number[],
5950
+ settings: ListSettings,
5951
+ ): ListColumnPaddingUpdates {
5952
+ const updates: ListColumnPaddingUpdates = {};
5953
+
5954
+ for (let index = 0; index < columns; index += 1) {
5955
+ const paddingLeftKey = COLUMN_PADDING_LEFT_KEYS[index];
5956
+ const paddingRightKey = COLUMN_PADDING_RIGHT_KEYS[index];
5957
+ const storedPaddingLeft = typeof settings[paddingLeftKey] === 'number'
5958
+ ? settings[paddingLeftKey] as number
5959
+ : 0;
5960
+ const storedPaddingRight = typeof settings[paddingRightKey] === 'number'
5961
+ ? settings[paddingRightKey] as number
5962
+ : 0;
5963
+ const resolvedPadding = resolveListColumnPadding(
5964
+ effectiveWidths[index] ?? 0,
5965
+ storedPaddingLeft,
5966
+ storedPaddingRight,
5967
+ );
5968
+
5969
+ if (resolvedPadding.paddingLeft !== storedPaddingLeft) {
5970
+ updates[paddingLeftKey] = resolvedPadding.paddingLeft;
5971
+ }
5972
+
5973
+ if (resolvedPadding.paddingRight !== storedPaddingRight) {
5974
+ updates[paddingRightKey] = resolvedPadding.paddingRight;
5975
+ }
5976
+ }
5977
+
5978
+ return updates;
5979
+ }
5980
+
5981
+ export function resolveListColumnWidths(
5982
+ columns: number,
5983
+ wrapperWidth: number,
5984
+ storedWidths: Record<ColumnWidthKey, number>,
5985
+ ): number[] {
5986
+ if (columns <= 0) {
5987
+ return [];
5988
+ }
5989
+
5990
+ const widths = COLUMN_WIDTH_KEYS.slice(0, columns).map(
5991
+ (key) => storedWidths[key],
5992
+ );
5993
+
5994
+ if (columns === 1) {
5995
+ return widths;
5996
+ }
5997
+
5998
+ const fixedWidths = widths.slice(0, columns - 1);
5999
+ const fixedSum = fixedWidths.reduce((sum, width) => sum + width, 0);
6000
+ const minTotalWidth = fixedSum + MIN_COLUMN_WIDTH;
6001
+
6002
+ if (wrapperWidth >= minTotalWidth) {
6003
+ return widths;
6004
+ }
6005
+
6006
+ const resolvedFixedWidths = [...fixedWidths];
6007
+ let overflow = minTotalWidth - wrapperWidth;
6008
+
6009
+ for (let index = resolvedFixedWidths.length - 1; index >= 0 && overflow > 0; index -= 1) {
6010
+ const shrinkable = resolvedFixedWidths[index] - MIN_COLUMN_WIDTH;
6011
+ if (shrinkable <= 0) {
6012
+ continue;
6013
+ }
6014
+
6015
+ const shrinkAmount = Math.min(overflow, shrinkable);
6016
+ resolvedFixedWidths[index] -= shrinkAmount;
6017
+ overflow -= shrinkAmount;
6018
+ }
6019
+
6020
+ return [...resolvedFixedWidths, widths[columns - 1]];
6021
+ }
6022
+
6023
+ function getListColumnWidthUpdatesForWrapperWidth(
6024
+ columns: number,
6025
+ wrapperWidth: number,
6026
+ storedWidths: Record<ColumnWidthKey, number>,
6027
+ ): ListColumnWidthUpdates {
6028
+ if (columns <= 1) {
6029
+ return {};
6030
+ }
6031
+
6032
+ const resolvedWidths = resolveListColumnWidths(columns, wrapperWidth, storedWidths);
6033
+ const updates: ListColumnWidthUpdates = {};
6034
+
6035
+ for (let index = 0; index < columns - 1; index += 1) {
6036
+ const key = COLUMN_WIDTH_KEYS[index];
6037
+ if (resolvedWidths[index] !== storedWidths[key]) {
6038
+ updates[key] = resolvedWidths[index];
6039
+ }
6040
+ }
6041
+
6042
+ return updates;
6043
+ }
6044
+
6045
+ function getColumnsOrder(settings: ListSettings): string[] {
6046
+ if (Array.isArray(settings.columnsOrder) && settings.columnsOrder.length > 0) {
6047
+ return settings.columnsOrder as string[];
6048
+ }
6049
+
6050
+ return [...COLUMN_CONTENT_KEYS];
6051
+ }
6052
+
6053
+ function areStringArraysEqual(left: string[], right: string[]): boolean {
6054
+ if (left.length !== right.length) {
6055
+ return false;
6056
+ }
6057
+
6058
+ return left.every((value, index) => value === right[index]);
6059
+ }
6060
+
6061
+ function getColumnLayoutUpdatesForOrderChange(
6062
+ nextOrder: string[],
6063
+ prevOrder: string[],
6064
+ prevSettings: ListSettings,
6065
+ columns: number,
6066
+ ): Record<string, number> {
6067
+ const count = Math.min(columns, nextOrder.length, COLUMN_WIDTH_KEYS.length);
6068
+ const updates: Record<string, number> = {};
6069
+
6070
+ for (let index = 0; index < count; index += 1) {
6071
+ const contentKey = nextOrder[index];
6072
+ const prevSlotIndex = prevOrder.indexOf(contentKey);
6073
+
6074
+ if (prevSlotIndex === -1) {
6075
+ continue;
6076
+ }
6077
+
6078
+ const prevWidthKey = COLUMN_WIDTH_KEYS[prevSlotIndex];
6079
+ const prevPaddingLeftKey = COLUMN_PADDING_LEFT_KEYS[prevSlotIndex];
6080
+ const prevPaddingRightKey = COLUMN_PADDING_RIGHT_KEYS[prevSlotIndex];
6081
+ const prevPaddingBottomKey = COLUMN_PADDING_BOTTOM_KEYS[prevSlotIndex];
6082
+ const widthKey = COLUMN_WIDTH_KEYS[index];
6083
+ const paddingLeftKey = COLUMN_PADDING_LEFT_KEYS[index];
6084
+ const paddingRightKey = COLUMN_PADDING_RIGHT_KEYS[index];
6085
+ const paddingBottomKey = COLUMN_PADDING_BOTTOM_KEYS[index];
6086
+
6087
+ const prevWidth = prevSettings[prevWidthKey];
6088
+ const prevPaddingLeft = prevSettings[prevPaddingLeftKey];
6089
+ const prevPaddingRight = prevSettings[prevPaddingRightKey];
6090
+ const prevPaddingBottom = prevSettings[prevPaddingBottomKey];
6091
+
6092
+ if (typeof prevWidth === 'number') {
6093
+ updates[widthKey] = prevWidth;
6094
+ }
6095
+
6096
+ if (typeof prevPaddingLeft === 'number') {
6097
+ updates[paddingLeftKey] = prevPaddingLeft;
6098
+ }
6099
+
6100
+ if (typeof prevPaddingRight === 'number') {
6101
+ updates[paddingRightKey] = prevPaddingRight;
6102
+ }
6103
+
6104
+ if (typeof prevPaddingBottom === 'number') {
6105
+ updates[paddingBottomKey] = prevPaddingBottom;
6106
+ }
6107
+ }
6108
+
6109
+ return updates;
6110
+ }
6111
+
6112
+ export function applyListSettingsChange(
6113
+ nextSettings: ListSettings,
6114
+ prevSettings: ListSettings,
6115
+ options?: { designWidth?: number },
6116
+ ): ListSettings {
6117
+ const textSyncUpdates = getListGlobalTextSyncUpdates(nextSettings, prevSettings);
6118
+ if (textSyncUpdates) {
6119
+ nextSettings = { ...nextSettings, ...textSyncUpdates };
6120
+ }
6121
+
6122
+ const valignSanitizeUpdates = getListColumnVerticalAlignSanitizeUpdates(nextSettings);
6123
+ if (valignSanitizeUpdates) {
6124
+ nextSettings = { ...nextSettings, ...valignSanitizeUpdates };
6125
+ }
6126
+
6127
+ const minColumnWidth = getListMinColumnWidth(options?.designWidth);
6128
+ const nextColumns = nextSettings.columns;
6129
+ const prevColumns = prevSettings.columns;
6130
+ const nextContentWidth = getListEffectiveContentWidth(nextSettings);
6131
+ const prevContentWidth = getListEffectiveContentWidth(prevSettings);
6132
+ const isVerticalLayout = nextSettings.type === 'B'
6133
+ || (nextSettings.type === undefined && prevSettings.type === 'B');
6134
+ const columns =
6135
+ typeof nextColumns === 'number'
6136
+ ? nextColumns
6137
+ : typeof prevColumns === 'number'
6138
+ ? prevColumns
6139
+ : COLUMN_CONTENT_KEYS.length;
6140
+
6141
+ const withColumnPaddingUpdates = (
6142
+ settings: ListSettings,
6143
+ ): ListSettings => {
6144
+ if (isVerticalLayout) {
6145
+ return settings;
6146
+ }
6147
+
6148
+ const storedWidths = getStoredColumnWidths({ ...prevSettings, ...settings });
6149
+ const contentWidth = getListEffectiveContentWidth(settings);
6150
+ const effectiveWidths = getEffectiveListColumnWidths(columns, contentWidth, storedWidths);
6151
+ const paddingUpdates = getListColumnPaddingUpdates(columns, effectiveWidths, {
6152
+ ...prevSettings,
6153
+ ...settings,
6154
+ });
6155
+
6156
+ if (Object.keys(paddingUpdates).length === 0) {
6157
+ return settings;
6158
+ }
6159
+
6160
+ return {
6161
+ ...settings,
6162
+ ...paddingUpdates,
6163
+ };
6164
+ };
6165
+
6166
+ if (typeof nextColumns === 'number' && nextColumns !== prevColumns) {
6167
+ const updates: ListSettings = {
6168
+ ...nextSettings,
6169
+ ...getEqualListColumnWidthUpdates(nextColumns, nextContentWidth),
6170
+ ...getResetListColumnPaddingUpdates(),
6171
+ };
6172
+
6173
+ if (isVerticalLayout) {
6174
+ for (const key of COLUMN_PADDING_BOTTOM_KEYS) {
6175
+ if (typeof prevSettings[key] === 'number') {
6176
+ updates[key] = prevSettings[key];
6177
+ }
6178
+ }
6179
+ } else {
6180
+ Object.assign(updates, getResetListColumnPaddingBottomUpdates());
6181
+ }
6182
+
6183
+ return updates;
6184
+ }
6185
+
6186
+ const nextOrder = getColumnsOrder(nextSettings);
6187
+ const prevOrder = getColumnsOrder(prevSettings);
6188
+
6189
+ if (!areStringArraysEqual(nextOrder, prevOrder)) {
6190
+ return withColumnPaddingUpdates({
6191
+ ...nextSettings,
6192
+ ...getColumnLayoutUpdatesForOrderChange(nextOrder, prevOrder, prevSettings, columns),
6193
+ });
6194
+ }
6195
+
6196
+ if (nextContentWidth < prevContentWidth) {
6197
+ if (typeof columns === 'number' && !isVerticalLayout) {
6198
+ const storedWidths = getStoredColumnWidths({ ...prevSettings, ...nextSettings });
6199
+
6200
+ return withColumnPaddingUpdates({
6201
+ ...nextSettings,
6202
+ ...getListColumnWidthUpdatesForWrapperWidth(columns, nextContentWidth, storedWidths),
6203
+ });
6204
+ }
6205
+ }
6206
+
6207
+ if (isVerticalLayout) {
6208
+ const storedTextPaddingLR = typeof nextSettings.textPaddingLR === 'number'
6209
+ ? nextSettings.textPaddingLR as number
6210
+ : 0;
6211
+ const maxAllowedPadding = Math.max(0, (nextContentWidth - minColumnWidth) / 2);
6212
+
6213
+ if (storedTextPaddingLR > maxAllowedPadding) {
6214
+ return { ...nextSettings, textPaddingLR: maxAllowedPadding };
6215
+ }
6216
+
6217
+ return nextSettings;
6218
+ }
6219
+
6220
+ const storedWidths = getStoredColumnWidths({ ...prevSettings, ...nextSettings });
6221
+ const prevEffectiveWidths = getEffectiveListColumnWidths(
6222
+ columns,
6223
+ prevContentWidth,
6224
+ getStoredColumnWidths(prevSettings),
6225
+ );
6226
+ const nextEffectiveWidths = getEffectiveListColumnWidths(
6227
+ columns,
6228
+ nextContentWidth,
6229
+ storedWidths,
6230
+ );
6231
+ const columnWidthDecreased = nextEffectiveWidths.some(
6232
+ (width, index) => width < (prevEffectiveWidths[index] ?? width),
6233
+ );
6234
+ const columnWidthSettingChanged = COLUMN_WIDTH_KEYS.some((key) => {
6235
+ const nextWidth = nextSettings[key];
6236
+ const prevWidth = prevSettings[key];
6237
+
6238
+ return typeof nextWidth === 'number'
6239
+ && typeof prevWidth === 'number'
6240
+ && nextWidth !== prevWidth;
6241
+ });
6242
+
6243
+ if (columnWidthDecreased || columnWidthSettingChanged) {
6244
+ return withColumnPaddingUpdates(nextSettings);
6245
+ }
6246
+
6247
+ return nextSettings;
6248
+ }
6249
+
6250
+ function getColumnMaxWidth(
6251
+ columnIndex: number,
6252
+ resolvedWidths: number[],
6253
+ storedWidths: number[],
6254
+ wrapperWidth: number,
6255
+ ): number {
6256
+ const leftWidth = resolvedWidths
6257
+ .slice(0, columnIndex)
6258
+ .reduce((sum, width) => sum + width, 0);
6259
+ const rightPreferredWidth = storedWidths
6260
+ .slice(columnIndex + 1, resolvedWidths.length - 1)
6261
+ .reduce((sum, width) => sum + width, 0);
6262
+
6263
+ return Math.max(
6264
+ MIN_COLUMN_WIDTH,
6265
+ wrapperWidth - leftWidth - rightPreferredWidth - MIN_COLUMN_WIDTH,
6266
+ );
6267
+ }
6268
+
6269
+ function randomBetween(min: number, max: number): number {
6270
+ return Math.random() * (max - min) + min;
6271
+ }
6272
+
6273
+ function getColumnWidthsFromSettings(
6274
+ settings: ListSettings,
6275
+ ): Record<ColumnWidthKey, number> {
6276
+ return Object.fromEntries(
6277
+ COLUMN_WIDTH_KEYS.map((key) => [
6278
+ key,
6279
+ typeof settings[key] === 'number' ? settings[key] as number : DEFAULT_COLUMN_WIDTHS[key],
6280
+ ]),
6281
+ ) as Record<ColumnWidthKey, number>;
6282
+ }
6283
+
6284
+ function getNumericSettingValues<K extends ColumnPaddingLeftKey | ColumnPaddingRightKey | ColumnPaddingBottomKey>(
6285
+ settings: ListSettings,
6286
+ keys: readonly K[],
6287
+ fallback = 0,
6288
+ ): Record<K, number> {
6289
+ return Object.fromEntries(
6290
+ keys.map((key) => [
6291
+ key,
6292
+ typeof settings[key] === 'number' ? settings[key] as number : fallback,
6293
+ ]),
6294
+ ) as Record<K, number>;
6295
+ }
6296
+
6297
+ function buildListColumns(
6298
+ columnContentOrder: readonly typeof COLUMN_CONTENT_KEYS[number][],
6299
+ columns: number,
6300
+ columnWidthByKey: Record<ColumnWidthKey, number>,
6301
+ columnPaddingLeftByKey: Record<ColumnPaddingLeftKey, number>,
6302
+ columnPaddingRightByKey: Record<ColumnPaddingRightKey, number>,
6303
+ columnPaddingBottomByKey: Record<ColumnPaddingBottomKey, number>,
6304
+ ): ListItemColumn[] {
6305
+ return columnContentOrder.slice(0, columns).map((key, index) => {
6306
+ const paddingLeftKey = COLUMN_PADDING_LEFT_KEYS[index];
6307
+ const paddingRightKey = COLUMN_PADDING_RIGHT_KEYS[index];
6308
+ const paddingBottomKey = COLUMN_PADDING_BOTTOM_KEYS[index];
6309
+
6310
+ return {
6311
+ key,
6312
+ textPrefix: COLUMN_CONTENT_KEY_TO_TEXT_PREFIX[key],
6313
+ widthKey: COLUMN_WIDTH_KEYS[index],
6314
+ width: columnWidthByKey[COLUMN_WIDTH_KEYS[index]],
6315
+ paddingLeftKey,
6316
+ paddingRightKey,
6317
+ paddingBottomKey,
6318
+ paddingLeft: columnPaddingLeftByKey[paddingLeftKey],
6319
+ paddingRight: columnPaddingRightByKey[paddingRightKey],
6320
+ paddingBottom: columnPaddingBottomByKey[paddingBottomKey],
6321
+ };
6322
+ });
6323
+ }
6324
+
6325
+ export function List({ settings, content, isEditor, isPreviewMode, activeEvent, layoutId, onUpdateSettings }: ListProps) {
6326
+ const { prefix: P } = useScopedStyles();
6327
+ const showControls = Boolean(isEditor && isPreviewMode);
6328
+ const {
6329
+ columns,
6330
+ type,
6331
+ wrapperWidth,
6332
+ entriesCount,
6333
+ cellMinHeight,
6334
+ dividerWidth,
6335
+ showVisibility,
6336
+ cut,
6337
+ showCut,
6338
+ cutCellMinHeight,
6339
+ cutLabel,
6340
+ imageSize,
6341
+ imageOnHover,
6342
+ entryHoverEffect,
6343
+ rowPaddingTop,
6344
+ rowPaddingBottom,
6345
+ rowPaddingTopB,
6346
+ columnsOrder,
6347
+ textPaddingLR,
6348
+ textColor,
6349
+ textFontFamily,
6350
+ textFontSettings,
6351
+ textFontSize,
6352
+ textLineHeight,
6353
+ textLetterSpacing,
6354
+ textWordSpacing,
6355
+ textTextAppearance,
6356
+ backgroundColor,
6357
+ dividerColor,
6358
+ textHoverColor,
6359
+ backgroundHoverColor,
6360
+ dividerHoverColor,
6361
+ } = settings;
6362
+
6363
+ const [visibleRowCount, setVisibleRowCount] = useState<number | undefined>(undefined);
6364
+ const [hoverImage, setHoverImage] = useState<HoverImageState | null>(null);
6365
+ const showHoverImage = imageOnHover === 'On' && (!isEditor || isPreviewMode);
6366
+ const cutEnabled = (cut ?? 0) > 0;
6367
+ const isVerticalLayout = type === 'B';
6368
+ const containerRef = useRef<HTMLDivElement>(null);
6369
+ const [designWidth, setDesignWidth] = useState(ARTICLE_DESIGN_WIDTH);
6370
+ const minColumnWidth = getListMinColumnWidth(designWidth);
6371
+
6372
+ const storedTextPaddingLRMax = Math.max(0, ((wrapperWidth ?? 0) - minColumnWidth) / 2);
6373
+ const effectiveTextPaddingLR = Math.min(textPaddingLR ?? 0, storedTextPaddingLRMax);
6374
+ const textPaddingLRHandleWidth = Math.max(effectiveTextPaddingLR, COL_PADDING_HANDLE_WIDTH);
6375
+ const textPaddingLRMaxFraction = ((wrapperWidth ?? 0) + minColumnWidth) / 2;
6376
+
6377
+ useLayoutEffect(() => {
6378
+ if (!isEditor) {
6379
+ setDesignWidth(ARTICLE_DESIGN_WIDTH);
6380
+ return;
6381
+ }
6382
+
6383
+ const syncDesignWidth = () => {
6384
+ setDesignWidth(getEditorDesignWidth(containerRef.current));
6385
+ };
6386
+
6387
+ syncDesignWidth();
6388
+
6389
+ const observed = containerRef.current;
6390
+ if (!observed) {
6391
+ return;
6392
+ }
6393
+
6394
+ const observer = new ResizeObserver(syncDesignWidth);
6395
+ observer.observe(observed);
6396
+
6397
+ let pageEl: HTMLElement | null = observed;
6398
+ while (pageEl && !pageEl.style.getPropertyValue('--cntrl-article-width')) {
6399
+ pageEl = pageEl.parentElement;
6400
+ }
6401
+ if (pageEl) {
6402
+ observer.observe(pageEl);
6403
+ }
6404
+
6405
+ return () => observer.disconnect();
6406
+ }, [isEditor, layoutId]);
6407
+
6408
+ useEffect(() => {
6409
+ setVisibleRowCount(undefined);
6410
+ }, [cut, showCut, content, entriesCount]);
6411
+
6412
+ const colorVars = buildColorVars(P, {
6413
+ textColor,
6414
+ backgroundColor,
6415
+ dividerColor,
6416
+ textHoverColor,
6417
+ backgroundHoverColor,
6418
+ dividerHoverColor
6419
+ }, COLOR_VAR_MAP, STATE_KEYS);
6420
+
6421
+ const stateClass = activeEvent && activeEvent !== 'default' ? \`\${P}-state-\${activeEvent}\` : '';
6422
+ const entryHoverClass =
6423
+ entryHoverEffect === 'Default'
6424
+ ? \`\${P}-entry-hover-default\`
6425
+ : entryHoverEffect === 'Blinds'
6426
+ ? \`\${P}-entry-hover-blinds\`
6427
+ : '';
6428
+ const wrapperStateClasses = \`\${entryHoverClass} \${stateClass}\`.trim();
6429
+ const showDividerTop = showVisibility?.[0] ?? false;
6430
+ const showDividerBottom = showVisibility?.[1] ?? false;
6431
+
6432
+ const prevSettingsRef = useRef(settings);
6433
+ const prevLayoutIdRef = useRef(layoutId);
6434
+
6435
+ useEffect(() => {
6436
+ if (!onUpdateSettings || !isEditor) {
6437
+ prevSettingsRef.current = settings;
6438
+ prevLayoutIdRef.current = layoutId;
6439
+ return;
6440
+ }
6441
+
6442
+ if (prevLayoutIdRef.current !== layoutId) {
6443
+ prevSettingsRef.current = settings;
6444
+ prevLayoutIdRef.current = layoutId;
6445
+ return;
6446
+ }
6447
+
6448
+ const prevSettings = prevSettingsRef.current;
6449
+ const updatedSettings = applyListSettingsChange(
6450
+ settings,
6451
+ prevSettings,
6452
+ { designWidth },
6453
+ );
6454
+
6455
+ prevSettingsRef.current = settings;
6456
+
6457
+ if (updatedSettings === settings) {
6458
+ return;
6459
+ }
6460
+
6461
+ onUpdateSettings(updatedSettings);
6462
+ }, [settings, onUpdateSettings, isEditor, layoutId, designWidth]);
6463
+
6464
+ const columnWidthByKey = useMemo(
6465
+ () => getColumnWidthsFromSettings(settings),
6466
+ [
6467
+ settings.AColumnWidth,
6468
+ settings.BColumnWidth,
6469
+ settings.CColumnWidth,
6470
+ settings.DColumnWidth,
6471
+ settings.EColumnWidth,
6472
+ ],
6473
+ );
6474
+
6475
+ const columnPaddingLeftByKey = useMemo(
6476
+ () => getNumericSettingValues(settings, COLUMN_PADDING_LEFT_KEYS),
6477
+ [
6478
+ settings.AColumnPaddingLeft,
6479
+ settings.BColumnPaddingLeft,
6480
+ settings.CColumnPaddingLeft,
6481
+ settings.DColumnPaddingLeft,
6482
+ settings.EColumnPaddingLeft,
6483
+ ],
6484
+ );
6485
+
6486
+ const columnPaddingRightByKey = useMemo(
6487
+ () => getNumericSettingValues(settings, COLUMN_PADDING_RIGHT_KEYS),
6488
+ [
6489
+ settings.AColumnPaddingRight,
6490
+ settings.BColumnPaddingRight,
6491
+ settings.CColumnPaddingRight,
6492
+ settings.DColumnPaddingRight,
6493
+ settings.EColumnPaddingRight,
6494
+ ],
6495
+ );
6496
+
6497
+ const columnPaddingBottomByKey = useMemo(
6498
+ () => getNumericSettingValues(settings, COLUMN_PADDING_BOTTOM_KEYS),
6499
+ [
6500
+ settings.AColumnPaddingBottom,
6501
+ settings.BColumnPaddingBottom,
6502
+ settings.CColumnPaddingBottom,
6503
+ settings.DColumnPaddingBottom,
6504
+ settings.EColumnPaddingBottom,
6505
+ ],
6506
+ );
6507
+
6508
+ const columnContentOrder = useMemo((): typeof COLUMN_CONTENT_KEYS[number][] => {
6509
+ if (Array.isArray(columnsOrder) && columnsOrder.length > 0) {
6510
+ return columnsOrder as typeof COLUMN_CONTENT_KEYS[number][];
6511
+ }
6512
+ return [...COLUMN_CONTENT_KEYS];
6513
+ }, [columnsOrder]);
6514
+
6515
+ const listColumns = useMemo(
6516
+ () => buildListColumns(
6517
+ columnContentOrder,
6518
+ columns,
6519
+ columnWidthByKey,
6520
+ columnPaddingLeftByKey,
6521
+ columnPaddingRightByKey,
6522
+ columnPaddingBottomByKey,
6523
+ ),
6524
+ [columnContentOrder, columns, columnWidthByKey, columnPaddingLeftByKey, columnPaddingRightByKey, columnPaddingBottomByKey],
6525
+ );
6526
+
6527
+ const resolvedContentWidth = getListEffectiveContentWidth(settings);
6528
+
6529
+ const storedColumnWidths = useMemo(
6530
+ () => COLUMN_WIDTH_KEYS.slice(0, columns).map((key) => columnWidthByKey[key]),
6531
+ [columns, columnWidthByKey],
6532
+ );
6533
+
6534
+ const resolvedColumnWidths = useMemo(
6535
+ () => resolveListColumnWidths(columns, resolvedContentWidth, columnWidthByKey),
6536
+ [columns, resolvedContentWidth, columnWidthByKey],
6537
+ );
6538
+
6539
+ const effectiveColumnWidths = useMemo(
6540
+ () => getEffectiveListColumnWidths(columns, resolvedContentWidth, columnWidthByKey),
6541
+ [columns, resolvedContentWidth, columnWidthByKey],
6542
+ );
6543
+
6544
+ const effectiveColumnPaddings = useMemo(
6545
+ () =>
6546
+ listColumns.map((col, index) =>
6547
+ resolveListColumnPadding(
6548
+ effectiveColumnWidths[index] ?? 0,
6549
+ col.paddingLeft,
6550
+ col.paddingRight,
6551
+ )),
6552
+ [listColumns, effectiveColumnWidths],
6553
+ );
6554
+
6555
+ const allRows: ListItemRow[] = useMemo(() => {
6556
+ const resEntriesCount = entriesCount === 0 ? Infinity : entriesCount;
6557
+ const items = (content ?? []).slice(0, resEntriesCount);
6558
+
6559
+ return items.map((item, index) => ({
6560
+ id: index,
6561
+ cells: Object.fromEntries(
6562
+ COLUMN_CONTENT_KEYS.map((key) => [key, item[key] ?? ''])
6563
+ ),
6564
+ image: item.image,
6565
+ link: item.link,
6566
+ }));
6567
+ }, [content, entriesCount]);
6568
+
6569
+ const effectiveVisibleCount = cutEnabled
6570
+ ? (visibleRowCount ?? cut)
6571
+ : allRows.length;
6572
+
6573
+ const visibleRows = useMemo(() => {
6574
+ if (cutEnabled) {
6575
+ return allRows.slice(0, effectiveVisibleCount);
6576
+ }
6577
+ return allRows;
6578
+ }, [allRows, cutEnabled, effectiveVisibleCount]);
6579
+
6580
+ const showCutLabel = cutEnabled && effectiveVisibleCount < allRows.length;
6581
+
6582
+ const hasBetweenItemDividers = visibleRows.length > 1 || showCutLabel;
6583
+ const dividerClassNames = [
6584
+ showDividerTop ? \`\${P}-divider-top\` : '',
6585
+ showDividerBottom || hasBetweenItemDividers ? \`\${P}-divider-bottom\` : '',
6586
+ ].filter(Boolean).join(' ');
6587
+
6588
+ const handleShowMore = () => {
6589
+ const currentVisible = visibleRowCount ?? cut;
6590
+ if (!showCut) {
6591
+ setVisibleRowCount(allRows.length);
6592
+ return;
6593
+ }
6594
+ setVisibleRowCount(Math.min(currentVisible + showCut, allRows.length));
6595
+ };
6596
+
6597
+ const scaled = (v: number) => scalingValue(v, isEditor ?? false);
6598
+ const resolvedRowPaddingTop = isVerticalLayout
6599
+ ? (rowPaddingTopB ?? 0)
6600
+ : (rowPaddingTop ?? 0);
6601
+ const resolvedRowPaddingBottom = rowPaddingBottom ?? 0;
6602
+ const resolvedCellMinHeight = cellMinHeight ?? 0;
6603
+ const rowPaddingTopControlKey = isVerticalLayout ? 'rowPaddingTopB' : 'rowPaddingTop';
6604
+ const firstColumn = listColumns[0];
6605
+ const lastColumn = listColumns[listColumns.length - 1];
6606
+ const firstColumnEffectivePadding = effectiveColumnPaddings[0];
6607
+ const lastColumnEffectivePadding = effectiveColumnPaddings[effectiveColumnPaddings.length - 1];
6608
+ const firstColumnPaddingLeftWidth = firstColumn && firstColumnEffectivePadding
6609
+ ? Math.max(firstColumnEffectivePadding.paddingLeft, COL_PADDING_HANDLE_WIDTH)
6610
+ : 0;
6611
+ const lastColumnPaddingRightWidth = lastColumn && lastColumnEffectivePadding
6612
+ ? Math.max(lastColumnEffectivePadding.paddingRight, COL_PADDING_HANDLE_WIDTH)
6613
+ : 0;
6614
+ const columnsRightEdge = resolvedContentWidth;
6615
+
6616
+ const getHoverImagePosition = (event: React.MouseEvent) => {
6617
+ const container = containerRef.current;
6618
+ if (!container) {
6619
+ return { x: 0, y: 0 };
6620
+ }
6621
+
6622
+ const rect = container.getBoundingClientRect();
6623
+ return {
6624
+ x: event.clientX - rect.left + HOVER_IMAGE_CURSOR_OFFSET,
6625
+ y: event.clientY - rect.top + HOVER_IMAGE_CURSOR_OFFSET,
6626
+ };
6627
+ };
6628
+
6629
+ const handleRowMouseEnter = (row: ListItemRow, event: React.MouseEvent) => {
6630
+ if (!showHoverImage) return;
6631
+
6632
+ const image = row.image;
6633
+ if (!image?.url) {
6634
+ setHoverImage(null);
6635
+ return;
6636
+ }
6637
+
6638
+ const { x, y } = getHoverImagePosition(event);
6639
+ const minWidth = imageSize?.min ?? 80;
6640
+ const maxWidth = imageSize?.max ?? 320;
6641
+ const widthPx = hoverImage?.rowId === row.id
6642
+ ? hoverImage.widthPx
6643
+ : randomBetween(minWidth, maxWidth);
6644
+
6645
+ setHoverImage({
6646
+ rowId: row.id,
6647
+ url: image.url,
6648
+ objectFit: image.objectFit ?? 'cover',
6649
+ widthPx,
6650
+ x,
6651
+ y,
6652
+ });
6653
+ };
6654
+
6655
+ const handleWrapperMouseMove = (event: React.MouseEvent) => {
6656
+ if (!showHoverImage || !hoverImage) return;
6657
+
6658
+ const { x, y } = getHoverImagePosition(event);
6659
+ setHoverImage((prev) => {
6660
+ if (!prev) return prev;
6661
+ if (prev.x === x && prev.y === y) return prev;
6662
+ return { ...prev, x, y };
6663
+ });
6664
+ };
6665
+
6666
+ const handleWrapperMouseLeave = () => {
6667
+ setHoverImage(null);
6668
+ };
6669
+
6670
+ const hasBaselineColumn = useMemo(
6671
+ () =>
6672
+ !isVerticalLayout &&
6673
+ COLUMN_TEXT_PREFIXES.some((prefix) => {
6674
+ const columnLetter = prefix.charAt(0);
6675
+ const valign = settings[\`\${prefix}VerticalAlign\` as ListColumnVerticalAlignKey];
6676
+ return isActiveBaselineVAlign(valign, settings, columnLetter);
6677
+ }),
6678
+ [
6679
+ isVerticalLayout,
6680
+ settings,
6681
+ settings.AColumnVerticalAlign,
6682
+ settings.BColumnVerticalAlign,
6683
+ settings.CColumnVerticalAlign,
6684
+ settings.DColumnVerticalAlign,
6685
+ settings.EColumnVerticalAlign,
6686
+ ],
6687
+ );
6688
+
6689
+ useLayoutEffect(() => {
6690
+ const container = containerRef.current;
6691
+ if (!container) return;
6692
+
6693
+ const clearBaselineStyles = () => {
6694
+ container.querySelectorAll<HTMLElement>('[data-list-col]').forEach((el) => {
6695
+ el.style.transform = '';
6696
+ const listCol = el.querySelector<HTMLElement>(\`.\${P}-list-col\`);
6697
+ if (listCol) {
6698
+ listCol.style.minHeight = '';
6699
+ listCol.style.height = '';
6700
+ }
6701
+ const title = el.querySelector<HTMLElement>(\`.\${P}-list-col-title\`);
6702
+ if (title) {
6703
+ title.style.transform = '';
6704
+ }
6705
+ });
6706
+ };
6707
+
6708
+ if (isVerticalLayout || !hasBaselineColumn) {
6709
+ clearBaselineStyles();
6710
+ return;
6711
+ }
6712
+
6713
+ const applyBaselines = () => {
6714
+ container.querySelectorAll<HTMLElement>('[data-list-row]').forEach((rowEl) => {
6715
+ const cols = Array.from(rowEl.querySelectorAll<HTMLElement>('[data-list-col]'));
6716
+ cols.forEach((el) => {
6717
+ el.style.transform = '';
6718
+ const listCol = el.querySelector<HTMLElement>(\`.\${P}-list-col\`);
6719
+ if (listCol) {
6720
+ listCol.style.minHeight = '';
6721
+ listCol.style.height = '';
6722
+ }
6723
+ const title = el.querySelector<HTMLElement>(\`.\${P}-list-col-title\`);
6724
+ if (title) {
6725
+ title.style.transform = '';
6726
+ }
6727
+ });
6728
+
6729
+ syncRowListColHeights(rowEl, cols, \`\${P}-list-col\`);
6730
+ void rowEl.offsetHeight;
6731
+ const rowTop = rowEl.getBoundingClientRect().top;
6732
+
6733
+ type ColInfo = {
6734
+ el: HTMLElement;
6735
+ titleEl: HTMLElement | null;
6736
+ letter: string;
6737
+ kind: string;
6738
+ anchor: string | null;
6739
+ };
6740
+
6741
+ const probeClassName = \`\${P}-baseline-probe\`;
6742
+ const byLetter = new Map<string, ColInfo>();
6743
+ const infos: ColInfo[] = cols.map((el) => {
6744
+ const titleEl = el.querySelector<HTMLElement>(\`.\${P}-list-col-title\`);
6745
+ const info: ColInfo = {
6746
+ el,
6747
+ titleEl,
6748
+ letter: el.getAttribute('data-col-letter') ?? '',
6749
+ kind: el.getAttribute('data-valign') ?? 'top',
6750
+ anchor: el.getAttribute('data-valign-anchor'),
6751
+ };
6752
+ byLetter.set(info.letter, info);
6753
+ return info;
6754
+ });
6755
+
6756
+ const finalBaseline = new Map<string, number>();
6757
+ const resolve = (info: ColInfo, stack: Set<string>): number => {
6758
+ const cached = finalBaseline.get(info.letter);
6759
+ if (cached !== undefined) return cached;
6760
+
6761
+ const anchor = info.anchor ? byLetter.get(info.anchor) : undefined;
6762
+ if (info.kind !== 'baseline' || !anchor || stack.has(info.letter)) {
6763
+ const baseline = measureColumnFirstLineBaselineOffset(
6764
+ info,
6765
+ rowTop,
6766
+ \`\${P}-list-col\`,
6767
+ probeClassName,
6768
+ );
6769
+ finalBaseline.set(info.letter, baseline);
6770
+ return baseline;
6771
+ }
6772
+
6773
+ stack.add(info.letter);
6774
+ const anchorBaseline = resolve(anchor, stack);
6775
+ stack.delete(info.letter);
6776
+
6777
+ const followerNatural = measureColumnFirstLineBaselineOffset(
6778
+ info,
6779
+ rowTop,
6780
+ \`\${P}-list-col\`,
6781
+ probeClassName,
6782
+ );
6783
+ const shift = anchorBaseline - followerNatural;
6784
+ applyBaselineTitleShift(info.titleEl, shift);
6785
+
6786
+ const result = measureColumnFirstLineBaselineOffset(
6787
+ info,
6788
+ rowTop,
6789
+ \`\${P}-list-col\`,
6790
+ probeClassName,
6791
+ );
6792
+ finalBaseline.set(info.letter, result);
6793
+ return result;
6794
+ };
6795
+
6796
+ infos.forEach((info) => resolve(info, new Set<string>()));
6797
+ });
6798
+ };
6799
+
6800
+ applyBaselines();
6801
+
6802
+ const observer = new ResizeObserver(() => applyBaselines());
6803
+ observer.observe(container);
6804
+
6805
+ let cancelled = false;
6806
+ if (typeof document !== 'undefined' && document.fonts?.ready) {
6807
+ document.fonts.ready.then(() => {
6808
+ if (!cancelled) applyBaselines();
6809
+ });
6810
+ }
6811
+
6812
+ return () => {
6813
+ cancelled = true;
6814
+ observer.disconnect();
6815
+ clearBaselineStyles();
6816
+ };
6817
+ }, [
6818
+ hasBaselineColumn,
6819
+ isVerticalLayout,
6820
+ settings,
6821
+ content,
6822
+ designWidth,
6823
+ visibleRows,
6824
+ effectiveColumnWidths,
6825
+ ]);
6826
+
6827
+ return (
6828
+ <>
6829
+ <style dangerouslySetInnerHTML={{ __html: getCSS(P) }} />
6830
+ <div style={colorVars}>
6831
+ <div
6832
+ ref={containerRef}
6833
+ className={\`\${P}-wrapper \${wrapperStateClasses}\${dividerClassNames ? \` \${dividerClassNames}\` : ''}\${isVerticalLayout ? \` \${P}-type-b\` : ''}\`.trim()}
6834
+ style={{
6835
+ width: scalingValue(wrapperWidth ?? 0, isEditor),
6836
+ }}
6837
+ onMouseMove={showHoverImage ? handleWrapperMouseMove : undefined}
6838
+ onMouseLeave={showHoverImage ? handleWrapperMouseLeave : undefined}
6839
+ >
6840
+ <div style={{ width: '100%' }}>
6841
+ {visibleRows.map((row, rowIdx) => {
6842
+ const hasLink = (row.link?.length ?? 0) > 0;
6843
+ const RowElement = hasLink ? 'a' : 'div';
6844
+ const rowStyle = getEntryDividerWidths(
6845
+ rowIdx,
6846
+ visibleRows.length,
6847
+ showDividerTop,
6848
+ showDividerBottom,
6849
+ showCutLabel,
6850
+ dividerWidth ?? 0,
6851
+ isEditor ?? false,
6852
+ );
6853
+
6854
+ return (
6855
+ <RowElement
6856
+ key={row.id}
6857
+ className={\`\${P}-list-item\${hasLink ? \` \${P}-list-item-has-link\` : ''}\`}
6858
+ {...(hasLink ? { href: row.link, target: '_blank' } : {})}
6859
+ style={rowStyle}
6860
+ onMouseEnter={showHoverImage ? (event) => handleRowMouseEnter(row, event) : undefined}
6861
+ >
6862
+ {(resolvedRowPaddingTop > 0 || showControls) && (
6863
+ <div
6864
+ {...(showControls ? {
6865
+ 'data-controls': rowPaddingTopControlKey,
6866
+ 'data-controls-axis': 'y',
6867
+ 'data-controls-min': '0',
6868
+ } : {})}
6869
+ className={\`\${P}-row-padding-handle\`}
6870
+ style={{ height: scaled(resolvedRowPaddingTop) }}
6871
+ />
6872
+ )}
6873
+ <div
6874
+ className={\`\${P}-list-cols-row\${isVerticalLayout ? '' : \` \${P}-list-cols-row-h\`}\`}
6875
+ {...(isVerticalLayout ? {} : { 'data-list-row': '' })}
6876
+ style={isVerticalLayout ? undefined : { minHeight: scaled(resolvedCellMinHeight) }}
6877
+ >
6878
+ {listColumns.map((col, colIndex) => {
6879
+ const isLastColumn = colIndex === listColumns.length - 1;
6880
+ const effectivePadding = effectiveColumnPaddings[colIndex];
6881
+ const columnPaddingBottom = col.paddingBottom;
6882
+ const hasColumnText = hasListColumnText(row.cells[col.key]);
6883
+ const showColumnPaddingBottom = isVerticalLayout
6884
+ && hasColumnText
6885
+ && (columnPaddingBottom > 0 || showControls);
6886
+ const columnSizeStyle = isVerticalLayout
6887
+ ? { minHeight: scaled(resolvedCellMinHeight) }
6888
+ : (isLastColumn ? {} : { width: scaled(effectiveColumnWidths[colIndex]) });
6889
+ const columnPaddingStyle = isVerticalLayout
6890
+ ? {
6891
+ paddingLeft: scaled(effectiveTextPaddingLR),
6892
+ paddingRight: scaled(effectiveTextPaddingLR),
6893
+ }
6894
+ : {
6895
+ paddingLeft: scaled(effectivePadding.paddingLeft),
6896
+ paddingRight: scaled(effectivePadding.paddingRight),
6897
+ };
6898
+ const columnLetter = col.textPrefix.charAt(0);
6899
+ const vAlign = isVerticalLayout
6900
+ ? { kind: 'top' as const }
6901
+ : resolveColumnVerticalAlign(
6902
+ settings[\`\${col.textPrefix}VerticalAlign\` as ListColumnVerticalAlignKey],
6903
+ settings,
6904
+ columnLetter,
6905
+ );
6906
+
6907
+ return (
6908
+ <div
6909
+ key={col.key}
6910
+ {...(isVerticalLayout
6911
+ ? {}
6912
+ : {
6913
+ 'data-list-col': '',
6914
+ 'data-col-letter': columnLetter,
6915
+ 'data-valign': vAlign.kind,
6916
+ ...(vAlign.kind === 'baseline'
6917
+ ? { 'data-valign-anchor': vAlign.anchorLetter }
6918
+ : {}),
6919
+ })}
6920
+ >
6921
+ <div
6922
+ className={\`\${P}-list-col\${isLastColumn ? \` \${P}-list-col-last\` : ''}\`}
6923
+ style={{
6924
+ ...columnPaddingStyle,
6925
+ ...columnSizeStyle,
6926
+ }}
6927
+ data-test={col.width}
6928
+ >
6929
+ <span
6930
+ className={getListColumnTitleClassName(
6931
+ settings,
6932
+ col.textPrefix,
6933
+ \`\${P}-list-col-title\`,
6934
+ \`\${P}-text-tight-leading\`,
6935
+ )}
6936
+ style={{
6937
+ ...listColumnTextFieldsToCss(resolveListColumnTextFields(settings, col.textPrefix), isEditor),
6938
+ ...getListColumnTitleVars(settings, col.textPrefix, P, isEditor),
6939
+ ...(!isVerticalLayout ? vAlignToTitleStyle(vAlign.kind) : {}),
6940
+ }}
6941
+ >
6942
+ {row.cells[col.key] ?? null}
6943
+ </span>
6944
+ </div>
6945
+ {showColumnPaddingBottom && (
6946
+ <div
6947
+ {...(showControls ? {
6948
+ 'data-controls': col.paddingBottomKey,
6949
+ 'data-controls-axis': 'y',
6950
+ 'data-controls-min': '0',
6951
+ } : {})}
6952
+ className={\`\${P}-row-padding-handle\`}
6953
+ style={{ height: scaled(columnPaddingBottom) }}
6954
+ />
6955
+ )}
6956
+ </div>
6957
+ );
6958
+ })}
6959
+ </div>
6960
+ {!isVerticalLayout && (resolvedRowPaddingBottom > 0 || showControls) && (
6961
+ <div
6962
+ {...(showControls ? {
6963
+ 'data-controls': 'rowPaddingBottom',
6964
+ 'data-controls-axis': 'y',
6965
+ 'data-controls-min': '0',
6966
+ } : {})}
6967
+ className={\`\${P}-row-padding-handle\`}
6968
+ style={{ height: scaled(resolvedRowPaddingBottom) }}
6969
+ />
6970
+ )}
6971
+ </RowElement>
6972
+ );
6973
+ })}
6974
+ {showCutLabel && (
6975
+ <button
6976
+ type="button"
6977
+ className={\`\${P}-cut-item\`}
6978
+ style={{
6979
+ minHeight: scaled(cutCellMinHeight ?? 0),
6980
+ ...getCutItemDividerWidths(
6981
+ showDividerBottom,
6982
+ dividerWidth ?? 0,
6983
+ isEditor ?? false,
6984
+ ),
6985
+ }}
6986
+ onClick={handleShowMore}
6987
+ >
6988
+ <div
6989
+ className={\`\${P}-list-cols-row\`}
6990
+ style={
6991
+ isVerticalLayout
6992
+ ? {
6993
+ paddingLeft: scaled(effectiveTextPaddingLR),
6994
+ paddingRight: scaled(effectiveTextPaddingLR),
6995
+ }
6996
+ : { justifyContent: 'center' }
6997
+ }
6998
+ >
6999
+ <span
7000
+ className={getListColumnTitleClassName(
7001
+ settings,
7002
+ CUT_LABEL_TEXT_PREFIX,
7003
+ \`\${P}-cut-label\`,
7004
+ \`\${P}-text-tight-leading\`,
7005
+ )}
7006
+ style={{
7007
+ ...listColumnTextFieldsToCss(resolveListColumnTextFields(settings, CUT_LABEL_TEXT_PREFIX), isEditor),
7008
+ ...getListColumnTitleVars(settings, CUT_LABEL_TEXT_PREFIX, P, isEditor),
7009
+ }}
7010
+ >
7011
+ {cutLabel}
7012
+ </span>
7013
+ </div>
7014
+ </button>
7015
+ )}
7016
+ </div>
7017
+ {showControls && !isVerticalLayout && firstColumn && lastColumn && (
7018
+ <div key="column-edge-padding-handles" style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
7019
+ <div
7020
+ data-controls={firstColumn.paddingLeftKey}
7021
+ data-controls-axis="x"
7022
+ data-controls-variant="column-padding"
7023
+ data-controls-min="0"
7024
+ data-controls-max-fraction={String(
7025
+ effectiveColumnWidths[0] - (firstColumnEffectivePadding?.paddingRight ?? 0),
7026
+ )}
7027
+ data-controls-static-handle=""
7028
+ className={\`\${P}-padding-control-handle\`}
7029
+ style={{
7030
+ position: 'absolute',
7031
+ top: 0,
7032
+ left: 0,
7033
+ width: scaled(firstColumnPaddingLeftWidth),
7034
+ height: '100%',
7035
+ pointerEvents: 'auto',
7036
+ zIndex: 2,
7037
+ }}
7038
+ />
7039
+ <div
7040
+ data-controls={lastColumn.paddingRightKey}
7041
+ data-controls-axis="x"
7042
+ data-controls-variant="column-padding"
7043
+ data-controls-reverse=""
7044
+ data-controls-min="0"
7045
+ data-controls-max-fraction={String(
7046
+ effectiveColumnWidths[listColumns.length - 1]
7047
+ - (lastColumnEffectivePadding?.paddingLeft ?? 0),
7048
+ )}
7049
+ data-controls-static-handle=""
7050
+ className={\`\${P}-padding-control-handle\`}
7051
+ style={{
7052
+ position: 'absolute',
7053
+ top: 0,
7054
+ left: scaled(columnsRightEdge - lastColumnPaddingRightWidth),
7055
+ width: scaled(lastColumnPaddingRightWidth),
7056
+ height: '100%',
7057
+ pointerEvents: 'auto',
7058
+ zIndex: 2,
7059
+ }}
7060
+ />
7061
+ </div>
7062
+ )}
7063
+ {showControls && !isVerticalLayout && listColumns.slice(0, -1).map((col, colIndex) => {
7064
+ const nextCol = listColumns[colIndex + 1];
7065
+ const maxColumnWidth = getColumnMaxWidth(
7066
+ colIndex,
7067
+ resolvedColumnWidths,
7068
+ storedColumnWidths,
7069
+ resolvedContentWidth,
7070
+ );
7071
+ const boundaryOffset = resolvedColumnWidths.slice(0, colIndex + 1).reduce((sum, width) => sum + width, 0);
7072
+ const colEffectivePadding = effectiveColumnPaddings[colIndex];
7073
+ const nextColEffectivePadding = effectiveColumnPaddings[colIndex + 1];
7074
+ const paddingRightWidth = Math.max(
7075
+ colEffectivePadding.paddingRight,
7076
+ COL_PADDING_HANDLE_WIDTH,
7077
+ );
7078
+ const paddingLeftWidth = Math.max(
7079
+ nextColEffectivePadding.paddingLeft,
7080
+ COL_PADDING_HANDLE_WIDTH,
7081
+ );
7082
+ const columnWidthHandleOffset = boundaryOffset - COL_RESIZE_HANDLE_WIDTH / 2;
7083
+
7084
+ return (
7085
+ <div key={\`\${col.widthKey}-junction\`} style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
7086
+ <div
7087
+ data-controls={col.paddingRightKey}
7088
+ data-controls-axis="x"
7089
+ data-controls-variant="column-padding"
7090
+ data-controls-reverse=""
7091
+ data-controls-min="0"
7092
+ data-controls-max-fraction={String(
7093
+ effectiveColumnWidths[colIndex] - colEffectivePadding.paddingLeft,
7094
+ )}
7095
+ data-controls-static-handle=""
7096
+ className={\`\${P}-padding-control-handle\`}
7097
+ style={{
7098
+ position: 'absolute',
7099
+ top: 0,
7100
+ left: scaled(boundaryOffset - paddingRightWidth),
7101
+ width: scaled(paddingRightWidth),
7102
+ height: '100%',
7103
+ pointerEvents: 'auto',
7104
+ zIndex: 2,
7105
+ }}
7106
+ />
7107
+ <div
7108
+ data-controls={col.widthKey}
7109
+ data-controls-axis="x"
7110
+ data-controls-min={String(MIN_COLUMN_WIDTH_PX)}
7111
+ data-controls-max-fraction={String(maxColumnWidth)}
7112
+ data-controls-variant="column-width"
7113
+ className={\`\${P}-col-resize-handle\`}
7114
+ style={{
7115
+ position: 'absolute',
7116
+ top: '0px',
7117
+ left: scaled(columnWidthHandleOffset),
7118
+ width: scaled(COL_RESIZE_HANDLE_WIDTH),
7119
+ height: 'calc(100%)',
7120
+ pointerEvents: 'auto',
7121
+ zIndex: 4,
7122
+ }}
7123
+ />
7124
+ <div
7125
+ data-controls={nextCol.paddingLeftKey}
7126
+ data-controls-axis="x"
7127
+ data-controls-variant="column-padding"
7128
+ data-controls-min="0"
7129
+ data-controls-max-fraction={String(
7130
+ effectiveColumnWidths[colIndex + 1] - nextColEffectivePadding.paddingRight,
7131
+ )}
7132
+ data-controls-static-handle=""
7133
+ className={\`\${P}-padding-control-handle\`}
7134
+ style={{
7135
+ position: 'absolute',
7136
+ top: 0,
7137
+ left: scaled(boundaryOffset),
7138
+ width: scaled(paddingLeftWidth),
7139
+ height: '100%',
7140
+ pointerEvents: 'auto',
7141
+ zIndex: 2,
7142
+ }}
7143
+ />
7144
+ </div>
7145
+ );
7146
+ })}
7147
+ {showControls && isVerticalLayout && (
7148
+ <div key="text-padding-lr-handles" style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
7149
+ <div
7150
+ data-controls="textPaddingLR"
7151
+ data-controls-paired=""
7152
+ data-controls-axis="x"
7153
+ data-controls-min="0"
7154
+ data-controls-max-fraction={String(textPaddingLRMaxFraction)}
7155
+ data-controls-static-handle=""
7156
+ className={\`\${P}-text-padding-lr-handle\`}
7157
+ style={{
7158
+ position: 'absolute',
7159
+ top: 0,
7160
+ left: 0,
7161
+ width: scaled(textPaddingLRHandleWidth),
7162
+ height: '100%',
7163
+ pointerEvents: 'auto',
7164
+ zIndex: 2,
7165
+ }}
7166
+ />
7167
+ <div
7168
+ data-controls="textPaddingLR"
7169
+ data-controls-paired=""
7170
+ data-controls-axis="x"
7171
+ data-controls-reverse=""
7172
+ data-controls-min="0"
7173
+ data-controls-max-fraction={String(textPaddingLRMaxFraction)}
7174
+ data-controls-static-handle=""
7175
+ className={\`\${P}-text-padding-lr-handle\`}
7176
+ style={{
7177
+ position: 'absolute',
7178
+ top: 0,
7179
+ left: scaled(Math.max(textPaddingLRHandleWidth, resolvedContentWidth - textPaddingLRHandleWidth)),
7180
+ width: scaled(textPaddingLRHandleWidth),
7181
+ height: '100%',
7182
+ pointerEvents: 'auto',
7183
+ zIndex: 2,
7184
+ }}
7185
+ />
7186
+ </div>
7187
+ )}
7188
+ {showHoverImage && hoverImage && (
7189
+ <img
7190
+ className={\`\${P}-hover-image\`}
7191
+ src={hoverImage.url}
7192
+ alt=""
7193
+ style={{
7194
+ width: sv(hoverImage.widthPx),
7195
+ objectFit: hoverImage.objectFit,
7196
+ left: hoverImage.x,
7197
+ top: hoverImage.y,
7198
+ }}
7199
+ />
7200
+ )}
7201
+ </div>
7202
+ </div>
7203
+ </>
7204
+ );
7205
+ }
7206
7206
  `,Bt=["A","B","C","D","E"],zo=[...Xc,"Baseline A","Baseline B","Baseline C","Baseline D","Baseline E"],Mt={fontSettings:{type:"object",display:{type:"font-settings-weight"},properties:{fontWeight:{type:"number"},fontStyle:{type:"string"}}},fontSize:{type:"number",display:{type:"font-size"}},lineHeight:{type:"number",display:{type:"line-height-input"}},letterSpacing:{type:"number",display:{type:"letter-spacing-input"}},wordSpacing:{type:"number",display:{type:"word-spacing-input"}},textAppearance:{type:"object",display:{type:"text-appearance"},properties:{textTransform:{type:"string",enum:["none","uppercase","lowercase","capitalize"]},textDecoration:{type:"string",enum:["none","underline"]},fontVariant:{type:"string",enum:["normal","small-caps"]}}}};function Td(e){return{type:"string",label:e,placeholder:"Add Title...",display:{type:"text-input"}}}function Hn(e){return{type:"number",scope:"layout",title:e,min:0,max:100,display:{type:"range-control"}}}function Ld(){return Object.fromEntries(Bt.map((e,t)=>{const n=Pt[t],r=`${e} column`;return[n,Td(r)]}))}function Ed(){const e={};for(const t of Bt)e[`${t}ColumnWidth`]=Hn(`${t} column width`),e[`${t}ColumnPaddingLeft`]=Hn(`${t} column padding left`),e[`${t}ColumnPaddingRight`]=Hn(`${t} column padding right`),e[`${t}ColumnPaddingBottom`]=Hn(`${t} column padding bottom`);return e}function jo(e={}){const t={columns:5,wrapperWidth:1,columnsOrder:[...Pt]};for(const n of Bt)t[`${n}ColumnWidth`]=.2,t[`${n}ColumnPaddingLeft`]=0,t[`${n}ColumnPaddingRight`]=0,t[`${n}ColumnPaddingBottom`]=0;return{...t,...e}}function _d(e){const t={};if(e!==vt){const n=e.charAt(0);t[`${e}VerticalAlign`]={type:"string",scope:"layout",title:"Vertical align",display:{type:"drop-down",enum:[...zo],filterBaselineByTopAnchor:!0,columnLetter:n},enum:[...zo]}}return t[we(e,"textFontFamily")]={type:"string",scope:"common",title:"Font family",display:{type:"font-family-select"}},t[we(e,"textFontSettings")]={...Mt.fontSettings,scope:"common",title:"",display:{type:"font-settings-weight"}},t[we(e,"textFontSize")]={...Mt.fontSize,scope:"layout",title:"Font Size",display:{type:"font-size"}},t[we(e,"textLineHeight")]={...Mt.lineHeight,scope:"layout",title:"Line Height",display:{type:"line-height-input"}},t[we(e,"textLetterSpacing")]={...Mt.letterSpacing,scope:"layout",title:"Letter Spacing",display:{type:"letter-spacing-input"}},t[we(e,"textWordSpacing")]={...Mt.wordSpacing,scope:"layout",title:"Word Spacing",display:{type:"word-spacing-input"}},t[we(e,"textTextAppearance")]={...Mt.textAppearance,scope:"layout",title:"Text Appearance",display:{type:"text-appearance"}},t}const Pd=Pn.reduce((e,t)=>({...e,..._d(t)}),{}),Ad=Pn.reduce((e,t)=>({...e,...t!==vt?{[`${t}VerticalAlign`]:"Top"}:{},[we(t,"textFontFamily")]:"Arial",[we(t,"textFontSettings")]:{fontWeight:400,fontStyle:"normal"},[we(t,"textLetterSpacing")]:0,[we(t,"textWordSpacing")]:0,[we(t,"textTextAppearance")]:{textTransform:"none",textDecoration:"none",fontVariant:"normal"}}),{});function Ko(e){const{textFontSize:t,textLineHeight:n}=e;return Pn.reduce((r,o)=>(t!==void 0&&(r[`${o}TextFontSize`]=t),n!==void 0&&(r[`${o}TextLineHeight`]=n),r),{})}const Rd={AColumn:"A column",BColumn:"B column",CColumn:"C column",DColumn:"D column",EColumn:"E column",cutLabel:"See all"},Id=Pn.map(e=>({type:"group",title:Rd[e],items:[we(e,"textFontFamily"),we(e,"textFontSettings"),{type:"row",items:[we(e,"textFontSize"),we(e,"textLineHeight"),we(e,"textLetterSpacing"),we(e,"textWordSpacing")]},we(e,"textTextAppearance"),...e!==vt?[`${e}VerticalAlign`]:[]]}));function Mi(e){return[we(e,"textFontFamily"),we(e,"textFontSettings"),we(e,"textFontSize"),we(e,"textLineHeight"),we(e,"textLetterSpacing"),we(e,"textWordSpacing"),we(e,"textTextAppearance"),...e!==vt?[`${e}VerticalAlign`]:[]]}function Wd(){const e=[];return eo.forEach((t,n)=>{const r=Pt[n],o=Mi(t);for(let s=1;s<Pt.length;s+=1){const i=[{name:"columns",value:s},...Array.from({length:s},(a,c)=>({name:`columnsOrder.${c}`,value:r,isNotEqual:!0}))];o.forEach(a=>{e.push({if:i,then:{name:`properties.${a}.display.visible`,value:!1}})})}}),e}const Fd=["textColor","backgroundColor","dividerColor","textHoverColor","backgroundHoverColor","dividerHoverColor"],kd=["cutLabel","cutCellMinHeight","showCut"],Md=Mi(vt),Nd=[...kd,...Md],Hd=[...Bt.flatMap(e=>[`${e}ColumnWidth`,`${e}ColumnPaddingLeft`,`${e}ColumnPaddingRight`]),"rowPaddingTop","rowPaddingBottom"];function Cr(e,t){const n=e?` ${e}`:"";return{AColumn:`AColumn${n}`,BColumnWidth:`BColumnWidth${n}`,CColumnWidth:`CColumnWidth${n}`,DColumnWidth:`DColumnWidth${n}`,EColumnWidth:`EColumnWidth${n}`,image:t,link:""}}const Od=[Cr("",{objectFit:"cover",url:"https://cdn.cntrl.site/projects/01JJKT02AWY2FGN2QJ7A173RNZ/articles-assets/01K7ERQK9211QXBE9W284ZNKB8.png",name:"Slider-1.png"}),Cr("2",{objectFit:"cover",url:"https://cdn.cntrl.site/projects/01JJKT02AWY2FGN2QJ7A173RNZ/articles-assets/01K7ERQMFT72JD18WKP0Q2DVAT.png",name:"Slider-2.png"}),Cr("3",{objectFit:"cover",url:"https://cdn.cntrl.site/projects/01JJKT02AWY2FGN2QJ7A173RNZ/articles-assets/01K7ERQNEVRXPSRX5K1YTMJQY9.png",name:"Slider-3.png"})],Bd=[...Bt.flatMap(e=>[`${e}ColumnWidth`,`${e}ColumnPaddingLeft`,`${e}ColumnPaddingRight`,`${e}ColumnPaddingBottom`]),"columnsOrder"],Vd={type:"object",version:1,content:{type:"array",settings:{addItemWithoutImage:!0},display:{type:"array",ref:{columnsOrder:"settings.properties.columnsOrder",columnsCount:"settings.properties.columns"}},items:{type:"object",properties:{...Ld(),image:{type:"object",label:"Image",display:{isObjectFitEditable:!1,type:"media-input"},properties:{url:{type:"string"},name:{type:"string"},objectFit:{type:"string",enum:["cover","contain"]}},required:["url","name"]},link:{type:"string",label:"Link",placeholder:"Add link...",display:{type:"text-input"}}},required:["image"]},default:Od},settings:{sizing:"auto auto",properties:{type:{type:"string",scope:"layout",title:"",display:{type:"radio-group"},enum:["A","B"]},columns:{type:"number",scope:"layout",title:"Columns",display:{type:"count-number"},min:1,max:5},wrapperWidth:{type:"number",scope:"layout",title:"Width",display:{type:"numeric-input"},min:0,max:9999},textPaddingLR:{type:"number",scope:"layout",title:"Text Padding LR",min:0,max:9999,display:{type:"range-control"}},entriesCount:{type:"number",scope:"layout",title:"Entries #",display:{type:"toggle-numeric-input",enum:["Auto","Fixed"]},min:1},cellMinHeight:{type:"number",scope:"layout",title:"Cell min height",display:{type:"numeric-input"},min:0,max:9999},imageOnHover:{type:"boolean",scope:"common",title:"Image On Hover",display:{type:"toggle-cycle",enum:["On","Off"]}},imageSize:{type:"object",scope:"layout",title:"Image size",display:{type:"min-max-input"},min:1,max:1440,properties:{min:{type:"number"},max:{type:"number"}}},dividerWidth:{type:"number",scope:"layout",title:"Divider width",display:{type:"numeric-input"},min:0,max:9999},showVisibility:{type:"array",scope:"common",title:"Show",display:{type:"double-toggle",enum:["Top","Bottom"]},items:{type:"boolean"},default:[!0,!1]},cut:{type:"number",scope:"layout",title:"Cut",display:{type:"toggle-numeric-input",enum:["Off","On"]},min:1},entryHoverEffect:{type:"string",scope:"common",title:"Entry Hover Effect",display:{type:"toggle-cycle",enum:["None","Default","Blinds"]}},cutCellMinHeight:{type:"number",scope:"layout",title:"Cell min height",display:{type:"numeric-input"},min:0,max:9999},cutLabel:{type:"string",scope:"common",title:"Cut Label",display:{type:"label-input"}},showCut:{type:"number",scope:"layout",title:"Show",display:{type:"toggle-numeric-input",enum:["All","Custom"]},min:1},rowPaddingTop:{type:"number",scope:"layout",title:"Row Padding Top",min:0,max:100,display:{type:"range-control"}},rowPaddingBottom:{type:"number",scope:"layout",title:"Row Padding Bottom",min:0,max:100,display:{type:"range-control"}},rowPaddingTopB:{type:"number",scope:"layout",title:"Row Padding Top",min:0,max:100,display:{type:"range-control"}},...Ed(),columnsOrder:{type:"array",scope:"layout",title:"Columns Order",display:{type:"reorder-input"},items:{type:"string"}},textColor:{type:"string",scope:"common",title:"Text Default",display:{type:"palette-color-picker"}},textHoverColor:{type:"string",scope:"common",title:"Text Hover",display:{type:"palette-color-picker"}},textFontFamily:{type:"string",scope:"common",title:"Font family",display:{type:"font-family-select"}},textFontSettings:{...Mt.fontSettings,scope:"common",title:"",display:{type:"font-settings-weight"}},textFontSize:{type:"number",scope:"layout",title:"Input Font Size",display:{type:"font-size"}},textLineHeight:{type:"number",scope:"layout",title:"Input Line Height",display:{type:"line-height-input"}},textLetterSpacing:{type:"number",scope:"layout",title:"Input Letter Spacing",display:{type:"letter-spacing-input"}},textWordSpacing:{type:"number",scope:"layout",title:"Input Word Spacing",display:{type:"word-spacing-input"}},textTextAppearance:{type:"object",scope:"layout",title:"Input Text Appearance",display:{type:"text-appearance"}},...Pd,backgroundColor:{type:"string",scope:"common",title:"BG Default",display:{type:"palette-color-picker"}},dividerColor:{type:"string",scope:"common",title:"Divider Default",display:{type:"palette-color-picker"}},backgroundHoverColor:{type:"string",scope:"common",title:"BG Hover",display:{type:"palette-color-picker"}},dividerHoverColor:{type:"string",scope:"common",title:"Divider Hover",display:{type:"palette-color-picker"}}},defaults:{imageOnHover:"Off",entryHoverEffect:"None",cutLabel:"SEE ALL",showVisibility:[!0,!0],textColor:"#767676",textHoverColor:"#767676",textFontFamily:"Arial",textFontSettings:{fontWeight:400,fontStyle:"normal"},textLetterSpacing:0,textWordSpacing:0,textTextAppearance:{textTransform:"none",textDecoration:"none",fontVariant:"normal"},...Ad,backgroundColor:"#FFFFFF00",dividerColor:"#767676",backgroundHoverColor:"#FFFFFF00",dividerHoverColor:"#767676"},layoutDefaults:{m:jo({type:"B",textPaddingLR:.0373,entriesCount:0,cellMinHeight:.02,imageSize:{min:80,max:320},dividerWidth:.002,cut:0,showCut:0,cutCellMinHeight:.043,rowPaddingTop:.01,rowPaddingBottom:.01,rowPaddingTopB:.01,textStroke:.003,textCorners:.192,textPadding:{top:.0373,right:.0373,bottom:.0373,left:.0373},textFontSize:.043,textLineHeight:.043,...Ko({textFontSize:.043,textLineHeight:.043})}),d:jo({type:"A",textPaddingLR:.01,entriesCount:0,cellMinHeight:.03,imageSize:{min:80,max:320},dividerWidth:6e-4,cut:0,showCut:0,cutCellMinHeight:.03,rowPaddingTop:.01,rowPaddingBottom:.01,rowPaddingTopB:.01,textStroke:.001,textCorners:.05,textPadding:{top:.01,right:.01,bottom:.01,left:.01},textFontSize:.01,textLineHeight:.01,...Ko({textFontSize:.01,textLineHeight:.01})})},displayRules:[...Wd(),...Nd.map(e=>({if:{name:"cut",value:0},then:{name:`properties.${e}.display.visible`,value:!1}})),{if:{name:"type",value:"A"},then:{name:"properties.textPaddingLR.display.visible",value:!1}},...Hd.map(e=>({if:{name:"type",value:"B"},then:{name:`properties.${e}.display.visible`,value:!1}})),{if:{name:"type",value:"A"},then:{name:"properties.rowPaddingTopB.display.visible",value:!1}},...Bt.map(e=>({if:{name:"type",value:"A"},then:{name:`properties.${e}ColumnPaddingBottom.display.visible`,value:!1}})),...Bt.map(e=>({if:{name:"type",value:"B"},then:{name:`properties.${e}ColumnVerticalAlign.display.visible`,value:!1}}))],layout:["__componentName__","name","type","columns","wrapperWidth","textPaddingLR","entriesCount","cellMinHeight","imageOnHover","imageSize","dividerWidth","showVisibility","cut","showCut","cutCellMinHeight","entryHoverEffect","cutLabel","rowPaddingTop","rowPaddingBottom","rowPaddingTopB",...Bd]},panels:[{id:"general",icon:"cursor",title:"General",tooltip:"General Settings",layout:[{type:"row",items:["__componentName__","name"]},"type",{type:"row",title:"",items:["columns","wrapperWidth"]},{type:"row",title:"",items:["entriesCount","cellMinHeight"]},{type:"row",title:"",items:["imageOnHover","imageSize"]},{type:"row",title:"",items:["entryHoverEffect"]},{type:"row",title:"Divider Settings",items:["dividerWidth","showVisibility"]},{type:"row",title:"",items:["cut"]},{type:"row",title:"Cut Settings",items:["cutLabel","cutCellMinHeight"]},{type:"row",title:"",items:["showCut"]}]},{id:"columnsOrder",icon:"layers",title:"Columns Order",tooltip:"Columns order",layout:["columnsOrder"]},{id:"typeStyle",icon:"text-icon",title:"Type Style",tooltip:"Typography",layout:[{type:"group",title:"All text",items:["textFontFamily","textFontSettings",{type:"row",items:["textFontSize","textLineHeight","textLetterSpacing","textWordSpacing"]},"textTextAppearance"]},...Id]}],paletteBookmark:{items:[...Fd],panelIds:["general","typeStyle"],stateItems:{default:["textColor","backgroundColor","dividerColor","textHoverColor","backgroundHoverColor","dividerHoverColor"]}}},Dd={element:wd,id:"list",name:"Default List",category:"lists",layoutMode:"structured",preview:{type:"image",url:"https://cdn.cntrl.site/component-assets/Programme_List.png "},version:1,defaultSize:{d:{width:720,height:540}},assetsPaths:{content:[{path:"image.url",placeholderEnabled:!0}],parameters:[]},schema:Vd,sourceCode:$d},zd=[Qs,al,Gl,rc,mc,wc,_c,Fc,Kc,Dd];exports.components=zd;exports.isSchemaV1=ji;