@orbytes/astrolab 0.4.0-next.1 → 0.4.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +184 -84
- package/bin/pin-gallery.mjs +53 -19
- package/defaults.mjs +7 -20
- package/docs/PIN-CONTRACT.md +76 -10
- package/docs/PIN.md +93 -23
- package/index.d.ts +1 -7
- package/index.mjs +14 -81
- package/package.json +2 -2
- package/src/Home.astro +7 -8
- package/src/LabHead.astro +1 -1
- package/src/chrome/ActionsMenu.astro +97 -0
- package/src/chrome/ComponentCard.astro +9 -2
- package/src/chrome/Nav.astro +36 -10
- package/src/chrome/Panel.astro +17 -4
- package/src/chrome/Properties.astro +104 -0
- package/src/chrome/SectionsTree.astro +128 -0
- package/src/chrome/Shell.astro +20 -6
- package/src/chrome/StoryView.astro +103 -162
- package/src/chrome/Tree.astro +56 -53
- package/src/chrome/ViewportControls.astro +136 -61
- package/src/chrome/ViewportStage.astro +26 -3
- package/src/chrome/icons.ts +9 -0
- package/src/chrome/marks-client.ts +26 -53
- package/src/chrome/model.ts +14 -0
- package/src/chrome/navbar-client.ts +324 -0
- package/src/chrome/params-client.ts +434 -0
- package/src/chrome/pins-data.ts +42 -9
- package/src/chrome/shell-client.ts +99 -3
- package/src/chrome/trees.ts +112 -7
- package/src/chrome/viewport-client.ts +68 -242
- package/src/chrome/views/Assets.astro +21 -6
- package/src/chrome/views/Pages.astro +90 -54
- package/src/chrome/views/Placeholder.astro +3 -3
- package/src/chrome/views/Tasks.astro +12 -40
- package/src/core/LICENSE-astrobook +5 -0
- package/src/core/utils/kebab-case.ts +2 -2
- package/src/pin/board.mjs +25 -15
- package/src/pin/index.mjs +34 -20
- package/src/pin/tickets.mjs +6 -5
- package/src/pin/toolbar.js +81 -3
- package/src/shell/Browse.astro +35 -10
- package/src/shell/lab-index.ts +5 -4
- package/src/shell/lab-params.ts +113 -6
- package/src/shell/live-files.mjs +212 -10
- package/src/shell/marks.mjs +17 -41
- package/src/ui/components/preview-layout.astro +17 -0
- package/src/ui/components/theme-script.astro +4 -3
- package/src/ui/lab.css +2167 -566
- package/virtual.d.ts +0 -4
- package/bin/lab-cull.mjs +0 -401
|
@@ -1,24 +1,33 @@
|
|
|
1
1
|
---
|
|
2
2
|
// A component's page — <subpath>/dashboard/<storyId>, the route Astrobook's core generates for every
|
|
3
|
-
// story (../core/lib/pages/story.astro renders this).
|
|
3
|
+
// story (../core/lib/pages/story.astro renders this).
|
|
4
4
|
//
|
|
5
|
-
// · the story is an <iframe> of its bare route on a canvas you size (./ViewportStage.astro),
|
|
6
|
-
//
|
|
7
|
-
// · the tree stops at the component
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
5
|
+
// · the story is an <iframe> of its bare route on a canvas you size (./ViewportStage.astro), never
|
|
6
|
+
// rendered inline beside the chrome — so this page carries none of the site's CSS;
|
|
7
|
+
// · the tree stops at the component; the component's variants are ALWAYS a dropdown ("Default
|
|
8
|
+
// 1 of 3"), at any count, and previous / next (and j / k) step through every variant of the
|
|
9
|
+
// tier in tree order (decided 2026-09-24: no tabs in the navbar);
|
|
10
|
+
// · the identity is the name, the version and an eye: no pills. The eye opens the Properties
|
|
11
|
+
// panel — live and slot, open pins, the responsive marks, the source file (./Properties.astro);
|
|
12
|
+
// · everything that leaves the lab, and the pin and preview switches, are in ⋯ (./ActionsMenu.astro).
|
|
11
13
|
//
|
|
12
|
-
//
|
|
14
|
+
// THE NAVBAR (Figma `Astrolab` › Lab / Components › Navbar, View=Story) is one grid laid out by a
|
|
15
|
+
// container query on its own width, because the sidebars change the main area and never the
|
|
16
|
+
// viewport: ONE row when the navbar is 1040px wide or more — identity · variants · previous / next
|
|
17
|
+
// · device switch + Viewport field · Comment · Parameters · ⋯ — otherwise TWO rows, the viewport
|
|
18
|
+
// row last, and under 552px three or four, the identity on a row of its own with ⋯. The rules are
|
|
19
|
+
// lab.css › "The navbar" and "The narrow navbar".
|
|
13
20
|
import Shell from "./Shell.astro";
|
|
14
21
|
import Tree from "./Tree.astro";
|
|
15
22
|
import Icon from "./Icon.astro";
|
|
23
|
+
import Properties from "./Properties.astro";
|
|
24
|
+
import ActionsMenu from "./ActionsMenu.astro";
|
|
16
25
|
import ViewportControls from "./ViewportControls.astro";
|
|
17
26
|
import ViewportStage from "./ViewportStage.astro";
|
|
18
|
-
import { hrefs,
|
|
27
|
+
import { hrefs, tasksBase, type Crumb, type TreeNode } from "./model";
|
|
19
28
|
import { componentsOf, tierTree } from "./trees";
|
|
20
29
|
import { pinCounts } from "./pins-data";
|
|
21
|
-
import { buildLabIndex, isSectionLike,
|
|
30
|
+
import { buildLabIndex, isSectionLike, tierLabel } from "../shell/lab-index";
|
|
22
31
|
|
|
23
32
|
interface Props {
|
|
24
33
|
story: string;
|
|
@@ -38,21 +47,23 @@ const prev = at > 0 ? sequence[at - 1] : null;
|
|
|
38
47
|
const next = at >= 0 && at < sequence.length - 1 ? sequence[at + 1] : null;
|
|
39
48
|
|
|
40
49
|
const pins = await pinCounts();
|
|
41
|
-
const
|
|
50
|
+
const tally = pins.forFile(mod.componentFile);
|
|
42
51
|
const liveStory = mod.stories.find((s) => s.live);
|
|
43
52
|
const section = isSectionLike(item);
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
53
|
+
const variantAt = mod.stories.indexOf(item) + 1;
|
|
54
|
+
|
|
55
|
+
// The Properties panel's "On the site" lines: every page the component is mounted on, or what
|
|
56
|
+
// uses it, or the honest grey "Not on any page".
|
|
57
|
+
const site = liveStory
|
|
58
|
+
? liveStory.liveOn.map((m) => ({ text: `Live on ${m.page} — slot ${m.slot} of ${m.of}`, live: true }))
|
|
48
59
|
: mod.usedBy.length
|
|
49
|
-
? `
|
|
50
|
-
:
|
|
60
|
+
? [{ text: `Used by ${mod.usedBy.length}`, live: true }]
|
|
61
|
+
: [{ text: "Not on any page", live: false }];
|
|
51
62
|
|
|
52
63
|
// Level 2's breadcrumb names the PANEL's place — Site › Sections — as the design does; where the
|
|
53
64
|
// component sits inside the tier is the tree's job, and which component it is, the navbar's.
|
|
54
65
|
const crumbs: Crumb[] = [{ label: "Site" }, { label: tierLabel(item.tier), href: hrefs.tier(item.tier) }];
|
|
55
|
-
const
|
|
66
|
+
const plural = (n: number, word: string) => `${n} ${word}${n === 1 ? "" : "s"}`;
|
|
56
67
|
---
|
|
57
68
|
|
|
58
69
|
<Shell
|
|
@@ -72,180 +83,110 @@ const TAB_LIMIT = 4;
|
|
|
72
83
|
>
|
|
73
84
|
<Tree slot="panel" nodes={tree} />
|
|
74
85
|
|
|
75
|
-
<
|
|
76
|
-
<div class="lab-
|
|
77
|
-
<
|
|
78
|
-
{mod.moduleName}
|
|
79
|
-
{mod.version && <
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
{mod.responsive.done ? "responsive" : "not responsive"}
|
|
88
|
-
</span>
|
|
89
|
-
)}
|
|
90
|
-
<span class="lab-pill lab-pill--marked" data-lab-cull-pill hidden>marked for deletion</span>
|
|
91
|
-
{openPins > 0 && <span class="lab-pill lab-pill--brand">{openPins} open pin{openPins === 1 ? "" : "s"}</span>}
|
|
92
|
-
<Icon name="chevron-down" size="sm" />
|
|
93
|
-
</button>
|
|
86
|
+
<div class="lab-nb" slot="navbar" data-lab-nb>
|
|
87
|
+
<div class="lab-nb__id">
|
|
88
|
+
<div class="lab-nb__line">
|
|
89
|
+
<h1 class="lab-nb__name" title={mod.moduleName}>{mod.moduleName}</h1>
|
|
90
|
+
{mod.version && <span class="lab-nb__tag">{mod.version}</span>}
|
|
91
|
+
<Properties
|
|
92
|
+
site={site}
|
|
93
|
+
pins={tasksBase ? { ...tally, href: `${tasksBase}/all` } : null}
|
|
94
|
+
responsive={mod.responsive ? { file: mod.moduleFile, ...mod.responsive } : null}
|
|
95
|
+
source={mod.componentFile}
|
|
96
|
+
/>
|
|
97
|
+
</div>
|
|
94
98
|
</div>
|
|
95
99
|
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
100
|
+
<div class="lab-nb__variants">
|
|
101
|
+
<button
|
|
102
|
+
class="lab-variant-btn"
|
|
103
|
+
type="button"
|
|
104
|
+
popovertarget="lab-variant-menu"
|
|
105
|
+
title={`${plural(mod.stories.length, "variant")} · j / k step`}
|
|
106
|
+
>
|
|
107
|
+
<span class="lab-variant-btn__name">{item.storyName}</span>
|
|
108
|
+
<span class="lab-variant-btn__count">{variantAt} of {mod.stories.length}</span>
|
|
109
|
+
<Icon name="chevron-down" size="sm" />
|
|
110
|
+
</button>
|
|
111
|
+
<div class="lab-menu lab-menu--variants" id="lab-variant-menu" popover role="menu" data-lab-align="end">
|
|
112
|
+
<p class="lab-menu__label">{plural(mod.stories.length, "variant")}</p>
|
|
113
|
+
{
|
|
99
114
|
mod.stories.map((s) => (
|
|
100
115
|
<a
|
|
101
|
-
class="lab-
|
|
116
|
+
class="lab-menu__item"
|
|
117
|
+
role="menuitemradio"
|
|
118
|
+
aria-checked={String(s.storyId === item.storyId)}
|
|
102
119
|
href={s.dashboardUrl}
|
|
103
|
-
aria-current={s.storyId === item.storyId ? "page" : undefined}
|
|
104
120
|
data-lab-keep-viewport
|
|
105
121
|
>
|
|
106
|
-
|
|
122
|
+
<span class="lab-menu__mark"><Icon name="check" size="sm" class="lab-menu__tick" /></span>
|
|
123
|
+
<span class="lab-menu__text">{s.storyName}</span>
|
|
107
124
|
</a>
|
|
108
125
|
))
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
<span class="lab-tabs__count">{mod.stories.indexOf(item) + 1} / {mod.stories.length}</span>
|
|
114
|
-
<Icon name="chevron-down" />
|
|
115
|
-
</button>
|
|
116
|
-
<div class="lab-menu" id="lab-story-menu" popover role="menu">
|
|
117
|
-
<p class="lab-menu__label">{mod.stories.length} stories</p>
|
|
118
|
-
{mod.stories.map((s) => (
|
|
119
|
-
<a
|
|
120
|
-
class="lab-menu__item"
|
|
121
|
-
role="menuitemradio"
|
|
122
|
-
aria-checked={String(s.storyId === item.storyId)}
|
|
123
|
-
href={s.dashboardUrl}
|
|
124
|
-
data-lab-keep-viewport
|
|
125
|
-
>
|
|
126
|
-
{s.storyName}
|
|
127
|
-
<Icon name="check" size="sm" class="lab-menu__tick" />
|
|
128
|
-
</a>
|
|
129
|
-
))}
|
|
130
|
-
</div>
|
|
131
|
-
</>
|
|
132
|
-
)
|
|
133
|
-
}
|
|
134
|
-
</nav>
|
|
126
|
+
}
|
|
127
|
+
<hr />
|
|
128
|
+
<p class="lab-menu__note">j / k — next and previous</p>
|
|
129
|
+
</div>
|
|
135
130
|
|
|
136
|
-
|
|
137
|
-
<div class="lab-seg" role="group" aria-label="Previous and next story">
|
|
131
|
+
<div class="lab-nb__step" role="group" aria-label="Previous and next variant">
|
|
138
132
|
{
|
|
139
133
|
prev ? (
|
|
140
|
-
<a
|
|
141
|
-
|
|
142
|
-
|
|
134
|
+
<a
|
|
135
|
+
class="lab-tool lab-tool--icon"
|
|
136
|
+
href={prev.dashboardUrl}
|
|
137
|
+
title={`Previous variant · k — ${prev.moduleName} — ${prev.storyName}`}
|
|
138
|
+
data-lab-step="prev"
|
|
139
|
+
data-lab-keep-viewport
|
|
140
|
+
>
|
|
141
|
+
<Icon name="chevron-left" size="sm" />
|
|
142
|
+
<span class="lab-visually-hidden">Previous variant</span>
|
|
143
143
|
</a>
|
|
144
144
|
) : (
|
|
145
|
-
<
|
|
145
|
+
<button class="lab-tool lab-tool--icon" type="button" disabled data-lab-step>
|
|
146
|
+
<Icon name="chevron-left" size="sm" />
|
|
147
|
+
<span class="lab-visually-hidden">Previous variant</span>
|
|
148
|
+
</button>
|
|
146
149
|
)
|
|
147
150
|
}
|
|
148
151
|
{
|
|
149
152
|
next ? (
|
|
150
|
-
<a
|
|
151
|
-
|
|
152
|
-
|
|
153
|
+
<a
|
|
154
|
+
class="lab-tool lab-tool--icon"
|
|
155
|
+
href={next.dashboardUrl}
|
|
156
|
+
title={`Next variant · j — ${next.moduleName} — ${next.storyName}`}
|
|
157
|
+
data-lab-step="next"
|
|
158
|
+
data-lab-keep-viewport
|
|
159
|
+
>
|
|
160
|
+
<Icon name="chevron-right" size="sm" />
|
|
161
|
+
<span class="lab-visually-hidden">Next variant</span>
|
|
153
162
|
</a>
|
|
154
163
|
) : (
|
|
155
|
-
<
|
|
164
|
+
<button class="lab-tool lab-tool--icon" type="button" disabled data-lab-step>
|
|
165
|
+
<Icon name="chevron-right" size="sm" />
|
|
166
|
+
<span class="lab-visually-hidden">Next variant</span>
|
|
167
|
+
</button>
|
|
156
168
|
)
|
|
157
169
|
}
|
|
158
170
|
</div>
|
|
159
171
|
</div>
|
|
160
172
|
|
|
161
|
-
<ViewportControls
|
|
173
|
+
<ViewportControls
|
|
174
|
+
defaultW={section ? 1440 : 960}
|
|
175
|
+
defaultH={section ? 900 : 540}
|
|
176
|
+
kind={section ? "section" : "component"}
|
|
177
|
+
comment={Boolean(tasksBase)}
|
|
178
|
+
parameters
|
|
179
|
+
/>
|
|
162
180
|
|
|
163
|
-
<div class="lab-
|
|
164
|
-
<
|
|
165
|
-
<Icon name="more" />
|
|
166
|
-
<span class="lab-visually-hidden">More actions</span>
|
|
167
|
-
</button>
|
|
168
|
-
</div>
|
|
169
|
-
|
|
170
|
-
<div class="lab-menu" id="lab-actions-menu" popover role="menu" data-lab-align="end">
|
|
171
|
-
{
|
|
172
|
-
item.editorUrl && (
|
|
173
|
-
<a class="lab-menu__item" role="menuitem" href={item.editorUrl}>
|
|
174
|
-
<Icon name="code" />
|
|
175
|
-
Open in VS Code
|
|
176
|
-
</a>
|
|
177
|
-
)
|
|
178
|
-
}
|
|
179
|
-
<a class="lab-menu__item" role="menuitem" href={item.storyUrl} target="_blank" rel="noopener">
|
|
180
|
-
<Icon name="expand" />
|
|
181
|
-
Open full screen
|
|
182
|
-
</a>
|
|
183
|
-
{
|
|
184
|
-
item.stagingUrl && (
|
|
185
|
-
<a class="lab-menu__item" role="menuitem" href={item.stagingUrl} target="_blank" rel="noopener">
|
|
186
|
-
<Icon name="external" />
|
|
187
|
-
View on staging
|
|
188
|
-
</a>
|
|
189
|
-
)
|
|
190
|
-
}
|
|
191
|
-
<button class="lab-menu__item" type="button" role="menuitem" data-lab-copy-link>
|
|
192
|
-
<Icon name="link" />
|
|
193
|
-
<span data-lab-copy-label>Copy link to this size</span>
|
|
194
|
-
</button>
|
|
195
|
-
</div>
|
|
196
|
-
|
|
197
|
-
<div class="lab-menu lab-status-menu" id="lab-status-menu" popover role="menu">
|
|
198
|
-
<p class="lab-menu__label">On the site</p>
|
|
199
|
-
<p class="lab-status-menu__fact">
|
|
200
|
-
{
|
|
201
|
-
liveStory
|
|
202
|
-
? liveStory.liveOn.map((m) => `${m.page} · slot ${m.slot} of ${m.of}`).join(", ")
|
|
203
|
-
: mod.usedBy.length
|
|
204
|
-
? `Used by ${mod.usedBy.map((f) => f.split("/").pop()).join(", ")}`
|
|
205
|
-
: "Not mounted by any page, and nothing live uses it."
|
|
206
|
-
}
|
|
207
|
-
</p>
|
|
208
|
-
{
|
|
209
|
-
mod.componentFile && (
|
|
210
|
-
<p class="lab-status-menu__fact lab-mono">{mod.componentFile}</p>
|
|
211
|
-
)
|
|
212
|
-
}
|
|
213
|
-
{
|
|
214
|
-
mod.responsive && (
|
|
215
|
-
<>
|
|
216
|
-
<hr />
|
|
217
|
-
<p class="lab-menu__label">Responsive</p>
|
|
218
|
-
<label class="lab-menu__item lab-menu__check">
|
|
219
|
-
<input type="checkbox" data-lab-mark="approved" data-file={mod.moduleFile} checked={mod.responsive.approved} disabled />
|
|
220
|
-
Approved for responsive work
|
|
221
|
-
</label>
|
|
222
|
-
<label class="lab-menu__item lab-menu__check">
|
|
223
|
-
<input type="checkbox" data-lab-mark="done" data-file={mod.moduleFile} checked={mod.responsive.done} disabled />
|
|
224
|
-
Made responsive
|
|
225
|
-
</label>
|
|
226
|
-
</>
|
|
227
|
-
)
|
|
228
|
-
}
|
|
229
|
-
{
|
|
230
|
-
cullable && (
|
|
231
|
-
<>
|
|
232
|
-
<hr />
|
|
233
|
-
<p class="lab-menu__label">Clean-up</p>
|
|
234
|
-
<label class="lab-menu__item lab-menu__check" title={blocked ?? undefined}>
|
|
235
|
-
<input type="checkbox" data-lab-mark="cull" data-file={mod.moduleFile} data-blocked={blocked ?? undefined} disabled />
|
|
236
|
-
Mark for deletion
|
|
237
|
-
</label>
|
|
238
|
-
{blocked && <p class="lab-status-menu__fact">{blocked}</p>}
|
|
239
|
-
</>
|
|
240
|
-
)
|
|
241
|
-
}
|
|
242
|
-
<p class="lab-status-menu__note" data-lab-marks-note>Marks can be changed on the dev server only.</p>
|
|
181
|
+
<div class="lab-nb__actions">
|
|
182
|
+
<ActionsMenu editorUrl={item.editorUrl} fullScreenUrl={item.storyUrl} stagingUrl={item.stagingUrl} pins={Boolean(tasksBase)} />
|
|
243
183
|
</div>
|
|
244
|
-
</
|
|
184
|
+
</div>
|
|
245
185
|
|
|
246
|
-
<ViewportStage src={item.storyUrl} title={`${mod.moduleName} — ${item.storyName}`} />
|
|
186
|
+
<ViewportStage src={item.storyUrl} title={`${mod.moduleName} — ${item.storyName}`} pins={Boolean(tasksBase)} tasksHref={tasksBase ? `${tasksBase}/all` : null} parameters />
|
|
247
187
|
</Shell>
|
|
248
188
|
|
|
249
189
|
<script>
|
|
250
190
|
import "./marks-client";
|
|
191
|
+
import "./navbar-client";
|
|
251
192
|
</script>
|
package/src/chrome/Tree.astro
CHANGED
|
@@ -3,7 +3,14 @@
|
|
|
3
3
|
// groups are <details>, rows are links. The shell script adds memory (which groups you closed),
|
|
4
4
|
// search, the filter menu and j/k on top. Connector lines are CSS on the <li>, so the tree carries
|
|
5
5
|
// no connector markup at all.
|
|
6
|
+
//
|
|
7
|
+
// Rows carry no icons and read at 12px (decided 2026-09-24, to condense level 2). A node's `icon`
|
|
8
|
+
// is still accepted — the data layer keeps it — and simply not drawn.
|
|
9
|
+
//
|
|
10
|
+
// A tree whose root rows carry a slot is the Sections tree, which draws its own rows and sort
|
|
11
|
+
// control (./SectionsTree.astro).
|
|
6
12
|
import Icon from "./Icon.astro";
|
|
13
|
+
import SectionsTree from "./SectionsTree.astro";
|
|
7
14
|
import type { TreeNode } from "./model";
|
|
8
15
|
|
|
9
16
|
interface Props {
|
|
@@ -14,6 +21,7 @@ interface Props {
|
|
|
14
21
|
}
|
|
15
22
|
|
|
16
23
|
const { nodes, depth = 0, root = true } = Astro.props;
|
|
24
|
+
const sections = root && nodes.some((node) => node.slot !== undefined);
|
|
17
25
|
|
|
18
26
|
/** Whether a node is, or holds, the current page — those groups render open whatever was stored. */
|
|
19
27
|
const holdsCurrent = (node: TreeNode): boolean =>
|
|
@@ -22,62 +30,57 @@ const holdsCurrent = (node: TreeNode): boolean =>
|
|
|
22
30
|
const searchText = (node: TreeNode) => `${node.label} ${node.search ?? ""}`.toLowerCase();
|
|
23
31
|
---
|
|
24
32
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
nodes
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
33
|
+
{
|
|
34
|
+
sections ? (
|
|
35
|
+
<SectionsTree nodes={nodes} />
|
|
36
|
+
) : (
|
|
37
|
+
<ul class={root ? "lab-tree" : "lab-tree__group"} role={root ? "tree" : "group"} data-lab-tree={root ? "" : undefined}>
|
|
38
|
+
{nodes.map((node) => {
|
|
39
|
+
const hasChildren = (node.children?.length ?? 0) > 0;
|
|
40
|
+
const trailing = (
|
|
41
|
+
<>
|
|
42
|
+
{node.count !== undefined && <span class="lab-tree__count">{node.count}</span>}
|
|
43
|
+
{node.dot && <span class={`lab-dot lab-dot--${node.dot}`} title={node.dotTitle} />}
|
|
44
|
+
</>
|
|
45
|
+
);
|
|
46
|
+
return (
|
|
47
|
+
<li
|
|
48
|
+
class="lab-tree__node"
|
|
49
|
+
role="none"
|
|
50
|
+
style={`--lab-d:${depth}`}
|
|
51
|
+
data-lab-search={searchText(node)}
|
|
52
|
+
data-lab-facets={node.facets}
|
|
53
|
+
>
|
|
54
|
+
{hasChildren ? (
|
|
55
|
+
<details open data-lab-tree-id={node.id} data-lab-holds-current={holdsCurrent(node) ? "" : undefined}>
|
|
56
|
+
<summary class="lab-tree__row" role="treeitem" aria-current={node.current ? "page" : undefined} title={node.title}>
|
|
57
|
+
<span class="lab-tree__label">{node.href ? <a href={node.href}>{node.label}</a> : node.label}</span>
|
|
58
|
+
{trailing}
|
|
59
|
+
<Icon name="chevron-down" size="sm" class="lab-tree__chevron" />
|
|
60
|
+
</summary>
|
|
61
|
+
<Astro.self nodes={node.children!} depth={depth + 1} root={false} />
|
|
62
|
+
</details>
|
|
63
|
+
) : node.href && !node.disabled ? (
|
|
64
|
+
<a
|
|
47
65
|
class="lab-tree__row"
|
|
48
66
|
role="treeitem"
|
|
67
|
+
href={node.href}
|
|
49
68
|
aria-current={node.current ? "page" : undefined}
|
|
50
69
|
title={node.title}
|
|
70
|
+
data-lab-leaf
|
|
51
71
|
>
|
|
52
|
-
<
|
|
53
|
-
<span class="lab-tree__label">{node.href ? <a href={node.href}>{node.label}</a> : node.label}</span>
|
|
72
|
+
<span class="lab-tree__label">{node.label}</span>
|
|
54
73
|
{trailing}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
<
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
<Icon name={icon} size="sm" />
|
|
69
|
-
<span class="lab-tree__label">{node.label}</span>
|
|
70
|
-
{trailing}
|
|
71
|
-
</a>
|
|
72
|
-
) : (
|
|
73
|
-
<span class="lab-tree__row" role="treeitem" aria-disabled="true" title={node.title}>
|
|
74
|
-
<Icon name={icon} size="sm" />
|
|
75
|
-
<span class="lab-tree__label">{node.label}</span>
|
|
76
|
-
{trailing}
|
|
77
|
-
</span>
|
|
78
|
-
)}
|
|
79
|
-
</li>
|
|
80
|
-
);
|
|
81
|
-
})
|
|
82
|
-
}
|
|
83
|
-
</ul>
|
|
74
|
+
</a>
|
|
75
|
+
) : (
|
|
76
|
+
<span class="lab-tree__row" role="treeitem" aria-disabled="true" title={node.title}>
|
|
77
|
+
<span class="lab-tree__label">{node.label}</span>
|
|
78
|
+
{trailing}
|
|
79
|
+
</span>
|
|
80
|
+
)}
|
|
81
|
+
</li>
|
|
82
|
+
);
|
|
83
|
+
})}
|
|
84
|
+
</ul>
|
|
85
|
+
)
|
|
86
|
+
}
|