diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md index 23251c3..821dfe6 100644 --- a/packages/integration/CHANGELOG.md +++ b/packages/integration/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [unreleased] + +- header and footer are displayed by default in mobile mode, but never in desktop mode. +- show only the first x (customizable) services and add view_more button + + + ## 1.0.3 - new grist, resana, docs, visio, rdv logos diff --git a/packages/widgets/src/widgets/lagaufre/chevron_downward.svg b/packages/widgets/src/widgets/lagaufre/chevron_downward.svg new file mode 100644 index 0000000..28e6c38 --- /dev/null +++ b/packages/widgets/src/widgets/lagaufre/chevron_downward.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/widgets/src/widgets/lagaufre/main.ts b/packages/widgets/src/widgets/lagaufre/main.ts index d41816d..6d36403 100644 --- a/packages/widgets/src/widgets/lagaufre/main.ts +++ b/packages/widgets/src/widgets/lagaufre/main.ts @@ -1,4 +1,5 @@ import styles from "./styles.css?inline"; +import chevronDownwardSvg from "./chevron_downward.svg?raw"; import { createShadowWidget } from "../../shared/shadow-dom"; import { installHook } from "../../shared/script"; import { listenEvent, triggerEvent } from "../../shared/events"; @@ -41,11 +42,13 @@ type GaufreWidgetArgs = { label?: string; closeLabel?: string; headerLabel?: string; + viewMoreLabel?: string; + viewLessLabel?: string; loadingText?: string; newWindowLabelSuffix?: string; - showFooter?: boolean; dialogElement?: HTMLElement; buttonElement?: HTMLElement; + showMoreLimit?: number; }; let loaded = false; @@ -65,26 +68,44 @@ listenEvent(widgetName, "init", null, false, async (args: GaufreWidgetArgs) => { const listeners: (() => void)[] = []; let isVisible = false; + const viewMoreLabel = args.viewMoreLabel || "More apps"; + const viewLessLabel = args.viewLessLabel || "Fewer apps"; + const showMoreLimit = args.showMoreLimit || 6; // https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/ /* prettier-ignore */ const htmlContent = ``; // Create shadow DOM widget @@ -94,6 +115,11 @@ listenEvent(widgetName, "init", null, false, async (args: GaufreWidgetArgs) => { const wrapper = shadowRoot.querySelector("#wrapper")!; const loadingDiv = shadowRoot.querySelector("#loading")!; const servicesGrid = shadowRoot.querySelector("#services-grid")!; + const moreAppsSection = shadowRoot.querySelector("#more-apps")!; + const moreServicesGrid = shadowRoot.querySelector("#more-services-grid")!; + const showMoreBtn = shadowRoot.querySelector("#show-more-button")!; + const showMoreChevron = shadowRoot.querySelector("#show-more-chevron")!; + const showMoreText = shadowRoot.querySelector("#show-more-text")!; const errorDiv = shadowRoot.querySelector("#error")!; const closeBtn = shadowRoot.querySelector("#close"); const okBtn = shadowRoot.querySelector("#ok-button")!; @@ -153,6 +179,10 @@ listenEvent(widgetName, "init", null, false, async (args: GaufreWidgetArgs) => { listeners.push( listenEvent("", "resize", window, false, () => { configure(args); + // Re-render services on resize to handle mobile/desktop switch + if (args.data) { + renderServices(args.data); + } }), ); @@ -169,9 +199,13 @@ listenEvent(widgetName, "init", null, false, async (args: GaufreWidgetArgs) => { const renderServices = (data: ServicesResponse) => { // Clear previous content servicesGrid.innerHTML = ""; + moreServicesGrid.innerHTML = ""; + const maxInitialServices = showMoreLimit; + const hasMoreServices = data.services.length > maxInitialServices; + - data.services.forEach((service) => { - if (!service.logo) return; + const createServiceCard = (service: Service) => { + if (!service.logo) return null; if (service.maturity == "stable") delete service.maturity; const serviceCard = document.createElement("li"); @@ -205,9 +239,51 @@ listenEvent(widgetName, "init", null, false, async (args: GaufreWidgetArgs) => { img.src = service.logo; serviceName.textContent = service.name; - servicesGrid.appendChild(serviceCard); + return serviceCard; + }; + + // Render initial services (first 6) + const initialServices = data.services.slice(0, maxInitialServices); + initialServices.forEach((service) => { + const serviceCard = createServiceCard(service); + if (serviceCard) { + servicesGrid.appendChild(serviceCard); + } }); + // Handle additional services if any + if (hasMoreServices) { + const additionalServices = data.services.slice(maxInitialServices); + + // Render additional services in the more services grid + additionalServices.forEach((service) => { + const serviceCard = createServiceCard(service); + if (serviceCard) { + moreServicesGrid.appendChild(serviceCard); + } + }); + + // Show the more apps section + moreAppsSection.style.display = "flex"; + moreServicesGrid.classList.add("hidden"); + showMoreChevron.classList.remove("opened"); + + // Update button text and handle click + const updateButton = () => { + moreServicesGrid.classList.toggle("hidden"); + showMoreChevron.classList.toggle("opened"); + const isOpened = showMoreChevron.classList.contains("opened"); + showMoreText.textContent = !isOpened ? viewLessLabel : viewMoreLabel; + }; + + showMoreBtn.addEventListener("click", () => { + updateButton(); + }); + } else { + // Hide the more apps section if no additional services + moreAppsSection.style.display = "none"; + } + loadingDiv.style.display = "none"; errorDiv.style.display = "none"; servicesGrid.style.display = "grid"; @@ -252,7 +328,7 @@ listenEvent(widgetName, "init", null, false, async (args: GaufreWidgetArgs) => { // Open widget (show the prepared shadow DOM) listeners.push( listenEvent(widgetName, "open", null, false, () => { - wrapper.style.display = "block"; + wrapper.style.display = "flex"; // Add click outside listener after a short delay to prevent immediate closing or double-clicks. setTimeout(() => { diff --git a/packages/widgets/src/widgets/lagaufre/styles.css b/packages/widgets/src/widgets/lagaufre/styles.css index 6f404ef..980df93 100644 --- a/packages/widgets/src/widgets/lagaufre/styles.css +++ b/packages/widgets/src/widgets/lagaufre/styles.css @@ -20,7 +20,7 @@ } #header { - display: flex; + display: none; /* Hidden by default on desktop */ justify-content: center; align-items: center; padding: 4px 16px; @@ -67,7 +67,7 @@ } #footer { - display: flex; + display: none; /* Hidden by default on desktop */ padding: 16px; background: transparent; border-top: 1px solid #dfe2ea; @@ -97,7 +97,6 @@ #content { flex: 1; - padding: 16px; display: flex; flex-direction: column; overflow-y: auto; @@ -112,6 +111,7 @@ padding: 40px 20px; color: #666; font-size: 14px; + margin: 16px; } /* Error state */ @@ -123,6 +123,7 @@ color: #dc3545; font-size: 14px; text-align: center; + margin: 16px; } /* Services grid */ @@ -150,6 +151,78 @@ margin: 0; } +/* Main apps section */ +#main-apps { + padding: 16px; +} + +/* More apps section */ +#more-apps { + border-top: 1px solid #dfe2ea; + padding: 16px; + background: transparent; + display: flex; + flex-direction: column-reverse; +} + +#more-services-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 4px; + justify-items: center; + list-style: none; + padding: 0; + margin: 0 0 16px 0; +} + +#show-more-container { + display: flex; + justify-content: center; + align-items: center; + width: 100%; +} + +#show-more-button { + background: none; + color: #64748b; + border: none; + border-radius: 6px; + padding: 8px 16px; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + min-width: 100px; + display: flex; + align-items: center; + justify-content: center; + gap: 8px; +} + +#show-more-button:hover { + background: #f1f5f9; + color: #475569; +} + +#show-more-button:focus { + outline: none; +} + +#show-more-button:focus-visible { + outline: 2px solid #0a76f6; + outline-offset: 2px; +} + +#show-more-chevron { + width: 16px; + height: 16px; + transition: transform 0.2s ease; +} + +#show-more-chevron.opened { + transform: rotate(180deg); +} + .service-card:hover { background-color: #eef1f4; border-radius: 6px; @@ -205,6 +278,14 @@ text-align: center; } +#more-services-grid { + display: grid; +} + +#more-services-grid.hidden { + display: none; +} + /* Responsive design */ @media (max-width: 480px) { #wrapper { @@ -218,9 +299,17 @@ position: fixed !important; } + #more-services-grid { + display: grid !important; + } + + #show-more-button { + display: none; + } + #header { height: 40px; - display: flex; + display: flex; /* Always show header on mobile */ } #header-logo { @@ -236,6 +325,11 @@ gap: 12px; } + #more-services-grid { + grid-template-columns: repeat(3, 1fr); + gap: 12px; + } + .service-card { width: 70px; padding: 6px; diff --git a/website/public/widgets/dist/lagaufre.js b/website/public/widgets/dist/lagaufre.js index c5c325d..4d7b1b5 100644 --- a/website/public/widgets/dist/lagaufre.js +++ b/website/public/widgets/dist/lagaufre.js @@ -1 +1,4 @@ -(function(){"use strict";const F="#wrapper{display:flex;flex-direction:column;font-family:inherit}.wrapper-dialog{position:fixed;top:60px;right:60px;z-index:1000;width:340px;max-height:480px;background:#fff;border-radius:.25rem;box-shadow:0 0 6px #0000911a;border:1px solid #e5e5e5;overflow:hidden}#header{display:flex;justify-content:center;align-items:center;padding:4px 16px;background:transparent;border-bottom:1px solid #dfe2ea;min-height:48px;position:relative}#header-logo{height:25px;width:auto;object-fit:contain;display:block;margin:0 auto}#close{position:absolute;right:16px}#close{background:none;border:none;color:#64748b;cursor:pointer;font-size:36px;width:36px;height:36px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:background-color .2s}#close:hover{background-color:#f0f0f0}#close:focus{outline:2px solid #0a76f6}#footer{display:flex;padding:16px;background:transparent;border-top:1px solid #dfe2ea;justify-content:flex-end}#ok-button{background:#3e5de7;color:#fff;border:none;border-radius:6px;padding:8px 16px;font-size:14px;font-weight:600;cursor:pointer;transition:background-color .2s;min-width:60px}#ok-button:hover{background:#1d4ed8}#ok-button:focus{outline:2px solid #0a76f6}#content{flex:1;padding:16px;display:flex;flex-direction:column;overflow-y:auto;min-height:0}#loading{display:flex;align-items:center;justify-content:center;padding:40px 20px;color:#666;font-size:14px}#error{display:flex;align-items:center;justify-content:center;padding:40px 20px;color:#dc3545;font-size:14px;text-align:center}#services-grid{grid-template-columns:repeat(3,1fr);gap:4px;justify-items:center;list-style:none;padding:0;margin:0}.service-card{background:transparent;text-align:center;transition:all .2s ease;position:relative;display:flex;flex-direction:column;align-items:center;width:100%;list-style:none;padding:0;margin:0}.service-card:hover{background-color:#eef1f4;border-radius:6px}.service-card a{position:relative;padding:8px;width:100%;text-decoration:none;display:block}.service-logo{width:42px;height:42px;object-fit:contain}.maturity-badge{position:absolute;top:40px;left:50%;transform:translate(-50%);background:#eef1f4;color:#2845c1;border-radius:12px;padding:2px 4px;font-size:9px;line-height:9px;font-weight:700;text-transform:uppercase;letter-spacing:.3px;white-space:nowrap}.service-info{display:flex;flex-direction:column;align-items:center;width:100%;padding-top:4px}.service-name{font-weight:600;font-size:14px;color:#1e40af;margin-bottom:2px;line-height:1.2;text-align:center}@media (max-width: 480px){#wrapper{width:100%;inset:0!important;border-radius:0;max-height:100vh;position:fixed!important}#header{height:40px;display:flex}#header-logo{height:35px}#footer{display:flex}#services-grid{grid-template-columns:repeat(3,1fr);gap:12px}.service-card{width:70px;padding:6px}.service-logo,.service-logo-placeholder{width:40px;height:40px}.service-name{font-size:11px}}#content::-webkit-scrollbar{width:4px}#content::-webkit-scrollbar-track{background:transparent}#content::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:2px}#content::-webkit-scrollbar-thumb:hover{background:#94a3b8}";function D(e,t,n){const s=`lasuite-widget-${e}-shadow`,d=document.getElementById(s);d&&d.remove();const l=document.createElement("div");l.id=s;const r=l.attachShadow({mode:"open"}),p=document.createElement("style");p.textContent=n;const u=document.createElement("div");return u.innerHTML=t,r.appendChild(p),r.appendChild(u),l}const C="lasuite-widget",c=(e,t,n,s)=>document.dispatchEvent(new CustomEvent(`${C}-${e}-${t}`,n?{detail:n}:void 0)),m=(e,t,n,s,d)=>{const l=p=>d(p.detail),r=e?`${C}-${e}-${t}`:t;return(n||document).addEventListener(r,l,s?{once:!0}:void 0),()=>(n||document).removeEventListener(r,l,s?{once:!0}:void 0)},v=2,$=e=>window._lasuite_widget?._loaded?.[e],W=(e,t)=>{window._lasuite_widget?._loaded&&(window._lasuite_widget._loaded[e]=t)},B=e=>{window._lasuite_widget||(window._lasuite_widget=[]);const t=window._lasuite_widget;if(t._loaded||(t._loaded={}),$(e)!==v){t.push=(...n)=>{for(const s of n)$(s[0])===v?c(s[0],s[1],s[2]):t[t.length]=s;return t.length},W(e,v);for(const n of t.splice(0,t.length))t.push(n)}c(e,"loaded")},H=e=>e.offsetWidth>0&&e.offsetHeight>0,K=(e,t,n)=>{const s=d=>{if(d.key!=="Tab")return;const l=Array.from(t.querySelectorAll(n)).filter(u=>H(u));if(l.length===0)return;const r=l[0],p=l[l.length-1];d.shiftKey&&e.activeElement===r?(d.preventDefault(),p.focus()):!d.shiftKey&&e.activeElement===p&&(d.preventDefault(),r.focus())};return t.addEventListener("keydown",s),()=>{t.removeEventListener("keydown",s)}},M=e=>{const t=n=>{n.key==="Escape"&&(n.preventDefault(),e())};return document.addEventListener("keydown",t),()=>{document.removeEventListener("keydown",t)}},i="lagaufre";let w=!1;m(i,"init",null,!1,async e=>{if(!e.api&&!e.data){console.error("Missing API URL");return}w&&(c(i,"destroy"),await new Promise(o=>setTimeout(o,10)));const t=[];let n=!1;const s='",d=D(i,s,F),l=d.shadowRoot,r=l.querySelector("#wrapper"),p=l.querySelector("#loading"),u=l.querySelector("#services-grid"),k=l.querySelector("#error"),x=l.querySelector("#close"),q=l.querySelector("#ok-button"),z=l.querySelector("#header-logo"),E=o=>{const a=["top","bottom","left","right"],f=h=>{a.forEach(b=>{r.style[b]=typeof h[b]=="number"?`${h[b]}px`:"unset"})};if(a.every(h=>o[h]===void 0)||f(o),o.position)if(typeof o.position=="function"){const h=o.position();r.style.position=h.position,f(h)}else r.style.position=o.position;o.fontFamily&&(r.style.fontFamily=o.fontFamily),o.background&&(r.style.background=o.background);const g=o.label||"Services",y=o.closeLabel||"Close";p.textContent=o.loadingText||"Loading…",r.setAttribute("aria-label",g),x&&x.setAttribute("aria-label",y),z&&(z.alt=(o.headerLabel||"About LaSuite")+(o.newWindowLabelSuffix||""))};E(e),t.push(m("","resize",window,!1,()=>{E(e)})),r.style.display="none";const L=o=>{p.style.display="none",u.style.display="none",k.style.display="block",k.textContent=o},T=o=>{u.innerHTML="",o.services.forEach(a=>{if(!a.logo)return;a.maturity=="stable"&&delete a.maturity;const f=document.createElement("li");f.className="service-card",f.innerHTML=`
`;const g=f.querySelector("a"),y=f.querySelector("img"),h=f.querySelector(".service-name");if(a.maturity){const b=document.createElement("div");b.className="maturity-badge",b.textContent=a.maturity,g.insertBefore(b,y.nextSibling)}g.setAttribute("aria-label",a.name+(a.maturity?` (${a.maturity})`:"")+(e.newWindowLabelSuffix||"")),g.href=a.url,y.src=a.logo,h.textContent=a.name,u.appendChild(f)}),p.style.display="none",k.style.display="none",u.style.display="grid"};if(e.data)T(e.data);else try{const a=await(await fetch(e.api,{method:"GET"})).json();a.error?L(`Error: ${JSON.stringify(a.error)}`):a.services&&a.services.length>0?T(a):L("No services found")}catch(o){L(`Failed to load services: ${o instanceof Error?o.message:"Unknown error"}`)}const j=o=>{e.dialogElement||d.contains(o.target)||c(i,"close")};let S=null,_=null;t.push(m(i,"open",null,!1,()=>{r.style.display="block",setTimeout(()=>{n=!0,document.addEventListener("click",j),r.focus()},200),S=K(l,r,"a,button"),e.dialogElement||(_=M(()=>{c(i,"close")})),e.buttonElement&&e.buttonElement.setAttribute("aria-expanded","true"),c(i,"opened")})),t.push(m(i,"close",null,!1,()=>{S&&S(),_&&_(),n&&(r.style.display="none",n=!1,e.buttonElement&&(e.buttonElement.focus(),e.buttonElement.setAttribute("aria-expanded","false")),document.removeEventListener("click",j),c(i,"closed"))})),t.push(m(i,"toggle",null,!1,()=>{n?c(i,"close"):c(i,"open")})),t.push(m(i,"configure",null,!1,E)),q&&q.addEventListener("click",()=>{c(i,"close")}),x&&x.addEventListener("click",()=>{c(i,"close")}),e.buttonElement&&t.push(m("","click",e.buttonElement,!1,()=>{c(i,"toggle")})),e.dialogElement?e.dialogElement.appendChild(d):(r.className="wrapper-dialog",document.body.appendChild(d)),m(i,"destroy",null,!0,()=>{c(i,"close"),w=!1,d.remove(),t.forEach(o=>o())}),w=!0,c(i,"initialized"),e.open&&c(i,"open")}),B(i)})(); +(function(){"use strict";const P="#wrapper{display:flex;flex-direction:column;font-family:inherit}.wrapper-dialog{position:fixed;top:60px;right:60px;z-index:1000;width:340px;max-height:480px;background:#fff;border-radius:.25rem;box-shadow:0 0 6px #0000911a;border:1px solid #e5e5e5;overflow:hidden}#header{display:none;justify-content:center;align-items:center;padding:4px 16px;background:transparent;border-bottom:1px solid #dfe2ea;min-height:48px;position:relative}#header-logo{height:25px;width:auto;object-fit:contain;display:block;margin:0 auto}#close{position:absolute;right:16px}#close{background:none;border:none;color:#64748b;cursor:pointer;font-size:36px;width:36px;height:36px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:background-color .2s}#close:hover{background-color:#f0f0f0}#close:focus{outline:2px solid #0a76f6}#footer{display:none;padding:16px;background:transparent;border-top:1px solid #dfe2ea;justify-content:flex-end}#ok-button{background:#3e5de7;color:#fff;border:none;border-radius:6px;padding:8px 16px;font-size:14px;font-weight:600;cursor:pointer;transition:background-color .2s;min-width:60px}#ok-button:hover{background:#1d4ed8}#ok-button:focus{outline:2px solid #0a76f6}#content{flex:1;display:flex;flex-direction:column;overflow-y:auto;min-height:0}#loading{display:flex;align-items:center;justify-content:center;padding:40px 20px;color:#666;font-size:14px;margin:16px}#error{display:flex;align-items:center;justify-content:center;padding:40px 20px;color:#dc3545;font-size:14px;text-align:center;margin:16px}#services-grid{grid-template-columns:repeat(3,1fr);gap:4px;justify-items:center;list-style:none;padding:0;margin:0}.service-card{background:transparent;text-align:center;transition:all .2s ease;position:relative;display:flex;flex-direction:column;align-items:center;width:100%;list-style:none;padding:0;margin:0}#main-apps{padding:16px}#more-apps{border-top:1px solid #dfe2ea;padding:16px;background:transparent;display:flex;flex-direction:column-reverse}#more-services-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:4px;justify-items:center;list-style:none;padding:0;margin:0 0 16px}#show-more-container{display:flex;justify-content:center;align-items:center;width:100%}#show-more-button{background:none;color:#64748b;border:none;border-radius:6px;padding:8px 16px;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s ease;min-width:100px;display:flex;align-items:center;justify-content:center;gap:8px}#show-more-button:hover{background:#f1f5f9;color:#475569}#show-more-button:focus{outline:none}#show-more-button:focus-visible{outline:2px solid #0a76f6;outline-offset:2px}#show-more-chevron{width:16px;height:16px;transition:transform .2s ease}#show-more-chevron.opened{transform:rotate(180deg)}.service-card:hover{background-color:#eef1f4;border-radius:6px}.service-card a{position:relative;padding:8px;width:100%;text-decoration:none;display:block}.service-logo{width:42px;height:42px;object-fit:contain}.maturity-badge{position:absolute;top:40px;left:50%;transform:translate(-50%);background:#eef1f4;color:#2845c1;border-radius:12px;padding:2px 4px;font-size:9px;line-height:9px;font-weight:700;text-transform:uppercase;letter-spacing:.3px;white-space:nowrap}.service-info{display:flex;flex-direction:column;align-items:center;width:100%;padding-top:4px}.service-name{font-weight:600;font-size:14px;color:#1e40af;margin-bottom:2px;line-height:1.2;text-align:center}#more-services-grid{display:grid}#more-services-grid.hidden{display:none}@media (max-width: 480px){#wrapper{width:100%;inset:0!important;border-radius:0;max-height:100vh;position:fixed!important}#more-services-grid{display:grid!important}#show-more-button{display:none}#header{height:40px;display:flex}#header-logo{height:35px}#footer{display:flex}#services-grid,#more-services-grid{grid-template-columns:repeat(3,1fr);gap:12px}.service-card{width:70px;padding:6px}.service-logo,.service-logo-placeholder{width:40px;height:40px}.service-name{font-size:11px}}#content::-webkit-scrollbar{width:4px}#content::-webkit-scrollbar-track{background:transparent}#content::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:2px}#content::-webkit-scrollbar-thumb:hover{background:#94a3b8}",U=` + + +`;function G(e,t,r){const s=`lasuite-widget-${e}-shadow`,u=document.getElementById(s);u&&u.remove();const c=document.createElement("div");c.id=s;const m=c.attachShadow({mode:"open"}),p=document.createElement("style");p.textContent=r;const l=document.createElement("div");return l.innerHTML=t,m.appendChild(p),m.appendChild(l),c}const D="lasuite-widget",a=(e,t,r,s)=>document.dispatchEvent(new CustomEvent(`${D}-${e}-${t}`,r?{detail:r}:void 0)),g=(e,t,r,s,u)=>{const c=p=>u(p.detail),m=e?`${D}-${e}-${t}`:t;return(r||document).addEventListener(m,c,s?{once:!0}:void 0),()=>(r||document).removeEventListener(m,c,s?{once:!0}:void 0)},E=2,F=e=>window._lasuite_widget?._loaded?.[e],I=(e,t)=>{window._lasuite_widget?._loaded&&(window._lasuite_widget._loaded[e]=t)},R=e=>{window._lasuite_widget||(window._lasuite_widget=[]);const t=window._lasuite_widget;if(t._loaded||(t._loaded={}),F(e)!==E){t.push=(...r)=>{for(const s of r)F(s[0])===E?a(s[0],s[1],s[2]):t[t.length]=s;return t.length},I(e,E);for(const r of t.splice(0,t.length))t.push(r)}a(e,"loaded")},V=e=>e.offsetWidth>0&&e.offsetHeight>0,A=(e,t,r)=>{const s=u=>{if(u.key!=="Tab")return;const c=Array.from(t.querySelectorAll(r)).filter(l=>V(l));if(c.length===0)return;const m=c[0],p=c[c.length-1];u.shiftKey&&e.activeElement===m?(u.preventDefault(),p.focus()):!u.shiftKey&&e.activeElement===p&&(u.preventDefault(),m.focus())};return t.addEventListener("keydown",s),()=>{t.removeEventListener("keydown",s)}},J=e=>{const t=r=>{r.key==="Escape"&&(r.preventDefault(),e())};return document.addEventListener("keydown",t),()=>{document.removeEventListener("keydown",t)}},n="lagaufre";let S=!1;g(n,"init",null,!1,async e=>{if(!e.api&&!e.data){console.error("Missing API URL");return}S&&(a(n,"destroy"),await new Promise(o=>setTimeout(o,10)));const t=[];let r=!1;const s=e.viewMoreLabel||"More apps",u=e.viewLessLabel||"Fewer apps",c=e.showMoreLimit||6,m='`,p=G(n,m,P),l=p.shadowRoot,f=l.querySelector("#wrapper"),C=l.querySelector("#loading"),y=l.querySelector("#services-grid"),H=l.querySelector("#more-apps"),b=l.querySelector("#more-services-grid"),Z=l.querySelector("#show-more-button"),_=l.querySelector("#show-more-chevron"),Q=l.querySelector("#show-more-text"),q=l.querySelector("#error"),w=l.querySelector("#close"),W=l.querySelector("#ok-button"),K=l.querySelector("#header-logo"),M=o=>{const h=["top","bottom","left","right"],k=i=>{h.forEach(d=>{f.style[d]=typeof i[d]=="number"?`${i[d]}px`:"unset"})};if(h.every(i=>o[i]===void 0)||k(o),o.position)if(typeof o.position=="function"){const i=o.position();f.style.position=i.position,k(i)}else f.style.position=o.position;o.fontFamily&&(f.style.fontFamily=o.fontFamily),o.background&&(f.style.background=o.background);const L=o.label||"Services",O=o.closeLabel||"Close";C.textContent=o.loadingText||"Loading…",f.setAttribute("aria-label",L),w&&w.setAttribute("aria-label",O),K&&(K.alt=(o.headerLabel||"About LaSuite")+(o.newWindowLabelSuffix||""))};M(e),t.push(g("","resize",window,!1,()=>{M(e),e.data&&T(e.data)})),f.style.display="none";const $=o=>{C.style.display="none",y.style.display="none",q.style.display="block",q.textContent=o},T=o=>{y.innerHTML="",b.innerHTML="";const h=c,k=o.services.length>h,L=i=>{if(!i.logo)return null;i.maturity=="stable"&&delete i.maturity;const d=document.createElement("li");d.className="service-card",d.innerHTML=`
`;const x=d.querySelector("a"),v=d.querySelector("img"),X=d.querySelector(".service-name");if(i.maturity){const B=document.createElement("div");B.className="maturity-badge",B.textContent=i.maturity,x.insertBefore(B,v.nextSibling)}return x.setAttribute("aria-label",i.name+(i.maturity?` (${i.maturity})`:"")+(e.newWindowLabelSuffix||"")),x.href=i.url,v.src=i.logo,X.textContent=i.name,d};if(o.services.slice(0,h).forEach(i=>{const d=L(i);d&&y.appendChild(d)}),k){o.services.slice(h).forEach(x=>{const v=L(x);v&&b.appendChild(v)}),H.style.display="flex",b.classList.add("hidden"),_.classList.remove("opened");const d=()=>{b.classList.toggle("hidden"),_.classList.toggle("opened");const x=_.classList.contains("opened");Q.textContent=x?s:u};Z.addEventListener("click",()=>{d()})}else H.style.display="none";C.style.display="none",q.style.display="none",y.style.display="grid"};if(e.data)T(e.data);else try{const h=await(await fetch(e.api,{method:"GET"})).json();h.error?$(`Error: ${JSON.stringify(h.error)}`):h.services&&h.services.length>0?T(h):$("No services found")}catch(o){$(`Failed to load services: ${o instanceof Error?o.message:"Unknown error"}`)}const N=o=>{e.dialogElement||p.contains(o.target)||a(n,"close")};let j=null,z=null;t.push(g(n,"open",null,!1,()=>{f.style.display="flex",setTimeout(()=>{r=!0,document.addEventListener("click",N),f.focus()},200),j=A(l,f,"a,button"),e.dialogElement||(z=J(()=>{a(n,"close")})),e.buttonElement&&e.buttonElement.setAttribute("aria-expanded","true"),a(n,"opened")})),t.push(g(n,"close",null,!1,()=>{j&&j(),z&&z(),r&&(f.style.display="none",r=!1,e.buttonElement&&(e.buttonElement.focus(),e.buttonElement.setAttribute("aria-expanded","false")),document.removeEventListener("click",N),a(n,"closed"))})),t.push(g(n,"toggle",null,!1,()=>{r?a(n,"close"):a(n,"open")})),t.push(g(n,"configure",null,!1,M)),W&&W.addEventListener("click",()=>{a(n,"close")}),w&&w.addEventListener("click",()=>{a(n,"close")}),e.buttonElement&&t.push(g("","click",e.buttonElement,!1,()=>{a(n,"toggle")})),e.dialogElement?e.dialogElement.appendChild(p):(f.className="wrapper-dialog",document.body.appendChild(p)),g(n,"destroy",null,!0,()=>{a(n,"close"),S=!1,p.remove(),t.forEach(o=>o())}),S=!0,a(n,"initialized"),e.open&&a(n,"open")}),R(n)})();