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