@screenbook/ui 0.1.0 → 1.1.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/CHANGELOG.md +54 -0
- package/astro.config.mjs +2 -0
- package/dist/client/_astro/MockFormEditor.0L29BkPy.js +9 -0
- package/dist/client/_astro/MockFormEditor.OiYzJAtR.css +1 -0
- package/dist/client/_astro/{_baseUniq.BGai4mcc.js → _baseUniq.D9ouiLRJ.js} +1 -1
- package/dist/client/_astro/_id_.BqQf-JH6.css +1 -0
- package/dist/client/_astro/{arc.DUp0dfXj.js → arc.CLU0JlVT.js} +1 -1
- package/dist/client/_astro/{architectureDiagram-VXUJARFQ.De_Gt-YC.js → architectureDiagram-VXUJARFQ.BF0V2v9-.js} +1 -1
- package/dist/client/_astro/{blockDiagram-VD42YOAC.BBt_VNhR.js → blockDiagram-VD42YOAC.6LO7yu7m.js} +1 -1
- package/dist/client/_astro/{c4Diagram-YG6GDRKO.DfgUlHvt.js → c4Diagram-YG6GDRKO.BqntXNsZ.js} +1 -1
- package/dist/client/_astro/channel._8es88oH.js +1 -0
- package/dist/client/_astro/{chunk-4BX2VUAB.BL0ar6du.js → chunk-4BX2VUAB.b97OIY94.js} +1 -1
- package/dist/client/_astro/{chunk-55IACEB6.CI6SkZkY.js → chunk-55IACEB6.Cf9hglsl.js} +1 -1
- package/dist/client/_astro/{chunk-B4BG7PRW.Z25N80K6.js → chunk-B4BG7PRW.vDfM6vb1.js} +1 -1
- package/dist/client/_astro/{chunk-DI55MBZ5.BqjPVmi1.js → chunk-DI55MBZ5.8pHdnkw9.js} +1 -1
- package/dist/client/_astro/{chunk-FMBD7UC4.bZ9DWnFm.js → chunk-FMBD7UC4.l_Ue7ZYJ.js} +1 -1
- package/dist/client/_astro/{chunk-QN33PNHL.BkzuUgWB.js → chunk-QN33PNHL.CyBZ7SCx.js} +1 -1
- package/dist/client/_astro/{chunk-QZHKN3VN.C__d68N_.js → chunk-QZHKN3VN.BC5tI2Vw.js} +1 -1
- package/dist/client/_astro/{chunk-TZMSLE5B.BIpu8bMn.js → chunk-TZMSLE5B.DxkkbOL4.js} +1 -1
- package/dist/client/_astro/classDiagram-2ON5EDUG.DMv55r4w.js +1 -0
- package/dist/client/_astro/classDiagram-v2-WZHVMYZB.DMv55r4w.js +1 -0
- package/dist/client/_astro/client.9unXo8s5.js +33 -0
- package/dist/client/_astro/clone.COAvtnt5.js +1 -0
- package/dist/client/_astro/{cose-bilkent-S5V4N54A.D48yfMll.js → cose-bilkent-S5V4N54A.DlRxGhCG.js} +1 -1
- package/dist/client/_astro/coverage.DLKSOM4m.css +1 -0
- package/dist/client/_astro/{dagre-6UL2VRFP.LKVH7b30.js → dagre-6UL2VRFP.tCLd0f1c.js} +1 -1
- package/dist/client/_astro/{diagram-PSM6KHXK.AHgUjH56.js → diagram-PSM6KHXK.CJA_rnN3.js} +1 -1
- package/dist/client/_astro/{diagram-QEK2KX5R.DvS33xWZ.js → diagram-QEK2KX5R.BoqLvsuS.js} +1 -1
- package/dist/client/_astro/{diagram-S2PKOQOG.BWisaYrQ.js → diagram-S2PKOQOG.T8h5wODN.js} +1 -1
- package/dist/client/_astro/{erDiagram-Q2GNP2WA.B7oID6oT.js → erDiagram-Q2GNP2WA.B4hpr69H.js} +1 -1
- package/dist/client/_astro/{flowDiagram-NV44I4VS.Bb1qJLxr.js → flowDiagram-NV44I4VS.CV4Oenkb.js} +1 -1
- package/dist/client/_astro/{ganttDiagram-JELNMOA3.3vGHETyo.js → ganttDiagram-JELNMOA3.DdpXJeX3.js} +1 -1
- package/dist/client/_astro/{gitGraphDiagram-NY62KEGX.Co2SKcif.js → gitGraphDiagram-NY62KEGX.BeY3JZYI.js} +1 -1
- package/dist/client/_astro/{graph.B5fevUwB.js → graph.CO6LxWoK.js} +1 -1
- package/dist/client/_astro/graph.astro_astro_type_script_index_0_lang.BxaPom9e.js +1 -0
- package/dist/client/_astro/{impact.astro_astro_type_script_index_0_lang.D4cAR9AL.js → impact.astro_astro_type_script_index_0_lang.VjeLQGe6.js} +1 -1
- package/dist/client/_astro/index.WFquGv8Z.js +9 -0
- package/dist/client/_astro/{infoDiagram-WHAUD3N6.B6ULtps1.js → infoDiagram-WHAUD3N6.D2_J_fR6.js} +1 -1
- package/dist/client/_astro/{journeyDiagram-XKPGCS4Q.BSOCzWmw.js → journeyDiagram-XKPGCS4Q.7c4ngVDw.js} +1 -1
- package/dist/client/_astro/{kanban-definition-3W4ZIXB7.D8KKGc1o.js → kanban-definition-3W4ZIXB7.D_eWex6x.js} +1 -1
- package/dist/client/_astro/{layout.8vv24qEg.js → layout.Cn9EjNLq.js} +1 -1
- package/dist/client/_astro/{linear.B6O9ymuK.js → linear.BlE_mLsy.js} +1 -1
- package/dist/client/_astro/{mermaid.core.CReXU7YN.js → mermaid.core.CgCLOZ6t.js} +5 -5
- package/dist/client/_astro/{min.CdGMGVU0.js → min.OtQS-qlD.js} +1 -1
- package/dist/client/_astro/{mindmap-definition-VGOIOE7T.G14HgtDw.js → mindmap-definition-VGOIOE7T.CjNYt18e.js} +1 -1
- package/dist/client/_astro/{pieDiagram-ADFJNKIX.bC2VkyoW.js → pieDiagram-ADFJNKIX.D18DPyo6.js} +1 -1
- package/dist/client/_astro/{quadrantDiagram-AYHSOK5B.BlLaQQxO.js → quadrantDiagram-AYHSOK5B.Cma08fPv.js} +1 -1
- package/dist/client/_astro/{requirementDiagram-UZGBJVZJ.DHRnMofO.js → requirementDiagram-UZGBJVZJ.BlhVOrX0.js} +1 -1
- package/dist/client/_astro/{sankeyDiagram-TZEHDZUN.BMuaJBmt.js → sankeyDiagram-TZEHDZUN.HRsqw4ej.js} +1 -1
- package/dist/client/_astro/{sequenceDiagram-WL72ISMW.CnU62wqy.js → sequenceDiagram-WL72ISMW.3cZYkaSP.js} +1 -1
- package/dist/client/_astro/{stateDiagram-FKZM4ZOC.CewI55YO.js → stateDiagram-FKZM4ZOC.DdlRd9N7.js} +1 -1
- package/dist/client/_astro/stateDiagram-v2-4FDKWEC3.DCPDjwi7.js +1 -0
- package/dist/client/_astro/{timeline-definition-IT6M3QCI.D1PLRwss.js → timeline-definition-IT6M3QCI.BshW8mMW.js} +1 -1
- package/dist/client/_astro/{treemap-KMMF4GRG.D3VNVvXF.js → treemap-KMMF4GRG.BxXN_YfK.js} +1 -1
- package/dist/client/_astro/{xychartDiagram-PRI3JC2R.CQex0-ul.js → xychartDiagram-PRI3JC2R.Mg5_s08f.js} +1 -1
- package/dist/server/entry.mjs +15 -11
- package/dist/server/manifest_smcahUO6.mjs +101 -0
- package/dist/server/pages/api/save-mock.astro.mjs +142 -0
- package/dist/server/pages/coverage.astro.mjs +1 -1
- package/dist/server/pages/editor.astro.mjs +30 -0
- package/dist/server/pages/graph.astro.mjs +18 -3
- package/dist/server/pages/impact.astro.mjs +1 -1
- package/dist/server/pages/index.astro.mjs +1 -1
- package/dist/server/pages/screen/_id_.astro.mjs +126 -3
- package/dist/server/renderers.mjs +200 -1
- package/package.json +8 -2
- package/src/components/MockFormEditor.tsx +1280 -0
- package/src/components/MockPreview.astro +811 -0
- package/src/pages/api/save-mock.ts +182 -0
- package/src/pages/editor.astro +33 -0
- package/src/pages/graph.astro +35 -1
- package/src/pages/screen/[id].astro +9 -0
- package/src/styles/mock-editor.css +1351 -0
- package/tsconfig.json +1 -0
- package/dist/client/_astro/channel.CNyr52v1.js +0 -1
- package/dist/client/_astro/classDiagram-2ON5EDUG.CxT3aW-h.js +0 -1
- package/dist/client/_astro/classDiagram-v2-WZHVMYZB.CxT3aW-h.js +0 -1
- package/dist/client/_astro/clone.U_lSZ6fe.js +0 -1
- package/dist/client/_astro/coverage.BnE2oGo8.css +0 -1
- package/dist/client/_astro/graph.astro_astro_type_script_index_0_lang.B0fEnVdy.js +0 -1
- package/dist/client/_astro/stateDiagram-v2-4FDKWEC3.7xUQqoNr.js +0 -1
- package/dist/server/manifest_CicDtuHD.mjs +0 -101
- /package/dist/server/chunks/{loadScreens_JhK3F9tC.mjs → loadScreens_CkCqdbH2.mjs} +0 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs"
|
|
2
|
+
import { join } from "node:path"
|
|
3
|
+
import type { APIRoute } from "astro"
|
|
4
|
+
import { Project, SyntaxKind } from "ts-morph"
|
|
5
|
+
|
|
6
|
+
interface ScreenWithFilePath {
|
|
7
|
+
id: string
|
|
8
|
+
filePath: string
|
|
9
|
+
[key: string]: unknown
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface SaveMockRequest {
|
|
13
|
+
screenId: string
|
|
14
|
+
mock: {
|
|
15
|
+
sections: Array<{
|
|
16
|
+
title?: string
|
|
17
|
+
layout?: string
|
|
18
|
+
elements: Array<Record<string, unknown>>
|
|
19
|
+
}>
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const POST: APIRoute = async ({ request }) => {
|
|
24
|
+
try {
|
|
25
|
+
const body = (await request.json()) as SaveMockRequest
|
|
26
|
+
const { screenId, mock } = body
|
|
27
|
+
|
|
28
|
+
if (!screenId || !mock) {
|
|
29
|
+
return new Response(
|
|
30
|
+
JSON.stringify({ error: "screenId and mock are required" }),
|
|
31
|
+
{ status: 400, headers: { "Content-Type": "application/json" } },
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Load screens.json to get filePath
|
|
36
|
+
const screensPath = join(process.cwd(), ".screenbook", "screens.json")
|
|
37
|
+
if (!existsSync(screensPath)) {
|
|
38
|
+
return new Response(
|
|
39
|
+
JSON.stringify({
|
|
40
|
+
error: "screens.json not found. Run screenbook build first.",
|
|
41
|
+
}),
|
|
42
|
+
{ status: 404, headers: { "Content-Type": "application/json" } },
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const screens = JSON.parse(
|
|
47
|
+
readFileSync(screensPath, "utf-8"),
|
|
48
|
+
) as ScreenWithFilePath[]
|
|
49
|
+
const screen = screens.find((s) => s.id === screenId)
|
|
50
|
+
|
|
51
|
+
if (!screen) {
|
|
52
|
+
return new Response(
|
|
53
|
+
JSON.stringify({ error: `Screen '${screenId}' not found` }),
|
|
54
|
+
{ status: 404, headers: { "Content-Type": "application/json" } },
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (!screen.filePath) {
|
|
59
|
+
return new Response(
|
|
60
|
+
JSON.stringify({
|
|
61
|
+
error: `Screen '${screenId}' does not have filePath. Rebuild with latest CLI.`,
|
|
62
|
+
}),
|
|
63
|
+
{ status: 400, headers: { "Content-Type": "application/json" } },
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Use ts-morph to update the file
|
|
68
|
+
const result = await updateMockInFile(screen.filePath, mock)
|
|
69
|
+
|
|
70
|
+
if (!result.success) {
|
|
71
|
+
return new Response(JSON.stringify({ error: result.error }), {
|
|
72
|
+
status: 500,
|
|
73
|
+
headers: { "Content-Type": "application/json" },
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return new Response(
|
|
78
|
+
JSON.stringify({ success: true, filePath: screen.filePath }),
|
|
79
|
+
{ status: 200, headers: { "Content-Type": "application/json" } },
|
|
80
|
+
)
|
|
81
|
+
} catch (error) {
|
|
82
|
+
const message = error instanceof Error ? error.message : "Unknown error"
|
|
83
|
+
return new Response(JSON.stringify({ error: message }), {
|
|
84
|
+
status: 500,
|
|
85
|
+
headers: { "Content-Type": "application/json" },
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function updateMockInFile(
|
|
91
|
+
filePath: string,
|
|
92
|
+
mock: SaveMockRequest["mock"],
|
|
93
|
+
): Promise<{ success: boolean; error?: string }> {
|
|
94
|
+
try {
|
|
95
|
+
const project = new Project()
|
|
96
|
+
const sourceFile = project.addSourceFileAtPath(filePath)
|
|
97
|
+
|
|
98
|
+
// Find the defineScreen call
|
|
99
|
+
const callExpressions = sourceFile.getDescendantsOfKind(
|
|
100
|
+
SyntaxKind.CallExpression,
|
|
101
|
+
)
|
|
102
|
+
const defineScreenCall = callExpressions.find((call) => {
|
|
103
|
+
const expression = call.getExpression()
|
|
104
|
+
return expression.getText() === "defineScreen"
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
if (!defineScreenCall) {
|
|
108
|
+
return { success: false, error: "defineScreen() call not found in file" }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Get the object literal argument
|
|
112
|
+
const args = defineScreenCall.getArguments()
|
|
113
|
+
const firstArg = args[0]
|
|
114
|
+
if (!firstArg) {
|
|
115
|
+
return { success: false, error: "defineScreen() has no arguments" }
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (firstArg.getKind() !== SyntaxKind.ObjectLiteralExpression) {
|
|
119
|
+
return {
|
|
120
|
+
success: false,
|
|
121
|
+
error: "defineScreen() argument is not an object literal",
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const obj = firstArg.asKind(SyntaxKind.ObjectLiteralExpression)
|
|
126
|
+
if (!obj) {
|
|
127
|
+
return { success: false, error: "Failed to parse object literal" }
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Find existing mock property
|
|
131
|
+
const mockProperty = obj.getProperty("mock")
|
|
132
|
+
|
|
133
|
+
// Generate mock code string
|
|
134
|
+
const mockCode = generateMockCode(mock)
|
|
135
|
+
|
|
136
|
+
if (mockProperty) {
|
|
137
|
+
// Update existing mock property
|
|
138
|
+
mockProperty.replaceWithText(`mock: ${mockCode}`)
|
|
139
|
+
} else {
|
|
140
|
+
// Add new mock property at the end
|
|
141
|
+
obj.addPropertyAssignment({
|
|
142
|
+
name: "mock",
|
|
143
|
+
initializer: mockCode,
|
|
144
|
+
})
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Save the file
|
|
148
|
+
await sourceFile.save()
|
|
149
|
+
|
|
150
|
+
return { success: true }
|
|
151
|
+
} catch (error) {
|
|
152
|
+
const message = error instanceof Error ? error.message : "Unknown error"
|
|
153
|
+
return { success: false, error: message }
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function generateMockCode(mock: SaveMockRequest["mock"]): string {
|
|
158
|
+
const sections = mock.sections.map((section) => {
|
|
159
|
+
const props: string[] = []
|
|
160
|
+
|
|
161
|
+
if (section.title) {
|
|
162
|
+
props.push(`title: ${JSON.stringify(section.title)}`)
|
|
163
|
+
}
|
|
164
|
+
if (section.layout && section.layout !== "vertical") {
|
|
165
|
+
props.push(`layout: ${JSON.stringify(section.layout)}`)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const elements = section.elements.map((element) => {
|
|
169
|
+
const elementProps = Object.entries(element)
|
|
170
|
+
.filter(([_, value]) => value !== undefined && value !== "")
|
|
171
|
+
.map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
|
|
172
|
+
.join(", ")
|
|
173
|
+
return `{ ${elementProps} }`
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
props.push(`elements: [\n\t\t\t${elements.join(",\n\t\t\t")},\n\t\t]`)
|
|
177
|
+
|
|
178
|
+
return `{\n\t\t${props.join(",\n\t\t")},\n\t}`
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
return `{\n\tsections: [\n\t${sections.join(",\n\t")},\n\t],\n}`
|
|
182
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
import Layout from "@/layouts/Layout.astro"
|
|
3
|
+
import { MockFormEditor } from "@/components/MockFormEditor"
|
|
4
|
+
import { loadScreens } from "@/utils/loadScreens"
|
|
5
|
+
|
|
6
|
+
const screens = loadScreens()
|
|
7
|
+
const url = Astro.url
|
|
8
|
+
const screenId = url.searchParams.get("screen")
|
|
9
|
+
|
|
10
|
+
const screen = screenId ? screens.find((s) => s.id === screenId) : null
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<Layout title="Mock Editor">
|
|
14
|
+
<div class="editor-container">
|
|
15
|
+
<MockFormEditor
|
|
16
|
+
client:only="react"
|
|
17
|
+
screenId={screen?.id}
|
|
18
|
+
screenTitle={screen?.title || "New Screen"}
|
|
19
|
+
initialMock={screen?.mock}
|
|
20
|
+
/>
|
|
21
|
+
</div>
|
|
22
|
+
</Layout>
|
|
23
|
+
|
|
24
|
+
<style>
|
|
25
|
+
.editor-container {
|
|
26
|
+
position: fixed;
|
|
27
|
+
top: 60px;
|
|
28
|
+
left: 0;
|
|
29
|
+
right: 0;
|
|
30
|
+
bottom: 0;
|
|
31
|
+
background: #141822;
|
|
32
|
+
}
|
|
33
|
+
</style>
|
package/src/pages/graph.astro
CHANGED
|
@@ -6,13 +6,19 @@ const screens = loadScreens()
|
|
|
6
6
|
|
|
7
7
|
// Generate Navigation Mermaid graph
|
|
8
8
|
let navigationGraph = ""
|
|
9
|
+
const screensWithMock: string[] = []
|
|
9
10
|
if (screens.length > 0) {
|
|
10
11
|
const lines: string[] = ["flowchart TD"]
|
|
11
12
|
|
|
12
13
|
for (const screen of screens) {
|
|
13
14
|
const label = screen.title.replace(/"/g, "'")
|
|
14
15
|
const id = screen.id.replace(/\./g, "_")
|
|
15
|
-
|
|
16
|
+
const mockIndicator = screen.mock ? " 📱" : ""
|
|
17
|
+
lines.push(` ${id}["${label}${mockIndicator}"]`)
|
|
18
|
+
lines.push(` click ${id} "/screen/${screen.id}"`)
|
|
19
|
+
if (screen.mock) {
|
|
20
|
+
screensWithMock.push(id)
|
|
21
|
+
}
|
|
16
22
|
}
|
|
17
23
|
|
|
18
24
|
lines.push("")
|
|
@@ -27,9 +33,22 @@ if (screens.length > 0) {
|
|
|
27
33
|
}
|
|
28
34
|
}
|
|
29
35
|
|
|
36
|
+
// Add styling for screens with mock
|
|
37
|
+
if (screensWithMock.length > 0) {
|
|
38
|
+
lines.push("")
|
|
39
|
+
lines.push(" %% Mock styling")
|
|
40
|
+
lines.push(" classDef hasMock stroke:#14b8a6,stroke-width:2px")
|
|
41
|
+
for (const id of screensWithMock) {
|
|
42
|
+
lines.push(` class ${id} hasMock`)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
30
46
|
navigationGraph = lines.join("\n")
|
|
31
47
|
}
|
|
32
48
|
|
|
49
|
+
// Count screens with mock
|
|
50
|
+
const mockCount = screens.filter(s => s.mock).length
|
|
51
|
+
|
|
33
52
|
// Generate API Dependency Mermaid graph
|
|
34
53
|
let apiGraph = ""
|
|
35
54
|
if (screens.length > 0) {
|
|
@@ -145,6 +164,7 @@ const apiCount = new Set(
|
|
|
145
164
|
<div class="graph-stats">
|
|
146
165
|
<span class="stat">{screens.length} screens</span>
|
|
147
166
|
<span class="stat">{apiCount} APIs</span>
|
|
167
|
+
{mockCount > 0 && <span class="stat stat-mock">📱 {mockCount} with mock</span>}
|
|
148
168
|
</div>
|
|
149
169
|
</div>
|
|
150
170
|
|
|
@@ -161,6 +181,10 @@ const apiCount = new Set(
|
|
|
161
181
|
<div class="legend-node"></div>
|
|
162
182
|
<span>Screen</span>
|
|
163
183
|
</div>
|
|
184
|
+
<div class="graph-legend-item">
|
|
185
|
+
<div class="legend-node legend-mock"></div>
|
|
186
|
+
<span>Screen with mock 📱</span>
|
|
187
|
+
</div>
|
|
164
188
|
<div class="graph-legend-item">
|
|
165
189
|
<div class="legend-edge"></div>
|
|
166
190
|
<span>Navigation flow</span>
|
|
@@ -191,6 +215,7 @@ const apiCount = new Set(
|
|
|
191
215
|
const mermaidConfig = {
|
|
192
216
|
startOnLoad: false,
|
|
193
217
|
theme: "dark",
|
|
218
|
+
securityLevel: "loose", // Enable click handlers
|
|
194
219
|
themeVariables: {
|
|
195
220
|
darkMode: true,
|
|
196
221
|
background: "transparent",
|
|
@@ -331,4 +356,13 @@ const apiCount = new Set(
|
|
|
331
356
|
background: #14b8a6 !important;
|
|
332
357
|
border-color: #5eead4 !important;
|
|
333
358
|
}
|
|
359
|
+
|
|
360
|
+
.legend-mock {
|
|
361
|
+
border-color: #14b8a6 !important;
|
|
362
|
+
border-width: 2px !important;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.stat-mock {
|
|
366
|
+
color: #14b8a6;
|
|
367
|
+
}
|
|
334
368
|
</style>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import Layout from "@/layouts/Layout.astro"
|
|
3
|
+
import MockPreview from "@/components/MockPreview.astro"
|
|
3
4
|
import { loadScreens } from "@/utils/loadScreens"
|
|
4
5
|
import { getApiDependencyCount } from "@/utils/impactAnalysis"
|
|
5
6
|
|
|
@@ -128,6 +129,14 @@ const nextScreens = screens.filter((s) => screen.next?.includes(s.id))
|
|
|
128
129
|
</div>
|
|
129
130
|
</div>
|
|
130
131
|
)}
|
|
132
|
+
|
|
133
|
+
<!-- Mock Preview -->
|
|
134
|
+
{screen.mock && (
|
|
135
|
+
<div class="section">
|
|
136
|
+
<h2 class="section-title">UI Wireframe</h2>
|
|
137
|
+
<MockPreview mock={screen.mock} screenId={screen.id} />
|
|
138
|
+
</div>
|
|
139
|
+
)}
|
|
131
140
|
</div>
|
|
132
141
|
|
|
133
142
|
<div>
|