@ikas/component-cli 1.4.0-beta.185 → 1.4.0-beta.187

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.
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuVpC,eAAO,MAAM,qBAAqB,SAAU;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,KAAG,OAA2D,CAAC;AAEhE;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,GACf;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAqBlE;AA2uBD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CA0B1E;AAMD,eAAO,MAAM,kBAAkB,UAkB9B,CAAC;AAOF,eAAO,MAAM,oBAAoB,aACrB,MAAM,YACN,MAAM,gBACF,OAAO,KACpB,IAUF,CAAC;AAuEF,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAwBf;AAOD;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,EAChB,oBAAoB,CAAC,EAAE,MAAM,EAAE,EAC/B,oBAAoB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACjC,MAAM,GAAG,IAAI,CA4Cf;AAoDD,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAoBf;AAUD,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,OAAO,EACd,eAAe,EACX;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAChE,SAAS,EACb,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAsCf;AASD,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAgBf;AA+FD,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,GACd,MAAM,GAAG,IAAI,CAwBf;AA85BD,wBAAgB,mBAAmB,IAAI,OAAO,CA+U7C"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiXpC,eAAO,MAAM,qBAAqB,SAAU;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,KAAG,OAA2D,CAAC;AAEhE;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,GACf;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAqBlE;AAmyBD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CA0B1E;AAMD,eAAO,MAAM,kBAAkB,UAkB9B,CAAC;AAOF,eAAO,MAAM,oBAAoB,aACrB,MAAM,YACN,MAAM,gBACF,OAAO,KACpB,IAUF,CAAC;AAuEF,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAwBf;AAOD;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,EAChB,oBAAoB,CAAC,EAAE,MAAM,EAAE,EAC/B,oBAAoB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACjC,MAAM,GAAG,IAAI,CAuDf;AAoDD,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAoBf;AAUD,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,OAAO,EACd,eAAe,EACX;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAChE,SAAS,EACb,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAsCf;AASD,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAgBf;AA+FD,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,GACd,MAAM,GAAG,IAAI,CAwBf;AAuiCD,wBAAgB,mBAAmB,IAAI,OAAO,CA+X7C"}
@@ -1,7 +1,7 @@
1
1
  import { Command } from "commander";
2
2
  import * as fs from "fs";
3
3
  import * as path from "path";
