* fix: keep bound text and visibility in step with their variables Text bound to a string variable was resolved only when a .fig file was read, and visibility bound to a boolean never, so editing the value or switching a mode left them showing the old one. The binding reconcile, renamed reconcileVariableBindings, now resolves text and visibility with numbers, scoped the same way, and .fig export writes them resolved in each collection's default mode. A bound font family is left as stored, since changing it needs the font loaded. * fix: keep text and visibility an instance overrides over their bindings Typing in a bound layer inside an instance or toggling its eye records an override but keeps the binding, so the next value edit or mode switch replaced what was typed or hidden. An overridden text or visibility now keeps its value, as an overridden width or height does.
57 lines
2 KiB
TypeScript
57 lines
2 KiB
TypeScript
import { describe, expect, test } from 'bun:test'
|
|
|
|
import {
|
|
reconcileVariableBindings,
|
|
SceneGraph,
|
|
variablesResolvingThrough
|
|
} from '@open-pencil/scene-graph'
|
|
|
|
/** Two layers saved at 10 while their bindings say otherwise, as layers in imported files can be. */
|
|
function drifted() {
|
|
const graph = new SceneGraph()
|
|
const collection = graph.createCollection('Size')
|
|
const base = graph.createVariable('Base', 'FLOAT', collection.id, 40)
|
|
const alias = graph.createVariable('Alias', 'FLOAT', collection.id, { aliasId: base.id })
|
|
const other = graph.createVariable('Other', 'FLOAT', collection.id, 24)
|
|
const page = graph.getPages()[0].id
|
|
const frame = graph.createNode('FRAME', page, { width: 10, boundVariables: { width: alias.id } })
|
|
const child = graph.createNode('RECTANGLE', frame.id, {
|
|
width: 10,
|
|
boundVariables: { width: other.id }
|
|
})
|
|
const elsewhere = graph.createNode('RECTANGLE', page, {
|
|
width: 10,
|
|
boundVariables: { width: other.id }
|
|
})
|
|
return { graph, base, alias, other, frame, child, elsewhere }
|
|
}
|
|
|
|
describe('binding scopes', () => {
|
|
test('a variable reaches the variables that alias it, at any depth', () => {
|
|
const { graph, base, alias } = drifted()
|
|
const deeper = graph.createVariable('Deeper', 'FLOAT', base.collectionId, {
|
|
aliasId: alias.id
|
|
})
|
|
|
|
expect(variablesResolvingThrough(graph, [base.id])).toEqual(
|
|
new Set([base.id, alias.id, deeper.id])
|
|
)
|
|
})
|
|
|
|
test('a variable scope resolves only the layers bound to it or its aliases', () => {
|
|
const { graph, base, frame, child, elsewhere } = drifted()
|
|
|
|
expect(reconcileVariableBindings(graph, { variables: [base.id] })).toEqual([frame.id])
|
|
expect(frame.width).toBe(40)
|
|
expect([child.width, elsewhere.width]).toEqual([10, 10])
|
|
})
|
|
|
|
test('a subtree scope resolves the layers inside it and nothing else', () => {
|
|
const { graph, frame, child, elsewhere } = drifted()
|
|
|
|
reconcileVariableBindings(graph, { subtrees: [frame.id] })
|
|
|
|
expect([frame.width, child.width, elsewhere.width]).toEqual([40, 24, 10])
|
|
})
|
|
})
|