@screenbook/ui 0.0.1 → 1.0.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/dist/client/_astro/coverage.BnE2oGo8.css +1 -0
  3. package/dist/client/_astro/coverage.Cb0pX2ic.css +1 -0
  4. package/dist/client/_astro/graph.astro_astro_type_script_index_0_lang.B0fEnVdy.js +1 -0
  5. package/dist/server/_@astrojs-ssr-adapter.mjs +1 -1
  6. package/dist/server/chunks/{_@astrojs-ssr-adapter_DgsYudHz.mjs → _@astrojs-ssr-adapter_BCPoO8PO.mjs} +1 -1
  7. package/dist/server/chunks/{astro-designed-error-pages_BvPhMmw0.mjs → astro-designed-error-pages_7IL58RLD.mjs} +2 -2
  8. package/dist/server/chunks/{impactAnalysis_Bz5lMdmy.mjs → impactAnalysis_LvYEc57d.mjs} +11 -4
  9. package/dist/server/chunks/loadScreens_JhK3F9tC.mjs +39 -0
  10. package/dist/server/chunks/{node_DoTkMCOi.mjs → node_u1SigWFL.mjs} +5 -5
  11. package/dist/server/chunks/{sharp_DHNfMLYY.mjs → sharp_ADxfwDJE.mjs} +1 -1
  12. package/dist/server/entry.mjs +5 -5
  13. package/dist/server/manifest_C21e-QyV.mjs +101 -0
  14. package/dist/server/pages/_image.astro.mjs +1 -1
  15. package/dist/server/pages/coverage.astro.mjs +8 -8
  16. package/dist/server/pages/graph.astro.mjs +8 -8
  17. package/dist/server/pages/impact.astro.mjs +10 -10
  18. package/dist/server/pages/index.astro.mjs +5 -5
  19. package/dist/server/pages/screen/_id_.astro.mjs +9 -9
  20. package/package.json +41 -41
  21. package/src/layouts/Layout.astro +28 -11
  22. package/src/pages/coverage.astro +6 -6
  23. package/src/pages/graph.astro +16 -12
  24. package/src/pages/impact.astro +12 -9
  25. package/src/pages/index.astro +18 -9
  26. package/src/pages/screen/[id].astro +6 -6
  27. package/src/styles/global.css +55 -13
  28. package/src/utils/impactAnalysis.ts +12 -5
  29. package/.astro/data-store.json +0 -1
  30. package/.astro/settings.json +0 -5
  31. package/.screenbook/coverage.json +0 -37
  32. package/.screenbook/screens.json +0 -90
  33. package/LICENSE +0 -21
  34. package/dist/client/_astro/coverage.CKIVg4LY.css +0 -1
  35. package/dist/client/_astro/coverage.DDJMzKCq.css +0 -1
  36. package/dist/client/_astro/graph.astro_astro_type_script_index_0_lang.1HlATQ1g.js +0 -1
  37. package/dist/server/chunks/loadScreens_DJf-tycc.mjs +0 -39
  38. package/dist/server/manifest_-V1HEnR8.mjs +0 -101
