openpencil/tests/engine/io/fig/import/legacy/shared-styles.test.ts
Danila Poyarkov c96f87bf9b feat(editor): add shared style bindings
- Model imported fill, stroke, text, effect, and grid style definitions and references

- Add SDK and app selectors with mixed-selection batching, detach-on-edit, and undo restoration

- Preserve style definitions through .fig export and extracted subgraphs

- Document the shared-style composable and update compatibility coverage
2026-07-17 20:28:22 +03:00

83 lines
2.5 KiB
TypeScript

import { describe, expect, test } from 'bun:test'
import { importNodeChanges } from '@open-pencil/core'
import type { NodeChange } from '@open-pencil/kiwi/fig/codec'
import { canvas, doc, node } from './helpers'
const paint = {
type: 'SOLID' as const,
color: { r: 0.2, g: 0.4, b: 0.9, a: 1 },
opacity: 1,
visible: true,
blendMode: 'NORMAL' as const
}
const effect = {
type: 'DROP_SHADOW' as const,
color: { r: 0, g: 0, b: 0, a: 0.25 },
offset: { x: 0, y: 4 },
radius: 8,
spread: 0,
visible: true
}
const grid = { pattern: 'COLUMNS', count: 12, gutterSize: 16, visible: true }
describe('fig-import: shared styles', () => {
test('models all style references and keeps definitions internal', () => {
const graph = importNodeChanges([
doc(),
canvas(),
node('ROUNDED_RECTANGLE', 20, 1, {
name: 'Brand/Fill',
styleType: 'FILL',
fillPaints: [paint]
} as Partial<NodeChange>),
node('TEXT', 21, 1, {
name: 'Type/Body',
styleType: 'TEXT',
fontSize: 18,
fontName: { family: 'Inter', style: 'Bold' },
lineHeight: { value: 26, units: 'PIXELS' }
} as Partial<NodeChange>),
node('ROUNDED_RECTANGLE', 22, 1, {
name: 'Effects/Card',
styleType: 'EFFECT',
effects: [effect]
} as Partial<NodeChange>),
node('FRAME', 23, 1, {
name: 'Grid/12 columns',
styleType: 'GRID',
layoutGrids: [grid]
} as Partial<NodeChange>),
node('FRAME', 10, 1, {
name: 'Styled target',
styleIdForFill: { guid: { sessionID: 1, localID: 20 } },
styleIdForStrokeFill: { guid: { sessionID: 1, localID: 20 } },
styleIdForText: { guid: { sessionID: 1, localID: 21 } },
styleIdForEffect: { guid: { sessionID: 1, localID: 22 } },
styleIdForGrid: { guid: { sessionID: 1, localID: 23 } }
} as Partial<NodeChange>)
])
const target = [...graph.getAllNodes()].find((item) => item.name === 'Styled target')
expect(target).toMatchObject({
fillStyleId: '1:20',
strokeStyleId: '1:20',
textStyleId: '1:21',
effectStyleId: '1:22',
gridStyleId: '1:23',
fontSize: 18,
fontWeight: 700,
lineHeight: 26,
fills: [paint],
effects: [effect],
layoutGrids: [grid]
})
const definitions = [...graph.getAllNodes()].filter((item) => item.sharedStyleType)
expect(definitions).toHaveLength(4)
expect(definitions.every((item) => item.internalOnly)).toBe(true)
})
})