4
- import { PROP_TYPES, toPascalCase, generateTypesFile, isBuiltInEnumTypeId, generateGlobalTypesFile, collectUsedEnumIds, generateComponentFile, generateStylesFile, generateProjectId, isValidProjectId, generateComponentId, generateUniqueId, updateBarrelExport, findPropGroup, collectPropGroupIds, movePropGroupInTree, validateFilteredComponentIds, } from "../utils/component-helpers.js";
4
+ import { PROP_TYPES, toPascalCase, generateTypesFile, isBuiltInEnumTypeId, generateGlobalTypesFile, collectUsedEnumIds, generateComponentFile, generateStylesFile, generateProjectId, isValidProjectId, generateComponentId, generateUniqueId, updateBarrelExport, findPropGroup, collectPropGroupIds, movePropGroupInTree, validateFilteredComponentIds, visibilityGateError, } from "../utils/component-helpers.js";
5
5
  function loadConfig() {
6
6
  const configPath = path.resolve(process.cwd(), "ikas.config.json");
7
7
  if (!fs.existsSync(configPath)) {
@@ -168,6 +168,10 @@ const ALLOWED_PROP_FIELDS = new Set([
168
168
  "filteredComponentIds",
169
169
  "privateVarMap",
170
170
  "numberRangeData",
171
+ "requiredProp",
172
+ "requiredPropValue",
173
+ "requiredEnumOptionId",
174
+ "requiredEnumOptionValue",
171
175
  ]);
172
176
  // Emit the standard CLI error envelope and exit(1) when a validator returned a message; a no-op
173
177
  // when the message is null. Collapses the repeated `if (err) { console.log(...); process.exit(1) }`
@@ -178,6 +182,24 @@ function failIf(error) {
178
182
  process.exit(1);
179
183
  }
180
184
  }
185
+ /**
186
+ * A `--requiredPropValue` flag as a boolean. Commander hands every flag over as a string, and this is
187
+ * the one place that turns it back; anything other than true/false is refused rather than coerced,
188
+ * since "0" or "off" silently becoming `true` is exactly the kind of gate nobody would think to
189
+ * check.
190
+ */
191
+ function parseRequiredPropValue(raw, where) {
192
+ if (raw === undefined)
193
+ return undefined;
194
+ if (typeof raw === "boolean")
195
+ return raw;
196
+ if (raw === "true")
197
+ return true;
198
+ if (raw === "false")
199
+ return false;
200
+ failIf(`--requiredPropValue for ${where} must be "true" or "false" (got "${raw}").`);
201
+ return undefined;
202
+ }
181
203
  /**
182
204
  * Validate/sanitize a numberRangeData object for a NUMBER_RANGE prop. Accepts an object
183
205
  * or a JSON string. min/max/interval are truncated to integers; only a positive interval
@@ -434,9 +456,30 @@ async function parsePropsFlag(propsJson, config, configPath) {
434
456
  ...(propType === "NUMBER_RANGE"
435
457
  ? { numberRangeData: requireNumberRangeData(r.numberRangeData, r.name) }
436
458
  : {}),
459
+ ...(r.requiredProp !== undefined
460
+ ? { requiredProp: r.requiredProp }
461
+ : {}),
462
+ ...(r.requiredPropValue !== undefined
463
+ ? { requiredPropValue: r.requiredPropValue }
464
+ : {}),
465
+ ...(r.requiredEnumOptionId !== undefined
466
+ ? { requiredEnumOptionId: r.requiredEnumOptionId }
467
+ : {}),
468
+ ...(r.requiredEnumOptionValue !== undefined
469
+ ? { requiredEnumOptionValue: r.requiredEnumOptionValue }
470
+ : {}),
437
471
  };
438
472
  props.push(prop);
439
473
  }
474
+ // Gates are checked once the whole batch is parsed: a prop may name one declared after it, and
475
+ // cycle detection needs every prop in hand. The batch IS the component's prop list here — the
476
+ // component itself does not exist yet — so it stands in as one.
477
+ const batch = { name: "the new component", props };
478
+ for (const prop of props) {
479
+ failIf(visibilityGateError(batch, prop, `prop "${prop.name}"`, {
480
+ selfPropName: prop.name,
481
+ }));
482
+ }
440
483
  return props;
441
484
  }
442
485
  // --- Subcommands ---
@@ -690,6 +733,7 @@ async function addProp(ref, options) {
690
733
  const numError = validateNumberDefaultValue(options.defaultValue, options.name);
691
734
  failIf(numError);
692
735
  }
736
+ const parsedVisibilityValue = parseRequiredPropValue(options.requiredPropValue, `prop "${options.name}"`);
693
737
  const parsedNumberRangeData = propType === "NUMBER_RANGE"
694
738
  ? requireNumberRangeData(options.numberRangeData, options.name)
695
739
  : undefined;
@@ -714,7 +758,21 @@ async function addProp(ref, options) {
714
758
  ...(parsedNumberRangeData
715
759
  ? { numberRangeData: parsedNumberRangeData }
716
760
  : {}),
761
+ ...(options.requiredProp ? { requiredProp: options.requiredProp } : {}),
762
+ ...(parsedVisibilityValue !== undefined
763
+ ? { requiredPropValue: parsedVisibilityValue }
764
+ : {}),
765
+ ...(options.requiredProp && options.requiredEnumOptionValue !== undefined
766
+ ? {
767
+ // The editor has no separate option id; the value doubles as one.
768
+ requiredEnumOptionId: options.requiredEnumOptionValue,
769
+ requiredEnumOptionValue: options.requiredEnumOptionValue,
770
+ }
771
+ : {}),
717
772
  };
773
+ failIf(visibilityGateError(component, newProp, `prop "${newProp.name}"`, {
774
+ selfPropName: newProp.name,
775
+ }));
718
776
  component.props.push(newProp);
719
777
  saveConfig(configPath, config);
720
778
  // Regenerate types.ts and global types
@@ -727,7 +785,6 @@ async function addProp(ref, options) {
727
785
  name: newProp.name,
728
786
  displayName: newProp.displayName,
729
787
  type: newProp.type,
730
- required: newProp.required,
731
788
  ...(newProp.groupId ? { groupId: newProp.groupId } : {}),
732
789
  ...(newProp.enumTypeId ? { enumTypeId: newProp.enumTypeId } : {}),
733
790
  ...(newProp.filteredComponentIds
@@ -739,6 +796,14 @@ async function addProp(ref, options) {
739
796
  ...(newProp.numberRangeData
740
797
  ? { numberRangeData: newProp.numberRangeData }
741
798
  : {}),
799
+ ...(newProp.requiredProp
800
+ ? {
801
+ requiredProp: newProp.requiredProp,
802
+ ...(newProp.requiredEnumOptionValue !== undefined
803
+ ? { requiredEnumOptionValue: newProp.requiredEnumOptionValue }
804
+ : { requiredPropValue: newProp.requiredPropValue ?? true }),
805
+ }
806
+ : {}),
742
807
  },
743
808
  }));
744
809
  }
@@ -871,9 +936,9 @@ export function validateLinkDefaultValue(propType, value, propName) {
871
936
  const links = value.links;
872
937
  return firstError(links, (link, i) => validateSingleLink(link, propName, `.links[${i}]`));
873
938
  }
874
- const COMPONENT_SHAPE_HELP = 'A COMPONENT / COMPONENT_LIST default must be an object listing child code components: ' +
939
+ const COMPONENT_SHAPE_HELP = "A COMPONENT / COMPONENT_LIST default must be an object listing child code components: " +
875
940
  '{ "components": [ { "codeComponentId": "<id>" } ] }. Only code components are allowed; each entry ' +
876
- "needs a string \"codeComponentId\" (no componentId, no inline propValues).";
941
+ 'needs a string "codeComponentId" (no componentId, no inline propValues).';
877
942
  /**
878
943
  * Validate a COMPONENT / COMPONENT_LIST defaultValue. Reference-only: each entry must name a code
879
944
  * component via `codeComponentId`. Rejects non-CC (`componentId`) children, missing ids, more than
@@ -887,14 +952,19 @@ export function validateComponentDefaultValue(propType, value, propName, filtere
887
952
  if (typeof value === "string") {
888
953
  return `${where} is a JSON string but must be an object. ${COMPONENT_SHAPE_HELP}`;
889
954
  }
890
- if (!value || typeof value !== "object" || Array.isArray(value) || !Array.isArray(value.components)) {
955
+ if (!value ||
956
+ typeof value !== "object" ||
957
+ Array.isArray(value) ||
958
+ !Array.isArray(value.components)) {
891
959
  return `${where} must be an object with a "components" array. ${COMPONENT_SHAPE_HELP}`;
892
960
  }
893
961
  const components = value.components;
894
962
  if (propType === "COMPONENT" && components.length > 1) {
895
963
  return `${where}: a COMPONENT prop holds a single child — provide at most one entry (use COMPONENT_LIST for many).`;
896
964
  }
897
- const allow = filteredComponentIds && filteredComponentIds.length ? new Set(filteredComponentIds) : null;
965
+ const allow = filteredComponentIds && filteredComponentIds.length
966
+ ? new Set(filteredComponentIds)
967
+ : null;
898
968
  return firstError(components, (entry, i) => {
899
969
  const at = `${where}.components[${i}]`;
900
970
  if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
@@ -904,7 +974,8 @@ export function validateComponentDefaultValue(propType, value, propName, filtere
904
974
  if ("componentId" in e && !("codeComponentId" in e)) {
905
975
  return `${at} references a non-code component (componentId). Only code components are allowed as defaults. ${COMPONENT_SHAPE_HELP}`;
906
976
  }
907
- if (typeof e.codeComponentId !== "string" || e.codeComponentId.trim().length === 0) {
977
+ if (typeof e.codeComponentId !== "string" ||
978
+ e.codeComponentId.trim().length === 0) {
908
979
  return `${at} must have a non-empty string "codeComponentId". ${COMPONENT_SHAPE_HELP}`;
909
980
  }
910
981
  if (allow && !allow.has(e.codeComponentId)) {
@@ -1338,6 +1409,33 @@ async function updateProp(ref, options) {
1338
1409
  }
1339
1410
  }
1340
1411
  }
1412
+ if (options.requiredProp !== undefined) {
1413
+ if (options.requiredProp === "" || options.requiredProp === "none") {
1414
+ // Every field goes together — see `IProp.requiredPropId`.
1415
+ delete prop.requiredProp;
1416
+ delete prop.requiredPropValue;
1417
+ delete prop.requiredEnumOptionId;
1418
+ delete prop.requiredEnumOptionValue;
1419
+ }
1420
+ else {
1421
+ prop.requiredProp = options.requiredProp;
1422
+ }
1423
+ }
1424
+ if (options.requiredEnumOptionValue !== undefined && prop.requiredProp) {
1425
+ prop.requiredEnumOptionId = options.requiredEnumOptionValue;
1426
+ prop.requiredEnumOptionValue = options.requiredEnumOptionValue;
1427
+ delete prop.requiredPropValue;
1428
+ }
1429
+ if (options.requiredPropValue !== undefined && prop.requiredProp) {
1430
+ delete prop.requiredEnumOptionId;
1431
+ delete prop.requiredEnumOptionValue;
1432
+ prop.requiredPropValue = parseRequiredPropValue(options.requiredPropValue, `prop "${prop.name}"`);
1433
+ }
1434
+ // Re-checked on every update, not only when a visibility flag is passed: flipping `required`, or
1435
+ // renaming the prop this one hangs on, can invalidate a gate that was sound when it was written.
1436
+ failIf(visibilityGateError(component, prop, `prop "${prop.name}"`, {
1437
+ selfPropName: prop.name,
1438
+ }));
1341
1439
  saveConfig(configPath, config);
1342
1440
  // Regenerate types.ts and global types
1343
1441
  regenerateTypes(component, undefined, config);
@@ -1349,7 +1447,6 @@ async function updateProp(ref, options) {
1349
1447
  name: prop.name,
1350
1448
  displayName: prop.displayName,
1351
1449
  type: prop.type,
1352
- required: prop.required,
1353
1450
  ...(prop.groupId ? { groupId: prop.groupId } : {}),
1354
1451
  ...(prop.typeId ? { typeId: prop.typeId } : {}),
1355
1452
  ...(prop.enumTypeId ? { enumTypeId: prop.enumTypeId } : {}),
@@ -1360,6 +1457,14 @@ async function updateProp(ref, options) {
1360
1457
  ...(prop.numberRangeData
1361
1458
  ? { numberRangeData: prop.numberRangeData }
1362
1459
  : {}),
1460
+ ...(prop.requiredProp
1461
+ ? {
1462
+ requiredProp: prop.requiredProp,
1463
+ ...(prop.requiredEnumOptionValue !== undefined
1464
+ ? { requiredEnumOptionValue: prop.requiredEnumOptionValue }
1465
+ : { requiredPropValue: prop.requiredPropValue ?? true }),
1466
+ }
1467
+ : {}),
1363
1468
  },
1364
1469
  }));
1365
1470
  }
@@ -1446,7 +1551,24 @@ function addPropGroup(ref, options) {
1446
1551
  id: options.id,
1447
1552
  name: options.name,
1448
1553
  ...(options.description ? { description: options.description } : {}),
1554
+ ...(options.requiredProp ? { requiredProp: options.requiredProp } : {}),
1555
+ ...(options.requiredProp && options.requiredEnumOptionValue !== undefined
1556
+ ? {
1557
+ requiredEnumOptionId: options.requiredEnumOptionValue,
1558
+ requiredEnumOptionValue: options.requiredEnumOptionValue,
1559
+ }
1560
+ : {}),
1561
+ ...(options.requiredProp &&
1562
+ options.requiredEnumOptionValue === undefined &&
1563
+ options.requiredPropValue !== undefined
1564
+ ? {
1565
+ requiredPropValue: parseRequiredPropValue(options.requiredPropValue, `group "${options.id}"`),
1566
+ }
1567
+ : {}),
1449
1568
  };
1569
+ failIf(visibilityGateError(component, newGroup, `group "${newGroup.id}"`, {
1570
+ group: newGroup,
1571
+ }));
1450
1572
  if (options.parent) {
1451
1573
  const found = findPropGroup(component.propGroups, options.parent);
1452
1574
  if (!found) {
@@ -1478,6 +1600,14 @@ function addPropGroup(ref, options) {
1478
1600
  id: newGroup.id,
1479
1601
  name: newGroup.name,
1480
1602
  ...(options.parent ? { parentId: options.parent } : {}),
1603
+ ...(newGroup.requiredProp
1604
+ ? {
1605
+ requiredProp: newGroup.requiredProp,
1606
+ ...(newGroup.requiredEnumOptionValue !== undefined
1607
+ ? { requiredEnumOptionValue: newGroup.requiredEnumOptionValue }
1608
+ : { requiredPropValue: newGroup.requiredPropValue ?? true }),
1609
+ }
1610
+ : {}),
1481
1611
  },
1482
1612
  }));
1483
1613
  }
@@ -1503,6 +1633,34 @@ function updatePropGroup(ref, options) {
1503
1633
  found.group.name = options.name;
1504
1634
  if (options.description !== undefined)
1505
1635
  found.group.description = options.description || undefined;
1636
+ if (options.requiredProp !== undefined) {
1637
+ if (options.requiredProp === "" || options.requiredProp === "none") {
1638
+ // Every field goes together — see `IThemePropGroup.requiredPropId`.
1639
+ delete found.group.requiredProp;
1640
+ delete found.group.requiredPropValue;
1641
+ delete found.group.requiredEnumOptionId;
1642
+ delete found.group.requiredEnumOptionValue;
1643
+ }
1644
+ else {
1645
+ found.group.requiredProp = options.requiredProp;
1646
+ }
1647
+ }
1648
+ if (options.requiredEnumOptionValue !== undefined &&
1649
+ found.group.requiredProp) {
1650
+ found.group.requiredEnumOptionId = options.requiredEnumOptionValue;
1651
+ found.group.requiredEnumOptionValue = options.requiredEnumOptionValue;
1652
+ delete found.group.requiredPropValue;
1653
+ }
1654
+ if (options.requiredPropValue !== undefined && found.group.requiredProp) {
1655
+ delete found.group.requiredEnumOptionId;
1656
+ delete found.group.requiredEnumOptionValue;
1657
+ found.group.requiredPropValue = parseRequiredPropValue(options.requiredPropValue, `group "${found.group.id}"`);
1658
+ }
1659
+ // Re-checked on every update: moving a prop into this group can invalidate a gate that was sound
1660
+ // when it was written.
1661
+ failIf(visibilityGateError(component, found.group, `group "${found.group.id}"`, {
1662
+ group: found.group,
1663
+ }));
1506
1664
  saveConfig(configPath, config);
1507
1665
  console.log(JSON.stringify({
1508
1666
  success: true,
@@ -1510,6 +1668,16 @@ function updatePropGroup(ref, options) {
1510
1668
  updatedPropGroup: {
1511
1669
  id: found.group.id,
1512
1670
  name: found.group.name,
1671
+ ...(found.group.requiredProp
1672
+ ? {
1673
+ requiredProp: found.group.requiredProp,
1674
+ ...(found.group.requiredEnumOptionValue !== undefined
1675
+ ? {
1676
+ requiredEnumOptionValue: found.group.requiredEnumOptionValue,
1677
+ }
1678
+ : { requiredPropValue: found.group.requiredPropValue ?? true }),
1679
+ }
1680
+ : {}),
1513
1681
  },
1514
1682
  }));
1515
1683
  }
@@ -1762,6 +1930,9 @@ function updateEnum(options) {
1762
1930
  }
1763
1931
  enumType.enumOptions = enumOptions;
1764
1932
  }
1933
+ // Stamp so the editor accepts this as newer than its own copy (it otherwise
1934
+ // only adds unknown ids and would revert this edit on its next sync-types).
1935
+ enumType.updatedAt = Date.now();
1765
1936
  saveConfig(configPath, config);
1766
1937
  // Regenerate global types and all component types
1767
1938
  regenerateGlobalTypes(config);
@@ -1859,6 +2030,9 @@ export function createConfigCommand() {
1859
2030
  .option("--filteredComponentIds <json>", "JSON array of component IDs to restrict selection (for COMPONENT/COMPONENT_LIST)")
1860
2031
  .option("--privateVarMap <json>", "JSON object mapping variable keys to {id, typeId} (for COMPONENT/COMPONENT_LIST)")
1861
2032
  .option("--numberRangeData <json>", 'JSON slider config for NUMBER_RANGE props, e.g. \'{"min":0,"max":100,"interval":5,"unit":"px"}\'')
2033
+ .option("--requiredProp <propName>", 'Show this only while the named BOOLEAN or ENUM prop satisfies the condition ("Koşullu Prop")')
2034
+ .option("--requiredPropValue <boolean>", "For a BOOLEAN --requiredProp: which state shows it, true (default) or false")
2035
+ .option("--requiredEnumOptionValue <value>", "For an ENUM --requiredProp: the option value that shows it")
1862
2036
  .action((options) => {
1863
2037
  addProp({ id: options.componentId, name: options.component }, options);
1864
2038
  });
@@ -1879,6 +2053,9 @@ export function createConfigCommand() {
1879
2053
  .option("--filteredComponentIds <json>", "JSON array of component IDs (use 'none' to clear)")
1880
2054
  .option("--privateVarMap <json>", "JSON object mapping variable keys to {id, typeId} (use 'none' to clear)")
1881
2055
  .option("--numberRangeData <json>", "JSON slider config for NUMBER_RANGE props (use 'none' to clear)")
2056
+ .option("--requiredProp <propName>", "BOOLEAN or ENUM prop that gates this prop in the editor panel (use 'none' to clear)")
2057
+ .option("--requiredPropValue <boolean>", "For a BOOLEAN --requiredProp: which state shows it, true (default) or false")
2058
+ .option("--requiredEnumOptionValue <value>", "For an ENUM --requiredProp: the option value that shows it")
1882
2059
  .action((options) => {
1883
2060
  updateProp({ id: options.componentId, name: options.component }, options);
1884
2061
  });
@@ -1920,6 +2097,9 @@ export function createConfigCommand() {
1920
2097
  .requiredOption("--name <name>", "Display name in editor")
1921
2098
  .option("--description <description>", "Group description")
1922
2099
  .option("--parent <parentId>", "Parent group ID (for nesting, max 1 level)")
2100
+ .option("--requiredProp <propName>", 'Show this only while the named BOOLEAN or ENUM prop satisfies the condition ("Koşullu Prop")')
2101
+ .option("--requiredPropValue <boolean>", "For a BOOLEAN --requiredProp: which state shows it, true (default) or false")
2102
+ .option("--requiredEnumOptionValue <value>", "For an ENUM --requiredProp: the option value that shows it")
1923
2103
  .action((options) => {
1924
2104
  addPropGroup({ id: options.componentId, name: options.component }, options);
1925
2105
  });
@@ -1931,6 +2111,9 @@ export function createConfigCommand() {
1931
2111
  .requiredOption("--id <id>", "Group ID to update")
1932
2112
  .option("--name <name>", "New display name")
1933
2113
  .option("--description <description>", "New description")
2114
+ .option("--requiredProp <propName>", "BOOLEAN or ENUM prop that gates this group in the editor panel (use 'none' to clear)")
2115
+ .option("--requiredPropValue <boolean>", "For a BOOLEAN --requiredProp: which state shows it, true (default) or false")
2116
+ .option("--requiredEnumOptionValue <value>", "For an ENUM --requiredProp: the option value that shows it")
1934
2117
  .action((options) => {
1935
2118
  updatePropGroup({ id: options.componentId, name: options.component }, options);
1936
2119
  });