@graphlearning/shell 0.7.0 → 0.10.0
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 +32 -0
- package/dist/NarrationBar.d.ts +1 -0
- package/dist/index.js +208 -199
- package/dist/index.js.map +1 -1
- package/dist/styles.css +36 -14
- package/package.json +2 -1
- package/scripts/record-all.mjs +193 -0
package/dist/index.js
CHANGED
|
@@ -1,67 +1,68 @@
|
|
|
1
1
|
import { jsx as t, jsxs as h, Fragment as H } from "react/jsx-runtime";
|
|
2
|
-
import { useRef as
|
|
3
|
-
import { SceneView as
|
|
4
|
-
import { Home as
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
function
|
|
2
|
+
import { useRef as $, useState as b, useLayoutEffect as O, useEffect as k, useCallback as I, useMemo as M } from "react";
|
|
3
|
+
import { SceneView as R } from "@graphlearning/flow";
|
|
4
|
+
import { Home as Y, Volume2 as Z, VolumeX as J, Moon as Q, Sun as U, ChevronLeft as ee, ChevronRight as te } from "lucide-react";
|
|
5
|
+
import ne from "react-markdown";
|
|
6
|
+
import ae from "remark-gfm";
|
|
7
|
+
function X(e, a) {
|
|
8
8
|
return `${e.id}-${a.id}`;
|
|
9
9
|
}
|
|
10
|
-
function
|
|
11
|
-
return e.sections.map((a) => ({ section: a, slug:
|
|
10
|
+
function D(e) {
|
|
11
|
+
return e.sections.map((a) => ({ section: a, slug: X(e, a) }));
|
|
12
12
|
}
|
|
13
|
-
const
|
|
14
|
-
function
|
|
15
|
-
const e =
|
|
16
|
-
return
|
|
17
|
-
const
|
|
18
|
-
if (!
|
|
19
|
-
const d = () =>
|
|
13
|
+
const G = 806;
|
|
14
|
+
function re() {
|
|
15
|
+
const e = $(null), [a, r] = b(1);
|
|
16
|
+
return O(() => {
|
|
17
|
+
const o = e.current;
|
|
18
|
+
if (!o) return;
|
|
19
|
+
const d = () => r(o.clientWidth / G);
|
|
20
20
|
d();
|
|
21
|
-
const
|
|
22
|
-
return
|
|
21
|
+
const g = new ResizeObserver(d);
|
|
22
|
+
return g.observe(o), () => g.disconnect();
|
|
23
23
|
}, []), { ref: e, zoom: a };
|
|
24
24
|
}
|
|
25
|
-
function
|
|
26
|
-
const { ref:
|
|
27
|
-
return /* @__PURE__ */ t("aside", { ref:
|
|
25
|
+
function se({ slide: e, open: a }) {
|
|
26
|
+
const { ref: r, zoom: o } = re();
|
|
27
|
+
return /* @__PURE__ */ t("aside", { ref: r, className: `slide-panel${a ? " slide-panel--open" : ""}`, children: /* @__PURE__ */ t("div", { className: "slide-panel__scaler", style: { width: G, zoom: o }, children: /* @__PURE__ */ t(ne, { remarkPlugins: [ae], children: e }) }) });
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
const z = 10;
|
|
30
|
+
function ie({ audio: e }) {
|
|
31
|
+
const [a, r] = b(0), [o, d] = b(0), g = $(null);
|
|
32
|
+
if (k(() => {
|
|
32
33
|
if (!e) return;
|
|
33
34
|
const n = () => {
|
|
34
|
-
|
|
35
|
+
r(e.currentTime), d(Number.isFinite(e.duration) ? e.duration : 0);
|
|
35
36
|
};
|
|
36
37
|
n();
|
|
37
38
|
const u = ["loadedmetadata", "durationchange", "timeupdate", "seeked", "ended", "emptied", "error"];
|
|
38
|
-
return u.forEach((
|
|
39
|
-
}, [e]), !e || !
|
|
39
|
+
return u.forEach((s) => e.addEventListener(s, n)), () => u.forEach((s) => e.removeEventListener(s, n));
|
|
40
|
+
}, [e]), !e || !o) return null;
|
|
40
41
|
const f = (n) => {
|
|
41
|
-
const u =
|
|
42
|
+
const u = g.current;
|
|
42
43
|
if (!u) return;
|
|
43
|
-
const
|
|
44
|
-
e.currentTime = m *
|
|
44
|
+
const s = u.getBoundingClientRect(), m = Math.min(1, Math.max(0, (n - s.left) / s.width));
|
|
45
|
+
e.currentTime = m * o, r(e.currentTime);
|
|
45
46
|
}, l = (n) => {
|
|
46
|
-
const u = (
|
|
47
|
-
n.preventDefault(), n.stopPropagation(), e.currentTime = Math.min(
|
|
47
|
+
const u = (s) => {
|
|
48
|
+
n.preventDefault(), n.stopPropagation(), e.currentTime = Math.min(o, Math.max(0, e.currentTime + s)), r(e.currentTime);
|
|
48
49
|
};
|
|
49
|
-
n.key === "ArrowLeft" ? u(-
|
|
50
|
-
},
|
|
50
|
+
n.key === "ArrowLeft" ? u(-z) : n.key === "ArrowRight" ? u(z) : n.key === "Home" ? u(-o) : n.key === "End" && u(o);
|
|
51
|
+
}, p = `${Math.min(100, a / o * 100)}%`;
|
|
51
52
|
return /* @__PURE__ */ h("span", { className: "reel-foot__audio", children: [
|
|
52
|
-
/* @__PURE__ */ t("span", { className: "reel-foot__count reel-foot__time", children:
|
|
53
|
+
/* @__PURE__ */ t("span", { className: "reel-foot__count reel-foot__time", children: A(a) }),
|
|
53
54
|
/* @__PURE__ */ h(
|
|
54
55
|
"div",
|
|
55
56
|
{
|
|
56
|
-
ref:
|
|
57
|
+
ref: g,
|
|
57
58
|
className: "reel-foot__track",
|
|
58
59
|
role: "slider",
|
|
59
60
|
tabIndex: 0,
|
|
60
61
|
"aria-label": "Narration position",
|
|
61
62
|
"aria-valuemin": 0,
|
|
62
|
-
"aria-valuemax": Math.round(
|
|
63
|
+
"aria-valuemax": Math.round(o),
|
|
63
64
|
"aria-valuenow": Math.round(a),
|
|
64
|
-
"aria-valuetext": `${
|
|
65
|
+
"aria-valuetext": `${A(a)} of ${A(o)}`,
|
|
65
66
|
onKeyDown: l,
|
|
66
67
|
onPointerDown: (n) => {
|
|
67
68
|
n.currentTarget.setPointerCapture(n.pointerId), f(n.clientX);
|
|
@@ -70,43 +71,43 @@ function se({ audio: e }) {
|
|
|
70
71
|
n.currentTarget.hasPointerCapture(n.pointerId) && f(n.clientX);
|
|
71
72
|
},
|
|
72
73
|
children: [
|
|
73
|
-
/* @__PURE__ */ t("span", { className: "reel-foot__fill", style: { width:
|
|
74
|
-
/* @__PURE__ */ t("span", { className: "reel-foot__thumb", style: { left:
|
|
74
|
+
/* @__PURE__ */ t("span", { className: "reel-foot__fill", style: { width: p } }),
|
|
75
|
+
/* @__PURE__ */ t("span", { className: "reel-foot__thumb", style: { left: p } })
|
|
75
76
|
]
|
|
76
77
|
}
|
|
77
78
|
),
|
|
78
|
-
/* @__PURE__ */ t("span", { className: "reel-foot__count reel-foot__time", children:
|
|
79
|
+
/* @__PURE__ */ t("span", { className: "reel-foot__count reel-foot__time", children: A(o) })
|
|
79
80
|
] });
|
|
80
81
|
}
|
|
81
|
-
function
|
|
82
|
+
function A(e) {
|
|
82
83
|
const a = Number.isFinite(e) && e > 0 ? e : 0;
|
|
83
84
|
return `${Math.floor(a / 60)}:${String(Math.floor(a % 60)).padStart(2, "0")}`;
|
|
84
85
|
}
|
|
85
86
|
function oe({
|
|
86
87
|
section: e,
|
|
87
88
|
getScene: a,
|
|
88
|
-
capture:
|
|
89
|
-
eyebrow:
|
|
89
|
+
capture: r = !1,
|
|
90
|
+
eyebrow: o,
|
|
90
91
|
index: d = 0,
|
|
91
|
-
total:
|
|
92
|
+
total: g = 0,
|
|
92
93
|
onHome: f,
|
|
93
94
|
onPrev: l,
|
|
94
|
-
onNext:
|
|
95
|
+
onNext: p,
|
|
95
96
|
narrating: n = !1,
|
|
96
97
|
onToggleNarration: u,
|
|
97
|
-
narrationAudio:
|
|
98
|
+
narrationAudio: s = null,
|
|
98
99
|
theme: m = "dark",
|
|
99
|
-
onToggleTheme:
|
|
100
|
+
onToggleTheme: v
|
|
100
101
|
}) {
|
|
101
|
-
const [_, w] = b(!1),
|
|
102
|
-
return
|
|
102
|
+
const [_, w] = b(!1), E = a(e.scene);
|
|
103
|
+
return E ? /* @__PURE__ */ h("div", { className: `stage stage--section${r ? " stage--capture" : ""}`, children: [
|
|
103
104
|
/* @__PURE__ */ h("header", { className: "reel-head", children: [
|
|
104
|
-
|
|
105
|
+
o && /* @__PURE__ */ t("button", { className: "reel-head__eyebrow", onClick: f, "aria-label": "Back to catalog (Esc)", title: "Back to catalog (Esc)", children: o }),
|
|
105
106
|
/* @__PURE__ */ t("h1", { className: "reel-head__title", children: e.title })
|
|
106
107
|
] }),
|
|
107
|
-
!
|
|
108
|
+
!r && /* @__PURE__ */ h("footer", { className: "reel-foot reel-foot--controls", children: [
|
|
108
109
|
/* @__PURE__ */ h("span", { className: "reel-foot__grp", children: [
|
|
109
|
-
/* @__PURE__ */ t("button", { className: "reel-foot__ctrl", onClick: f, "aria-label": "Back to catalog (Esc)", title: "Back to catalog (Esc)", children: /* @__PURE__ */ t(
|
|
110
|
+
/* @__PURE__ */ t("button", { className: "reel-foot__ctrl", onClick: f, "aria-label": "Back to catalog (Esc)", title: "Back to catalog (Esc)", children: /* @__PURE__ */ t(Y, { size: 17 }) }),
|
|
110
111
|
/* @__PURE__ */ t(
|
|
111
112
|
"button",
|
|
112
113
|
{
|
|
@@ -114,53 +115,53 @@ function oe({
|
|
|
114
115
|
onClick: u,
|
|
115
116
|
"aria-label": n ? "Pause narration (Space)" : "Play narration (Space)",
|
|
116
117
|
title: n ? "Pause narration (Space)" : "Play narration (Space)",
|
|
117
|
-
children: n ? /* @__PURE__ */ t(
|
|
118
|
+
children: n ? /* @__PURE__ */ t(Z, { size: 18 }) : /* @__PURE__ */ t(J, { size: 18 })
|
|
118
119
|
}
|
|
119
120
|
),
|
|
120
|
-
|
|
121
|
+
v && /* @__PURE__ */ t(
|
|
121
122
|
"button",
|
|
122
123
|
{
|
|
123
124
|
className: "reel-foot__ctrl",
|
|
124
|
-
onClick:
|
|
125
|
+
onClick: v,
|
|
125
126
|
"aria-label": m === "dark" ? "Dark theme. Switch to light theme." : "Light theme. Switch to dark theme.",
|
|
126
127
|
title: m === "dark" ? "Dark theme. Switch to light theme." : "Light theme. Switch to dark theme.",
|
|
127
|
-
children: m === "dark" ? /* @__PURE__ */ t(
|
|
128
|
+
children: m === "dark" ? /* @__PURE__ */ t(Q, { size: 17 }) : /* @__PURE__ */ t(U, { size: 17 })
|
|
128
129
|
}
|
|
129
130
|
)
|
|
130
131
|
] }),
|
|
131
|
-
/* @__PURE__ */ t(
|
|
132
|
+
/* @__PURE__ */ t(ie, { audio: s }),
|
|
132
133
|
/* @__PURE__ */ h("span", { className: "reel-foot__nav", children: [
|
|
133
|
-
/* @__PURE__ */ t("button", { className: "reel-foot__ctrl", onClick: l, "aria-label": "Previous section (
|
|
134
|
+
/* @__PURE__ */ t("button", { className: "reel-foot__ctrl", onClick: l, "aria-label": "Previous section (Shift+←)", title: "Previous section (Shift+←)", children: /* @__PURE__ */ t(ee, { size: 19 }) }),
|
|
134
135
|
/* @__PURE__ */ h("span", { className: "reel-foot__count reel-foot__count--live", children: [
|
|
135
136
|
d + 1,
|
|
136
137
|
" / ",
|
|
137
|
-
|
|
138
|
+
g
|
|
138
139
|
] }),
|
|
139
|
-
/* @__PURE__ */ t("button", { className: "reel-foot__ctrl", onClick:
|
|
140
|
+
/* @__PURE__ */ t("button", { className: "reel-foot__ctrl", onClick: p, "aria-label": "Next section (Shift+→)", title: "Next section (Shift+→)", children: /* @__PURE__ */ t(te, { size: 19 }) })
|
|
140
141
|
] })
|
|
141
142
|
] }),
|
|
142
|
-
/* @__PURE__ */ t("div", { className: "scene-area", children: /* @__PURE__ */ t(
|
|
143
|
-
!
|
|
143
|
+
/* @__PURE__ */ t("div", { className: "scene-area", children: /* @__PURE__ */ t(R, { scene: E, focusId: e.focus, theme: m }) }),
|
|
144
|
+
!r && /* @__PURE__ */ t(
|
|
144
145
|
"button",
|
|
145
146
|
{
|
|
146
147
|
className: "slide-toggle",
|
|
147
|
-
onClick: () => w((
|
|
148
|
+
onClick: () => w((S) => !S),
|
|
148
149
|
"aria-label": _ ? "Hide slide" : "Show slide",
|
|
149
150
|
children: _ ? "›" : "‹"
|
|
150
151
|
}
|
|
151
152
|
),
|
|
152
|
-
/* @__PURE__ */ t(
|
|
153
|
+
/* @__PURE__ */ t(se, { slide: e.slide, open: _ })
|
|
153
154
|
] }) : /* @__PURE__ */ h("div", { className: "stage stage--missing", children: [
|
|
154
155
|
"no scene: ",
|
|
155
156
|
e.scene
|
|
156
157
|
] });
|
|
157
158
|
}
|
|
158
|
-
const
|
|
159
|
+
const le = [
|
|
159
160
|
{ id: "courses", label: "Courses" },
|
|
160
161
|
{ id: "labs", label: "Labs" },
|
|
161
162
|
{ id: "coach", label: "Coach" }
|
|
162
163
|
];
|
|
163
|
-
function
|
|
164
|
+
function ce() {
|
|
164
165
|
return /* @__PURE__ */ h("svg", { className: "site__logo", width: "28", height: "28", viewBox: "0 0 512 512", "aria-hidden": "true", children: [
|
|
165
166
|
/* @__PURE__ */ t("rect", { width: "512", height: "512", rx: "80", fill: "#e8804f" }),
|
|
166
167
|
/* @__PURE__ */ h("g", { fill: "none", stroke: "#ffffff", strokeWidth: "58", strokeLinecap: "butt", strokeLinejoin: "miter", children: [
|
|
@@ -169,38 +170,38 @@ function le() {
|
|
|
169
170
|
] })
|
|
170
171
|
] });
|
|
171
172
|
}
|
|
172
|
-
function
|
|
173
|
+
function de({
|
|
173
174
|
kind: e = "courses",
|
|
174
|
-
nav: a =
|
|
175
|
-
home:
|
|
176
|
-
actions:
|
|
175
|
+
nav: a = le,
|
|
176
|
+
home: r = "/",
|
|
177
|
+
actions: o
|
|
177
178
|
}) {
|
|
178
179
|
return /* @__PURE__ */ t("header", { className: "site", children: /* @__PURE__ */ h("div", { className: "site__inner", children: [
|
|
179
|
-
/* @__PURE__ */ h("a", { className: "site__brand", href:
|
|
180
|
-
/* @__PURE__ */ t(
|
|
180
|
+
/* @__PURE__ */ h("a", { className: "site__brand", href: r, children: [
|
|
181
|
+
/* @__PURE__ */ t(ce, {}),
|
|
181
182
|
/* @__PURE__ */ t("span", { className: "site__name", children: "GraphL" })
|
|
182
183
|
] }),
|
|
183
184
|
/* @__PURE__ */ t("nav", { className: "site__nav", "aria-label": "Sections", children: a.map((d) => /* @__PURE__ */ t(
|
|
184
185
|
"a",
|
|
185
186
|
{
|
|
186
187
|
className: "site__link",
|
|
187
|
-
href: `${
|
|
188
|
+
href: `${r}#${d.id}`,
|
|
188
189
|
...d.id === e ? { "aria-current": "page" } : {},
|
|
189
190
|
children: d.label
|
|
190
191
|
},
|
|
191
192
|
d.id
|
|
192
193
|
)) }),
|
|
193
|
-
/* @__PURE__ */ t("div", { className: "site__actions", children:
|
|
194
|
+
/* @__PURE__ */ t("div", { className: "site__actions", children: o })
|
|
194
195
|
] }) });
|
|
195
196
|
}
|
|
196
|
-
function
|
|
197
|
+
function he({
|
|
197
198
|
courses: e,
|
|
198
199
|
subject: a,
|
|
199
|
-
kind:
|
|
200
|
-
actions:
|
|
200
|
+
kind: r,
|
|
201
|
+
actions: o
|
|
201
202
|
}) {
|
|
202
|
-
const [d,
|
|
203
|
-
const n = new Set(
|
|
203
|
+
const [d, g] = b(() => /* @__PURE__ */ new Set()), f = (l) => g((p) => {
|
|
204
|
+
const n = new Set(p);
|
|
204
205
|
return n.has(l) ? n.delete(l) : n.add(l), n;
|
|
205
206
|
});
|
|
206
207
|
return (
|
|
@@ -208,11 +209,11 @@ function de({
|
|
|
208
209
|
// viewport) while .idx is a 940px centred column. Both use the same width and gutters, so the
|
|
209
210
|
// brand lines up with the card edge below it.
|
|
210
211
|
/* @__PURE__ */ h(H, { children: [
|
|
211
|
-
/* @__PURE__ */ t(
|
|
212
|
+
/* @__PURE__ */ t(de, { kind: r, actions: o }),
|
|
212
213
|
/* @__PURE__ */ h("div", { className: "idx", children: [
|
|
213
214
|
/* @__PURE__ */ t("header", { className: "idx__head", children: /* @__PURE__ */ t("h1", { className: "idx__subject", children: a }) }),
|
|
214
|
-
e.length === 0 ? /* @__PURE__ */ t("p", { className: "idx__empty", children: "No courses authored yet — the app shell is ready." }) : /* @__PURE__ */ t("ol", { className: "idx__grid", children: e.map((l,
|
|
215
|
-
const n =
|
|
215
|
+
e.length === 0 ? /* @__PURE__ */ t("p", { className: "idx__empty", children: "No courses authored yet — the app shell is ready." }) : /* @__PURE__ */ t("ol", { className: "idx__grid", children: e.map((l, p) => {
|
|
216
|
+
const n = D(l), u = d.has(l.id);
|
|
216
217
|
return /* @__PURE__ */ h("li", { className: `idx-card${u ? " idx-card--open" : ""}`, children: [
|
|
217
218
|
/* @__PURE__ */ h(
|
|
218
219
|
"button",
|
|
@@ -221,7 +222,7 @@ function de({
|
|
|
221
222
|
onClick: () => f(l.id),
|
|
222
223
|
"aria-expanded": u,
|
|
223
224
|
children: [
|
|
224
|
-
/* @__PURE__ */ t("span", { className: "idx-card__num", children: String(
|
|
225
|
+
/* @__PURE__ */ t("span", { className: "idx-card__num", children: String(p + 1).padStart(2, "0") }),
|
|
225
226
|
/* @__PURE__ */ t("span", { className: "idx-card__title", children: l.title }),
|
|
226
227
|
/* @__PURE__ */ h("span", { className: "idx-card__count", children: [
|
|
227
228
|
n.length,
|
|
@@ -231,9 +232,9 @@ function de({
|
|
|
231
232
|
]
|
|
232
233
|
}
|
|
233
234
|
),
|
|
234
|
-
u && /* @__PURE__ */ t("ol", { className: "idx-sec", children: n.map(({ section:
|
|
235
|
-
/* @__PURE__ */ t("span", { className: "idx-sec__num", children:
|
|
236
|
-
/* @__PURE__ */ t("span", { className: "idx-sec__title", children:
|
|
235
|
+
u && /* @__PURE__ */ t("ol", { className: "idx-sec", children: n.map(({ section: s, slug: m }, v) => /* @__PURE__ */ t("li", { className: "idx-sec__row", children: /* @__PURE__ */ h("a", { href: `#/${m}`, children: [
|
|
236
|
+
/* @__PURE__ */ t("span", { className: "idx-sec__num", children: v + 1 }),
|
|
237
|
+
/* @__PURE__ */ t("span", { className: "idx-sec__title", children: s.title }),
|
|
237
238
|
/* @__PURE__ */ t("span", { className: "idx-sec__chev", "aria-hidden": "true", children: "›" })
|
|
238
239
|
] }) }, m)) })
|
|
239
240
|
] }, l.id);
|
|
@@ -250,194 +251,202 @@ function de({
|
|
|
250
251
|
] })
|
|
251
252
|
);
|
|
252
253
|
}
|
|
253
|
-
function
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
const [f, l] = b(!1),
|
|
257
|
-
return
|
|
258
|
-
const
|
|
259
|
-
return
|
|
260
|
-
}, []),
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
})) : (
|
|
254
|
+
function ue(e, a) {
|
|
255
|
+
const r = $(null), [o, d] = b(null), g = $(a);
|
|
256
|
+
g.current = a;
|
|
257
|
+
const [f, l] = b(!1), p = $(f);
|
|
258
|
+
return p.current = f, k(() => {
|
|
259
|
+
const s = new Audio();
|
|
260
|
+
return s.addEventListener("ended", () => g.current()), s.addEventListener("error", () => l(!1)), r.current = s, d(s), () => s.pause();
|
|
261
|
+
}, []), k(() => {
|
|
262
|
+
const s = r.current;
|
|
263
|
+
s && (s.pause(), e ? (s.src = e, s.currentTime = 0, p.current && s.play().catch(() => {
|
|
264
|
+
})) : (s.removeAttribute("src"), s.load(), l(!1)));
|
|
264
265
|
}, [e]), { playing: f, toggle: () => {
|
|
265
|
-
const
|
|
266
|
-
!
|
|
266
|
+
const s = r.current;
|
|
267
|
+
!s || !s.getAttribute("src") || (p.current ? (s.pause(), l(!1)) : (s.play().catch(() => {
|
|
267
268
|
}), l(!0)));
|
|
268
269
|
}, stop: () => {
|
|
269
|
-
var
|
|
270
|
-
(
|
|
271
|
-
}, audio:
|
|
270
|
+
var s;
|
|
271
|
+
(s = r.current) == null || s.pause(), l(!1);
|
|
272
|
+
}, audio: o };
|
|
272
273
|
}
|
|
273
|
-
const
|
|
274
|
-
function
|
|
274
|
+
const B = "graphl:theme";
|
|
275
|
+
function F() {
|
|
275
276
|
try {
|
|
276
|
-
const e = localStorage.getItem(
|
|
277
|
+
const e = localStorage.getItem(B);
|
|
277
278
|
return e === "light" || e === "dark" ? e : null;
|
|
278
279
|
} catch {
|
|
279
280
|
return null;
|
|
280
281
|
}
|
|
281
282
|
}
|
|
282
|
-
function
|
|
283
|
+
function me(e) {
|
|
283
284
|
try {
|
|
284
|
-
localStorage.setItem(
|
|
285
|
+
localStorage.setItem(B, e);
|
|
285
286
|
} catch {
|
|
286
287
|
}
|
|
287
288
|
}
|
|
288
|
-
const
|
|
289
|
-
function
|
|
290
|
-
const [
|
|
291
|
-
|
|
289
|
+
const fe = (e, a, r) => r || !a ? e : a;
|
|
290
|
+
function ge(e, a) {
|
|
291
|
+
const [r, o] = b(() => a ? null : F()), d = fe(e, r, a);
|
|
292
|
+
k(() => (document.documentElement.setAttribute("data-theme", d), () => document.documentElement.removeAttribute("data-theme")), [d]), k(() => {
|
|
292
293
|
if (a) return;
|
|
293
294
|
const f = (l) => {
|
|
294
|
-
(l.key ===
|
|
295
|
+
(l.key === B || l.key === null) && o(F());
|
|
295
296
|
};
|
|
296
297
|
return window.addEventListener("storage", f), () => window.removeEventListener("storage", f);
|
|
297
298
|
}, [a]);
|
|
298
|
-
const
|
|
299
|
+
const g = I(() => {
|
|
299
300
|
const f = d === "dark" ? "light" : "dark";
|
|
300
|
-
|
|
301
|
+
me(f);
|
|
301
302
|
const l = document.documentElement;
|
|
302
|
-
l.classList.add("theme-swap"),
|
|
303
|
+
l.classList.add("theme-swap"), o(f), requestAnimationFrame(() => requestAnimationFrame(() => l.classList.remove("theme-swap")));
|
|
303
304
|
}, [d]);
|
|
304
|
-
return { theme: d, toggle:
|
|
305
|
+
return { theme: d, toggle: g };
|
|
305
306
|
}
|
|
306
307
|
const P = {
|
|
307
308
|
dark: { glyph: "☾", label: "Dark theme" },
|
|
308
309
|
light: { glyph: "☀", label: "Light theme" }
|
|
309
310
|
};
|
|
310
311
|
function pe({ theme: e, onToggle: a }) {
|
|
311
|
-
const
|
|
312
|
-
return /* @__PURE__ */ t("button", { className: "site__icon", type: "button", onClick: a, "aria-label":
|
|
312
|
+
const r = e === "dark" ? "light" : "dark", o = `${P[e].label}. Switch to ${P[r].label.toLowerCase()}.`;
|
|
313
|
+
return /* @__PURE__ */ t("button", { className: "site__icon", type: "button", onClick: a, "aria-label": o, title: o, children: P[e].glyph });
|
|
313
314
|
}
|
|
314
|
-
function
|
|
315
|
+
function ye({
|
|
315
316
|
subject: e,
|
|
316
317
|
eyebrow: a,
|
|
317
|
-
courses:
|
|
318
|
-
getScene:
|
|
318
|
+
courses: r,
|
|
319
|
+
getScene: o,
|
|
319
320
|
audioBase: d = "/",
|
|
320
|
-
kind:
|
|
321
|
+
kind: g = "courses",
|
|
321
322
|
theme: f = "dark"
|
|
322
323
|
}) {
|
|
323
|
-
const [l,
|
|
324
|
-
|
|
325
|
-
const
|
|
326
|
-
return window.addEventListener("hashchange",
|
|
324
|
+
const [l, p] = b(() => location.hash);
|
|
325
|
+
k(() => {
|
|
326
|
+
const i = () => p(location.hash);
|
|
327
|
+
return window.addEventListener("hashchange", i), () => window.removeEventListener("hashchange", i);
|
|
327
328
|
}, []);
|
|
328
|
-
const n = new URLSearchParams(location.search).get("capture") === "1", { theme: u, toggle:
|
|
329
|
-
if (
|
|
330
|
-
for (const
|
|
331
|
-
if (
|
|
332
|
-
return Object.values(
|
|
333
|
-
}, [m,
|
|
334
|
-
|
|
335
|
-
if (n || !
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
}, [n, m, _]),
|
|
329
|
+
const n = new URLSearchParams(location.search).get("capture") === "1", { theme: u, toggle: s } = ge(f, n), m = l.replace(/^#\/?/, ""), v = M(() => {
|
|
330
|
+
if (r[m]) return r[m];
|
|
331
|
+
for (const i of Object.values(r))
|
|
332
|
+
if (i.sections.some((c) => X(i, c) === m)) return i;
|
|
333
|
+
return Object.values(r)[0];
|
|
334
|
+
}, [m, r]), _ = M(() => D(v), [v]), w = M(() => Object.values(r).flatMap(D), [r]);
|
|
335
|
+
k(() => {
|
|
336
|
+
if (n || !r[m]) return;
|
|
337
|
+
const i = _[0];
|
|
338
|
+
i && (history.replaceState(null, "", `${location.pathname}${location.search}#/${i.slug}`), p(`#/${i.slug}`));
|
|
339
|
+
}, [n, m, _]), k(() => {
|
|
339
340
|
n && (window.__scene = {
|
|
340
|
-
plan: () => _.map(({ slug:
|
|
341
|
-
slug:
|
|
342
|
-
course:
|
|
341
|
+
plan: () => _.map(({ slug: i, section: c }) => ({
|
|
342
|
+
slug: i,
|
|
343
|
+
course: v.id,
|
|
343
344
|
// audio lives at audio/<course>/<id>.wav
|
|
344
345
|
id: c.id,
|
|
345
346
|
scene: c.scene,
|
|
346
347
|
focus: c.focus ?? null
|
|
347
348
|
}))
|
|
348
349
|
});
|
|
349
|
-
}, [n, _,
|
|
350
|
-
const
|
|
351
|
-
(
|
|
352
|
-
const c = location.hash.replace(/^#\/?/, ""),
|
|
353
|
-
if (
|
|
354
|
-
const
|
|
355
|
-
location.hash =
|
|
350
|
+
}, [n, _, v]);
|
|
351
|
+
const E = I(
|
|
352
|
+
(i) => {
|
|
353
|
+
const c = location.hash.replace(/^#\/?/, ""), N = w.findIndex(({ slug: x }) => x === c);
|
|
354
|
+
if (N !== -1) {
|
|
355
|
+
const x = w[N + i];
|
|
356
|
+
location.hash = x ? `#/${x.slug}` : "";
|
|
356
357
|
return;
|
|
357
358
|
}
|
|
358
359
|
if (c === "") {
|
|
359
|
-
|
|
360
|
+
i === 1 && w[0] && (location.hash = `#/${w[0].slug}`);
|
|
360
361
|
return;
|
|
361
362
|
}
|
|
362
|
-
const
|
|
363
|
-
|
|
363
|
+
const L = i === 1 ? _[0] : _[_.length - 1];
|
|
364
|
+
L && (location.hash = `#/${L.slug}`);
|
|
364
365
|
},
|
|
365
366
|
[_, w]
|
|
366
|
-
)
|
|
367
|
-
v(() => {
|
|
368
|
-
const o = (c) => {
|
|
369
|
-
c.key !== "ArrowRight" && c.key !== "ArrowLeft" || (c.preventDefault(), y(c.key === "ArrowRight" ? 1 : -1));
|
|
370
|
-
};
|
|
371
|
-
return window.addEventListener("keydown", o), () => window.removeEventListener("keydown", o);
|
|
372
|
-
}, [y]);
|
|
373
|
-
const x = M(() => {
|
|
367
|
+
), S = I(() => {
|
|
374
368
|
location.hash ? location.hash = "" : location.pathname !== "/" && (location.href = "/");
|
|
375
369
|
}, []);
|
|
376
|
-
|
|
377
|
-
const
|
|
378
|
-
c.key === "Escape" &&
|
|
370
|
+
k(() => {
|
|
371
|
+
const i = (c) => {
|
|
372
|
+
c.key === "Escape" && S();
|
|
379
373
|
};
|
|
380
|
-
return window.addEventListener("keydown",
|
|
381
|
-
}, [
|
|
382
|
-
const
|
|
383
|
-
const
|
|
384
|
-
|
|
374
|
+
return window.addEventListener("keydown", i), () => window.removeEventListener("keydown", i);
|
|
375
|
+
}, [S]);
|
|
376
|
+
const T = _.find(({ slug: i }) => i === m), V = T ? `${d}audio/${v.id}/${T.section.id}.wav` : void 0, { playing: q, toggle: K, stop: W, audio: y } = ue(V, () => {
|
|
377
|
+
const i = location.hash.replace(/^#\/?/, ""), c = w.findIndex(({ slug: L }) => L === i), N = w[c + 1];
|
|
378
|
+
N ? location.hash = `#/${N.slug}` : W();
|
|
385
379
|
});
|
|
386
|
-
if (
|
|
387
|
-
const
|
|
380
|
+
if (k(() => {
|
|
381
|
+
const i = (c) => {
|
|
382
|
+
if (c.key !== "ArrowRight" && c.key !== "ArrowLeft") return;
|
|
383
|
+
const N = c.target;
|
|
384
|
+
if (N && (N.tagName === "INPUT" || N.tagName === "TEXTAREA" || N.isContentEditable)) return;
|
|
385
|
+
const L = c.key === "ArrowRight" ? 1 : -1;
|
|
386
|
+
c.preventDefault();
|
|
387
|
+
const x = (y == null ? void 0 : y.duration) ?? 0;
|
|
388
|
+
if (y && !c.shiftKey && Number.isFinite(x) && x > 0) {
|
|
389
|
+
y.currentTime = Math.min(x, Math.max(0, y.currentTime + L * z));
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
E(L);
|
|
393
|
+
};
|
|
394
|
+
return window.addEventListener("keydown", i), () => window.removeEventListener("keydown", i);
|
|
395
|
+
}, [E, y]), k(() => {
|
|
396
|
+
const i = (c) => {
|
|
388
397
|
if (c.key !== " " && c.code !== "Space") return;
|
|
389
|
-
const
|
|
390
|
-
|
|
398
|
+
const N = c.target;
|
|
399
|
+
N && (N.tagName === "INPUT" || N.tagName === "TEXTAREA" || N.isContentEditable) || (c.preventDefault(), K());
|
|
391
400
|
};
|
|
392
|
-
return window.addEventListener("keydown",
|
|
401
|
+
return window.addEventListener("keydown", i), () => window.removeEventListener("keydown", i);
|
|
393
402
|
}), !m)
|
|
394
403
|
return /* @__PURE__ */ t(
|
|
395
|
-
|
|
404
|
+
he,
|
|
396
405
|
{
|
|
397
|
-
courses: Object.values(
|
|
406
|
+
courses: Object.values(r),
|
|
398
407
|
subject: e,
|
|
399
|
-
kind:
|
|
400
|
-
actions: n ? null : /* @__PURE__ */ t(pe, { theme: u, onToggle:
|
|
408
|
+
kind: g,
|
|
409
|
+
actions: n ? null : /* @__PURE__ */ t(pe, { theme: u, onToggle: s })
|
|
401
410
|
}
|
|
402
411
|
);
|
|
403
|
-
let
|
|
404
|
-
if (
|
|
405
|
-
const
|
|
406
|
-
|
|
412
|
+
let C, j = null;
|
|
413
|
+
if (T) {
|
|
414
|
+
const i = _.findIndex(({ slug: c }) => c === m);
|
|
415
|
+
C = /* @__PURE__ */ t(
|
|
407
416
|
oe,
|
|
408
417
|
{
|
|
409
|
-
section:
|
|
410
|
-
getScene:
|
|
418
|
+
section: T.section,
|
|
419
|
+
getScene: o,
|
|
411
420
|
capture: n,
|
|
412
|
-
eyebrow: `${a ?? e.toUpperCase()} · ${
|
|
413
|
-
index:
|
|
421
|
+
eyebrow: `${a ?? e.toUpperCase()} · ${v.id.toUpperCase()}`,
|
|
422
|
+
index: i,
|
|
414
423
|
total: _.length,
|
|
415
|
-
onHome:
|
|
416
|
-
onPrev: () =>
|
|
417
|
-
onNext: () =>
|
|
418
|
-
narrating:
|
|
419
|
-
onToggleNarration:
|
|
420
|
-
narrationAudio:
|
|
424
|
+
onHome: S,
|
|
425
|
+
onPrev: () => E(-1),
|
|
426
|
+
onNext: () => E(1),
|
|
427
|
+
narrating: q,
|
|
428
|
+
onToggleNarration: K,
|
|
429
|
+
narrationAudio: y,
|
|
421
430
|
theme: u,
|
|
422
|
-
onToggleTheme: n ? void 0 :
|
|
431
|
+
onToggleTheme: n ? void 0 : s
|
|
423
432
|
}
|
|
424
433
|
);
|
|
425
434
|
} else {
|
|
426
|
-
const
|
|
427
|
-
|
|
435
|
+
const i = o(m);
|
|
436
|
+
C = i ? /* @__PURE__ */ t("div", { className: "stage", children: /* @__PURE__ */ t(R, { scene: i, theme: u }) }) : /* @__PURE__ */ h("div", { className: "stage stage--missing", children: [
|
|
428
437
|
"no scene or slug: ",
|
|
429
438
|
m
|
|
430
|
-
] }),
|
|
439
|
+
] }), j = n ? null : /* @__PURE__ */ t("button", { className: "brand-home", onClick: S, "aria-label": "Back to catalog (Esc)", title: "Back to catalog (Esc)", children: "GraphL" });
|
|
431
440
|
}
|
|
432
441
|
return /* @__PURE__ */ h(H, { children: [
|
|
433
|
-
|
|
434
|
-
|
|
442
|
+
j,
|
|
443
|
+
C
|
|
435
444
|
] });
|
|
436
445
|
}
|
|
437
446
|
export {
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
447
|
+
ye as ConceptApp,
|
|
448
|
+
de as SiteHeader,
|
|
449
|
+
D as allSections,
|
|
450
|
+
X as slugOf
|
|
442
451
|
};
|
|
443
452
|
//# sourceMappingURL=index.js.map
|