@directededges/specs-from-figma 0.21.0 → 0.22.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/dist/Adapters/RestApi/NodeIndexer.d.ts +118 -0
- package/dist/Adapters/RestApi/RestBaseNode.d.ts +271 -0
- package/dist/Adapters/RestApi/RestComponentNode.d.ts +30 -0
- package/dist/Adapters/RestApi/RestInstanceNode.d.ts +50 -0
- package/dist/Adapters/RestApi/RestLibraryFile.d.ts +51 -0
- package/dist/Adapters/RestApi/RestTextNode.d.ts +41 -0
- package/dist/Component/Anatomy/Anatomy.d.ts +97 -0
- package/dist/Component/Anatomy/AnatomyElement.d.ts +24 -0
- package/dist/Component/Children/Children.d.ts +96 -0
- package/dist/Component/Color/Color.d.ts +63 -0
- package/dist/Component/Component.d.ts +71 -0
- package/dist/Component/Effects/Blur.d.ts +41 -0
- package/dist/Component/Effects/Effects.d.ts +51 -0
- package/dist/Component/Effects/EffectsProcessor.d.ts +15 -0
- package/dist/Component/Effects/Shadow.d.ts +51 -0
- package/dist/Component/Effects/index.d.ts +4 -0
- package/dist/Component/Elements/BaseElement.d.ts +87 -0
- package/dist/Component/Elements/ElementFactory.d.ts +7 -0
- package/dist/Component/Elements/ElementFactoryRegistry.d.ts +21 -0
- package/dist/Component/Elements/Elements.d.ts +86 -0
- package/dist/Component/Elements/Primitives/ComponentElement.d.ts +8 -0
- package/dist/Component/Elements/Primitives/EllipseElement.d.ts +8 -0
- package/dist/Component/Elements/Primitives/FrameElement.d.ts +8 -0
- package/dist/Component/Elements/Primitives/GlyphElement.d.ts +21 -0
- package/dist/Component/Elements/Primitives/InstanceElement.d.ts +24 -0
- package/dist/Component/Elements/Primitives/LineElement.d.ts +8 -0
- package/dist/Component/Elements/Primitives/PolygonElement.d.ts +8 -0
- package/dist/Component/Elements/Primitives/RectangleElement.d.ts +8 -0
- package/dist/Component/Elements/Primitives/SlotElement.d.ts +8 -0
- package/dist/Component/Elements/Primitives/StarElement.d.ts +8 -0
- package/dist/Component/Elements/Primitives/TextElement.d.ts +8 -0
- package/dist/Component/Elements/Primitives/VectorElement.d.ts +8 -0
- package/dist/Component/Elements/index.d.ts +12 -0
- package/dist/Component/Gradient/Gradient.d.ts +73 -0
- package/dist/Component/Gradient/GradientProcessor.d.ts +18 -0
- package/dist/Component/Gradient/index.d.ts +2 -0
- package/dist/Component/InstanceExamples/InstanceExample.d.ts +35 -0
- package/dist/Component/InstanceExamples/InstanceExamples.d.ts +49 -0
- package/dist/Component/Layout/Layout.d.ts +26 -0
- package/dist/Component/Layout/types.d.ts +61 -0
- package/dist/Component/Metadata/Metadata.d.ts +13 -0
- package/dist/Component/Metadata/constants.d.ts +8 -0
- package/dist/Component/Nodes/types.d.ts +4 -0
- package/dist/Component/PropConfigurations/PropConfiguration.d.ts +15 -0
- package/dist/Component/PropConfigurations/PropConfigurations.d.ts +55 -0
- package/dist/Component/Props/CodeOnlyProps/BooleanCodeOnlyProp.d.ts +11 -0
- package/dist/Component/Props/CodeOnlyProps/CodeOnlyProps.d.ts +36 -0
- package/dist/Component/Props/CodeOnlyProps/InstanceCodeOnlyProp.d.ts +19 -0
- package/dist/Component/Props/CodeOnlyProps/TextCodeOnlyProp.d.ts +18 -0
- package/dist/Component/Props/CodeOnlyProps/index.d.ts +4 -0
- package/dist/Component/Props/PropBinding.d.ts +69 -0
- package/dist/Component/Props/PropPair.d.ts +16 -0
- package/dist/Component/Props/PropPairings.d.ts +89 -0
- package/dist/Component/Props/Props.d.ts +93 -0
- package/dist/Component/Props/SlotConstraints.d.ts +37 -0
- package/dist/Component/SlotContent/SlotCandidate.d.ts +42 -0
- package/dist/Component/SlotContent/SlotContent.d.ts +84 -0
- package/dist/Component/SlotContent/SlotDetector.d.ts +85 -0
- package/dist/Component/SlotContent/SlotItem.d.ts +44 -0
- package/dist/Component/SlotContent/SlotRegistry.d.ts +61 -0
- package/dist/Component/Styles/Composites/BiaxialComposite.d.ts +64 -0
- package/dist/Component/Styles/Composites/QuadComposite.d.ts +80 -0
- package/dist/Component/Styles/Composites/index.d.ts +4 -0
- package/dist/Component/Styles/Primitives/AspectRatioStyle.d.ts +34 -0
- package/dist/Component/Styles/Primitives/BooleanStyle.d.ts +6 -0
- package/dist/Component/Styles/Primitives/ColorStyle.d.ts +29 -0
- package/dist/Component/Styles/Primitives/ConditionalStyle.d.ts +30 -0
- package/dist/Component/Styles/Primitives/CornerStyle.d.ts +12 -0
- package/dist/Component/Styles/Primitives/EffectsStyle.d.ts +13 -0
- package/dist/Component/Styles/Primitives/IconFillStyle.d.ts +40 -0
- package/dist/Component/Styles/Primitives/MixedStyle.d.ts +5 -0
- package/dist/Component/Styles/Primitives/NumberStyle.d.ts +7 -0
- package/dist/Component/Styles/Primitives/PaddingStyle.d.ts +13 -0
- package/dist/Component/Styles/Primitives/StringStyle.d.ts +5 -0
- package/dist/Component/Styles/Primitives/StrokeStyle.d.ts +12 -0
- package/dist/Component/Styles/Primitives/TypographyStyle.d.ts +21 -0
- package/dist/Component/Styles/Primitives/index.d.ts +13 -0
- package/dist/Component/Styles/Primitives/mapping.d.ts +85 -0
- package/dist/Component/Styles/References/FigmaStyleReference.d.ts +45 -0
- package/dist/Component/Styles/References/FigmaVariableReference.d.ts +61 -0
- package/dist/Component/Styles/References/index.d.ts +24 -0
- package/dist/Component/Styles/Style.d.ts +88 -0
- package/dist/Component/Styles/Styles.d.ts +108 -0
- package/dist/Component/Styles/StylesProcessor.d.ts +96 -0
- package/dist/Component/Styles/defaults.d.ts +2 -0
- package/dist/Component/Styles/figmaKeyMap.d.ts +12 -0
- package/dist/Component/Styles/keys.d.ts +20 -0
- package/dist/Component/Subcomponents/Subcomponent.d.ts +20 -0
- package/dist/Component/Subcomponents/Subcomponents.d.ts +83 -0
- package/dist/Component/Typography/FontStyle.d.ts +6 -0
- package/dist/Component/Typography/LetterSpacingStyle.d.ts +4 -0
- package/dist/Component/Typography/LineHeightStyle.d.ts +4 -0
- package/dist/Component/Typography/Typography.d.ts +105 -0
- package/dist/Component/Typography/TypographyProcessor.d.ts +33 -0
- package/dist/Component/Typography/constants.d.ts +20 -0
- package/dist/Component/Typography/defaults.d.ts +30 -0
- package/dist/Component/Typography/keys.d.ts +12 -0
- package/dist/Component/Variants/Differencer.d.ts +47 -0
- package/dist/Component/Variants/Variant.d.ts +55 -0
- package/dist/Component/Variants/Variants.d.ts +91 -0
- package/dist/Components/Components.d.ts +68 -0
- package/dist/Config/types.Settings.d.ts +30 -0
- package/dist/Constants/ApiMappings.d.ts +31 -0
- package/dist/Constants/BindingKeys.d.ts +2 -0
- package/dist/Constants/DevSettings.d.ts +4 -0
- package/dist/Constants/Nodes.d.ts +1 -0
- package/dist/License/LicenseManager.d.ts +43 -0
- package/dist/License/ProxyClient.d.ts +25 -0
- package/dist/License/constants.d.ts +41 -0
- package/dist/License/types.d.ts +83 -0
- package/dist/Progress/PhaseConfiguration.d.ts +20 -0
- package/dist/Progress/Progress.d.ts +107 -0
- package/dist/Progress/ProgressCoordinator.d.ts +33 -0
- package/dist/Runtime/Context/interfaces.d.ts +73 -0
- package/dist/Runtime/Foundations/FigmaPluginFoundations.d.ts +37 -0
- package/dist/Runtime/Foundations/FigmaRESTFoundations.d.ts +72 -0
- package/dist/Runtime/Foundations/FigmaRESTMaps.d.ts +55 -0
- package/dist/Runtime/Foundations/interfaces.d.ts +72 -0
- package/dist/Runtime/Nodes/FigmaPluginNodes.d.ts +45 -0
- package/dist/Runtime/Nodes/FigmaRestNodes.d.ts +43 -0
- package/dist/Runtime/Nodes/NodeAccess.d.ts +23 -0
- package/dist/Runtime/Nodes/interfaces.d.ts +60 -0
- package/dist/Utilities/Utilities.d.ts +44 -0
- package/dist/Utilities/types.ReferenceValue.d.ts +16 -0
- package/dist/index.js +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Per-variant binding co-occurrence detected on a single element */
|
|
2
|
+
export interface PropPairCandidate {
|
|
3
|
+
elementName: string;
|
|
4
|
+
visiblePropName: string;
|
|
5
|
+
contentKey: 'mainComponent' | 'characters' | 'slotContentId';
|
|
6
|
+
contentPropName: string;
|
|
7
|
+
}
|
|
8
|
+
/** Cross-variant validated binding pair */
|
|
9
|
+
export interface PropPair {
|
|
10
|
+
elementName: string;
|
|
11
|
+
booleanPropName: string;
|
|
12
|
+
contentKey: 'mainComponent' | 'characters' | 'slotContentId';
|
|
13
|
+
contentPropName: string;
|
|
14
|
+
contentType: 'glyph' | 'string' | 'slot';
|
|
15
|
+
booleanDefault: boolean;
|
|
16
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { FigmaElementNode } from '../Nodes/types.js';
|
|
2
|
+
import type { SpecableNode } from '../Nodes/types.js';
|
|
3
|
+
import type { AnyProp as AnovaAnyProp, ResolvedConfig } from '@directededges/specs-schema';
|
|
4
|
+
import type { PropPairCandidate, PropPair } from './PropPair.js';
|
|
5
|
+
import { ConditionalStyle } from '../Styles/Primitives/ConditionalStyle.js';
|
|
6
|
+
/**
|
|
7
|
+
* Variant type subset used by from(). Avoids importing Variant directly
|
|
8
|
+
* to prevent circular dependencies.
|
|
9
|
+
*/
|
|
10
|
+
interface PairableVariant {
|
|
11
|
+
invalid: boolean;
|
|
12
|
+
bindingPairCandidates: PropPairCandidate[];
|
|
13
|
+
full: {
|
|
14
|
+
get(name: string): {
|
|
15
|
+
node: FigmaElementNode;
|
|
16
|
+
} | undefined;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* PropPairings — collection class for validated prop pairs.
|
|
21
|
+
*
|
|
22
|
+
* Follows the _items + method pattern of Elements, Variants, and Styles.
|
|
23
|
+
* Owns detection, cross-variant validation, active-pair orchestration,
|
|
24
|
+
* and prop enrichment.
|
|
25
|
+
*/
|
|
26
|
+
export declare class PropPairings {
|
|
27
|
+
private _items;
|
|
28
|
+
private _byElement;
|
|
29
|
+
private static _active?;
|
|
30
|
+
constructor(items: PropPair[]);
|
|
31
|
+
/**
|
|
32
|
+
* Scan nodes for visible + content binding co-occurrence.
|
|
33
|
+
* Called per-variant during construction. Returns candidates (not yet validated).
|
|
34
|
+
*/
|
|
35
|
+
static scan(nodes: FigmaElementNode[]): PropPairCandidate[];
|
|
36
|
+
/**
|
|
37
|
+
* Cross-variant validation of binding pair candidates.
|
|
38
|
+
* Applies validation rules (FR-002 through FR-005) and resolves content type and boolean default.
|
|
39
|
+
*/
|
|
40
|
+
static from(variants: PairableVariant[], node: SpecableNode): PropPairings;
|
|
41
|
+
/**
|
|
42
|
+
* Activate the pair for a given element name.
|
|
43
|
+
* Called during element evaluation so Style can read the active pair.
|
|
44
|
+
*/
|
|
45
|
+
activate(elementName: string): void;
|
|
46
|
+
/**
|
|
47
|
+
* Clear the active pair after element evaluation.
|
|
48
|
+
*/
|
|
49
|
+
deactivate(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Evaluate whether the current element's visible binding should become
|
|
52
|
+
* a ConditionalStyle. Returns the ConditionalStyle if paired, undefined otherwise.
|
|
53
|
+
*/
|
|
54
|
+
static evaluateVisible(node: FigmaElementNode): ConditionalStyle | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Returns the set of boolean prop names that are paired and should be
|
|
57
|
+
* excluded from prop output.
|
|
58
|
+
*/
|
|
59
|
+
pairedBooleans(): Set<string>;
|
|
60
|
+
/**
|
|
61
|
+
* Build a lookup from content prop name to its validated pair.
|
|
62
|
+
* Used by Props.process() to apply nullable pairing during prop iteration.
|
|
63
|
+
*/
|
|
64
|
+
pairsByProp(): Map<string, PropPair>;
|
|
65
|
+
/**
|
|
66
|
+
* Apply binding pair merging to a content prop: set nullable, default, and metadata.
|
|
67
|
+
*/
|
|
68
|
+
static apply(item: AnovaAnyProp, pair: PropPair, keyFormat: ResolvedConfig['format']['keys']): void;
|
|
69
|
+
get items(): readonly PropPair[];
|
|
70
|
+
get size(): number;
|
|
71
|
+
isEmpty(): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Group binding pair candidates by boolean prop name across all variants.
|
|
74
|
+
*/
|
|
75
|
+
private static groupCandidatesByBoolean;
|
|
76
|
+
/**
|
|
77
|
+
* Track content-only bindings (no visible co-occurrence) for subset rule.
|
|
78
|
+
*/
|
|
79
|
+
private static trackContentOnlyBindings;
|
|
80
|
+
/**
|
|
81
|
+
* Resolve the default value of a boolean component property definition.
|
|
82
|
+
*/
|
|
83
|
+
private static resolveBooleanDefault;
|
|
84
|
+
/**
|
|
85
|
+
* Set nullable and default on a content prop based on the pair's content type.
|
|
86
|
+
*/
|
|
87
|
+
private static setNullable;
|
|
88
|
+
}
|
|
89
|
+
export {};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { SpecableNode, FigmaElementNode } from '../Nodes/types.js';
|
|
2
|
+
import { Props as AnovaProps } from '@directededges/specs-schema';
|
|
3
|
+
import { Utilities } from "../../Utilities/Utilities.js";
|
|
4
|
+
import type { ProcessingContext } from '../../Runtime/Context/interfaces.js';
|
|
5
|
+
import { ResolvedConfig } from '@directededges/specs-schema';
|
|
6
|
+
import { PropPairings } from './PropPairings.js';
|
|
7
|
+
export type PropDefinition = ComponentPropertyDefinitions[string];
|
|
8
|
+
export type VariantPropDefinition = PropDefinition & {
|
|
9
|
+
type: 'VARIANT';
|
|
10
|
+
defaultValue: string;
|
|
11
|
+
variantOptions?: string[];
|
|
12
|
+
};
|
|
13
|
+
export declare class Props {
|
|
14
|
+
private _component;
|
|
15
|
+
private _items;
|
|
16
|
+
private _definitions;
|
|
17
|
+
private _validDefinition;
|
|
18
|
+
get validDefinition(): boolean;
|
|
19
|
+
get props(): AnovaProps;
|
|
20
|
+
private config;
|
|
21
|
+
constructor(component: SpecableNode, config: ResolvedConfig);
|
|
22
|
+
process(context?: ProcessingContext, pairings?: PropPairings, codeOnlyContainer?: FigmaElementNode): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Resolve INSTANCE_SWAP component ID to human-readable component name
|
|
25
|
+
* @param componentId - Component node ID (e.g., "1:1")
|
|
26
|
+
* @param context - Processing context with node resolver
|
|
27
|
+
* @returns ComponentSet name, Component name, or null if not found
|
|
28
|
+
*/
|
|
29
|
+
private resolveInstanceSwapDefault;
|
|
30
|
+
/**
|
|
31
|
+
* Numeric inference guard (ADR 029).
|
|
32
|
+
* Returns true only when the value is a finite number with no leading zeros.
|
|
33
|
+
*/
|
|
34
|
+
static isNumericValue(value: string): boolean;
|
|
35
|
+
data(): AnovaProps | undefined;
|
|
36
|
+
static propNameWithoutId(key: string): string;
|
|
37
|
+
static getDefinitions(component: InstanceNode | ComponentNode | ComponentSetNode): Promise<ComponentPropertyDefinitions | 'exception'>;
|
|
38
|
+
static exception(component: InstanceNode | ComponentNode | ComponentSetNode): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Check if component has any properties
|
|
41
|
+
*/
|
|
42
|
+
hasProperties(): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Get raw property definitions, optionally filtered by type
|
|
45
|
+
*/
|
|
46
|
+
getDefinitions(): Awaited<ReturnType<typeof Utilities.getPropertyDefinitions>> | undefined;
|
|
47
|
+
getDefinitions(type: 'VARIANT'): Record<string, VariantPropDefinition> | undefined;
|
|
48
|
+
getDefinitions(type: 'BOOLEAN' | 'TEXT' | 'INSTANCE_SWAP' | 'SLOT'): Record<string, PropDefinition> | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Returns an iterator over [propName, definition] entries.
|
|
51
|
+
* @example
|
|
52
|
+
* for (const [name, definition] of props.entries()) {
|
|
53
|
+
* console.log(name, definition.type);
|
|
54
|
+
* }
|
|
55
|
+
*/
|
|
56
|
+
entries(): IterableIterator<[string, PropDefinition]>;
|
|
57
|
+
/**
|
|
58
|
+
* Returns an iterator over property definition values.
|
|
59
|
+
* @example
|
|
60
|
+
* for (const definition of props.values()) {
|
|
61
|
+
* console.log(definition.type);
|
|
62
|
+
* }
|
|
63
|
+
*/
|
|
64
|
+
values(): IterableIterator<PropDefinition>;
|
|
65
|
+
/**
|
|
66
|
+
* Returns an iterator over property names.
|
|
67
|
+
* @example
|
|
68
|
+
* for (const name of props.keys()) {
|
|
69
|
+
* console.log(name);
|
|
70
|
+
* }
|
|
71
|
+
*/
|
|
72
|
+
keys(): IterableIterator<string>;
|
|
73
|
+
/**
|
|
74
|
+
* Makes Props directly iterable (defaults to entries).
|
|
75
|
+
* @example
|
|
76
|
+
* for (const [name, definition] of props) {
|
|
77
|
+
* console.log(name, definition);
|
|
78
|
+
* }
|
|
79
|
+
*/
|
|
80
|
+
[Symbol.iterator](): IterableIterator<[string, PropDefinition]>;
|
|
81
|
+
/**
|
|
82
|
+
* Returns the number of property definitions.
|
|
83
|
+
*/
|
|
84
|
+
get size(): number;
|
|
85
|
+
/**
|
|
86
|
+
* Checks if there are no property definitions.
|
|
87
|
+
* @example
|
|
88
|
+
* if (props.isEmpty()) {
|
|
89
|
+
* return;
|
|
90
|
+
* }
|
|
91
|
+
*/
|
|
92
|
+
isEmpty(): boolean;
|
|
93
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { AnyProp } from '@directededges/specs-schema';
|
|
2
|
+
export declare class SlotConstraints {
|
|
3
|
+
/**
|
|
4
|
+
* Post-process the merged props map to promote slot constraint code-only props
|
|
5
|
+
* onto their matching SlotProp fields.
|
|
6
|
+
*
|
|
7
|
+
* Scans for code-only props whose names match `{existingSlotName} minItems|maxItems|anyOf`.
|
|
8
|
+
* When a match is found against an existing slot prop, the constraint value is promoted
|
|
9
|
+
* onto the SlotProp and the constraint prop is removed from the map.
|
|
10
|
+
*
|
|
11
|
+
* Follows the StylesProcessor.postProcess() pattern.
|
|
12
|
+
*/
|
|
13
|
+
static postProcess(props: Record<string, AnyProp>): void;
|
|
14
|
+
/**
|
|
15
|
+
* Parse a prop key to see if it matches the pattern `{slotName} {constraintType}`.
|
|
16
|
+
* Keys are raw (unformatted), so "Children minItems" matches slot "Children" + suffix "minItems".
|
|
17
|
+
*/
|
|
18
|
+
private static parseConstraintKey;
|
|
19
|
+
/**
|
|
20
|
+
* True if a raw prop key is a slot constraint (`{slotName} minItems|maxItems|anyOf`)
|
|
21
|
+
* for one of the given slot names. Used to keep instance propConfigurations symmetric
|
|
22
|
+
* with the component side, which promotes these onto the SlotProp and removes them.
|
|
23
|
+
*/
|
|
24
|
+
static isConstraintKey(key: string, slotNames: Set<string>): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Extract the constraint value from a code-only prop.
|
|
27
|
+
* The value lives in examples[0] (preferred) or default. Both string and number
|
|
28
|
+
* props are supported: with inferNumberProps enabled, minItems/maxItems constraint
|
|
29
|
+
* props are inferred as number, so their value must be coerced to string here.
|
|
30
|
+
*/
|
|
31
|
+
private static getConstraintValue;
|
|
32
|
+
/**
|
|
33
|
+
* Promote a constraint value onto a SlotProp.
|
|
34
|
+
* Returns true if promotion succeeded, false if value is invalid.
|
|
35
|
+
*/
|
|
36
|
+
private static promote;
|
|
37
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ResolvedConfig } from '@directededges/specs-schema';
|
|
2
|
+
import type { SlotItem } from './SlotItem.js';
|
|
3
|
+
/**
|
|
4
|
+
* One candidate slot fill, produced by SlotDetector and consumed by SlotRegistry.
|
|
5
|
+
* Transient: carries the resolved SlotItem payload, a derived key candidate, and
|
|
6
|
+
* the wiring coordinates (element name + variant) needed to attach the example
|
|
7
|
+
* reference back onto the slot binding after de-duplication. Discarded once the
|
|
8
|
+
* registry emits.
|
|
9
|
+
*/
|
|
10
|
+
export declare class SlotCandidate {
|
|
11
|
+
/** Proposed key (may be superseded by an existing entry after de-dup). */
|
|
12
|
+
readonly keyCandidate: string;
|
|
13
|
+
/** The resolved slot fill payload — provides layout/anatomy/elements data. */
|
|
14
|
+
readonly item: SlotItem;
|
|
15
|
+
/** Figma layer name of the slot element — used to wire the example reference. */
|
|
16
|
+
readonly elementName: string;
|
|
17
|
+
/** Variant configuration string used in key derivation and wiring. */
|
|
18
|
+
readonly variantKey: string;
|
|
19
|
+
/** True if this slot was found inside an instance (nested), not directly in the component tree. */
|
|
20
|
+
readonly nested: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Figma node id of the slot. Collision-proof wiring identity for nested slots —
|
|
23
|
+
* slot *names* repeat across sibling instances (e.g. two "Slot" layers), node ids
|
|
24
|
+
* do not. The human-readable spec key (`keyCandidate`) stays name-derived and is
|
|
25
|
+
* disambiguated only at registry emission.
|
|
26
|
+
*/
|
|
27
|
+
readonly slotNodeId: string;
|
|
28
|
+
constructor(elementName: string, variantKey: string, hostComponentName: string, item: SlotItem, config: ResolvedConfig, nested?: boolean, keyPrefix?: string, slotNodeId?: string);
|
|
29
|
+
/**
|
|
30
|
+
* Canonical string for layout-only de-duplication.
|
|
31
|
+
* Depth-first traversal of the layout tree.
|
|
32
|
+
*/
|
|
33
|
+
layoutKey(): string;
|
|
34
|
+
/**
|
|
35
|
+
* Compound key for layout + anatomy de-duplication.
|
|
36
|
+
*/
|
|
37
|
+
layoutAnatomyKey(): string;
|
|
38
|
+
/**
|
|
39
|
+
* Compound key for full de-duplication (layout + anatomy + elements).
|
|
40
|
+
*/
|
|
41
|
+
fullKey(): string;
|
|
42
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { SlotRegistry } from './SlotRegistry.js';
|
|
2
|
+
import type { NestedSlotRelation } from './SlotDetector.js';
|
|
3
|
+
import type { ResolvedConfig, SlotContent as AnovaSlotContent } from '@directededges/specs-schema';
|
|
4
|
+
import type { Variant } from '../Variants/Variant.js';
|
|
5
|
+
import { type ProcessingContext } from '../../Runtime/Context/interfaces.js';
|
|
6
|
+
export interface SlotContentOptions {
|
|
7
|
+
/** Component (or subcomponent) name that hosts the slots — used in entry keys. */
|
|
8
|
+
hostComponentName: string;
|
|
9
|
+
/** JSON Pointer base for example references (e.g. `#/components/egdsAlert`). */
|
|
10
|
+
basePath: string;
|
|
11
|
+
/** Output field this content serializes under. */
|
|
12
|
+
outputKey: 'slotContentExamples' | 'slotContent';
|
|
13
|
+
config: ResolvedConfig;
|
|
14
|
+
/**
|
|
15
|
+
* Shared slot registry. Component creates one registry and passes it to both
|
|
16
|
+
* SlotContent and InstanceExamples so identical fills dedup to a single entry
|
|
17
|
+
* regardless of source. When omitted, a private registry is created (legacy /
|
|
18
|
+
* standalone behavior).
|
|
19
|
+
*/
|
|
20
|
+
registry?: SlotRegistry;
|
|
21
|
+
/**
|
|
22
|
+
* Whether to stamp `$slotContent` references onto the component's own slot
|
|
23
|
+
* bindings (and thereby mark those registry entries referenced for emission).
|
|
24
|
+
* Maps to `include.defaultSlotContent`. When false, fills are still detected
|
|
25
|
+
* and contributed to the shared registry, but no component-side pointers are
|
|
26
|
+
* emitted and no entries are marked referenced by this collaborator.
|
|
27
|
+
*/
|
|
28
|
+
stampReferences?: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Top-level collaborator for slot content — sibling to Variants, Props, Anatomy,
|
|
32
|
+
* Subcomponents. Detects (SlotDetector) the component's own slot fills,
|
|
33
|
+
* contributes them to a (shared) SlotRegistry for de-duplication, and — when
|
|
34
|
+
* stamping is enabled — wires example references onto slot bindings and marks
|
|
35
|
+
* the referenced entries for emission. Parameterized so it serves both Component
|
|
36
|
+
* (`slotContentExamples`) and the future Composition (`slotContent`).
|
|
37
|
+
*/
|
|
38
|
+
export declare class SlotContent {
|
|
39
|
+
private _detector;
|
|
40
|
+
private _hostComponentName;
|
|
41
|
+
private _basePath;
|
|
42
|
+
private _outputKey;
|
|
43
|
+
private _config;
|
|
44
|
+
private _registry;
|
|
45
|
+
private _stampReferences;
|
|
46
|
+
private _nestedRelations;
|
|
47
|
+
constructor(options: SlotContentOptions);
|
|
48
|
+
/**
|
|
49
|
+
* Detect slot fills across variants, contribute them to the shared registry,
|
|
50
|
+
* and (when stamping is enabled) stamp example references onto each variant's
|
|
51
|
+
* `full` slot bindings, marking the referenced entries for emission. Must run
|
|
52
|
+
* after variants are evaluated but BEFORE variants.layer(), so differencing
|
|
53
|
+
* captures the example references.
|
|
54
|
+
*/
|
|
55
|
+
process(variants: Variant[], context?: ProcessingContext): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* The serialized slot content record (keyed by final key), referenced entries
|
|
58
|
+
* only. When this collaborator owns its registry (standalone use) this is the
|
|
59
|
+
* full picture; when the registry is shared, the Component reads the registry
|
|
60
|
+
* directly so all sources contribute.
|
|
61
|
+
*/
|
|
62
|
+
data(): Record<string, AnovaSlotContent>;
|
|
63
|
+
get outputKey(): 'slotContentExamples' | 'slotContent';
|
|
64
|
+
/** True when this collaborator's own registry has emitted nothing. */
|
|
65
|
+
get isEmpty(): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Stamp the example reference for each de-duplicated entry onto the matching
|
|
68
|
+
* slot-bound Children in each variant's `full` element map, and mark the
|
|
69
|
+
* referenced registry entries for emission.
|
|
70
|
+
*/
|
|
71
|
+
private _wireExamples;
|
|
72
|
+
private _injectNestedPointers;
|
|
73
|
+
/**
|
|
74
|
+
* Inject SlotContentRef into instance elements nested inside slot content entries.
|
|
75
|
+
* For each relation (containingSlot → instance → childSlot), resolve both final
|
|
76
|
+
* keys (parent from top-level wiring, child from nested wiring — they may share a
|
|
77
|
+
* Figma name like "Children"), and add propConfigurations.<childSlotName>:
|
|
78
|
+
* { $slotContent } to the instance element in the parent entry. Marks both
|
|
79
|
+
* entries referenced. Shared by component slot content and instance examples.
|
|
80
|
+
*/
|
|
81
|
+
static injectNestedPointers(nestedRelations: NestedSlotRelation[], registry: SlotRegistry, basePath: string, outputKey: 'slotContentExamples' | 'slotContent', config: ResolvedConfig): void;
|
|
82
|
+
/** Variant suffix used as the wiring key — must match SlotDetector's derivation. */
|
|
83
|
+
private _variantKey;
|
|
84
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { SlotCandidate } from './SlotCandidate.js';
|
|
2
|
+
import type { ResolvedConfig } from '@directededges/specs-schema';
|
|
3
|
+
import type { FigmaElementNode } from '../Nodes/types.js';
|
|
4
|
+
import type { Variant } from '../Variants/Variant.js';
|
|
5
|
+
import type { ProcessingContext } from '../../Runtime/Context/interfaces.js';
|
|
6
|
+
/**
|
|
7
|
+
* Describes a slot nested inside an instance element within a slot content space.
|
|
8
|
+
* Used to inject SlotContentRef into the parent slot content's elements after registry finalization.
|
|
9
|
+
*
|
|
10
|
+
* Structure: ContainingSlot → (slot content) → InstanceNode → ChildSlot
|
|
11
|
+
*/
|
|
12
|
+
export interface NestedSlotRelation {
|
|
13
|
+
/** Element name of the slot whose content contains the instance. */
|
|
14
|
+
containingSlotElementName: string;
|
|
15
|
+
containingVariantKey: string;
|
|
16
|
+
/**
|
|
17
|
+
* Figma node id of the containing slot. Used as the wiring identity (node ids are
|
|
18
|
+
* unique; slot *names* collide across sibling instances). Resolves the parent
|
|
19
|
+
* entry when the containing slot is itself nested.
|
|
20
|
+
*/
|
|
21
|
+
containingSlotId: string;
|
|
22
|
+
/** Figma node name of the instance element (must be present in containingSlot's elements). */
|
|
23
|
+
instanceNodeName: string;
|
|
24
|
+
/** Element name of the slot found inside the instance. */
|
|
25
|
+
childSlotElementName: string;
|
|
26
|
+
childVariantKey: string;
|
|
27
|
+
/** Figma node id of the child slot — the collision-proof wiring identity. */
|
|
28
|
+
childSlotId: string;
|
|
29
|
+
/**
|
|
30
|
+
* Instance names crossed BELOW the anchor instance (`instanceNodeName`) down to
|
|
31
|
+
* the instance that owns the child slot. Empty for the single-hop case
|
|
32
|
+
* (slot → instance → childSlot); non-empty for deeper chains, where it becomes
|
|
33
|
+
* the `path` of a `$nested` entry on the anchor instance (ADR-052).
|
|
34
|
+
*/
|
|
35
|
+
nestedInstancePath: string[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Walks all variants of a component, finds slot layers with authored content,
|
|
39
|
+
* and produces SlotCandidate instances for SlotRegistry.
|
|
40
|
+
*
|
|
41
|
+
* Walk rule:
|
|
42
|
+
* - Walk the variant node's children recursively
|
|
43
|
+
* - When a SLOT node is found, check if it has authored content (non-empty children)
|
|
44
|
+
* - If it does, build a SlotCandidate for it
|
|
45
|
+
* - INSTANCE children: recurse into them to find nested slots
|
|
46
|
+
* - Guard against cycles using the instance's componentId
|
|
47
|
+
* - Each slot found inside an instance produces its own SlotCandidate
|
|
48
|
+
*/
|
|
49
|
+
export declare class SlotDetector {
|
|
50
|
+
private config;
|
|
51
|
+
constructor(config: ResolvedConfig);
|
|
52
|
+
/**
|
|
53
|
+
* Traverse all variants and produce slot fill candidates.
|
|
54
|
+
* Returns candidates (one per filled slot × variant) and nestedRelations
|
|
55
|
+
* (instance-within-slot relationships needed for SlotContentRef injection).
|
|
56
|
+
*/
|
|
57
|
+
traverse(variants: Variant[], hostComponentName: string, context?: ProcessingContext): Promise<{
|
|
58
|
+
candidates: SlotCandidate[];
|
|
59
|
+
nestedRelations: NestedSlotRelation[];
|
|
60
|
+
}>;
|
|
61
|
+
/**
|
|
62
|
+
* Traverse a single node (e.g. an instance-example node) with the same recursive
|
|
63
|
+
* slot/nesting rules as {@link traverse}. `variantSuffix` is the disambiguated
|
|
64
|
+
* example key (used as the wiring coordinate); `keyPrefix` (the base example key,
|
|
65
|
+
* un-disambiguated) prefixes every produced slot-content key at all nesting depths,
|
|
66
|
+
* so the registry entries an instance example contributes all begin with the
|
|
67
|
+
* instance name and any `__N` disambiguator lands at the end of the final key.
|
|
68
|
+
*/
|
|
69
|
+
traverseNode(node: FigmaElementNode, variantSuffix: string, hostComponentName: string, context?: ProcessingContext, keyPrefix?: string): Promise<{
|
|
70
|
+
candidates: SlotCandidate[];
|
|
71
|
+
nestedRelations: NestedSlotRelation[];
|
|
72
|
+
}>;
|
|
73
|
+
/**
|
|
74
|
+
* Recursively walk a node's children looking for SLOT nodes with authored content.
|
|
75
|
+
* Recurses into INSTANCE children to find nested slots, guarded by componentId.
|
|
76
|
+
*
|
|
77
|
+
* containingSlotName: the Figma name of the nearest ancestor slot node (if any).
|
|
78
|
+
* containingInstanceName: the Figma name of the nearest instance node within that slot's content.
|
|
79
|
+
* When a slot is found inside an instance that is inside a slot, a NestedSlotRelation is recorded.
|
|
80
|
+
*/
|
|
81
|
+
private _visit;
|
|
82
|
+
private _processSlotNode;
|
|
83
|
+
/** Derive the variant suffix portion of the entry key. */
|
|
84
|
+
private _variantSuffix;
|
|
85
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ResolvedConfig, SlotContent as AnovaSlotContent } from '@directededges/specs-schema';
|
|
2
|
+
import type { ProcessingContext } from '../../Runtime/Context/interfaces.js';
|
|
3
|
+
/**
|
|
4
|
+
* The resolved payload for a single Figma slot layer — the anatomy + elements + layout triplet.
|
|
5
|
+
*
|
|
6
|
+
* Each slot's content is its own "space" — traversed independently from the component anatomy.
|
|
7
|
+
* Traversal starts at the slot's children (not the slot node itself), stops at instances.
|
|
8
|
+
* Mirrors the Variant lifecycle (evaluate → postProcess → data) but never calls difference().
|
|
9
|
+
* Stored as a value in the output `slotContentExamples` / `slotContent` record.
|
|
10
|
+
*/
|
|
11
|
+
export declare class SlotItem {
|
|
12
|
+
private _elements;
|
|
13
|
+
private _anatomy;
|
|
14
|
+
private _layout?;
|
|
15
|
+
private _config;
|
|
16
|
+
readonly isEmpty: boolean;
|
|
17
|
+
constructor(slotNode: SlotNode, config: ResolvedConfig);
|
|
18
|
+
evaluate(context?: ProcessingContext): Promise<void>;
|
|
19
|
+
postProcess(context?: ProcessingContext): Promise<void>;
|
|
20
|
+
data(): AnovaSlotContent;
|
|
21
|
+
/**
|
|
22
|
+
* Canonical string for the layout tree.
|
|
23
|
+
* Serializes the slot content children (the synthetic root's children),
|
|
24
|
+
* so two structurally identical content trees produce the same key
|
|
25
|
+
* regardless of which slot hosts them.
|
|
26
|
+
*/
|
|
27
|
+
layoutKey(): string;
|
|
28
|
+
anatomyKey(): string;
|
|
29
|
+
layoutAnatomyKey(): string;
|
|
30
|
+
/** Elements equality key: SHA-256 of canonicalized elements (fixed-length Map key). */
|
|
31
|
+
elementsKey(): string;
|
|
32
|
+
private static _canonicalize;
|
|
33
|
+
/**
|
|
34
|
+
* Emit elements keyed by actual Figma node name (not Elements map key, which uses 'root'
|
|
35
|
+
* for the first element). Keeps anatomy, layout, and elements names consistent.
|
|
36
|
+
*/
|
|
37
|
+
private _elementsData;
|
|
38
|
+
/**
|
|
39
|
+
* The synthetic root holds the slot's content children. Layout.data() returns [{ root: [...] }].
|
|
40
|
+
* Unwrap to return the children array directly as the slot content's layout.
|
|
41
|
+
*/
|
|
42
|
+
private _fillLayout;
|
|
43
|
+
private _serializeLayoutNode;
|
|
44
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { SlotContent as AnovaSlotContent } from '@directededges/specs-schema';
|
|
2
|
+
import type { SlotCandidate } from './SlotCandidate.js';
|
|
3
|
+
/**
|
|
4
|
+
* De-duplicates SlotCandidate instances and assigns stable keys.
|
|
5
|
+
*
|
|
6
|
+
* De-dup is slot-agnostic: two candidates that produce identical structure
|
|
7
|
+
* (regardless of which slot element or variant they came from) share one entry.
|
|
8
|
+
* The same registry is shared between a component's own slot fills (via
|
|
9
|
+
* SlotContent) and the slot fills found inside instanceExamples, so identical
|
|
10
|
+
* fills from either source collapse to a single `slotContentExamples` entry with
|
|
11
|
+
* one reused key.
|
|
12
|
+
*
|
|
13
|
+
* De-dup fingerprint: layout + anatomy + elements (the candidate's fullKey).
|
|
14
|
+
*
|
|
15
|
+
* Emission is reference-gated: an entry is only serialized by `data()` if a
|
|
16
|
+
* consumer has marked its finalKey as referenced (`markReferenced`). This keeps
|
|
17
|
+
* the registry free of dangling entries when a consumer's `include.*` flag is
|
|
18
|
+
* off and avoids emitting fills that nothing points at.
|
|
19
|
+
*/
|
|
20
|
+
export declare class SlotRegistry {
|
|
21
|
+
/** finalKey → SlotContent data */
|
|
22
|
+
private _items;
|
|
23
|
+
/** fingerprint → finalKey (de-dup index) */
|
|
24
|
+
private _fingerprintIndex;
|
|
25
|
+
/** (elementName + variantKey) → finalKey for top-level slots (setExample wiring) */
|
|
26
|
+
private _topLevelWiring;
|
|
27
|
+
/** (elementName + variantKey) → finalKey for slots nested inside instances (Phase 5 wiring) */
|
|
28
|
+
private _nestedWiring;
|
|
29
|
+
/** finalKeys that an emitted consumer actually references — only these are serialized. */
|
|
30
|
+
private _referenced;
|
|
31
|
+
/**
|
|
32
|
+
* Register a candidate, de-duplicating against existing entries.
|
|
33
|
+
* Returns the finalKey assigned (existing key on a fingerprint match, else a
|
|
34
|
+
* freshly-resolved key). Registration alone does NOT emit the entry — call
|
|
35
|
+
* `markReferenced(finalKey)` once a consumer stamps a pointer to it.
|
|
36
|
+
*/
|
|
37
|
+
add(candidate: SlotCandidate): string;
|
|
38
|
+
/** Mark a finalKey as referenced by an emitted consumer so `data()` serializes it. */
|
|
39
|
+
markReferenced(finalKey: string): void;
|
|
40
|
+
/** The live SlotContent entry for a finalKey (mutable), or undefined. */
|
|
41
|
+
entry(finalKey: string): AnovaSlotContent | undefined;
|
|
42
|
+
/** Top-level wiring lookup: (elementName + '|' + variantKey) → finalKey. */
|
|
43
|
+
topLevelKey(wiringKey: string): string | undefined;
|
|
44
|
+
/** Nested wiring lookup: (elementName + '|' + variantKey) → finalKey. */
|
|
45
|
+
nestedKey(wiringKey: string): string | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Returns the slotContentExamples record (referenced entries only) and the
|
|
48
|
+
* wiring maps. Each wiring map: (elementName + '|' + variantKey) → finalKey.
|
|
49
|
+
*/
|
|
50
|
+
data(): {
|
|
51
|
+
slotContentExamples: Record<string, AnovaSlotContent>;
|
|
52
|
+
topLevelWiring: Map<string, string>;
|
|
53
|
+
nestedWiring: Map<string, string>;
|
|
54
|
+
};
|
|
55
|
+
/** True when no candidates have been registered. */
|
|
56
|
+
get isEmpty(): boolean;
|
|
57
|
+
/** True when nothing has been marked referenced (so `data()` would be empty). */
|
|
58
|
+
get hasReferences(): boolean;
|
|
59
|
+
/** Produce a unique final key, avoiding collisions with already-registered keys. */
|
|
60
|
+
private _resolveCollision;
|
|
61
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ResolvedConfig } from '@directededges/specs-schema';
|
|
2
|
+
import { FigmaVariableReference } from '../References/index.js';
|
|
3
|
+
import type { FigmaElementNode } from '../../Nodes/types.js';
|
|
4
|
+
/** Per-field value: raw number or variable reference */
|
|
5
|
+
export type BiaxialFieldValue = number | FigmaVariableReference;
|
|
6
|
+
export type BiaxialValue = number | FigmaVariableReference | BiaxialComposite;
|
|
7
|
+
/**
|
|
8
|
+
* Bi-axial composite for `{ horizontal, vertical }` spacing values.
|
|
9
|
+
* Used for `itemSpacing` when wrap is enabled and axes differ.
|
|
10
|
+
* Direction-aware: maps Figma primary/counter-axis to absolute horizontal/vertical
|
|
11
|
+
* based on layoutMode.
|
|
12
|
+
*/
|
|
13
|
+
export declare class BiaxialComposite {
|
|
14
|
+
private _fields;
|
|
15
|
+
constructor(fields: {
|
|
16
|
+
horizontal?: BiaxialFieldValue;
|
|
17
|
+
vertical?: BiaxialFieldValue;
|
|
18
|
+
});
|
|
19
|
+
/**
|
|
20
|
+
* Factory: read itemSpacing + counterAxisSpacing from a Figma node and produce
|
|
21
|
+
* a BiaxialComposite with direction-aware axis mapping.
|
|
22
|
+
* Picks up variable bindings when present and licensed.
|
|
23
|
+
*/
|
|
24
|
+
static fromNode(node: FigmaElementNode, layoutMode: 'HORIZONTAL' | 'VERTICAL', licensed?: boolean): BiaxialComposite;
|
|
25
|
+
/**
|
|
26
|
+
* Resolve a bound variable for a Figma node property key.
|
|
27
|
+
*/
|
|
28
|
+
private static getVariableForKey;
|
|
29
|
+
/**
|
|
30
|
+
* Compare against a baseline. Returns a sparse composite with only changed fields,
|
|
31
|
+
* or null if no fields differ.
|
|
32
|
+
*/
|
|
33
|
+
difference(baseline: BiaxialValue): BiaxialValue | null;
|
|
34
|
+
/**
|
|
35
|
+
* Style-level union router (like QuadComposite.differenceValues).
|
|
36
|
+
* Returns undefined when biaxial semantics do not apply.
|
|
37
|
+
*/
|
|
38
|
+
static differenceValues(current: unknown, baseline: unknown): BiaxialValue | null | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Merge a layered variant composite onto a baseline.
|
|
41
|
+
* Layer wins on overlapping axes.
|
|
42
|
+
*/
|
|
43
|
+
static merge(base: BiaxialValue, layer: BiaxialComposite | null): BiaxialValue;
|
|
44
|
+
clone(): BiaxialComposite;
|
|
45
|
+
data(config: ResolvedConfig): Record<string, unknown>;
|
|
46
|
+
/** Resolve variable names for all FigmaVariableReference fields */
|
|
47
|
+
resolveVariables(foundations: import('../../../Runtime/Foundations/interfaces.js').FigmaFoundations | undefined): Promise<void>;
|
|
48
|
+
/** True when all fields are plain numbers equal to the given scalar (for default removal) */
|
|
49
|
+
isEqualToScalar(scalar: number): boolean;
|
|
50
|
+
/** Get a field value by axis name */
|
|
51
|
+
get(field: 'horizontal' | 'vertical'): BiaxialFieldValue | undefined;
|
|
52
|
+
/** Returns axis names that have values */
|
|
53
|
+
fields(): string[];
|
|
54
|
+
private fieldValue;
|
|
55
|
+
private static resolveField;
|
|
56
|
+
private static fieldDiffers;
|
|
57
|
+
private static cloneField;
|
|
58
|
+
private static cloneValue;
|
|
59
|
+
/**
|
|
60
|
+
* Normalize: always preserve composite form (never collapse to scalar).
|
|
61
|
+
* Bi-axial values remain explicit even when both axes are equal.
|
|
62
|
+
*/
|
|
63
|
+
private static normalize;
|
|
64
|
+
}
|