@compact-design/core 0.1.0 → 0.2.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/generated-schema.d.ts +90 -3
- package/dist/index.cjs +178 -7
- package/dist/index.js +178 -7
- package/dist/types.d.ts +21 -1
- package/package.json +1 -1
|
@@ -462,7 +462,7 @@ declare const _default: {
|
|
|
462
462
|
readonly required: readonly ["type"];
|
|
463
463
|
readonly properties: {
|
|
464
464
|
readonly type: {
|
|
465
|
-
readonly enum: readonly ["DROP_SHADOW", "INNER_SHADOW", "LAYER_BLUR", "BACKGROUND_BLUR"];
|
|
465
|
+
readonly enum: readonly ["DROP_SHADOW", "INNER_SHADOW", "LAYER_BLUR", "BACKGROUND_BLUR", "NOISE", "TEXTURE", "GLASS", "SHADER"];
|
|
466
466
|
};
|
|
467
467
|
readonly color: {
|
|
468
468
|
readonly oneOf: readonly [{
|
|
@@ -489,7 +489,94 @@ declare const _default: {
|
|
|
489
489
|
readonly blendMode: {
|
|
490
490
|
readonly type: "string";
|
|
491
491
|
};
|
|
492
|
+
readonly showShadowBehindNode: {
|
|
493
|
+
readonly type: "boolean";
|
|
494
|
+
};
|
|
495
|
+
readonly blurType: {
|
|
496
|
+
readonly enum: readonly ["NORMAL", "PROGRESSIVE"];
|
|
497
|
+
};
|
|
498
|
+
readonly startRadius: {
|
|
499
|
+
readonly $ref: "#/$defs/nonNegativeNumber";
|
|
500
|
+
};
|
|
501
|
+
readonly startOffset: {
|
|
502
|
+
readonly $ref: "#/$defs/vector";
|
|
503
|
+
};
|
|
504
|
+
readonly endOffset: {
|
|
505
|
+
readonly $ref: "#/$defs/vector";
|
|
506
|
+
};
|
|
507
|
+
readonly noiseType: {
|
|
508
|
+
readonly enum: readonly ["MONOTONE", "DUOTONE", "MULTITONE"];
|
|
509
|
+
};
|
|
510
|
+
readonly noiseSize: {
|
|
511
|
+
readonly $ref: "#/$defs/nonNegativeNumber";
|
|
512
|
+
};
|
|
513
|
+
readonly density: {
|
|
514
|
+
readonly type: "number";
|
|
515
|
+
readonly minimum: 0;
|
|
516
|
+
readonly maximum: 1;
|
|
517
|
+
};
|
|
518
|
+
readonly secondaryColor: {
|
|
519
|
+
readonly oneOf: readonly [{
|
|
520
|
+
readonly $ref: "#/$defs/hexColor";
|
|
521
|
+
}, {
|
|
522
|
+
readonly $ref: "#/$defs/color";
|
|
523
|
+
}];
|
|
524
|
+
};
|
|
525
|
+
readonly opacity: {
|
|
526
|
+
readonly type: "number";
|
|
527
|
+
readonly minimum: 0;
|
|
528
|
+
readonly maximum: 1;
|
|
529
|
+
};
|
|
530
|
+
readonly clipToShape: {
|
|
531
|
+
readonly type: "boolean";
|
|
532
|
+
};
|
|
533
|
+
readonly lightIntensity: {
|
|
534
|
+
readonly type: "number";
|
|
535
|
+
readonly minimum: 0;
|
|
536
|
+
readonly maximum: 1;
|
|
537
|
+
};
|
|
538
|
+
readonly lightAngle: {
|
|
539
|
+
readonly type: "number";
|
|
540
|
+
};
|
|
541
|
+
readonly refraction: {
|
|
542
|
+
readonly type: "number";
|
|
543
|
+
readonly minimum: 0;
|
|
544
|
+
readonly maximum: 1;
|
|
545
|
+
};
|
|
546
|
+
readonly depth: {
|
|
547
|
+
readonly type: "number";
|
|
548
|
+
readonly minimum: 1;
|
|
549
|
+
};
|
|
550
|
+
readonly dispersion: {
|
|
551
|
+
readonly type: "number";
|
|
552
|
+
readonly minimum: 0;
|
|
553
|
+
readonly maximum: 1;
|
|
554
|
+
};
|
|
555
|
+
readonly id: {
|
|
556
|
+
readonly type: "string";
|
|
557
|
+
readonly minLength: 1;
|
|
558
|
+
};
|
|
559
|
+
readonly properties: {
|
|
560
|
+
readonly type: "object";
|
|
561
|
+
readonly description: "SHADER property assignments keyed by Figma property-definition id. Values pass through verbatim (numbers, booleans, strings, colors, points, gradients, or variable aliases).";
|
|
562
|
+
readonly additionalProperties: {
|
|
563
|
+
readonly type: readonly ["boolean", "string", "number", "object"];
|
|
564
|
+
};
|
|
565
|
+
};
|
|
492
566
|
};
|
|
567
|
+
readonly allOf: readonly [{
|
|
568
|
+
readonly if: {
|
|
569
|
+
readonly properties: {
|
|
570
|
+
readonly type: {
|
|
571
|
+
readonly const: "SHADER";
|
|
572
|
+
};
|
|
573
|
+
};
|
|
574
|
+
readonly required: readonly ["type"];
|
|
575
|
+
};
|
|
576
|
+
readonly then: {
|
|
577
|
+
readonly required: readonly ["id"];
|
|
578
|
+
};
|
|
579
|
+
}];
|
|
493
580
|
};
|
|
494
581
|
readonly shadow: {
|
|
495
582
|
readonly type: "object";
|
|
@@ -873,7 +960,7 @@ declare const _default: {
|
|
|
873
960
|
readonly required: readonly ["data"];
|
|
874
961
|
readonly properties: {
|
|
875
962
|
readonly windingRule: {
|
|
876
|
-
readonly enum: readonly ["NONZERO", "EVENODD"];
|
|
963
|
+
readonly enum: readonly ["NONZERO", "EVENODD", "NONE"];
|
|
877
964
|
};
|
|
878
965
|
readonly data: {
|
|
879
966
|
readonly type: "string";
|
|
@@ -1187,7 +1274,7 @@ declare const _default: {
|
|
|
1187
1274
|
};
|
|
1188
1275
|
};
|
|
1189
1276
|
readonly overflowDirection: {
|
|
1190
|
-
readonly enum: readonly ["NONE", "HORIZONTAL_SCROLLING", "VERTICAL_SCROLLING", "HORIZONTAL_AND_VERTICAL_SCROLLING"];
|
|
1277
|
+
readonly enum: readonly ["NONE", "HORIZONTAL", "VERTICAL", "BOTH", "HORIZONTAL_SCROLLING", "VERTICAL_SCROLLING", "HORIZONTAL_AND_VERTICAL_SCROLLING"];
|
|
1191
1278
|
};
|
|
1192
1279
|
readonly numberOfFixedChildren: {
|
|
1193
1280
|
readonly type: "integer";
|
package/dist/index.cjs
CHANGED
|
@@ -7314,15 +7314,85 @@ function effects(raw) {
|
|
|
7314
7314
|
values.push(...raw.effects || []);
|
|
7315
7315
|
return values.map(effect);
|
|
7316
7316
|
}
|
|
7317
|
+
function resolveColor(value) {
|
|
7318
|
+
return hexColor(value) || (typeof value === "object" && value ? value : void 0);
|
|
7319
|
+
}
|
|
7317
7320
|
function effect(value) {
|
|
7318
7321
|
if (!value || typeof value !== "object") return value;
|
|
7322
|
+
const type = String(value.type || "DROP_SHADOW").toUpperCase();
|
|
7323
|
+
const visible = value.visible !== false;
|
|
7324
|
+
if (type === "DROP_SHADOW" || type === "INNER_SHADOW") {
|
|
7325
|
+
return {
|
|
7326
|
+
type,
|
|
7327
|
+
color: resolveColor(value.color),
|
|
7328
|
+
offset: value.offset || { x: 0, y: 4 },
|
|
7329
|
+
radius: value.blur ?? value.radius ?? 8,
|
|
7330
|
+
spread: value.spread || 0,
|
|
7331
|
+
visible,
|
|
7332
|
+
...value.blendMode ? { blendMode: value.blendMode } : {},
|
|
7333
|
+
...type === "DROP_SHADOW" && typeof value.showShadowBehindNode === "boolean" ? { showShadowBehindNode: value.showShadowBehindNode } : {}
|
|
7334
|
+
};
|
|
7335
|
+
}
|
|
7336
|
+
if (type === "LAYER_BLUR" || type === "BACKGROUND_BLUR") {
|
|
7337
|
+
return {
|
|
7338
|
+
type,
|
|
7339
|
+
radius: value.blur ?? value.radius ?? 8,
|
|
7340
|
+
visible,
|
|
7341
|
+
...value.blurType ? { blurType: value.blurType } : {},
|
|
7342
|
+
...value.startRadius !== void 0 ? { startRadius: value.startRadius } : {},
|
|
7343
|
+
...value.startOffset ? { startOffset: value.startOffset } : {},
|
|
7344
|
+
...value.endOffset ? { endOffset: value.endOffset } : {}
|
|
7345
|
+
};
|
|
7346
|
+
}
|
|
7347
|
+
if (type === "NOISE") {
|
|
7348
|
+
return {
|
|
7349
|
+
type,
|
|
7350
|
+
color: resolveColor(value.color),
|
|
7351
|
+
visible,
|
|
7352
|
+
...value.blendMode ? { blendMode: value.blendMode } : {},
|
|
7353
|
+
noiseType: value.noiseType || "MONOTONE",
|
|
7354
|
+
noiseSize: value.noiseSize ?? 1,
|
|
7355
|
+
density: value.density ?? 1,
|
|
7356
|
+
...value.secondaryColor !== void 0 ? { secondaryColor: resolveColor(value.secondaryColor) } : {},
|
|
7357
|
+
...value.opacity !== void 0 ? { opacity: value.opacity } : {}
|
|
7358
|
+
};
|
|
7359
|
+
}
|
|
7360
|
+
if (type === "TEXTURE") {
|
|
7361
|
+
return {
|
|
7362
|
+
type,
|
|
7363
|
+
visible,
|
|
7364
|
+
noiseSize: value.noiseSize ?? 1,
|
|
7365
|
+
radius: value.blur ?? value.radius ?? 0,
|
|
7366
|
+
clipToShape: value.clipToShape !== false
|
|
7367
|
+
};
|
|
7368
|
+
}
|
|
7369
|
+
if (type === "GLASS") {
|
|
7370
|
+
return {
|
|
7371
|
+
type,
|
|
7372
|
+
visible,
|
|
7373
|
+
lightIntensity: value.lightIntensity ?? 0.5,
|
|
7374
|
+
lightAngle: value.lightAngle ?? -45,
|
|
7375
|
+
refraction: value.refraction ?? 0.5,
|
|
7376
|
+
depth: value.depth ?? 1,
|
|
7377
|
+
dispersion: value.dispersion ?? 0.1,
|
|
7378
|
+
radius: value.blur ?? value.radius ?? 0
|
|
7379
|
+
};
|
|
7380
|
+
}
|
|
7381
|
+
if (type === "SHADER") {
|
|
7382
|
+
return {
|
|
7383
|
+
type,
|
|
7384
|
+
id: typeof value.id === "string" ? value.id : "",
|
|
7385
|
+
visible,
|
|
7386
|
+
...value.properties && typeof value.properties === "object" && !Array.isArray(value.properties) ? { properties: value.properties } : {}
|
|
7387
|
+
};
|
|
7388
|
+
}
|
|
7319
7389
|
return {
|
|
7320
|
-
type
|
|
7321
|
-
color:
|
|
7390
|
+
type,
|
|
7391
|
+
color: resolveColor(value.color),
|
|
7322
7392
|
offset: value.offset || { x: 0, y: 4 },
|
|
7323
7393
|
radius: value.blur ?? value.radius ?? 8,
|
|
7324
7394
|
spread: value.spread || 0,
|
|
7325
|
-
visible
|
|
7395
|
+
visible
|
|
7326
7396
|
};
|
|
7327
7397
|
}
|
|
7328
7398
|
var passthrough = [
|
|
@@ -7399,6 +7469,9 @@ function normalizeNode(node, parent, path) {
|
|
|
7399
7469
|
if (typeof raw.overflowDirection === "string") {
|
|
7400
7470
|
const overflowDirections = {
|
|
7401
7471
|
NONE: "NONE",
|
|
7472
|
+
HORIZONTAL: "HORIZONTAL",
|
|
7473
|
+
VERTICAL: "VERTICAL",
|
|
7474
|
+
BOTH: "BOTH",
|
|
7402
7475
|
HORIZONTAL_SCROLLING: "HORIZONTAL",
|
|
7403
7476
|
VERTICAL_SCROLLING: "VERTICAL",
|
|
7404
7477
|
HORIZONTAL_AND_VERTICAL_SCROLLING: "BOTH"
|
|
@@ -7528,6 +7601,8 @@ function normalizeDocument(value) {
|
|
|
7528
7601
|
children: canvas.nodes || []
|
|
7529
7602
|
}, { x: 0, y: 0 }, `canvas-${index}`);
|
|
7530
7603
|
root.properties.breakpoint = canvas.breakpoint;
|
|
7604
|
+
if (canvas.variableModes) root.properties.variableModes = canvas.variableModes;
|
|
7605
|
+
if (canvas.bindings) root.properties.bindings = canvas.bindings;
|
|
7531
7606
|
return root;
|
|
7532
7607
|
}),
|
|
7533
7608
|
styles: normalizeStyles(source.styles),
|
|
@@ -7866,15 +7941,43 @@ var generated_schema_default = {
|
|
|
7866
7941
|
"additionalProperties": false,
|
|
7867
7942
|
"required": ["type"],
|
|
7868
7943
|
"properties": {
|
|
7869
|
-
"type": { "enum": ["DROP_SHADOW", "INNER_SHADOW", "LAYER_BLUR", "BACKGROUND_BLUR"] },
|
|
7944
|
+
"type": { "enum": ["DROP_SHADOW", "INNER_SHADOW", "LAYER_BLUR", "BACKGROUND_BLUR", "NOISE", "TEXTURE", "GLASS", "SHADER"] },
|
|
7870
7945
|
"color": { "oneOf": [{ "$ref": "#/$defs/hexColor" }, { "$ref": "#/$defs/color" }] },
|
|
7871
7946
|
"offset": { "$ref": "#/$defs/vector" },
|
|
7872
7947
|
"blur": { "$ref": "#/$defs/nonNegativeNumber" },
|
|
7873
7948
|
"radius": { "$ref": "#/$defs/nonNegativeNumber" },
|
|
7874
7949
|
"spread": { "type": "number" },
|
|
7875
7950
|
"visible": { "type": "boolean" },
|
|
7876
|
-
"blendMode": { "type": "string" }
|
|
7877
|
-
|
|
7951
|
+
"blendMode": { "type": "string" },
|
|
7952
|
+
"showShadowBehindNode": { "type": "boolean" },
|
|
7953
|
+
"blurType": { "enum": ["NORMAL", "PROGRESSIVE"] },
|
|
7954
|
+
"startRadius": { "$ref": "#/$defs/nonNegativeNumber" },
|
|
7955
|
+
"startOffset": { "$ref": "#/$defs/vector" },
|
|
7956
|
+
"endOffset": { "$ref": "#/$defs/vector" },
|
|
7957
|
+
"noiseType": { "enum": ["MONOTONE", "DUOTONE", "MULTITONE"] },
|
|
7958
|
+
"noiseSize": { "$ref": "#/$defs/nonNegativeNumber" },
|
|
7959
|
+
"density": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
7960
|
+
"secondaryColor": { "oneOf": [{ "$ref": "#/$defs/hexColor" }, { "$ref": "#/$defs/color" }] },
|
|
7961
|
+
"opacity": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
7962
|
+
"clipToShape": { "type": "boolean" },
|
|
7963
|
+
"lightIntensity": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
7964
|
+
"lightAngle": { "type": "number" },
|
|
7965
|
+
"refraction": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
7966
|
+
"depth": { "type": "number", "minimum": 1 },
|
|
7967
|
+
"dispersion": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
7968
|
+
"id": { "type": "string", "minLength": 1 },
|
|
7969
|
+
"properties": {
|
|
7970
|
+
"type": "object",
|
|
7971
|
+
"description": "SHADER property assignments keyed by Figma property-definition id. Values pass through verbatim (numbers, booleans, strings, colors, points, gradients, or variable aliases).",
|
|
7972
|
+
"additionalProperties": { "type": ["boolean", "string", "number", "object"] }
|
|
7973
|
+
}
|
|
7974
|
+
},
|
|
7975
|
+
"allOf": [
|
|
7976
|
+
{
|
|
7977
|
+
"if": { "properties": { "type": { "const": "SHADER" } }, "required": ["type"] },
|
|
7978
|
+
"then": { "required": ["id"] }
|
|
7979
|
+
}
|
|
7980
|
+
]
|
|
7878
7981
|
},
|
|
7879
7982
|
"shadow": {
|
|
7880
7983
|
"type": "object",
|
|
@@ -8180,7 +8283,7 @@ var generated_schema_default = {
|
|
|
8180
8283
|
"additionalProperties": false,
|
|
8181
8284
|
"required": ["data"],
|
|
8182
8285
|
"properties": {
|
|
8183
|
-
"windingRule": { "enum": ["NONZERO", "EVENODD"] },
|
|
8286
|
+
"windingRule": { "enum": ["NONZERO", "EVENODD", "NONE"] },
|
|
8184
8287
|
"data": { "type": "string", "minLength": 1 }
|
|
8185
8288
|
}
|
|
8186
8289
|
},
|
|
@@ -8338,6 +8441,9 @@ var generated_schema_default = {
|
|
|
8338
8441
|
"overflowDirection": {
|
|
8339
8442
|
"enum": [
|
|
8340
8443
|
"NONE",
|
|
8444
|
+
"HORIZONTAL",
|
|
8445
|
+
"VERTICAL",
|
|
8446
|
+
"BOTH",
|
|
8341
8447
|
"HORIZONTAL_SCROLLING",
|
|
8342
8448
|
"VERTICAL_SCROLLING",
|
|
8343
8449
|
"HORIZONTAL_AND_VERTICAL_SCROLLING"
|
|
@@ -8702,6 +8808,7 @@ function validateDocument(document) {
|
|
|
8702
8808
|
if (node.type === "SVG" && typeof props.svg !== "string") add(`${path}.svg`, "SVG requires markup");
|
|
8703
8809
|
if (node.type === "VECTOR" && !Array.isArray(props.vectorPaths)) add(`${path}.vectorPaths`, "VECTOR requires vectorPaths");
|
|
8704
8810
|
if (node.type === "INSTANCE" && typeof props.componentId !== "string") add(`${path}.componentId`, "INSTANCE requires componentId");
|
|
8811
|
+
if (node.type === "BOOLEAN_OPERATION" && (typeof props.operation !== "string" || !["UNION", "SUBTRACT", "INTERSECT", "EXCLUDE"].includes(props.operation))) add(`${path}.operation`, "BOOLEAN_OPERATION requires operation UNION, SUBTRACT, INTERSECT, or EXCLUDE");
|
|
8705
8812
|
if (node.type === "COMPONENT_SET" && (!node.children.length || node.children.some((child) => child.type !== "COMPONENT"))) add(`${path}.children`, "COMPONENT_SET requires COMPONENT children");
|
|
8706
8813
|
if (node.type === "COMPONENT_SET" && props.variantAxes) {
|
|
8707
8814
|
for (const [axis, options] of Object.entries(props.variantAxes)) if (!axis || !Array.isArray(options) || !options.length || options.some((option) => typeof option !== "string")) add(`${path}.variantAxes.${axis}`, "must be a non-empty string array");
|
|
@@ -8720,13 +8827,29 @@ function validateDocument(document) {
|
|
|
8720
8827
|
node.children.forEach((child, index) => references(child, `${path}.children[${index}]`));
|
|
8721
8828
|
}
|
|
8722
8829
|
document.nodes.forEach((node, index) => references(node, `nodes[${index}]`));
|
|
8830
|
+
const styleKeys = /* @__PURE__ */ new Map();
|
|
8831
|
+
for (const style of document.styles || []) {
|
|
8832
|
+
if (typeof style.id === "string" && style.id) styleKeys.set(style.id, style.type);
|
|
8833
|
+
if (typeof style.name === "string" && style.name) styleKeys.set(style.name, style.type);
|
|
8834
|
+
}
|
|
8835
|
+
const variableKeys = /* @__PURE__ */ new Set();
|
|
8836
|
+
const collectionNames = /* @__PURE__ */ new Set();
|
|
8837
|
+
const modesByCollection = /* @__PURE__ */ new Map();
|
|
8723
8838
|
for (const [collectionIndex, collection] of (document.variables || []).entries()) {
|
|
8724
8839
|
const modes = Array.isArray(collection.modes) && collection.modes.length ? collection.modes : [];
|
|
8725
8840
|
if (collection.modes !== void 0 && (!modes.length || modes.some((mode) => typeof mode !== "string"))) add(`variables[${collectionIndex}].modes`, "must be a non-empty array of mode names");
|
|
8841
|
+
if (typeof collection.name === "string" && collection.name) {
|
|
8842
|
+
collectionNames.add(collection.name);
|
|
8843
|
+
if (collection.modes !== void 0 && modes.length && modes.every((mode) => typeof mode === "string")) {
|
|
8844
|
+
modesByCollection.set(collection.name, modes);
|
|
8845
|
+
}
|
|
8846
|
+
}
|
|
8726
8847
|
for (const [variableIndex, variable] of (collection.items || []).entries()) {
|
|
8727
8848
|
const path = `variables[${collectionIndex}].items[${variableIndex}]`;
|
|
8728
8849
|
if (!variable.name || typeof variable.name !== "string") add(`${path}.name`, "must be a non-empty string");
|
|
8729
8850
|
if (!["COLOR", "FLOAT", "STRING", "BOOLEAN"].includes(variable.type)) add(`${path}.type`, "must be COLOR, FLOAT, STRING, or BOOLEAN");
|
|
8851
|
+
if (typeof variable.id === "string" && variable.id) variableKeys.add(variable.id);
|
|
8852
|
+
if (typeof variable.name === "string" && variable.name) variableKeys.add(variable.name);
|
|
8730
8853
|
const values = variable.values || (variable.value !== void 0 ? { default: variable.value } : {});
|
|
8731
8854
|
if (!Object.keys(values).length) add(`${path}`, "requires value or values");
|
|
8732
8855
|
if (variable.values && modes.length) {
|
|
@@ -8741,6 +8864,54 @@ function validateDocument(document) {
|
|
|
8741
8864
|
}
|
|
8742
8865
|
}
|
|
8743
8866
|
}
|
|
8867
|
+
function tokenReferences(node, path) {
|
|
8868
|
+
const bindings = node.properties.bindings;
|
|
8869
|
+
if (bindings) {
|
|
8870
|
+
for (const [field, key] of Object.entries(bindings)) {
|
|
8871
|
+
if (typeof key !== "string" || !key) {
|
|
8872
|
+
add(`${path}.bindings.${field}`, "must be a non-empty variable id or name");
|
|
8873
|
+
continue;
|
|
8874
|
+
}
|
|
8875
|
+
if (!variableKeys.has(key)) add(`${path}.bindings.${field}`, `variable '${key}' is not defined in this document`);
|
|
8876
|
+
}
|
|
8877
|
+
}
|
|
8878
|
+
const variableModes = node.properties.variableModes;
|
|
8879
|
+
if (variableModes) {
|
|
8880
|
+
for (const [collectionName, modeName] of Object.entries(variableModes)) {
|
|
8881
|
+
if (!collectionNames.has(collectionName)) {
|
|
8882
|
+
add(`${path}.variableModes.${collectionName}`, `variable collection '${collectionName}' is not defined in this document`);
|
|
8883
|
+
continue;
|
|
8884
|
+
}
|
|
8885
|
+
if (typeof modeName !== "string" || !modeName) {
|
|
8886
|
+
add(`${path}.variableModes.${collectionName}`, "must be a non-empty mode name");
|
|
8887
|
+
continue;
|
|
8888
|
+
}
|
|
8889
|
+
const declared = modesByCollection.get(collectionName);
|
|
8890
|
+
if (declared && !declared.includes(modeName)) add(`${path}.variableModes.${collectionName}`, `mode '${modeName}' is not declared on collection '${collectionName}'`);
|
|
8891
|
+
}
|
|
8892
|
+
}
|
|
8893
|
+
const styleRefs = node.properties.styleRefs;
|
|
8894
|
+
if (styleRefs) {
|
|
8895
|
+
for (const [field, key] of Object.entries(styleRefs)) {
|
|
8896
|
+
if (typeof key !== "string" || !key) {
|
|
8897
|
+
add(`${path}.styleRefs.${field}`, "must be a non-empty style id or name");
|
|
8898
|
+
continue;
|
|
8899
|
+
}
|
|
8900
|
+
const styleType = styleKeys.get(key);
|
|
8901
|
+
if (!styleType) {
|
|
8902
|
+
add(`${path}.styleRefs.${field}`, `style '${key}' is not defined in this document`);
|
|
8903
|
+
continue;
|
|
8904
|
+
}
|
|
8905
|
+
if ((field === "fill" || field === "stroke") && styleType !== "PAINT") {
|
|
8906
|
+
add(`${path}.styleRefs.${field}`, `style '${key}' has type ${styleType} but ${field} requires PAINT`);
|
|
8907
|
+
} else if (field === "text" && styleType !== "TEXT") {
|
|
8908
|
+
add(`${path}.styleRefs.${field}`, `style '${key}' has type ${styleType} but text requires TEXT`);
|
|
8909
|
+
}
|
|
8910
|
+
}
|
|
8911
|
+
}
|
|
8912
|
+
node.children.forEach((child, index) => tokenReferences(child, `${path}.children[${index}]`));
|
|
8913
|
+
}
|
|
8914
|
+
document.nodes.forEach((node, index) => tokenReferences(node, `nodes[${index}]`));
|
|
8744
8915
|
return errors;
|
|
8745
8916
|
}
|
|
8746
8917
|
|
package/dist/index.js
CHANGED
|
@@ -7293,15 +7293,85 @@ function effects(raw) {
|
|
|
7293
7293
|
values.push(...raw.effects || []);
|
|
7294
7294
|
return values.map(effect);
|
|
7295
7295
|
}
|
|
7296
|
+
function resolveColor(value) {
|
|
7297
|
+
return hexColor(value) || (typeof value === "object" && value ? value : void 0);
|
|
7298
|
+
}
|
|
7296
7299
|
function effect(value) {
|
|
7297
7300
|
if (!value || typeof value !== "object") return value;
|
|
7301
|
+
const type = String(value.type || "DROP_SHADOW").toUpperCase();
|
|
7302
|
+
const visible = value.visible !== false;
|
|
7303
|
+
if (type === "DROP_SHADOW" || type === "INNER_SHADOW") {
|
|
7304
|
+
return {
|
|
7305
|
+
type,
|
|
7306
|
+
color: resolveColor(value.color),
|
|
7307
|
+
offset: value.offset || { x: 0, y: 4 },
|
|
7308
|
+
radius: value.blur ?? value.radius ?? 8,
|
|
7309
|
+
spread: value.spread || 0,
|
|
7310
|
+
visible,
|
|
7311
|
+
...value.blendMode ? { blendMode: value.blendMode } : {},
|
|
7312
|
+
...type === "DROP_SHADOW" && typeof value.showShadowBehindNode === "boolean" ? { showShadowBehindNode: value.showShadowBehindNode } : {}
|
|
7313
|
+
};
|
|
7314
|
+
}
|
|
7315
|
+
if (type === "LAYER_BLUR" || type === "BACKGROUND_BLUR") {
|
|
7316
|
+
return {
|
|
7317
|
+
type,
|
|
7318
|
+
radius: value.blur ?? value.radius ?? 8,
|
|
7319
|
+
visible,
|
|
7320
|
+
...value.blurType ? { blurType: value.blurType } : {},
|
|
7321
|
+
...value.startRadius !== void 0 ? { startRadius: value.startRadius } : {},
|
|
7322
|
+
...value.startOffset ? { startOffset: value.startOffset } : {},
|
|
7323
|
+
...value.endOffset ? { endOffset: value.endOffset } : {}
|
|
7324
|
+
};
|
|
7325
|
+
}
|
|
7326
|
+
if (type === "NOISE") {
|
|
7327
|
+
return {
|
|
7328
|
+
type,
|
|
7329
|
+
color: resolveColor(value.color),
|
|
7330
|
+
visible,
|
|
7331
|
+
...value.blendMode ? { blendMode: value.blendMode } : {},
|
|
7332
|
+
noiseType: value.noiseType || "MONOTONE",
|
|
7333
|
+
noiseSize: value.noiseSize ?? 1,
|
|
7334
|
+
density: value.density ?? 1,
|
|
7335
|
+
...value.secondaryColor !== void 0 ? { secondaryColor: resolveColor(value.secondaryColor) } : {},
|
|
7336
|
+
...value.opacity !== void 0 ? { opacity: value.opacity } : {}
|
|
7337
|
+
};
|
|
7338
|
+
}
|
|
7339
|
+
if (type === "TEXTURE") {
|
|
7340
|
+
return {
|
|
7341
|
+
type,
|
|
7342
|
+
visible,
|
|
7343
|
+
noiseSize: value.noiseSize ?? 1,
|
|
7344
|
+
radius: value.blur ?? value.radius ?? 0,
|
|
7345
|
+
clipToShape: value.clipToShape !== false
|
|
7346
|
+
};
|
|
7347
|
+
}
|
|
7348
|
+
if (type === "GLASS") {
|
|
7349
|
+
return {
|
|
7350
|
+
type,
|
|
7351
|
+
visible,
|
|
7352
|
+
lightIntensity: value.lightIntensity ?? 0.5,
|
|
7353
|
+
lightAngle: value.lightAngle ?? -45,
|
|
7354
|
+
refraction: value.refraction ?? 0.5,
|
|
7355
|
+
depth: value.depth ?? 1,
|
|
7356
|
+
dispersion: value.dispersion ?? 0.1,
|
|
7357
|
+
radius: value.blur ?? value.radius ?? 0
|
|
7358
|
+
};
|
|
7359
|
+
}
|
|
7360
|
+
if (type === "SHADER") {
|
|
7361
|
+
return {
|
|
7362
|
+
type,
|
|
7363
|
+
id: typeof value.id === "string" ? value.id : "",
|
|
7364
|
+
visible,
|
|
7365
|
+
...value.properties && typeof value.properties === "object" && !Array.isArray(value.properties) ? { properties: value.properties } : {}
|
|
7366
|
+
};
|
|
7367
|
+
}
|
|
7298
7368
|
return {
|
|
7299
|
-
type
|
|
7300
|
-
color:
|
|
7369
|
+
type,
|
|
7370
|
+
color: resolveColor(value.color),
|
|
7301
7371
|
offset: value.offset || { x: 0, y: 4 },
|
|
7302
7372
|
radius: value.blur ?? value.radius ?? 8,
|
|
7303
7373
|
spread: value.spread || 0,
|
|
7304
|
-
visible
|
|
7374
|
+
visible
|
|
7305
7375
|
};
|
|
7306
7376
|
}
|
|
7307
7377
|
var passthrough = [
|
|
@@ -7378,6 +7448,9 @@ function normalizeNode(node, parent, path) {
|
|
|
7378
7448
|
if (typeof raw.overflowDirection === "string") {
|
|
7379
7449
|
const overflowDirections = {
|
|
7380
7450
|
NONE: "NONE",
|
|
7451
|
+
HORIZONTAL: "HORIZONTAL",
|
|
7452
|
+
VERTICAL: "VERTICAL",
|
|
7453
|
+
BOTH: "BOTH",
|
|
7381
7454
|
HORIZONTAL_SCROLLING: "HORIZONTAL",
|
|
7382
7455
|
VERTICAL_SCROLLING: "VERTICAL",
|
|
7383
7456
|
HORIZONTAL_AND_VERTICAL_SCROLLING: "BOTH"
|
|
@@ -7507,6 +7580,8 @@ function normalizeDocument(value) {
|
|
|
7507
7580
|
children: canvas.nodes || []
|
|
7508
7581
|
}, { x: 0, y: 0 }, `canvas-${index}`);
|
|
7509
7582
|
root.properties.breakpoint = canvas.breakpoint;
|
|
7583
|
+
if (canvas.variableModes) root.properties.variableModes = canvas.variableModes;
|
|
7584
|
+
if (canvas.bindings) root.properties.bindings = canvas.bindings;
|
|
7510
7585
|
return root;
|
|
7511
7586
|
}),
|
|
7512
7587
|
styles: normalizeStyles(source.styles),
|
|
@@ -7845,15 +7920,43 @@ var generated_schema_default = {
|
|
|
7845
7920
|
"additionalProperties": false,
|
|
7846
7921
|
"required": ["type"],
|
|
7847
7922
|
"properties": {
|
|
7848
|
-
"type": { "enum": ["DROP_SHADOW", "INNER_SHADOW", "LAYER_BLUR", "BACKGROUND_BLUR"] },
|
|
7923
|
+
"type": { "enum": ["DROP_SHADOW", "INNER_SHADOW", "LAYER_BLUR", "BACKGROUND_BLUR", "NOISE", "TEXTURE", "GLASS", "SHADER"] },
|
|
7849
7924
|
"color": { "oneOf": [{ "$ref": "#/$defs/hexColor" }, { "$ref": "#/$defs/color" }] },
|
|
7850
7925
|
"offset": { "$ref": "#/$defs/vector" },
|
|
7851
7926
|
"blur": { "$ref": "#/$defs/nonNegativeNumber" },
|
|
7852
7927
|
"radius": { "$ref": "#/$defs/nonNegativeNumber" },
|
|
7853
7928
|
"spread": { "type": "number" },
|
|
7854
7929
|
"visible": { "type": "boolean" },
|
|
7855
|
-
"blendMode": { "type": "string" }
|
|
7856
|
-
|
|
7930
|
+
"blendMode": { "type": "string" },
|
|
7931
|
+
"showShadowBehindNode": { "type": "boolean" },
|
|
7932
|
+
"blurType": { "enum": ["NORMAL", "PROGRESSIVE"] },
|
|
7933
|
+
"startRadius": { "$ref": "#/$defs/nonNegativeNumber" },
|
|
7934
|
+
"startOffset": { "$ref": "#/$defs/vector" },
|
|
7935
|
+
"endOffset": { "$ref": "#/$defs/vector" },
|
|
7936
|
+
"noiseType": { "enum": ["MONOTONE", "DUOTONE", "MULTITONE"] },
|
|
7937
|
+
"noiseSize": { "$ref": "#/$defs/nonNegativeNumber" },
|
|
7938
|
+
"density": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
7939
|
+
"secondaryColor": { "oneOf": [{ "$ref": "#/$defs/hexColor" }, { "$ref": "#/$defs/color" }] },
|
|
7940
|
+
"opacity": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
7941
|
+
"clipToShape": { "type": "boolean" },
|
|
7942
|
+
"lightIntensity": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
7943
|
+
"lightAngle": { "type": "number" },
|
|
7944
|
+
"refraction": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
7945
|
+
"depth": { "type": "number", "minimum": 1 },
|
|
7946
|
+
"dispersion": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
7947
|
+
"id": { "type": "string", "minLength": 1 },
|
|
7948
|
+
"properties": {
|
|
7949
|
+
"type": "object",
|
|
7950
|
+
"description": "SHADER property assignments keyed by Figma property-definition id. Values pass through verbatim (numbers, booleans, strings, colors, points, gradients, or variable aliases).",
|
|
7951
|
+
"additionalProperties": { "type": ["boolean", "string", "number", "object"] }
|
|
7952
|
+
}
|
|
7953
|
+
},
|
|
7954
|
+
"allOf": [
|
|
7955
|
+
{
|
|
7956
|
+
"if": { "properties": { "type": { "const": "SHADER" } }, "required": ["type"] },
|
|
7957
|
+
"then": { "required": ["id"] }
|
|
7958
|
+
}
|
|
7959
|
+
]
|
|
7857
7960
|
},
|
|
7858
7961
|
"shadow": {
|
|
7859
7962
|
"type": "object",
|
|
@@ -8159,7 +8262,7 @@ var generated_schema_default = {
|
|
|
8159
8262
|
"additionalProperties": false,
|
|
8160
8263
|
"required": ["data"],
|
|
8161
8264
|
"properties": {
|
|
8162
|
-
"windingRule": { "enum": ["NONZERO", "EVENODD"] },
|
|
8265
|
+
"windingRule": { "enum": ["NONZERO", "EVENODD", "NONE"] },
|
|
8163
8266
|
"data": { "type": "string", "minLength": 1 }
|
|
8164
8267
|
}
|
|
8165
8268
|
},
|
|
@@ -8317,6 +8420,9 @@ var generated_schema_default = {
|
|
|
8317
8420
|
"overflowDirection": {
|
|
8318
8421
|
"enum": [
|
|
8319
8422
|
"NONE",
|
|
8423
|
+
"HORIZONTAL",
|
|
8424
|
+
"VERTICAL",
|
|
8425
|
+
"BOTH",
|
|
8320
8426
|
"HORIZONTAL_SCROLLING",
|
|
8321
8427
|
"VERTICAL_SCROLLING",
|
|
8322
8428
|
"HORIZONTAL_AND_VERTICAL_SCROLLING"
|
|
@@ -8681,6 +8787,7 @@ function validateDocument(document) {
|
|
|
8681
8787
|
if (node.type === "SVG" && typeof props.svg !== "string") add(`${path}.svg`, "SVG requires markup");
|
|
8682
8788
|
if (node.type === "VECTOR" && !Array.isArray(props.vectorPaths)) add(`${path}.vectorPaths`, "VECTOR requires vectorPaths");
|
|
8683
8789
|
if (node.type === "INSTANCE" && typeof props.componentId !== "string") add(`${path}.componentId`, "INSTANCE requires componentId");
|
|
8790
|
+
if (node.type === "BOOLEAN_OPERATION" && (typeof props.operation !== "string" || !["UNION", "SUBTRACT", "INTERSECT", "EXCLUDE"].includes(props.operation))) add(`${path}.operation`, "BOOLEAN_OPERATION requires operation UNION, SUBTRACT, INTERSECT, or EXCLUDE");
|
|
8684
8791
|
if (node.type === "COMPONENT_SET" && (!node.children.length || node.children.some((child) => child.type !== "COMPONENT"))) add(`${path}.children`, "COMPONENT_SET requires COMPONENT children");
|
|
8685
8792
|
if (node.type === "COMPONENT_SET" && props.variantAxes) {
|
|
8686
8793
|
for (const [axis, options] of Object.entries(props.variantAxes)) if (!axis || !Array.isArray(options) || !options.length || options.some((option) => typeof option !== "string")) add(`${path}.variantAxes.${axis}`, "must be a non-empty string array");
|
|
@@ -8699,13 +8806,29 @@ function validateDocument(document) {
|
|
|
8699
8806
|
node.children.forEach((child, index) => references(child, `${path}.children[${index}]`));
|
|
8700
8807
|
}
|
|
8701
8808
|
document.nodes.forEach((node, index) => references(node, `nodes[${index}]`));
|
|
8809
|
+
const styleKeys = /* @__PURE__ */ new Map();
|
|
8810
|
+
for (const style of document.styles || []) {
|
|
8811
|
+
if (typeof style.id === "string" && style.id) styleKeys.set(style.id, style.type);
|
|
8812
|
+
if (typeof style.name === "string" && style.name) styleKeys.set(style.name, style.type);
|
|
8813
|
+
}
|
|
8814
|
+
const variableKeys = /* @__PURE__ */ new Set();
|
|
8815
|
+
const collectionNames = /* @__PURE__ */ new Set();
|
|
8816
|
+
const modesByCollection = /* @__PURE__ */ new Map();
|
|
8702
8817
|
for (const [collectionIndex, collection] of (document.variables || []).entries()) {
|
|
8703
8818
|
const modes = Array.isArray(collection.modes) && collection.modes.length ? collection.modes : [];
|
|
8704
8819
|
if (collection.modes !== void 0 && (!modes.length || modes.some((mode) => typeof mode !== "string"))) add(`variables[${collectionIndex}].modes`, "must be a non-empty array of mode names");
|
|
8820
|
+
if (typeof collection.name === "string" && collection.name) {
|
|
8821
|
+
collectionNames.add(collection.name);
|
|
8822
|
+
if (collection.modes !== void 0 && modes.length && modes.every((mode) => typeof mode === "string")) {
|
|
8823
|
+
modesByCollection.set(collection.name, modes);
|
|
8824
|
+
}
|
|
8825
|
+
}
|
|
8705
8826
|
for (const [variableIndex, variable] of (collection.items || []).entries()) {
|
|
8706
8827
|
const path = `variables[${collectionIndex}].items[${variableIndex}]`;
|
|
8707
8828
|
if (!variable.name || typeof variable.name !== "string") add(`${path}.name`, "must be a non-empty string");
|
|
8708
8829
|
if (!["COLOR", "FLOAT", "STRING", "BOOLEAN"].includes(variable.type)) add(`${path}.type`, "must be COLOR, FLOAT, STRING, or BOOLEAN");
|
|
8830
|
+
if (typeof variable.id === "string" && variable.id) variableKeys.add(variable.id);
|
|
8831
|
+
if (typeof variable.name === "string" && variable.name) variableKeys.add(variable.name);
|
|
8709
8832
|
const values = variable.values || (variable.value !== void 0 ? { default: variable.value } : {});
|
|
8710
8833
|
if (!Object.keys(values).length) add(`${path}`, "requires value or values");
|
|
8711
8834
|
if (variable.values && modes.length) {
|
|
@@ -8720,6 +8843,54 @@ function validateDocument(document) {
|
|
|
8720
8843
|
}
|
|
8721
8844
|
}
|
|
8722
8845
|
}
|
|
8846
|
+
function tokenReferences(node, path) {
|
|
8847
|
+
const bindings = node.properties.bindings;
|
|
8848
|
+
if (bindings) {
|
|
8849
|
+
for (const [field, key] of Object.entries(bindings)) {
|
|
8850
|
+
if (typeof key !== "string" || !key) {
|
|
8851
|
+
add(`${path}.bindings.${field}`, "must be a non-empty variable id or name");
|
|
8852
|
+
continue;
|
|
8853
|
+
}
|
|
8854
|
+
if (!variableKeys.has(key)) add(`${path}.bindings.${field}`, `variable '${key}' is not defined in this document`);
|
|
8855
|
+
}
|
|
8856
|
+
}
|
|
8857
|
+
const variableModes = node.properties.variableModes;
|
|
8858
|
+
if (variableModes) {
|
|
8859
|
+
for (const [collectionName, modeName] of Object.entries(variableModes)) {
|
|
8860
|
+
if (!collectionNames.has(collectionName)) {
|
|
8861
|
+
add(`${path}.variableModes.${collectionName}`, `variable collection '${collectionName}' is not defined in this document`);
|
|
8862
|
+
continue;
|
|
8863
|
+
}
|
|
8864
|
+
if (typeof modeName !== "string" || !modeName) {
|
|
8865
|
+
add(`${path}.variableModes.${collectionName}`, "must be a non-empty mode name");
|
|
8866
|
+
continue;
|
|
8867
|
+
}
|
|
8868
|
+
const declared = modesByCollection.get(collectionName);
|
|
8869
|
+
if (declared && !declared.includes(modeName)) add(`${path}.variableModes.${collectionName}`, `mode '${modeName}' is not declared on collection '${collectionName}'`);
|
|
8870
|
+
}
|
|
8871
|
+
}
|
|
8872
|
+
const styleRefs = node.properties.styleRefs;
|
|
8873
|
+
if (styleRefs) {
|
|
8874
|
+
for (const [field, key] of Object.entries(styleRefs)) {
|
|
8875
|
+
if (typeof key !== "string" || !key) {
|
|
8876
|
+
add(`${path}.styleRefs.${field}`, "must be a non-empty style id or name");
|
|
8877
|
+
continue;
|
|
8878
|
+
}
|
|
8879
|
+
const styleType = styleKeys.get(key);
|
|
8880
|
+
if (!styleType) {
|
|
8881
|
+
add(`${path}.styleRefs.${field}`, `style '${key}' is not defined in this document`);
|
|
8882
|
+
continue;
|
|
8883
|
+
}
|
|
8884
|
+
if ((field === "fill" || field === "stroke") && styleType !== "PAINT") {
|
|
8885
|
+
add(`${path}.styleRefs.${field}`, `style '${key}' has type ${styleType} but ${field} requires PAINT`);
|
|
8886
|
+
} else if (field === "text" && styleType !== "TEXT") {
|
|
8887
|
+
add(`${path}.styleRefs.${field}`, `style '${key}' has type ${styleType} but text requires TEXT`);
|
|
8888
|
+
}
|
|
8889
|
+
}
|
|
8890
|
+
}
|
|
8891
|
+
node.children.forEach((child, index) => tokenReferences(child, `${path}.children[${index}]`));
|
|
8892
|
+
}
|
|
8893
|
+
document.nodes.forEach((node, index) => tokenReferences(node, `nodes[${index}]`));
|
|
8723
8894
|
return errors;
|
|
8724
8895
|
}
|
|
8725
8896
|
|
package/dist/types.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export interface LetterSpacing {
|
|
|
11
11
|
value: number;
|
|
12
12
|
}
|
|
13
13
|
export interface VectorPath {
|
|
14
|
-
windingRule: "NONZERO" | "EVENODD";
|
|
14
|
+
windingRule: "NONZERO" | "EVENODD" | "NONE";
|
|
15
15
|
data: string;
|
|
16
16
|
}
|
|
17
17
|
export interface VariableAlias {
|
|
@@ -80,6 +80,26 @@ export interface DesignEffect {
|
|
|
80
80
|
spread?: number;
|
|
81
81
|
visible?: boolean;
|
|
82
82
|
blendMode?: string;
|
|
83
|
+
showShadowBehindNode?: boolean;
|
|
84
|
+
blurType?: string;
|
|
85
|
+
startRadius?: number;
|
|
86
|
+
startOffset?: DesignPoint;
|
|
87
|
+
endOffset?: DesignPoint;
|
|
88
|
+
noiseType?: string;
|
|
89
|
+
noiseSize?: number;
|
|
90
|
+
density?: number;
|
|
91
|
+
secondaryColor?: DesignColor;
|
|
92
|
+
opacity?: number;
|
|
93
|
+
clipToShape?: boolean;
|
|
94
|
+
lightIntensity?: number;
|
|
95
|
+
lightAngle?: number;
|
|
96
|
+
refraction?: number;
|
|
97
|
+
depth?: number;
|
|
98
|
+
dispersion?: number;
|
|
99
|
+
/** SHADER only: Figma shader id (from listAvailableShaders / importShaderById). */
|
|
100
|
+
id?: string;
|
|
101
|
+
/** SHADER only: property assignments keyed by property-definition id, passed through verbatim. */
|
|
102
|
+
properties?: Record<string, JsonValue>;
|
|
83
103
|
}
|
|
84
104
|
export interface DesignStyles {
|
|
85
105
|
fills: DesignPaint[];
|