social components inlay-proto.up.railway.app/
atproto components sdui

fix default layout

+44 -10
+40 -4
proto/src/index.tsx
··· 14 type JSXElement, 15 } from "./render.tsx"; 16 import { deserializeTree, $ } from "@inlay/core"; 17 - import { setComponentUri } from "./primitives.tsx"; 18 import { resolveDidToService } from "./resolve.ts"; 19 import "./types.ts"; 20 ··· 49 <script src="https://unpkg.com/htmx.org@2.0.4"></script> 50 <script src="https://unpkg.com/htmx-ext-preload@2.1.0/preload.js"></script> 51 {raw(`<style> 52 - body { margin: 0; font-family: system-ui, sans-serif; background: var(--surface); color: var(--text); } 53 .error { color: red; padding: 8px; font-size: 12px; } 54 .list-sentinel { padding: 20px; text-align: center; color: var(--text-secondary); } 55 .tabs-bar { display: flex; gap: 0; border-bottom: 1px solid var(--border); } 56 .tabs-bar button { padding: 12px 20px; border: none; background: none; color: var(--text-secondary); cursor: pointer; border-bottom: 2px solid transparent; font-size: 14px; font-weight: 500; } 57 .tabs-bar button[aria-selected="true"] { color: var(--text); border-bottom-color: var(--accent); } 58 hr { border: none; border-top: 1px solid var(--border); margin: 0; display: var(--separator, block); } 59 </style>`)} 60 {raw(`<script> 61 function switchTab(btn, index) { ··· 107 app.get("/at/:did/:collection/:rkey", async (c) => { 108 const { did, collection, rkey } = c.req.param(); 109 const componentUri = c.req.query("componentUri"); 110 111 if (!componentUri) { 112 return c.html( ··· 135 const uri = `at://${did}/${collection}/${rkey}`; 136 const element = $(componentRecord.type, { uri }); 137 const context = createContext(componentRecord as any, componentUri); 138 - setComponentUri(componentUri); 139 140 const body = await renderNode(element, context, renderOptions); 141 142 const stream = renderToReadableStream( 143 <Shell> 144 <ErrorBoundary 145 fallbackRender={(e) => <div class="error">{e.message}</div>} 146 > 147 - {body} 148 </ErrorBoundary> 149 </Shell> 150 );
··· 14 type JSXElement, 15 } from "./render.tsx"; 16 import { deserializeTree, $ } from "@inlay/core"; 17 + import { setQueryString } from "./primitives.tsx"; 18 import { resolveDidToService } from "./resolve.ts"; 19 import "./types.ts"; 20 ··· 49 <script src="https://unpkg.com/htmx.org@2.0.4"></script> 50 <script src="https://unpkg.com/htmx-ext-preload@2.1.0/preload.js"></script> 51 {raw(`<style> 52 + body { margin: 0; font-family: system-ui, sans-serif; background: #f5f5f5; color: var(--text); } 53 .error { color: red; padding: 8px; font-size: 12px; } 54 .list-sentinel { padding: 20px; text-align: center; color: var(--text-secondary); } 55 .tabs-bar { display: flex; gap: 0; border-bottom: 1px solid var(--border); } 56 .tabs-bar button { padding: 12px 20px; border: none; background: none; color: var(--text-secondary); cursor: pointer; border-bottom: 2px solid transparent; font-size: 14px; font-weight: 500; } 57 .tabs-bar button[aria-selected="true"] { color: var(--text); border-bottom-color: var(--accent); } 58 hr { border: none; border-top: 1px solid var(--border); margin: 0; display: var(--separator, block); } 59 + .layout-full, .layout-page { 60 + display: flex; 61 + flex-direction: column; 62 + min-height: 100vh; 63 + } 64 + .layout-full > .layout-content, 65 + .layout-page > .layout-content { 66 + flex: 1; 67 + display: flex; 68 + flex-direction: column; 69 + align-items: center; 70 + overflow-y: auto; 71 + box-sizing: border-box; 72 + } 73 + .layout-full > .layout-content { 74 + align-items: stretch; 75 + } 76 </style>`)} 77 {raw(`<script> 78 function switchTab(btn, index) { ··· 124 app.get("/at/:did/:collection/:rkey", async (c) => { 125 const { did, collection, rkey } = c.req.param(); 126 const componentUri = c.req.query("componentUri"); 127 + const layout = c.req.query("layout") as "page" | "full" | undefined; 128 129 if (!componentUri) { 130 return c.html( ··· 153 const uri = `at://${did}/${collection}/${rkey}`; 154 const element = $(componentRecord.type, { uri }); 155 const context = createContext(componentRecord as any, componentUri); 156 + setQueryString(new URL(c.req.url).search.slice(1)); 157 158 const body = await renderNode(element, context, renderOptions); 159 160 + const isFull = layout === "full"; 161 + const isPage = layout === "page"; 162 + 163 + const wrapped = 164 + isFull || isPage ? ( 165 + <div class={isFull ? "layout-full" : "layout-page"}> 166 + <div class="layout-content"> 167 + {isFull ? ( 168 + <at-inlay-root data-full>{body}</at-inlay-root> 169 + ) : ( 170 + <at-inlay-root data-page>{body}</at-inlay-root> 171 + )} 172 + </div> 173 + </div> 174 + ) : ( 175 + <at-inlay-root>{body}</at-inlay-root> 176 + ); 177 + 178 const stream = renderToReadableStream( 179 <Shell> 180 <ErrorBoundary 181 fallbackRender={(e) => <div class="error">{e.message}</div>} 182 > 183 + {wrapped} 184 </ErrorBoundary> 185 </Shell> 186 );
+4 -6
proto/src/primitives.tsx
··· 12 13 // renderNode is injected to avoid circular deps 14 let _renderNode: (node: unknown, ctx: RenderContext) => Promise<JSXElement>; 15 - let _componentUri: string | undefined; 16 17 export function setRenderNode( 18 fn: (node: unknown, ctx: RenderContext) => Promise<JSXElement> ··· 20 _renderNode = fn; 21 } 22 23 - export function setComponentUri(uri: string) { 24 - _componentUri = uri; 25 } 26 27 function rn(node: unknown, ctx: RenderContext): Promise<JSXElement> { ··· 276 if (!p.uri) return <></>; 277 278 const content = p.children != null ? await rn(p.children, ctx) : p.uri; 279 - const qs = _componentUri 280 - ? `?componentUri=${encodeURIComponent(_componentUri)}` 281 - : ""; 282 283 if (p.uri.startsWith("did:")) { 284 return (
··· 12 13 // renderNode is injected to avoid circular deps 14 let _renderNode: (node: unknown, ctx: RenderContext) => Promise<JSXElement>; 15 + let _qs: string = ""; 16 17 export function setRenderNode( 18 fn: (node: unknown, ctx: RenderContext) => Promise<JSXElement> ··· 20 _renderNode = fn; 21 } 22 23 + export function setQueryString(qs: string) { 24 + _qs = qs; 25 } 26 27 function rn(node: unknown, ctx: RenderContext): Promise<JSXElement> { ··· 276 if (!p.uri) return <></>; 277 278 const content = p.children != null ? await rn(p.children, ctx) : p.uri; 279 + const qs = _qs ? `?${_qs}` : ""; 280 281 if (p.uri.startsWith("did:")) { 282 return (