fix(demo): restore showcase validation

- Replace nested tone branches with a typed color map

- Cover the rebuilt component library and analytics demo
This commit is contained in:
Danila Poyarkov 2026-07-21 02:32:03 +03:00
parent f6e4dd4c83
commit 8561d73eaf
2 changed files with 24 additions and 41 deletions

View file

@ -1,3 +1,5 @@
import type { Color } from '@open-pencil/scene-graph'
import { DEMO_COLORS, gradient, solid, thinStroke } from '@/app/demo/colors'
import type { EditorStore } from '@/app/editor/session'
@ -10,6 +12,14 @@ interface DemoComponents {
toggleComp: string
}
type StatTone = 'success' | 'accent' | 'danger'
const STAT_TONE_COLORS: Record<StatTone, { foreground: Color; background: Color }> = {
success: { foreground: DEMO_COLORS.success, background: DEMO_COLORS.successSoft },
accent: { foreground: DEMO_COLORS.accent, background: DEMO_COLORS.accentSoft },
danger: { foreground: DEMO_COLORS.danger, background: DEMO_COLORS.dangerSoft }
}
/**
* One cohesive product screen assembled from INSTANCEs of the component
* library, laid out with real auto-layout, and themed via bound variables.
@ -193,25 +203,14 @@ export function createAppPreviewSection(store: EditorStore, comps: DemoComponent
})
const badge = graph.createInstance(comps.badgeComp, card)
if (badge) {
const tone =
s.tone === 'success'
? DEMO_COLORS.success
: s.tone === 'danger'
? DEMO_COLORS.danger
: DEMO_COLORS.accent
const toneSoft =
s.tone === 'success'
? DEMO_COLORS.successSoft
: s.tone === 'danger'
? DEMO_COLORS.dangerSoft
: DEMO_COLORS.accentSoft
const tone = STAT_TONE_COLORS[s.tone]
const bLabel = badge.childIds.map((cid) => graph.getNode(cid)).find((n) => n?.type === 'TEXT')
if (bLabel) {
const overrides: Record<string, unknown> = { ...badge.overrides }
graph.updateNode(bLabel.id, { text: s.trend, fills: [solid(tone)] })
graph.updateNode(bLabel.id, { text: s.trend, fills: [solid(tone.foreground)] })
overrides[`${bLabel.id}:text`] = s.trend
overrides[`${bLabel.id}:fills`] = [solid(tone)]
graph.updateNode(badge.id, { fills: [solid(toneSoft)], overrides })
overrides[`${bLabel.id}:fills`] = [solid(tone.foreground)]
graph.updateNode(badge.id, { fills: [solid(tone.background)], overrides })
statBadges.push({ id: badge.id, labelId: bLabel.id, tone: s.tone })
}
}
@ -311,5 +310,5 @@ export function createAppPreviewSection(store: EditorStore, comps: DemoComponent
interface StatBadge {
id: string
labelId: string
tone: 'success' | 'accent' | 'danger'
tone: StatTone
}

View file

@ -1,36 +1,20 @@
import { describe, expect, test } from 'bun:test'
import { createStandaloneShapes } from '@/app/demo/sections/standalone'
import { createDemoShapes } from '@/app/demo/document'
import { createEditorStore } from '@/app/editor/session'
describe('demo document', () => {
test('showcases imported OpenType and text decoration features', () => {
test('builds the component library and analytics showcase', () => {
const store = createEditorStore()
createStandaloneShapes(store)
createDemoShapes(store)
const nodes = [...store.graph.getAllNodes()]
const ligatures = nodes.find((node) => node.name === 'Ligatures')
const rawTags = nodes.find((node) => node.name === 'Raw')
const wavy = nodes.find((node) => node.name === 'Wavy')
const dotted = nodes.find((node) => node.name === 'Dotted')
expect(ligatures?.fontFeatures).toEqual([{ tag: 'LIGA', enabled: false }])
expect(rawTags?.fontFeatures).toEqual([
{ tag: 'DLIG', enabled: true },
{ tag: 'KERN', enabled: false }
])
expect(wavy).toMatchObject({
textDecoration: 'UNDERLINE',
textDecorationStyle: 'WAVY',
textDecorationThickness: 1.6
})
expect(wavy?.textDecorationFills[0]?.type).toBe('SOLID')
expect(dotted).toMatchObject({
textDecoration: 'UNDERLINE',
textDecorationStyle: 'DOTTED',
textDecorationThickness: 2
})
expect(dotted?.textDecorationFills[0]?.type).toBe('SOLID')
expect(nodes.some((node) => node.name === 'Component Library')).toBe(true)
expect(nodes.some((node) => node.name === 'App — Analytics')).toBe(true)
expect(nodes.some((node) => node.name === 'Chart')).toBe(true)
expect(nodes.filter((node) => node.type === 'COMPONENT').length).toBeGreaterThanOrEqual(6)
expect(nodes.filter((node) => node.type === 'INSTANCE').length).toBeGreaterThan(6)
expect(store.graph.variables.size).toBeGreaterThan(0)
})
})