@@ -36,7 +36,7 @@ if (apiQuery && screens.length > 0) {
36
36
 
37
37
  {screens.length === 0 ? (
38
38
  <div class="empty-state">
39
- <svg class="empty-state-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
39
+ <svg class="empty-state-icon" aria-hidden="true" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
40
40
  <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" />
41
41
  </svg>
42
42
  <h2 class="empty-state-title">No screen data</h2>
@@ -50,13 +50,15 @@ if (apiQuery && screens.length > 0) {
50
50
  ) : (
51
51
  <>
52
52
  <div class="impact-search">
53
- <form method="get" class="search-form">
53
+ <form method="get" class="search-form" role="search">
54
54
  <div class="search-wrapper impact-search-wrapper">
55
- <svg class="search-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
55
+ <svg class="search-icon" aria-hidden="true" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
56
56
  <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" />
57
57
  </svg>
58
+ <label for="api-input" class="sr-only">API name to analyze</label>
58
59
  <input
59
60
  type="text"
61
+ id="api-input"
60
62
  name="api"
61
63
  class="search-input"
62
64
  placeholder="Enter API name (e.g., InvoiceAPI.getDetail)"
@@ -113,8 +115,9 @@ if (apiQuery && screens.length > 0) {
113
115
  id="copy-markdown"
114
116
  class="copy-button"
115
117
  data-markdown={markdown}
118
+ aria-label="Copy impact analysis as Markdown"
116
119
  >
117
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
120
+ <svg aria-hidden="true" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
118
121
  <path stroke-linecap="round" stroke-linejoin="round" d="M15.666 3.888A2.25 2.25 0 0013.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 01-.75.75H9a.75.75 0 01-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 01-2.25 2.25H6.75A2.25 2.25 0 014.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 011.927-.184" />
119
122
  </svg>
120
123
  Copy as Markdown
@@ -123,16 +126,16 @@ if (apiQuery && screens.length > 0) {
123
126
 
124
127
  {result.totalCount === 0 ? (
125
128
  <div class="no-impact">
126
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
129
+ <svg aria-hidden="true" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
127
130
  <path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
128
131
  </svg>
129
132
  <p>No screens depend on <code>{apiQuery}</code></p>
130
133
  </div>
131
134
  ) : (
132
135
  <>
133
- <div class="impact-graph">
136
+ <div class="impact-graph" role="img" aria-label={`Impact analysis graph showing ${result.direct.length} direct and ${result.transitive.length} transitive dependencies for ${apiQuery}`}>
134
137
  <div class="graph-container">
135
- <pre class="mermaid">{mermaidGraph}</pre>
138
+ <pre class="mermaid" aria-hidden="true">{mermaidGraph}</pre>
136
139
  </div>
137
140
  <div class="graph-legend">
138
141
  <div class="graph-legend-item">
@@ -154,7 +157,7 @@ if (apiQuery && screens.length > 0) {
154
157
  {result.direct.length > 0 && (
155
158
  <div class="section">
156
159
  <h3 class="section-title">
157
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
160
+ <svg aria-hidden="true" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
158
161
  <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" />
159
162
  </svg>
160
163
  Direct Dependencies ({result.direct.length})
@@ -180,7 +183,7 @@ if (apiQuery && screens.length > 0) {
180
183
  {result.transitive.length > 0 && (
181
184
  <div class="section">
182
185
  <h3 class="section-title">
183
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
186
+ <svg aria-hidden="true" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
184
187
  <path stroke-linecap="round" stroke-linejoin="round" d="M7.5 21L3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5" />
185
188
  </svg>
186
189
  Transitive Dependencies ({result.transitive.length})
@@ -17,7 +17,7 @@ const allTags = [...new Set(screens.flatMap((s) => s.tags ?? []))]
17
17
 
18
18
  {screens.length === 0 ? (
19
19
  <div class="empty-state">
20
- <svg class="empty-state-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
20
+ <svg class="empty-state-icon" aria-hidden="true" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
21
21
  <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" />
22
22
  </svg>
23
23
  <h2 class="empty-state-title">No screens found</h2>
@@ -62,9 +62,10 @@ const allTags = [...new Set(screens.flatMap((s) => s.tags ?? []))]
62
62
  ) : (
63
63
  <>
64
64
  <div class="search-wrapper">
65
- <svg class="search-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
65
+ <svg class="search-icon" aria-hidden="true" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
66
66
  <path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
67
67
  </svg>
68
+ <label for="search" class="sr-only">Search screens</label>
68
69
  <input
69
70
  type="text"
70
71
  id="search"
@@ -74,14 +75,15 @@ const allTags = [...new Set(screens.flatMap((s) => s.tags ?? []))]
74
75
  </div>
75
76
 
76
77
  {allTags.length > 0 && (
77
- <div class="tags">
78
+ <div class="tags" role="group" aria-label="Filter by tag">
78
79
  {allTags.map((tag) => (
79
- <button class="tag" data-tag={tag}>{tag}</button>
80
+ <button class="tag" data-tag={tag} aria-pressed="false">{tag}</button>
80
81
  ))}
81
82
  </div>
82
83
  )}
83
84
 
84
- <div class="screen-grid" id="screen-list">
85
+ <h2 class="sr-only">All Screens</h2>
86
+ <div class="screen-grid" id="screen-list" aria-live="polite">
85
87
  {screens.map((screen) => (
86
88
  <a
87
89
  href={`/screen/${screen.id}`}
@@ -95,14 +97,14 @@ const allTags = [...new Set(screens.flatMap((s) => s.tags ?? []))]
95
97
  <div class="card-route">{screen.route}</div>
96
98
  <div class="card-meta">
97
99
  <span class="card-meta-item">
98
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
100
+ <svg aria-hidden="true" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
99
101
  <path stroke-linecap="round" stroke-linejoin="round" d="M5.25 8.25h15m-16.5 7.5h15m-1.8-13.5l-3.9 19.5m-2.1-19.5l-3.9 19.5" />
100
102
  </svg>
101
103
  {screen.id}
102
104
  </span>
103
105
  {screen.owner && screen.owner.length > 0 && (
104
106
  <span class="card-meta-item">
105
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
107
+ <svg aria-hidden="true" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
106
108
  <path stroke-linecap="round" stroke-linejoin="round" d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z" />
107
109
  </svg>
108
110
  {screen.owner.join(", ")}
@@ -154,11 +156,18 @@ const allTags = [...new Set(screens.flatMap((s) => s.tags ?? []))]
154
156
  const tag = (btn as HTMLElement).dataset.tag
155
157
  if (activeTag === tag) {
156
158
  activeTag = null
157
- tagButtons.forEach((b) => b.classList.remove("active"))
159
+ tagButtons.forEach((b) => {
160
+ b.classList.remove("active")
161
+ b.setAttribute("aria-pressed", "false")
162
+ })
158
163
  } else {
159
- tagButtons.forEach((b) => b.classList.remove("active"))
164
+ tagButtons.forEach((b) => {
165
+ b.classList.remove("active")
166
+ b.setAttribute("aria-pressed", "false")
167
+ })
160
168
  activeTag = tag ?? null
161
169
  btn.classList.add("active")
170
+ btn.setAttribute("aria-pressed", "true")
162
171
  }
163
172
  filterScreens()
164
173
  })
@@ -28,7 +28,7 @@ const nextScreens = screens.filter((s) => screen.next?.includes(s.id))
28
28
  <Layout title={screen.title}>
29
29
  <div class="container">
30
30
  <a href="/" class="back-link">
31
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
31
+ <svg aria-hidden="true" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
32
32
  <path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18" />
33
33
  </svg>
34
34
  Back to screens
@@ -37,7 +37,7 @@ const nextScreens = screens.filter((s) => screen.next?.includes(s.id))
37
37
  <div class="detail-header">
38
38
  <h1 class="detail-title">{screen.title}</h1>
39
39
  <div class="detail-route">
40
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
40
+ <svg aria-hidden="true" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
41
41
  <path stroke-linecap="round" stroke-linejoin="round" d="M13.19 8.688a4.5 4.5 0 011.242 7.244l-4.5 4.5a4.5 4.5 0 01-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 00-6.364-6.364l-4.5 4.5a4.5 4.5 0 001.242 7.244" />
42
42
  </svg>
43
43
  {screen.route}
@@ -92,7 +92,7 @@ const nextScreens = screens.filter((s) => screen.next?.includes(s.id))
92
92
  return (
93
93
  <a href={`/impact?api=${encodeURIComponent(dep)}`} class="dep-item dep-item-link">
94
94
  <div class="dep-item-main">
95
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
95
+ <svg aria-hidden="true" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
96
96
  <path stroke-linecap="round" stroke-linejoin="round" d="M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5" />
97
97
  </svg>
98
98
  <span>{dep}</span>
@@ -119,7 +119,7 @@ const nextScreens = screens.filter((s) => screen.next?.includes(s.id))
119
119
  <div class="dep-list">
120
120
  {screen.links.map((link) => (
121
121
  <a href={link.url} target="_blank" rel="noopener noreferrer" class="dep-item">
122
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
122
+ <svg aria-hidden="true" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
123
123
  <path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25" />
124
124
  </svg>
125
125
  {link.label}
@@ -135,7 +135,7 @@ const nextScreens = screens.filter((s) => screen.next?.includes(s.id))
135
135
  {entryScreens.length > 0 && (
136
136
  <div class="sidebar-card">
137
137
  <h3 class="sidebar-card-title">
138
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
138
+ <svg aria-hidden="true" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
139
139
  <path stroke-linecap="round" stroke-linejoin="round" d="M9 15L3 9m0 0l6-6M3 9h12a6 6 0 010 12h-3" />
140
140
  </svg>
141
141
  Entry Points
@@ -160,7 +160,7 @@ const nextScreens = screens.filter((s) => screen.next?.includes(s.id))
160
160
  {nextScreens.length > 0 && (
161
161
  <div class="sidebar-card">
162
162
  <h3 class="sidebar-card-title">
163
- <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
163
+ <svg aria-hidden="true" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
164
164
  <path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3" />
165
165
  </svg>
166
166
  Next Screens
@@ -15,7 +15,7 @@
15
15
 
16
16
  --color-text: #eeeeee;
17
17
  --color-text-secondary: #a0a0a0;
18
- --color-text-muted: #707070;
18
+ --color-text-muted: #8a8a8a;
19
19
 
20
20
  /* Accent - Subtle Teal */
21
21
  --color-accent: #5eead4;
@@ -823,30 +823,30 @@ code {
823
823
 
824
824
  /* Mermaid */
825
825
  .mermaid {
826
- background: transparent !important;
826
+ background: transparent;
827
827
  }
828
828
 
829
829
  .mermaid .node rect {
830
- fill: var(--color-bg-muted) !important;
831
- stroke: var(--color-border-hover) !important;
832
- stroke-width: 1px !important;
833
- rx: 6px !important;
830
+ fill: var(--color-bg-muted);
831
+ stroke: var(--color-border-hover);
832
+ stroke-width: 1px;
833
+ rx: 6px;
834
834
  }
835
835
 
836
836
  .mermaid .nodeLabel {
837
- color: var(--color-text) !important;
838
- font-family: system-ui, sans-serif !important;
839
- font-size: 13px !important;
837
+ color: var(--color-text);
838
+ font-family: system-ui, sans-serif;
839
+ font-size: 13px;
840
840
  }
841
841
 
842
842
  .mermaid .edgePath .path {
843
- stroke: var(--color-accent) !important;
844
- stroke-width: 1.5px !important;
843
+ stroke: var(--color-accent);
844
+ stroke-width: 1.5px;
845
845
  }
846
846
 
847
847
  .mermaid .edgeLabel {
848
- background: var(--color-bg) !important;
849
- color: var(--color-text-muted) !important;
848
+ background: var(--color-bg);
849
+ color: var(--color-text-muted);
850
850
  }
851
851
 
852
852
  /* Utility */
@@ -860,3 +860,45 @@ code {
860
860
  clip: rect(0, 0, 0, 0);
861
861
  border: 0;
862
862
  }
863
+
864
+ /* Skip Link */
865
+ .skip-link {
866
+ position: absolute;
867
+ top: -100%;
868
+ left: 16px;
869
+ z-index: 1000;
870
+ padding: 12px 24px;
871
+ background: var(--color-accent);
872
+ color: var(--color-bg);
873
+ font-weight: 600;
874
+ font-size: var(--text-sm);
875
+ border-radius: var(--radius-md);
876
+ text-decoration: none;
877
+ transition: top 0.2s ease;
878
+ }
879
+
880
+ .skip-link:focus {
881
+ top: 16px;
882
+ outline: none;
883
+ }
884
+
885
+ /* Focus Styles */
886
+ :focus-visible {
887
+ outline: 2px solid var(--color-accent);
888
+ outline-offset: 2px;
889
+ }
890
+
891
+ /* Remove outline for mouse clicks, keep for keyboard */
892
+ :focus:not(:focus-visible) {
893
+ outline: none;
894
+ }
895
+
896
+ /* Ensure buttons and links have visible focus */
897
+ a:focus-visible,
898
+ button:focus-visible,
899
+ input:focus-visible,
900
+ select:focus-visible,
901
+ textarea:focus-visible {
902
+ outline: 2px solid var(--color-accent);
903
+ outline-offset: 2px;
904
+ }
@@ -50,7 +50,7 @@ function buildNavigationGraph(screens: Screen[]): Map<string, Set<string>> {
50
50
  graph.set(screen.id, new Set())
51
51
  }
52
52
  for (const nextId of screen.next) {
53
- graph.get(screen.id)!.add(nextId)
53
+ graph.get(screen.id)?.add(nextId)
54
54
  }
55
55
  }
56
56
 
@@ -72,7 +72,8 @@ function findPathToDirectDependent(
72
72
  const localVisited = new Set<string>([startId])
73
73
 
74
74
  while (queue.length > 0) {
75
- const current = queue.shift()!
75
+ const current = queue.shift()
76
+ if (!current) break
76
77
 
77
78
  if (current.path.length > maxDepth + 1) {
78
79
  continue
@@ -205,9 +206,15 @@ export function generateImpactMermaid(
205
206
  const lines: string[] = ["flowchart TD"]
206
207
 
207
208
  // Define styles - high contrast colors with readable text
208
- lines.push(" classDef direct fill:#dc2626,stroke:#fef2f2,color:#ffffff,stroke-width:3px,font-weight:bold")
209
- lines.push(" classDef transitive fill:#ea580c,stroke:#fff7ed,color:#ffffff,stroke-width:3px,font-weight:bold")
210
- lines.push(" classDef normal fill:#1e293b,stroke:#64748b,color:#e2e8f0,stroke-width:1px")
209
+ lines.push(
210
+ " classDef direct fill:#dc2626,stroke:#fef2f2,color:#ffffff,stroke-width:3px,font-weight:bold",
211
+ )
212
+ lines.push(
213
+ " classDef transitive fill:#ea580c,stroke:#fff7ed,color:#ffffff,stroke-width:3px,font-weight:bold",
214
+ )
215
+ lines.push(
216
+ " classDef normal fill:#1e293b,stroke:#64748b,color:#e2e8f0,stroke-width:1px",
217
+ )
211
218
 
212
219
  // Add nodes
213
220
  for (const screen of screens) {
@@ -1 +0,0 @@
1
- [["Map",1,2],"meta::meta",["Map",3,4,5,6],"astro-version","5.16.6","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"server\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":false,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\",\"entrypoint\":\"astro/assets/endpoint/dev\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[],\"responsiveStyles\":false},\"devToolbar\":{\"enabled\":false},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true,\"allowedDomains\":[]},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false,\"liveContentCollections\":false,\"csp\":false,\"staticImportMetaEnv\":false,\"chromeDevtoolsWorkspace\":false,\"failOnPrerenderConflict\":false,\"svgo\":false},\"legacy\":{\"collections\":false},\"session\":{\"driver\":\"fs-lite\",\"options\":{\"base\":\"/Users/wadakatu/www/experiments/screenbook/packages/ui/node_modules/.astro/sessions\"}}}"]
@@ -1,5 +0,0 @@
1
- {
2
- "_variables": {
3
- "lastUpdateCheck": 1766834752420
4
- }
5
- }
@@ -1,37 +0,0 @@
1
- {
2
- "total": 5,
3
- "covered": 5,
4
- "percentage": 100,
5
- "missing": [],
6
- "byOwner": {
7
- "platform": {
8
- "count": 2,
9
- "screens": [
10
- "dashboard",
11
- "home"
12
- ]
13
- },
14
- "unassigned": {
15
- "count": 1,
16
- "screens": [
17
- "settings"
18
- ]
19
- },
20
- "billing": {
21
- "count": 2,
22
- "screens": [
23
- "billing.invoices",
24
- "billing.payments"
25
- ]
26
- }
27
- },
28
- "byTag": {
29
- "dashboard": 1,
30
- "analytics": 1,
31
- "landing": 1,
32
- "billing": 2,
33
- "invoices": 1,
34
- "payments": 1
35
- },
36
- "timestamp": "2025-12-27T13:39:10.210Z"
37
- }
@@ -1,90 +0,0 @@
1
- [
2
- {
3
- "id": "dashboard",
4
- "title": "Dashboard",
5
- "route": "/dashboard",
6
- "owner": [
7
- "platform"
8
- ],
9
- "tags": [
10
- "dashboard",
11
- "analytics"
12
- ],
13
- "dependsOn": [
14
- "MetricsAPI.getSummary",
15
- "UserAPI.getProfile"
16
- ],
17
- "entryPoints": [
18
- "home"
19
- ],
20
- "next": [
21
- "billing.invoices",
22
- "billing.payments",
23
- "settings"
24
- ],
25
- "description": "Main dashboard with key metrics and quick actions"
26
- },
27
- {
28
- "id": "settings",
29
- "title": "Settings",
30
- "route": "/settings"
31
- },
32
- {
33
- "id": "home",
34
- "title": "Home",
35
- "route": "/",
36
- "owner": [
37
- "platform"
38
- ],
39
- "tags": [
40
- "landing"
41
- ],
42
- "next": [
43
- "dashboard"
44
- ],
45
- "description": "The main landing page"
46
- },
47
- {
48
- "id": "billing.invoices",
49
- "title": "Invoices",
50
- "route": "/billing/invoices",
51
- "owner": [
52
- "billing"
53
- ],
54
- "tags": [
55
- "billing",
56
- "invoices"
57
- ],
58
- "dependsOn": [
59
- "BillingAPI.listInvoices"
60
- ],
61
- "entryPoints": [
62
- "dashboard"
63
- ],
64
- "next": [
65
- "billing.payments"
66
- ],
67
- "description": "List of all invoices"
68
- },
69
- {
70
- "id": "billing.payments",
71
- "title": "Payments",
72
- "route": "/billing/payments",
73
- "owner": [
74
- "billing"
75
- ],
76
- "tags": [
77
- "billing",
78
- "payments"
79
- ],
80
- "dependsOn": [
81
- "BillingAPI.listPayments",
82
- "BillingAPI.getPaymentMethods"
83
- ],
84
- "entryPoints": [
85
- "dashboard",
86
- "billing.invoices"
87
- ],
88
- "description": "Payment history and methods"
89
- }
90
- ]
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Screenbook Contributors
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1 +0,0 @@
1
- .coverage-hero[data-astro-cid-vq7rje7m]{display:flex;gap:32px;align-items:center;margin-bottom:48px}.coverage-percentage[data-astro-cid-vq7rje7m]{display:flex;flex-direction:column;align-items:center;justify-content:center;width:180px;height:180px;border-radius:50%;border:3px solid;flex-shrink:0}.percentage-value[data-astro-cid-vq7rje7m]{font-size:3.5rem;font-weight:700;line-height:1}.percentage-label[data-astro-cid-vq7rje7m]{font-size:var(--text-sm);color:var(--color-text-muted);margin-top:4px}.coverage-stats[data-astro-cid-vq7rje7m]{display:flex;gap:24px;flex-wrap:wrap}.stat-card[data-astro-cid-vq7rje7m]{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:24px 32px;text-align:center;min-width:120px}.stat-value[data-astro-cid-vq7rje7m]{font-size:var(--text-3xl);font-weight:700;color:var(--color-text)}.stat-label[data-astro-cid-vq7rje7m]{font-size:var(--text-sm);color:var(--color-text-muted);margin-top:4px}.coverage-grid[data-astro-cid-vq7rje7m]{display:grid;grid-template-columns:repeat(auto-fit,minmax(350px,1fr));gap:32px;margin-bottom:48px}.coverage-section[data-astro-cid-vq7rje7m]{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:24px}.section-title[data-astro-cid-vq7rje7m]{display:flex;align-items:center;gap:10px;font-size:var(--text-lg);font-weight:600;margin-bottom:20px;color:var(--color-text)}.section-title[data-astro-cid-vq7rje7m] svg[data-astro-cid-vq7rje7m]{width:20px;height:20px;color:var(--color-accent)}.section-description[data-astro-cid-vq7rje7m]{font-size:var(--text-sm);color:var(--color-text-muted);margin-bottom:16px}.owner-list[data-astro-cid-vq7rje7m]{display:flex;flex-direction:column;gap:16px}.owner-item[data-astro-cid-vq7rje7m]{display:flex;flex-direction:column;gap:8px}.owner-info[data-astro-cid-vq7rje7m]{display:flex;justify-content:space-between;align-items:center}.owner-name[data-astro-cid-vq7rje7m]{font-size:var(--text-sm);font-weight:500;color:var(--color-text)}.owner-count[data-astro-cid-vq7rje7m]{font-size:var(--text-xs);color:var(--color-text-muted)}.owner-bar[data-astro-cid-vq7rje7m]{height:8px;background:var(--color-bg-muted);border-radius:4px;overflow:hidden}.owner-bar-fill[data-astro-cid-vq7rje7m]{height:100%;background:var(--color-accent);border-radius:4px;transition:width .3s ease}.tags-grid[data-astro-cid-vq7rje7m]{display:flex;flex-wrap:wrap;gap:8px}.tag-card[data-astro-cid-vq7rje7m]{display:flex;align-items:center;gap:8px;padding:8px 12px;background:var(--color-bg-muted);border-radius:var(--radius-md);text-decoration:none;transition:background .15s ease}.tag-card[data-astro-cid-vq7rje7m]:hover{background:var(--color-surface-hover)}.tag-name[data-astro-cid-vq7rje7m]{font-size:var(--text-sm);color:var(--color-text)}.tag-count[data-astro-cid-vq7rje7m]{font-size:var(--text-xs);color:var(--color-accent);font-weight:600;background:var(--color-accent-bg);padding:2px 6px;border-radius:4px}.missing-section[data-astro-cid-vq7rje7m]{grid-column:1 / -1}.missing-list[data-astro-cid-vq7rje7m]{display:flex;flex-direction:column;gap:12px}.missing-item[data-astro-cid-vq7rje7m]{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;background:var(--color-bg-muted);border-radius:var(--radius-md);border-left:3px solid var(--color-warning)}.missing-route[data-astro-cid-vq7rje7m]{display:flex;align-items:center;gap:10px;font-size:var(--text-sm);color:var(--color-text)}.missing-route[data-astro-cid-vq7rje7m] svg[data-astro-cid-vq7rje7m]{width:16px;height:16px;color:var(--color-text-muted)}.suggested-path[data-astro-cid-vq7rje7m]{font-size:var(--text-xs);color:var(--color-text-muted)}.coverage-footer[data-astro-cid-vq7rje7m]{text-align:center;padding-top:24px;border-top:1px solid var(--color-border)}.timestamp[data-astro-cid-vq7rje7m]{font-size:var(--text-xs);color:var(--color-text-muted)}@media(max-width:768px){.coverage-hero[data-astro-cid-vq7rje7m]{flex-direction:column;text-align:center}.coverage-stats[data-astro-cid-vq7rje7m]{justify-content:center}.missing-item[data-astro-cid-vq7rje7m]{flex-direction:column;align-items:flex-start;gap:8px}}
@@ -1 +0,0 @@
1
- /*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-yellow-400:oklch(85.2% .199 91.936);--color-yellow-500:oklch(79.5% .184 86.047);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--text-xs:.75rem;--text-sm:.875rem;--text-base:1rem;--text-lg:1.125rem;--text-xl:1.25rem;--text-2xl:1.5rem;--text-3xl:2rem;--radius-sm:6px;--radius-md:8px;--radius-lg:12px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-bg:#111;--color-bg-muted:#222;--color-surface:#1a1a1a;--color-surface-hover:#252525;--color-border:#2e2e2e;--color-border-hover:#3a3a3a;--color-text:#eee;--color-text-secondary:#a0a0a0;--color-text-muted:#707070;--color-accent:#5eead4;--color-accent-hover:#99f6e4;--color-accent-bg:#5eead41a;--color-success:#4ade80;--color-warning:#fbbf24}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.block{display:block}.flex{display:flex}.hidden{display:none}.flex-shrink{flex-shrink:1}.flex-wrap{flex-wrap:wrap}.border{border-style:var(--tw-border-style);border-width:1px}.border-green-500\/30{border-color:#00c7584d}@supports (color:color-mix(in lab,red,red)){.border-green-500\/30{border-color:color-mix(in oklab,var(--color-green-500)30%,transparent)}}.border-red-500\/30{border-color:#fb2c364d}@supports (color:color-mix(in lab,red,red)){.border-red-500\/30{border-color:color-mix(in oklab,var(--color-red-500)30%,transparent)}}.border-yellow-500\/30{border-color:#edb2004d}@supports (color:color-mix(in lab,red,red)){.border-yellow-500\/30{border-color:color-mix(in oklab,var(--color-yellow-500)30%,transparent)}}.bg-green-500\/20{background-color:#00c75833}@supports (color:color-mix(in lab,red,red)){.bg-green-500\/20{background-color:color-mix(in oklab,var(--color-green-500)20%,transparent)}}.bg-red-500\/20{background-color:#fb2c3633}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/20{background-color:color-mix(in oklab,var(--color-red-500)20%,transparent)}}.bg-yellow-500\/20{background-color:#edb20033}@supports (color:color-mix(in lab,red,red)){.bg-yellow-500\/20{background-color:color-mix(in oklab,var(--color-yellow-500)20%,transparent)}}.text-green-400{color:var(--color-green-400)}.text-red-400{color:var(--color-red-400)}.text-yellow-400{color:var(--color-yellow-400)}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}}*{box-sizing:border-box;margin:0;padding:0}html{-webkit-font-smoothing:antialiased;scroll-behavior:smooth}body{background:var(--color-bg);color:var(--color-text);font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:var(--text-base);line-height:1.6}h1,h2,h3,h4{color:var(--color-text);font-weight:600;line-height:1.3}h1{font-size:var(--text-3xl)}h2{font-size:var(--text-2xl)}h3{font-size:var(--text-xl)}h4{font-size:var(--text-lg)}p{color:var(--color-text-secondary)}a{color:var(--color-accent);text-decoration:none}a:hover{color:var(--color-accent-hover)}code{background:var(--color-bg-muted);border-radius:var(--radius-sm);padding:.2em .4em;font-family:ui-monospace,SF Mono,Menlo,Monaco,monospace;font-size:.9em}::selection{background:#5eead433}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:4px}::-webkit-scrollbar-thumb:hover{background:var(--color-border-hover)}.container{max-width:1200px;margin:0 auto;padding:0 24px}.header{border-bottom:1px solid var(--color-border);background:var(--color-bg);z-index:100;padding:16px 0;position:sticky;top:0}.header-content{justify-content:space-between;align-items:center;gap:24px;display:flex}.logo{font-weight:600;font-size:var(--text-lg);color:var(--color-text);align-items:center;gap:10px;display:flex}.logo:hover{color:var(--color-text)}.logo-icon{width:28px;height:28px;color:var(--color-accent)}.nav{align-items:center;gap:4px;display:flex}.nav-link{font-size:var(--text-sm);color:var(--color-text-secondary);border-radius:var(--radius-md);align-items:center;gap:6px;padding:8px 14px;font-weight:500;transition:all .15s;display:flex}.nav-link:hover{color:var(--color-text);background:var(--color-surface-hover)}.nav-link.active{color:var(--color-accent);background:var(--color-accent-bg)}.nav-link svg{width:16px;height:16px}.page-header{padding:48px 0 32px}.page-title{margin-bottom:8px}.page-description{font-size:var(--text-lg);color:var(--color-text-muted);max-width:600px}.search-wrapper{max-width:400px;margin-bottom:32px;position:relative}.search-icon{width:18px;height:18px;color:var(--color-text-muted);pointer-events:none;position:absolute;top:50%;left:14px;transform:translateY(-50%)}.search-input{width:100%;font-size:var(--text-sm);color:var(--color-text);background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-md);outline:none;padding:10px 14px 10px 42px;transition:border-color .15s}.search-input::placeholder{color:var(--color-text-muted)}.search-input:focus{border-color:var(--color-accent)}.tags{flex-wrap:wrap;gap:8px;margin-bottom:32px;display:flex}.tag{font-size:var(--text-xs);color:var(--color-text-secondary);background:var(--color-surface);border:1px solid var(--color-border);cursor:pointer;border-radius:9999px;align-items:center;padding:5px 12px;font-weight:500;transition:all .15s;display:inline-flex}.tag:hover{border-color:var(--color-border-hover);color:var(--color-text)}.tag.active{background:var(--color-accent-bg);border-color:var(--color-accent);color:var(--color-accent)}.card{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:20px;transition:border-color .15s}.card-link{color:inherit;display:block}.card-link:hover{color:inherit}.card-link:hover .card{border-color:var(--color-border-hover)}.card-link:hover .card-title{color:var(--color-accent)}.card-title{font-size:var(--text-base);margin-bottom:4px;font-weight:600;transition:color .15s}.card-route{font-family:ui-monospace,monospace;font-size:var(--text-sm);color:var(--color-text-muted);margin-bottom:12px}.card-meta{font-size:var(--text-xs);color:var(--color-text-muted);flex-wrap:wrap;gap:12px;margin-bottom:12px;display:flex}.card-meta-item{align-items:center;gap:4px;display:flex}.card-meta-item svg{width:14px;height:14px}.card-tags{flex-wrap:wrap;gap:6px;display:flex}.card-tag{font-size:var(--text-xs);background:var(--color-bg-muted);color:var(--color-text-secondary);border-radius:4px;padding:3px 8px}.screen-grid{grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:16px;display:grid}.section{margin-bottom:32px}.section-title{font-size:var(--text-sm);color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.05em;border-bottom:1px solid var(--color-border);margin-bottom:16px;padding-bottom:8px;font-weight:600}.detail-header{border-bottom:1px solid var(--color-border);margin-bottom:32px;padding:32px 0}.detail-title{font-size:var(--text-2xl);margin-bottom:8px}.detail-route{font-family:ui-monospace,monospace;font-size:var(--text-sm);color:var(--color-accent);background:var(--color-accent-bg);border-radius:var(--radius-md);align-items:center;gap:8px;padding:6px 12px;display:inline-flex}.detail-route svg{width:16px;height:16px}.detail-content{grid-template-columns:1fr 320px;gap:48px;display:grid}@media(max-width:900px){.detail-content{grid-template-columns:1fr;gap:32px}}.info-list{flex-direction:column;gap:16px;display:flex}.info-item{gap:16px;display:flex}.info-label{width:100px;font-size:var(--text-sm);color:var(--color-text-muted);flex-shrink:0}.info-value{font-size:var(--text-sm);color:var(--color-text)}.dep-list{flex-direction:column;gap:8px;display:flex}.dep-item{background:var(--color-bg-muted);border-radius:var(--radius-md);font-family:ui-monospace,monospace;font-size:var(--text-sm);align-items:center;gap:10px;padding:10px 12px;display:flex}.dep-item svg{width:16px;height:16px;color:var(--color-text-muted)}.dep-item-link{color:inherit;justify-content:space-between;align-items:center;text-decoration:none;transition:all .15s;display:flex}.dep-item-link:hover{background:var(--color-surface-hover);color:inherit}.dep-item-main{align-items:center;gap:10px;display:flex}.dep-item-meta{align-items:center;gap:8px;display:flex}.dep-count{font-size:var(--text-xs);color:var(--color-text-muted);background:var(--color-bg);border-radius:var(--radius-sm);padding:2px 8px}.dep-arrow{width:14px;height:14px;color:var(--color-accent);opacity:0;transition:opacity .15s}.dep-item-link:hover .dep-arrow{opacity:1}.screen-link-list{flex-direction:column;gap:8px;display:flex}.screen-link{background:var(--color-bg-muted);border-radius:var(--radius-md);color:var(--color-text);justify-content:space-between;align-items:center;padding:12px;transition:background .15s;display:flex}.screen-link:hover{background:var(--color-surface-hover);color:var(--color-text)}.screen-link-info{flex-direction:column;gap:2px;display:flex}.screen-link-title{font-size:var(--text-sm);font-weight:500}.screen-link-id{font-size:var(--text-xs);color:var(--color-text-muted);font-family:ui-monospace,monospace}.screen-link-arrow{width:16px;height:16px;color:var(--color-text-muted)}.sidebar-card{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);margin-bottom:16px;padding:20px}.sidebar-card-title{font-size:var(--text-sm);color:var(--color-text-muted);align-items:center;gap:8px;margin-bottom:16px;font-weight:600;display:flex}.sidebar-card-title svg{width:16px;height:16px}.graph-container{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);justify-content:center;align-items:center;min-height:400px;padding:32px;display:flex}.graph-legend{font-size:var(--text-sm);color:var(--color-text-muted);justify-content:center;gap:32px;margin-top:24px;display:flex}.graph-legend-item{align-items:center;gap:8px;display:flex}.legend-node{background:var(--color-bg-muted);border:1px solid var(--color-border-hover);border-radius:4px;width:32px;height:20px}.legend-edge{background:var(--color-accent);width:32px;height:2px}.empty-state{text-align:center;max-width:400px;margin:0 auto;padding:64px 24px}.empty-state-icon{width:48px;height:48px;color:var(--color-text-muted);margin:0 auto 16px}.empty-state-title{font-size:var(--text-lg);margin-bottom:8px}.empty-state-description{color:var(--color-text-muted);margin-bottom:24px}.empty-state-code{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-md);font-family:ui-monospace,monospace;font-size:var(--text-sm);align-items:center;gap:8px;padding:12px 20px;display:inline-flex}.empty-state-code .prompt{color:var(--color-text-muted)}.empty-state-steps{text-align:left;flex-direction:column;gap:16px;margin:32px 0;display:flex}.empty-state-step{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-md);align-items:flex-start;gap:16px;padding:16px;display:flex}.step-number{background:var(--color-accent-bg);width:28px;height:28px;color:var(--color-accent);font-size:var(--text-sm);border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;font-weight:600;display:flex}.step-content{flex:1}.step-title{font-size:var(--text-sm);color:var(--color-text);margin-bottom:4px}.step-code{font-family:ui-monospace,monospace;font-size:var(--text-sm);color:var(--color-text-secondary);background:var(--color-bg);border-radius:var(--radius-sm);padding:4px 8px}.empty-state-features{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-md);text-align:left;margin-top:32px;padding:20px}.features-title{font-size:var(--text-sm);color:var(--color-text);margin-bottom:12px;font-weight:500}.features-list{margin:0;padding:0;list-style:none}.features-list li{font-size:var(--text-sm);color:var(--color-text-secondary);padding:6px 0 6px 20px;position:relative}.features-list li:before{content:"";background:var(--color-accent);border-radius:50%;width:6px;height:6px;position:absolute;top:12px;left:0}.back-link{font-size:var(--text-sm);color:var(--color-text-muted);align-items:center;gap:6px;margin-bottom:24px;display:inline-flex}.back-link:hover{color:var(--color-text)}.back-link svg{width:16px;height:16px}.stats{gap:24px;display:flex}.stat{text-align:center}.stat-value{font-size:var(--text-2xl);color:var(--color-text);font-weight:600}.stat-label{font-size:var(--text-xs);color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.05em}.mermaid{background:0 0!important}.mermaid .node rect{fill:var(--color-bg-muted)!important;stroke:var(--color-border-hover)!important;stroke-width:1px!important;rx:6px!important}.mermaid .nodeLabel{color:var(--color-text)!important;font-family:system-ui,sans-serif!important;font-size:13px!important}.mermaid .edgePath .path{stroke:var(--color-accent)!important;stroke-width:1.5px!important}.mermaid .edgeLabel{background:var(--color-bg)!important;color:var(--color-text-muted)!important}.sr-only{clip:rect(0,0,0,0);border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}
@@ -1 +0,0 @@
1
- import{m as c}from"./mermaid.core.CReXU7YN.js";const m={startOnLoad:!1,theme:"dark",themeVariables:{darkMode:!0,background:"transparent",primaryColor:"#222222",primaryBorderColor:"#3a3a3a",primaryTextColor:"#eeeeee",lineColor:"#5eead4",fontFamily:"system-ui, sans-serif"},flowchart:{useMaxWidth:!0,htmlLabels:!0,curve:"basis",padding:20,nodeSpacing:50,rankSpacing:60}};c.initialize(m);async function g(){const e=document.querySelectorAll(".mermaid");for(const t of e){const a=t.getAttribute("data-graph"),l=t.textContent||"";try{const{svg:n}=await c.render(`mermaid-${a}`,l);t.innerHTML=n}catch(n){console.error(`Failed to render ${a} graph:`,n)}}}g();const r=document.querySelectorAll(".toggle-btn"),d=document.getElementById("navigation-graph"),i=document.getElementById("api-graph"),s=document.getElementById("navigation-legend"),o=document.getElementById("api-legend");r.forEach(e=>{e.addEventListener("click",()=>{const t=e.getAttribute("data-view");r.forEach(a=>a.classList.remove("active")),e.classList.add("active"),t==="navigation"?(d?.classList.remove("hidden"),i?.classList.add("hidden"),s?.classList.remove("hidden"),o?.classList.add("hidden")):(d?.classList.add("hidden"),i?.classList.remove("hidden"),s?.classList.add("hidden"),o?.classList.remove("hidden"))})});
@@ -1,39 +0,0 @@
1
- import { e as createComponent, f as createAstro, o as renderHead, h as addAttribute, p as renderSlot, r as renderTemplate } from './astro/server_m7yT4wCr.mjs';
2
- import 'piccolore';
3
- import 'clsx';
4
- /* empty css */
5
- import { existsSync, readFileSync } from 'node:fs';
6
- import { join } from 'node:path';
7
-
8
- const $$Astro = createAstro();
9
- const $$Layout = createComponent(($$result, $$props, $$slots) => {
10
- const Astro2 = $$result.createAstro($$Astro, $$props, $$slots);
11
- Astro2.self = $$Layout;
12
- const { title, currentPage } = Astro2.props;
13
- return renderTemplate`<html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>${title} | Screenbook</title>${renderHead()}</head> <body> <header class="header"> <div class="container"> <div class="header-content"> <a href="/" class="logo"> <img src="/logo.svg" alt="" class="logo-icon" width="24" height="24">
14
- Screenbook
15
- </a> <nav class="nav"> <a href="/"${addAttribute(["nav-link", { active: currentPage === "screens" }], "class:list")}> <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6A2.25 2.25 0 016 3.75h2.25A2.25 2.25 0 0110.5 6v2.25a2.25 2.25 0 01-2.25 2.25H6a2.25 2.25 0 01-2.25-2.25V6zM3.75 15.75A2.25 2.25 0 016 13.5h2.25a2.25 2.25 0 012.25 2.25V18a2.25 2.25 0 01-2.25 2.25H6A2.25 2.25 0 013.75 18v-2.25zM13.5 6a2.25 2.25 0 012.25-2.25H18A2.25 2.25 0 0120.25 6v2.25A2.25 2.25 0 0118 10.5h-2.25a2.25 2.25 0 01-2.25-2.25V6zM13.5 15.75a2.25 2.25 0 012.25-2.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-2.25A2.25 2.25 0 0113.5 18v-2.25z"></path> </svg>
16
- Screens
17
- </a> <a href="/graph"${addAttribute(["nav-link", { active: currentPage === "graph" }], "class:list")}> <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> <path stroke-linecap="round" stroke-linejoin="round" d="M7.5 21L3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5"></path> </svg>
18
- Graph
19
- </a> <a href="/impact"${addAttribute(["nav-link", { active: currentPage === "impact" }], "class:list")}> <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z"></path> </svg>
20
- Impact
21
- </a> <a href="/coverage"${addAttribute(["nav-link", { active: currentPage === "coverage" }], "class:list")}> <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> <path stroke-linecap="round" stroke-linejoin="round" d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 013 19.875v-6.75zM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V8.625zM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V4.125z"></path> </svg>
22
- Coverage
23
- </a> </nav> </div> </div> </header> <main> ${renderSlot($$result, $$slots["default"])} </main> </body></html>`;
24
- }, "/Users/wadakatu/www/experiments/screenbook/packages/ui/src/layouts/Layout.astro", void 0);
25
-
26
- function loadScreens() {
27
- const screensPath = join(process.cwd(), ".screenbook", "screens.json");
28
- if (!existsSync(screensPath)) {
29
- return [];
30
- }
31
- try {
32
- const content = readFileSync(screensPath, "utf-8");
33
- return JSON.parse(content);
34
- } catch {
35
- return [];
36
- }
37
- }
38
-
39
- export { $$Layout as $, loadScreens as l };