Skip to content

Commit 0b39f3b

Browse files
committed
Improve tracking of applied plugin data
1 parent 53217de commit 0b39f3b

11 files changed

Lines changed: 604 additions & 310 deletions

File tree

packages/adaptive-ui-designer-core/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ export {
1414
DesignTokenValues
1515
} from "./model.js";
1616
export { mapReplacer, mapReviver, deserializeMap, serializeMap } from "./serialization.js";
17-
export { State, StatesState, PluginNode, focusIndicatorNodeName, } from "./node.js";
17+
export { State, StatesState, PluginNode, PluginNodeDataAccessor, focusIndicatorNodeName, } from "./node.js";
1818
export { AdaptiveDesignToken, AdaptiveDesignTokenOrGroup, DesignTokenRegistry } from "./registry/design-token-registry.js";
1919
export { registerAppliableTokens, registerTokens } from "./registry/recipes.js";

packages/adaptive-ui-designer-core/src/model.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export class DesignTokenValue {
6464
* A token + value pair from an applied design token.
6565
*/
6666
export class AppliedDesignToken {
67-
constructor(public tokenID: string, public value: string) {
67+
constructor(public tokenID: string) {
6868
}
6969
}
7070

@@ -89,12 +89,12 @@ export type ReadonlyDesignTokenValues = ReadonlyMap<string, DesignTokenValue>;
8989
/**
9090
* Array of style modules applied to the style of a node.
9191
*/
92-
export class AppliedStyleModules extends Array<string> {}
92+
export class AppliedStyleModules extends Array<string> {} // TODO This is more accurate as a Set
9393

9494
/**
9595
* Readonly Array of style modules applied to the style of a node.
9696
*/
97-
export type ReadonlyAppliedStyleModules = ReadonlyArray<string>;
97+
export type ReadonlyAppliedStyleModules = ReadonlyArray<string>; // TODO This is more accurate as a Set
9898

9999
/**
100100
* Map of design tokens applied to the style of a node. The key is the target style property.

packages/adaptive-ui-designer-core/src/node.ts

Lines changed: 142 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,71 @@ export const StatesState = {
4242

4343
export type StatesState = ValuesOf<typeof StatesState>;
4444

45+
/**
46+
* The states for an interactive component.
47+
*/
4548
export type State = "Rest" | "Hover" | "Active" | "Focus" | "Disabled";
4649

50+
/**
51+
* Interface for accessing plugin node data storage.
52+
*/
53+
export interface PluginNodeDataAccessor {
54+
/**
55+
* Gets custom data from the design tool storage.
56+
* @param key - The data storage key.
57+
*/
58+
getPluginData<K extends keyof PluginNodeData>(node: PluginNode, key: K): string | null;
59+
60+
/**
61+
* Sets custom data to the design tool storage.
62+
* @param key - The data storage key.
63+
* @param value - The new serialized value.
64+
*/
65+
setPluginData<K extends keyof PluginNodeData>(node: PluginNode, key: K, value: string): void;
66+
67+
/**
68+
* Deletes custom data from the design tool storage.
69+
* @param key - The data storage key.
70+
*/
71+
deletePluginData<K extends keyof PluginNodeData>(node: PluginNode, key: K): void;
72+
73+
/**
74+
* Gets the local design tokens for a given node, without inherited values.
75+
* @param node - The node to get the local design tokens for.
76+
* @param rawData - The raw data to extract the design tokens from.
77+
* @returns The local design tokens for the node.
78+
*/
79+
getLocalDesignTokens(node: PluginNode): Promise<DesignTokenValues>;
80+
81+
/**
82+
* Gets the local applied design tokens for a given node, without inherited values.
83+
* @param node - The node to get the local applied design tokens for.
84+
* @param rawData - The raw data to extract the applied design tokens from.
85+
* @returns The local applied design tokens for the node.
86+
*/
87+
getAppliedDesignTokens(node: PluginNode): Promise<AppliedDesignTokens>;
88+
89+
/**
90+
* Gets the local styles for a given node, without inherited values.
91+
* @param node - The node to get the local styles for.
92+
* @param rawData - The raw data to extract the styles from.
93+
* @returns The local styles for the node.
94+
*/
95+
getAppliedStyleModules(node: PluginNode): Promise<AppliedStyleModules>;
96+
}
97+
4798
/**
4899
* The abstract class the plugin Controller interacts with.
49100
* Acts as a basic intermediary for node structure and data storage only.
50101
* Implementation details of this class will need to be created
51102
* for each design tool.
52103
*/
53104
export abstract class PluginNode {
105+
/**
106+
* Accessor for plugin node data storage.
107+
*/
108+
public static pluginDataAccessor: PluginNodeDataAccessor;
109+
54110
/**
55111
* Design tokens inherited by an instance node from the main component.
56112
*
@@ -116,7 +172,7 @@ export abstract class PluginNode {
116172
...await parent.getInheritedDesignTokens(),
117173
...(parent.componentDesignTokens
118174
? parent.componentDesignTokens
119-
: new DesignTokenValues()),
175+
: []),
120176
...parent.localDesignTokens,
121177
]);
122178
}
@@ -132,28 +188,50 @@ export abstract class PluginNode {
132188
* Gets the applied style modules inherited by an instance node from the main component.
133189
*/
134190
public get componentAppliedStyleModules(): ReadonlyAppliedStyleModules | undefined {
135-
return this._componentAppliedStyleModules;
191+
const refNode = this.getRefNode();
192+
const appliedStyleModules = new AppliedStyleModules();
193+
194+
if (refNode && refNode.componentAppliedStyleModules) {
195+
appliedStyleModules.push(...refNode.componentAppliedStyleModules);
196+
}
197+
198+
if (this._componentAppliedStyleModules) {
199+
appliedStyleModules.push(...this._componentAppliedStyleModules);
200+
}
201+
202+
return appliedStyleModules;
136203
}
137204

138205
/**
139206
* Gets the applied design tokens inherited by an instance node from the main component.
140207
*/
141208
public get componentAppliedDesignTokens(): ReadonlyAppliedDesignTokens | undefined {
142-
return this._componentAppliedDesignTokens;
143-
}
144-
145-
/**
146-
* Gets the design tokens set for this node.
147-
*/
148-
public get localDesignTokens(): ReadonlyDesignTokenValues {
149-
return this._localDesignTokens;
209+
const refNode = this.getRefNode();
210+
const appliedDesignTokens = new AppliedDesignTokens([
211+
...(refNode && refNode.componentAppliedDesignTokens
212+
? refNode.componentAppliedDesignTokens
213+
: []),
214+
...this._componentAppliedDesignTokens
215+
? this._componentAppliedDesignTokens
216+
: [],
217+
]);
218+
return appliedDesignTokens;
150219
}
151220

152221
/**
153222
* Gets the design tokens inherited by an instance node from the main component.
154223
*/
155224
public get componentDesignTokens(): ReadonlyDesignTokenValues | undefined {
156-
return this._componentDesignTokens;
225+
const refNode = this.getRefNode();
226+
const designTokens = new DesignTokenValues([
227+
...(refNode && refNode.componentDesignTokens
228+
? refNode.componentDesignTokens
229+
: []),
230+
...this._componentDesignTokens
231+
? this._componentDesignTokens
232+
: [],
233+
]);
234+
return designTokens;
157235
}
158236

159237
/**
@@ -196,6 +274,11 @@ export abstract class PluginNode {
196274
*/
197275
public abstract getState(): Promise<string | null>;
198276

277+
/**
278+
* Gets the reference node for this node, if it is part of an instance or composition.
279+
*/
280+
public abstract getRefNode(): PluginNode | null;
281+
199282
/**
200283
* Gets whether this type of node can have children or not.
201284
*/
@@ -226,9 +309,22 @@ export abstract class PluginNode {
226309
*/
227310
public config: Config = new Config();
228311

229-
protected deserializeLocalDesignTokens(): DesignTokenValues {
230-
const json = this.getPluginData("designTokens");
231-
// console.log(" deserializeLocalDesignTokens", this.debugInfo, json);
312+
/**
313+
* Gets the design tokens set for this node.
314+
*/
315+
public get localDesignTokens(): ReadonlyDesignTokenValues {
316+
return this._localDesignTokens;
317+
}
318+
319+
/**
320+
* Deserializes design tokens set to the node.
321+
* @param json - The raw plugin data string.
322+
* @returns The deserialized design tokens set to the node.
323+
*/
324+
public deserializeLocalDesignTokens(json: string | null): DesignTokenValues {
325+
if (json !== null) {
326+
// console.log(" deserializeLocalDesignTokens", this.debugInfo, json);
327+
}
232328
const map: DesignTokenValues = deserializeMap(json);
233329

234330
// A future feature of this tooling is to support renaming tokens. For now, use a list for the reference tokens.
@@ -243,15 +339,15 @@ export abstract class PluginNode {
243339

244340
/**
245341
* Sets the design tokens to the node and design tool.
246-
* @param tokens The complete design tokens override map.
342+
* @param tokens - The complete design tokens override map.
247343
*/
248344
public async setDesignTokens(tokens: DesignTokenValues) {
249345
this._localDesignTokens = tokens;
250346
if (tokens.size) {
251347
const json = serializeMap(tokens);
252-
this.setPluginData("designTokens", json);
348+
PluginNode.pluginDataAccessor.setPluginData(this, "designTokens", json);
253349
} else {
254-
this.deletePluginData("designTokens");
350+
PluginNode.pluginDataAccessor.deletePluginData(this, "designTokens");
255351
}
256352

257353
await this.invalidateDesignTokenCache();
@@ -264,9 +360,15 @@ export abstract class PluginNode {
264360
return this._appliedDesignTokens;
265361
}
266362

267-
protected deserializeAppliedDesignTokens(): AppliedDesignTokens {
268-
const json = this.getPluginData("appliedDesignTokens");
269-
// console.log(" deserializeAppliedDesignTokens", this.debugInfo, json);
363+
/**
364+
* Deserializes the design tokens applied to the style of this node.
365+
* @param json - The raw plugin data string.
366+
* @returns The deserialized applied design tokens.
367+
*/
368+
public deserializeAppliedDesignTokens(json: string | null): AppliedDesignTokens {
369+
if (json !== null) {
370+
// console.log(" deserializeAppliedDesignTokens", this.debugInfo, json);
371+
}
270372
const map: AppliedDesignTokens = deserializeMap(json);
271373

272374
// A future feature of this tooling is to support renaming tokens. For now, use a list for the reference tokens.
@@ -284,15 +386,15 @@ export abstract class PluginNode {
284386

285387
/**
286388
* Sets the design tokens applied to the style of this node.
287-
* @param appliedTokens The complete design tokens applied to the style.
389+
* @param appliedTokens - The complete design tokens applied to the style.
288390
*/
289391
public setAppliedDesignTokens(appliedTokens: AppliedDesignTokens) {
290392
this._appliedDesignTokens = appliedTokens;
291393
if (appliedTokens.size) {
292394
const json = serializeMap(appliedTokens);
293-
this.setPluginData("appliedDesignTokens", json);
395+
PluginNode.pluginDataAccessor.setPluginData(this, "appliedDesignTokens", json);
294396
} else {
295-
this.deletePluginData("appliedDesignTokens");
397+
PluginNode.pluginDataAccessor.deletePluginData(this, "appliedDesignTokens");
296398
}
297399
}
298400

@@ -303,23 +405,29 @@ export abstract class PluginNode {
303405
return this._appliedStyleModules;
304406
}
305407

306-
protected deserializeAppliedStyleModules(): AppliedStyleModules {
307-
const json = this.getPluginData("appliedStyleModules");
308-
// console.log(" deserializeAppliedStyleModules", this.debugInfo, json);
408+
/**
409+
* Deserializes the style modules applied to the style of this node.
410+
* @param json - The raw plugin data string.
411+
* @returns The deserialized applied style modules.
412+
*/
413+
public deserializeAppliedStyleModules(json: string | null): AppliedStyleModules {
414+
if (json !== null) {
415+
// console.log(" deserializeAppliedStyleModules", this.debugInfo, json);
416+
}
309417
return JSON.parse(json || "[]");
310418
}
311419

312420
/**
313421
* Sets the style modules applied to the style of this node.
314-
* @param appliedModules The complete style modules applied to the style.
422+
* @param appliedModules - The complete style modules applied to the style.
315423
*/
316424
public setAppliedStyleModules(appliedModules: AppliedStyleModules) {
317425
this._appliedStyleModules = appliedModules;
318426
if (appliedModules.length) {
319427
const json = JSON.stringify(appliedModules);
320-
this.setPluginData("appliedStyleModules", json);
428+
PluginNode.pluginDataAccessor.setPluginData(this, "appliedStyleModules", json);
321429
} else {
322-
this.deletePluginData("appliedStyleModules");
430+
PluginNode.pluginDataAccessor.deletePluginData(this, "appliedStyleModules");
323431
}
324432
}
325433

@@ -355,7 +463,7 @@ export abstract class PluginNode {
355463

356464
/**
357465
* Updates the style property applied to this node.
358-
* @param values All applied style value.
466+
* @param values - All applied style value.
359467
*/
360468
public abstract paint(values: AppliedStyleValues): Promise<void>;
361469

@@ -383,30 +491,14 @@ export abstract class PluginNode {
383491
}
384492
}
385493

386-
protected get debugInfo() {
494+
/**
495+
* Gets debug information for this node.
496+
*/
497+
public get debugInfo() {
387498
return {
388499
id: this.id,
389500
type: this.type,
390501
name: this.name,
391502
};
392503
}
393-
394-
/**
395-
* Gets custom data from the design tool storage.
396-
* @param key The data storage key.
397-
*/
398-
protected abstract getPluginData<K extends keyof PluginNodeData>(key: K): string | undefined;
399-
400-
/**
401-
* Sets custom data to the design tool storage.
402-
* @param key The data storage key.
403-
* @param value The new serialized value.
404-
*/
405-
protected abstract setPluginData<K extends keyof PluginNodeData>(key: K, value: string): void;
406-
407-
/**
408-
* Deletes custom data from the design tool storage.
409-
* @param key The data storage key.
410-
*/
411-
protected abstract deletePluginData<K extends keyof PluginNodeData>(key: K): void;
412504
}

packages/adaptive-ui-designer-core/src/serialization.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export function mapReviver(key: string, value: any): any {
2828
return value;
2929
}
3030

31-
export function deserializeMap<K, V>(json?: string): Map<K, V> {
31+
export function deserializeMap<K, V>(json: string | null): Map<K, V> {
3232
if (json) {
3333
try {
3434
const map = JSON.parse(json, mapReviver) as Map<K, V>;

0 commit comments

Comments
 (0)