handzon-core 0.6.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/package.json +74 -0
- package/src/collections.ts +150 -0
- package/src/components/Footer.astro +85 -0
- package/src/components/Navbar.astro +74 -0
- package/src/components/Progress.tsx +36 -0
- package/src/components/Sidebar.astro +162 -0
- package/src/components/StepNav.astro +107 -0
- package/src/components/ai/ByokSetup.tsx +90 -0
- package/src/components/ai/ChatButton.tsx +30 -0
- package/src/components/ai/ChatPanel.tsx +244 -0
- package/src/components/auth/SignInButton.astro +41 -0
- package/src/components/auth/UserMenu.astro +79 -0
- package/src/components/auth/UserMenu.tsx +136 -0
- package/src/components/home/FilterBar.tsx +152 -0
- package/src/components/home/Hero.astro +60 -0
- package/src/components/home/Pagination.tsx +89 -0
- package/src/components/home/ResumeRail.tsx +50 -0
- package/src/components/home/TutorialCard.astro +185 -0
- package/src/components/mdx/Callout.astro +77 -0
- package/src/components/mdx/Checkpoint.astro +14 -0
- package/src/components/mdx/Checkpoint.tsx +49 -0
- package/src/components/mdx/Diff.astro +6 -0
- package/src/components/mdx/Diff.tsx +100 -0
- package/src/components/mdx/Download.astro +37 -0
- package/src/components/mdx/Embed.astro +56 -0
- package/src/components/mdx/File.astro +28 -0
- package/src/components/mdx/FileTree.astro +6 -0
- package/src/components/mdx/FileTree.tsx +71 -0
- package/src/components/mdx/Hint.astro +51 -0
- package/src/components/mdx/Mermaid.astro +6 -0
- package/src/components/mdx/Mermaid.tsx +47 -0
- package/src/components/mdx/Playground.astro +6 -0
- package/src/components/mdx/Playground.tsx +34 -0
- package/src/components/mdx/Quiz.astro +6 -0
- package/src/components/mdx/Quiz.tsx +102 -0
- package/src/components/mdx/Recap.astro +65 -0
- package/src/components/mdx/Reveal.astro +7 -0
- package/src/components/mdx/Reveal.tsx +25 -0
- package/src/components/mdx/Step.astro +12 -0
- package/src/components/mdx/Steps.astro +40 -0
- package/src/components/mdx/Tab.astro +22 -0
- package/src/components/mdx/Tabs.astro +67 -0
- package/src/components/mdx/Terminal.astro +6 -0
- package/src/components/mdx/Terminal.tsx +47 -0
- package/src/index.ts +55 -0
- package/src/layouts/BaseLayout.astro +112 -0
- package/src/layouts/TutorialLayout.astro +218 -0
- package/src/lib/ai/client.ts +92 -0
- package/src/lib/ai/context.ts +97 -0
- package/src/lib/content.ts +73 -0
- package/src/lib/mdx-components.ts +47 -0
- package/src/lib/progress/local.ts +89 -0
- package/src/lib/progress/remote.ts +199 -0
- package/src/lib/progress/types.ts +63 -0
- package/src/lib/progress/useProgress.ts +117 -0
- package/src/lib/rehype-mermaid-passthrough.ts +31 -0
- package/src/pages/Home.astro +408 -0
- package/src/pages/TutorialLanding.astro +324 -0
- package/src/pages/TutorialStep.astro +67 -0
- package/src/pages/paths.ts +36 -0
- package/src/server/auth/config.ts +102 -0
- package/src/server/auth/schema.ts +66 -0
- package/src/server/auth/session.ts +27 -0
- package/src/server/auth.ts +127 -0
- package/src/server/db/client.ts +14 -0
- package/src/server/db/migrate.ts +29 -0
- package/src/server/db/schema.ts +65 -0
- package/src/server/handlers/healthz.ts +6 -0
- package/src/server/handlers/progress.ts +90 -0
- package/src/server/handlers/tutorialStats.ts +67 -0
- package/src/server/http.ts +33 -0
- package/src/types/ai.ts +17 -0
- package/styles/base.css +127 -0
- package/styles/components/a11y.css +12 -0
- package/styles/components/byok.css +50 -0
- package/styles/components/chat.css +304 -0
- package/styles/components/checkpoint.css +49 -0
- package/styles/components/diff.css +44 -0
- package/styles/components/expressive-code.css +61 -0
- package/styles/components/filetree.css +68 -0
- package/styles/components/mermaid.css +19 -0
- package/styles/components/modal.css +25 -0
- package/styles/components/progress.css +19 -0
- package/styles/components/quiz.css +101 -0
- package/styles/components/reveal.css +25 -0
- package/styles/components/tabs.css +60 -0
- package/styles/components/terminal.css +55 -0
- package/styles/components.css +28 -0
- package/styles/global.css +15 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/* Reveal */
|
|
2
|
+
.reveal { margin: 1rem 0; }
|
|
3
|
+
.reveal-btn {
|
|
4
|
+
display: inline-flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
gap: 0.5rem;
|
|
7
|
+
padding: 0.5rem 1rem;
|
|
8
|
+
background: var(--color-accent);
|
|
9
|
+
color: var(--color-accent-fg);
|
|
10
|
+
border: 0;
|
|
11
|
+
font: inherit;
|
|
12
|
+
font-size: 0.9em;
|
|
13
|
+
font-weight: 500;
|
|
14
|
+
cursor: pointer;
|
|
15
|
+
border-radius: 0;
|
|
16
|
+
}
|
|
17
|
+
.reveal-btn:hover {
|
|
18
|
+
background: color-mix(in oklab, var(--color-accent) 88%, white);
|
|
19
|
+
}
|
|
20
|
+
.reveal-content {
|
|
21
|
+
margin-top: 0.75rem;
|
|
22
|
+
padding: 0.95rem 1.1rem;
|
|
23
|
+
background: var(--color-surface);
|
|
24
|
+
border-left: var(--border-thick) solid var(--color-accent);
|
|
25
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/* Tabs — browser-tab look. Triggers at top, content directly below.
|
|
2
|
+
* No outer container. Active trigger shares the content's surface bg
|
|
3
|
+
* so the underline appears to extend under the inactive triggers and
|
|
4
|
+
* the active one visually attaches to the content area below it.
|
|
5
|
+
*/
|
|
6
|
+
.tut-tabs {
|
|
7
|
+
margin: 1.25rem 0;
|
|
8
|
+
}
|
|
9
|
+
.tut-tabs-list {
|
|
10
|
+
display: flex;
|
|
11
|
+
gap: 0;
|
|
12
|
+
margin: 0;
|
|
13
|
+
padding: 0;
|
|
14
|
+
border-bottom: var(--border-default) solid var(--color-border);
|
|
15
|
+
}
|
|
16
|
+
.tut-tabs-trigger {
|
|
17
|
+
padding: 0.55rem 1.1rem;
|
|
18
|
+
/* Inactive tab: clearly visible chip in the secondary surface tier. */
|
|
19
|
+
background: color-mix(in oklab, var(--color-surface) 75%, var(--color-bg));
|
|
20
|
+
border: 0;
|
|
21
|
+
color: var(--color-muted);
|
|
22
|
+
font: inherit;
|
|
23
|
+
font-size: 0.85em;
|
|
24
|
+
font-weight: 500;
|
|
25
|
+
cursor: pointer;
|
|
26
|
+
border-radius: 0;
|
|
27
|
+
margin-bottom: -1px;
|
|
28
|
+
/* Tabs share edges — every trigger draws top/right/bottom; the first
|
|
29
|
+
* one also gets a left border. Adjacent edges collapse to one line. */
|
|
30
|
+
border-top: var(--border-default) solid var(--color-border);
|
|
31
|
+
border-right: var(--border-default) solid var(--color-border);
|
|
32
|
+
border-bottom: var(--border-default) solid var(--color-border);
|
|
33
|
+
transition: color 0.12s ease, background 0.12s ease, border-color 0.12s ease;
|
|
34
|
+
}
|
|
35
|
+
.tut-tabs-trigger:first-child {
|
|
36
|
+
border-left: var(--border-default) solid var(--color-border);
|
|
37
|
+
}
|
|
38
|
+
.tut-tabs-trigger:hover {
|
|
39
|
+
color: var(--color-fg);
|
|
40
|
+
background: var(--color-surface);
|
|
41
|
+
}
|
|
42
|
+
.tut-tabs-trigger[data-active="true"] {
|
|
43
|
+
color: var(--color-fg);
|
|
44
|
+
font-weight: 600;
|
|
45
|
+
/* Lifted bg — distinct from the content panel below. */
|
|
46
|
+
background: var(--color-surface-2);
|
|
47
|
+
border-top: var(--border-thick) solid var(--color-accent);
|
|
48
|
+
/* Drop the bottom border so the active tab opens into the panel. */
|
|
49
|
+
border-bottom-color: transparent;
|
|
50
|
+
}
|
|
51
|
+
.tut-tabs-content {
|
|
52
|
+
background: var(--color-surface);
|
|
53
|
+
padding: 0.95rem 1.1rem;
|
|
54
|
+
border-left: var(--border-default) solid var(--color-border);
|
|
55
|
+
border-right: var(--border-default) solid var(--color-border);
|
|
56
|
+
border-bottom: var(--border-default) solid var(--color-border);
|
|
57
|
+
}
|
|
58
|
+
.tut-tab-panel[hidden] { display: none; }
|
|
59
|
+
.tut-tab-panel > :first-child { margin-top: 0; }
|
|
60
|
+
.tut-tab-panel > :last-child { margin-bottom: 0; }
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/* Terminal */
|
|
2
|
+
.term {
|
|
3
|
+
margin: 1.25rem 0;
|
|
4
|
+
background: var(--color-surface);
|
|
5
|
+
overflow: hidden;
|
|
6
|
+
position: relative;
|
|
7
|
+
border-radius: 0;
|
|
8
|
+
border: var(--border-default) solid var(--color-border);
|
|
9
|
+
}
|
|
10
|
+
.term-bar {
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
gap: 0.5rem;
|
|
14
|
+
padding: 0.45rem 0.75rem;
|
|
15
|
+
background: var(--color-surface-2);
|
|
16
|
+
font-family: var(--font-mono);
|
|
17
|
+
font-size: 0.72em;
|
|
18
|
+
color: var(--color-muted);
|
|
19
|
+
}
|
|
20
|
+
.term-dots { display: inline-flex; gap: 0.3rem; }
|
|
21
|
+
.term-dots span {
|
|
22
|
+
width: 10px; height: 10px; border-radius: 50%;
|
|
23
|
+
background: var(--color-border-strong);
|
|
24
|
+
display: inline-block;
|
|
25
|
+
}
|
|
26
|
+
.term-dots span:nth-child(1) { background: oklch(60% 0.22 25); }
|
|
27
|
+
.term-dots span:nth-child(2) { background: oklch(75% 0.16 75); }
|
|
28
|
+
.term-dots span:nth-child(3) { background: oklch(70% 0.18 145); }
|
|
29
|
+
.term-body {
|
|
30
|
+
margin: 0;
|
|
31
|
+
padding: 0.85rem 1rem;
|
|
32
|
+
color: var(--color-fg);
|
|
33
|
+
font-family: var(--font-mono);
|
|
34
|
+
font-size: 0.85em;
|
|
35
|
+
line-height: 1.55;
|
|
36
|
+
background: transparent;
|
|
37
|
+
border: 0;
|
|
38
|
+
overflow-x: auto;
|
|
39
|
+
}
|
|
40
|
+
.term-line { display: flex; gap: 0.5rem; }
|
|
41
|
+
.term-prompt { color: var(--color-accent); user-select: none; }
|
|
42
|
+
.term-out { color: var(--color-muted); white-space: pre-wrap; }
|
|
43
|
+
.term-run {
|
|
44
|
+
position: absolute;
|
|
45
|
+
top: 0.4rem;
|
|
46
|
+
right: 0.5rem;
|
|
47
|
+
background: var(--color-accent);
|
|
48
|
+
color: var(--color-accent-fg);
|
|
49
|
+
border: 0;
|
|
50
|
+
padding: 0.25rem 0.6rem;
|
|
51
|
+
font-family: var(--font-mono);
|
|
52
|
+
font-size: 0.72em;
|
|
53
|
+
cursor: pointer;
|
|
54
|
+
border-radius: 0;
|
|
55
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/* Component styles for React islands + MDX components.
|
|
2
|
+
*
|
|
3
|
+
* Each feature lives in its own file under ./components/. Imports are
|
|
4
|
+
* ordered so cross-cutting rules (Expressive Code overrides, modal
|
|
5
|
+
* helpers, a11y utilities) come before component-specific stylesheets.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/* Cross-cutting + utilities */
|
|
9
|
+
@import "./components/expressive-code.css";
|
|
10
|
+
@import "./components/a11y.css";
|
|
11
|
+
@import "./components/modal.css";
|
|
12
|
+
|
|
13
|
+
/* Site chrome */
|
|
14
|
+
@import "./components/progress.css";
|
|
15
|
+
|
|
16
|
+
/* AI assistant */
|
|
17
|
+
@import "./components/chat.css";
|
|
18
|
+
@import "./components/byok.css";
|
|
19
|
+
|
|
20
|
+
/* MDX components */
|
|
21
|
+
@import "./components/tabs.css";
|
|
22
|
+
@import "./components/filetree.css";
|
|
23
|
+
@import "./components/reveal.css";
|
|
24
|
+
@import "./components/terminal.css";
|
|
25
|
+
@import "./components/mermaid.css";
|
|
26
|
+
@import "./components/diff.css";
|
|
27
|
+
@import "./components/quiz.css";
|
|
28
|
+
@import "./components/checkpoint.css";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Handzon framework styles. Consumers should chain this with their own
|
|
3
|
+
* theme tokens:
|
|
4
|
+
*
|
|
5
|
+
* @import "handzon-core/styles/global.css";
|
|
6
|
+
* @import "./themes/<chosen>.css";
|
|
7
|
+
*
|
|
8
|
+
* Theme tokens (--color-*, --font-*, --border-*, --shadow-*) are NOT
|
|
9
|
+
* provided here — they live in user-owned `src/styles/themes/*.css` so
|
|
10
|
+
* the scaffold can pick or override them without ejecting the framework.
|
|
11
|
+
*/
|
|
12
|
+
@import "tailwindcss";
|
|
13
|
+
|
|
14
|
+
@import "./base.css";
|
|
15
|
+
@import "./components.css";
|