velloo 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.
Files changed (96) hide show
  1. package/README.md +66 -40
  2. package/canvas/assets/index-ClaBqcaS.js +28 -0
  3. package/canvas/assets/lucide-all-iIF-pmzN.js +1 -0
  4. package/canvas/index.html +1 -1
  5. package/{chunk-k6ferbam.js → chunk-08sv3k41.js} +1 -1
  6. package/{chunk-74skmg76.js → chunk-0fe83yzt.js} +1 -1
  7. package/{chunk-n5007jcz.js → chunk-1h55s5he.js} +1 -1
  8. package/{chunk-5js0qw32.js → chunk-2c7jbx46.js} +1 -1
  9. package/chunk-308ynsxd.js +2 -0
  10. package/{chunk-w5rzk6ms.js → chunk-3e8vez4d.js} +2 -2
  11. package/{chunk-bk8b7f9a.js → chunk-40xgcth8.js} +4 -3
  12. package/chunk-4dn75m6t.js +3 -0
  13. package/chunk-4fj5tahv.js +3 -0
  14. package/chunk-6nqghjda.js +3 -0
  15. package/chunk-6w6ch4ce.js +2 -0
  16. package/chunk-735ezz23.js +86 -0
  17. package/chunk-7eq7nx37.js +7 -0
  18. package/chunk-7eyb8yrf.js +6 -0
  19. package/{chunk-8ssr8a8w.js → chunk-80fjfyha.js} +3 -6
  20. package/{chunk-b7j86xq7.js → chunk-80r93t2e.js} +1 -1
  21. package/chunk-94vx1yb0.js +3 -0
  22. package/{chunk-g02nd9hn.js → chunk-a84n72m2.js} +1 -1
  23. package/chunk-ampmdzz4.js +10 -0
  24. package/chunk-avns4dbf.js +2 -0
  25. package/{chunk-kxk5x7g6.js → chunk-ayrb3qnm.js} +1 -1
  26. package/{chunk-fgw3hp2v.js → chunk-bwnvcncx.js} +1 -1
  27. package/chunk-ccszg02q.js +5 -0
  28. package/{chunk-jnsfgtn9.js → chunk-cvn689d5.js} +1 -1
  29. package/{chunk-65wb0g7d.js → chunk-dg6z4vdd.js} +1 -1
  30. package/chunk-dgwjpbp9.js +3 -0
  31. package/{chunk-hs2j6s1v.js → chunk-dy41n60j.js} +8 -31
  32. package/{chunk-e2ag33vd.js → chunk-ek71z2fv.js} +2 -2
  33. package/{chunk-h0c36khx.js → chunk-er1fxb7d.js} +1 -1
  34. package/{chunk-xr6f94rj.js → chunk-eyr8hrzf.js} +1 -1
  35. package/{chunk-56vqqr8s.js → chunk-fsbsksga.js} +1 -1
  36. package/{chunk-t2ttkxe9.js → chunk-hcb68zt7.js} +1 -1
  37. package/chunk-j11fyeqh.js +2 -0
  38. package/{chunk-d385435m.js → chunk-jb21jkp1.js} +1 -1
  39. package/{chunk-7e39xe21.js → chunk-jfx9xjmr.js} +1 -1
  40. package/{chunk-b2ebm1t3.js → chunk-jr0ss0mm.js} +1 -1
  41. package/chunk-jv0xggh0.js +2 -0
  42. package/chunk-k17gfwq3.js +2 -0
  43. package/chunk-mh2pr7cq.js +5 -0
  44. package/chunk-mnapdp1y.js +2 -0
  45. package/chunk-n9gs6yx9.js +2 -0
  46. package/chunk-ngnymg2q.js +3 -0
  47. package/{chunk-79ykzywe.js → chunk-pjtg3wnm.js} +1 -1
  48. package/{chunk-2z0k59hz.js → chunk-pp86v6m6.js} +1 -1
  49. package/chunk-r22epxz2.js +3 -0
  50. package/chunk-rgasy862.js +5 -0
  51. package/{chunk-7p7ha0qk.js → chunk-rpwpeph5.js} +1 -1
  52. package/{chunk-k784090q.js → chunk-sjgqnykd.js} +1 -1
  53. package/chunk-sn3x2m0m.js +6 -0
  54. package/{chunk-mq4znqv2.js → chunk-t448rrfr.js} +1 -1
  55. package/{chunk-329e3phg.js → chunk-tdsk5wxa.js} +25 -25
  56. package/{chunk-2vx420g2.js → chunk-v40fn08f.js} +1 -1
  57. package/chunk-vdkrbzh1.js +2 -0
  58. package/{chunk-1gx45384.js → chunk-vgmr98cv.js} +7 -8
  59. package/chunk-vsv8z729.js +6 -0
  60. package/chunk-x4f4k9pp.js +26 -0
  61. package/{chunk-cep3ktr3.js → chunk-xt5ayg7g.js} +1 -1
  62. package/{chunk-rksq3w72.js → chunk-ydhwv29b.js} +1 -1
  63. package/chunk-zb6hc1y0.js +2 -0
  64. package/cli.js +1 -1
  65. package/launcher.cjs +1 -1
  66. package/package.json +3 -3
  67. package/pkgs/schema/src/config.ts +8 -1
  68. package/pkgs/schema/src/index.ts +8 -0
  69. package/pkgs/schema/src/migrate.ts +57 -4
  70. package/pkgs/schema/src/repo.ts +98 -16
  71. package/pkgs/schema/src/svg-sanitize.ts +472 -59
  72. package/skills/velloo-setup/SKILL.md +1 -1
  73. package/canvas/assets/index-BcBJ11d2.js +0 -28
  74. package/canvas/assets/lucide-all-BdEyryfF.js +0 -1
  75. package/chunk-1bywxgc5.js +0 -4
  76. package/chunk-1y50g9vp.js +0 -2
  77. package/chunk-1yhc252b.js +0 -3
  78. package/chunk-2mv65qxs.js +0 -5
  79. package/chunk-40657ggd.js +0 -10
  80. package/chunk-582y60bv.js +0 -2
  81. package/chunk-5x173xay.js +0 -2
  82. package/chunk-75wbh438.js +0 -2
  83. package/chunk-7dggmqwq.js +0 -53
  84. package/chunk-946pcnt5.js +0 -5
  85. package/chunk-aapybh30.js +0 -6
  86. package/chunk-bjnhhsak.js +0 -2
  87. package/chunk-dt03awr1.js +0 -2
  88. package/chunk-erwfk47h.js +0 -3
  89. package/chunk-nfr3q7mg.js +0 -5
  90. package/chunk-nsqs1bqf.js +0 -2
  91. package/chunk-pphgrsxa.js +0 -2
  92. package/chunk-qpvj6kzq.js +0 -6
  93. package/chunk-qwv7xkms.js +0 -2
  94. package/chunk-tmtzxcs5.js +0 -2
  95. package/chunk-y0zxzefg.js +0 -5
  96. package/chunk-zf3xc1wz.js +0 -2
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{clsx_default,helpersRegistry,parse_default,formatRgb,SX_PROP,catalogFromManifest,helperSourcePath}from"./chunk-329e3phg.js";import{require_react_is_development,require_object_assign,require_emotion_serialize_development_cjs,$_default,import_emotion_react_development_cjs,$_default2,$_default3}from"./chunk-7e39xe21.js";import{DEFAULT_TYPESET_NAME,typesetScale,resolveColors}from"./chunk-bk8b7f9a.js";import{_objectWithoutPropertiesLoose,_extends,_assertThisInitialized,_setPrototypeOf}from"./chunk-h6gchare.js";import{resolveProviderSrcDir}from"./chunk-fjbzk4sw.js";import{require_react_jsx_runtime_development}from"./chunk-d385435m.js";import{require_react_development,require_react_dom}from"./chunk-w5rzk6ms.js";import{__toESM,__commonJS}from"./chunk-2smsg2ct.js";import{MUI_VERSION}from"./chunk-mzhdrawd.js";var require_ReactPropTypesSecret=__commonJS(function(exports,module){var ReactPropTypesSecret="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";module.exports=ReactPropTypesSecret});var require_has=__commonJS(function(exports,module){module.exports=Function.call.bind(Object.prototype.hasOwnProperty)});var require_checkPropTypes=__commonJS(function(exports,module){var printWarning=function(){};ReactPropTypesSecret=require_ReactPropTypesSecret(),loggedTypeFailures={},has=require_has(),printWarning=function(text){var message="Warning: "+text;if(typeof console<"u")console.error(message);try{throw Error(message)}catch(x){}};var ReactPropTypesSecret,loggedTypeFailures,has;function checkPropTypes(typeSpecs,values,location,componentName,getStack){for(var typeSpecName in typeSpecs)if(has(typeSpecs,typeSpecName)){var error;try{if(typeof typeSpecs[typeSpecName]!=="function"){var err=Error((componentName||"React class")+": "+location+" type `"+typeSpecName+"` is invalid; it must be a function, usually from the `prop-types` package, but received `"+typeof typeSpecs[typeSpecName]+"`.This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.");throw err.name="Invariant Violation",err}error=typeSpecs[typeSpecName](values,typeSpecName,componentName,location,null,ReactPropTypesSecret)}catch(ex){error=ex}if(error&&!(error instanceof Error))printWarning((componentName||"React class")+": type specification of "+location+" `"+typeSpecName+"` is invalid; the type checker function must return `null` or an `Error` but returned a "+typeof error+". You may have forgotten to pass an argument to the type checker creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and shape all require an argument).");if(error instanceof Error&&!(error.message in loggedTypeFailures)){loggedTypeFailures[error.message]=!0;var stack=getStack?getStack():"";printWarning("Failed "+location+" type: "+error.message+(stack!=null?stack:""))}}}checkPropTypes.resetWarningCache=function(){loggedTypeFailures={}};module.exports=checkPropTypes});var require_factoryWithTypeCheckers=__commonJS(function(exports,module){var ReactIs=__toESM(require_react_is_development()),assign=require_object_assign(),ReactPropTypesSecret=require_ReactPropTypesSecret(),has=require_has(),checkPropTypes=require_checkPropTypes(),printWarning=function(){};printWarning=function(text){var message="Warning: "+text;if(typeof console<"u")console.error(message);try{throw Error(message)}catch(x){}};function emptyFunctionThatReturnsNull(){return null}module.exports=function(isValidElement,throwOnDirectAccess){var ITERATOR_SYMBOL=typeof Symbol==="function"&&Symbol.iterator,FAUX_ITERATOR_SYMBOL="@@iterator";function getIteratorFn(maybeIterable){var iteratorFn=maybeIterable&&(ITERATOR_SYMBOL&&maybeIterable[ITERATOR_SYMBOL]||maybeIterable[FAUX_ITERATOR_SYMBOL]);if(typeof iteratorFn==="function")return iteratorFn}var ANONYMOUS="<<anonymous>>",ReactPropTypes={array:createPrimitiveTypeChecker("array"),bigint:createPrimitiveTypeChecker("bigint"),bool:createPrimitiveTypeChecker("boolean"),func:createPrimitiveTypeChecker("function"),number:createPrimitiveTypeChecker("number"),object:createPrimitiveTypeChecker("object"),string:createPrimitiveTypeChecker("string"),symbol:createPrimitiveTypeChecker("symbol"),any:createAnyTypeChecker(),arrayOf:createArrayOfTypeChecker,element:createElementTypeChecker(),elementType:createElementTypeTypeChecker(),instanceOf:createInstanceTypeChecker,node:createNodeChecker(),objectOf:createObjectOfTypeChecker,oneOf:createEnumTypeChecker,oneOfType:createUnionTypeChecker,shape:createShapeTypeChecker,exact:createStrictShapeTypeChecker};function is(x,y){if(x===y)return x!==0||1/x===1/y;else return x!==x&&y!==y}function PropTypeError(message,data){this.message=message,this.data=data&&typeof data==="object"?data:{},this.stack=""}PropTypeError.prototype=Error.prototype;function createChainableTypeChecker(validate){var manualPropTypeCallCache={},manualPropTypeWarningCount=0;function checkType(isRequired,props,propName,componentName,location,propFullName,secret){if(componentName=componentName||ANONYMOUS,propFullName=propFullName||propName,secret!==ReactPropTypesSecret){if(throwOnDirectAccess){var err=Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use `PropTypes.checkPropTypes()` to call them. Read more at http://fb.me/use-check-prop-types");throw err.name="Invariant Violation",err}else if(typeof console<"u"){var cacheKey=componentName+":"+propName;if(!manualPropTypeCallCache[cacheKey]&&manualPropTypeWarningCount<3)printWarning("You are manually calling a React.PropTypes validation function for the `"+propFullName+"` prop on `"+componentName+"`. This is deprecated and will throw in the standalone `prop-types` package. You may be seeing this warning due to a third-party PropTypes library. See https://fb.me/react-warning-dont-call-proptypes for details."),manualPropTypeCallCache[cacheKey]=!0,manualPropTypeWarningCount++}}if(props[propName]==null){if(isRequired){if(props[propName]===null)return new PropTypeError("The "+location+" `"+propFullName+"` is marked as required "+("in `"+componentName+"`, but its value is `null`."));return new PropTypeError("The "+location+" `"+propFullName+"` is marked as required in "+("`"+componentName+"`, but its value is `undefined`."))}return null}else return validate(props,propName,componentName,location,propFullName)}var chainedCheckType=checkType.bind(null,!1);return chainedCheckType.isRequired=checkType.bind(null,!0),chainedCheckType}function createPrimitiveTypeChecker(expectedType){function validate(props,propName,componentName,location,propFullName,secret){var propValue=props[propName],propType=getPropType(propValue);if(propType!==expectedType){var preciseType=getPreciseType(propValue);return new PropTypeError("Invalid "+location+" `"+propFullName+"` of type "+("`"+preciseType+"` supplied to `"+componentName+"`, expected ")+("`"+expectedType+"`."),{expectedType})}return null}return createChainableTypeChecker(validate)}function createAnyTypeChecker(){return createChainableTypeChecker(emptyFunctionThatReturnsNull)}function createArrayOfTypeChecker(typeChecker){function validate(props,propName,componentName,location,propFullName){if(typeof typeChecker!=="function")return new PropTypeError("Property `"+propFullName+"` of component `"+componentName+"` has invalid PropType notation inside arrayOf.");var propValue=props[propName];if(!Array.isArray(propValue)){var propType=getPropType(propValue);return new PropTypeError("Invalid "+location+" `"+propFullName+"` of type "+("`"+propType+"` supplied to `"+componentName+"`, expected an array."))}for(var i=0;i<propValue.length;i++){var error=typeChecker(propValue,i,componentName,location,propFullName+"["+i+"]",ReactPropTypesSecret);if(error instanceof Error)return error}return null}return createChainableTypeChecker(validate)}function createElementTypeChecker(){function validate(props,propName,componentName,location,propFullName){var propValue=props[propName];if(!isValidElement(propValue)){var propType=getPropType(propValue);return new PropTypeError("Invalid "+location+" `"+propFullName+"` of type "+("`"+propType+"` supplied to `"+componentName+"`, expected a single ReactElement."))}return null}return createChainableTypeChecker(validate)}function createElementTypeTypeChecker(){function validate(props,propName,componentName,location,propFullName){var propValue=props[propName];if(!ReactIs.isValidElementType(propValue)){var propType=getPropType(propValue);return new PropTypeError("Invalid "+location+" `"+propFullName+"` of type "+("`"+propType+"` supplied to `"+componentName+"`, expected a single ReactElement type."))}return null}return createChainableTypeChecker(validate)}function createInstanceTypeChecker(expectedClass){function validate(props,propName,componentName,location,propFullName){if(!(props[propName]instanceof expectedClass)){var expectedClassName=expectedClass.name||ANONYMOUS,actualClassName=getClassName(props[propName]);return new PropTypeError("Invalid "+location+" `"+propFullName+"` of type "+("`"+actualClassName+"` supplied to `"+componentName+"`, expected ")+("instance of `"+expectedClassName+"`."))}return null}return createChainableTypeChecker(validate)}function createEnumTypeChecker(expectedValues){if(!Array.isArray(expectedValues)){if(arguments.length>1)printWarning("Invalid arguments supplied to oneOf, expected an array, got "+arguments.length+" arguments. A common mistake is to write oneOf(x, y, z) instead of oneOf([x, y, z]).");else printWarning("Invalid argument supplied to oneOf, expected an array.");return emptyFunctionThatReturnsNull}function validate(props,propName,componentName,location,propFullName){var propValue=props[propName];for(var i=0;i<expectedValues.length;i++)if(is(propValue,expectedValues[i]))return null;var valuesString=JSON.stringify(expectedValues,function(key,value){var type=getPreciseType(value);if(type==="symbol")return String(value);return value});return new PropTypeError("Invalid "+location+" `"+propFullName+"` of value `"+String(propValue)+"` "+("supplied to `"+componentName+"`, expected one of "+valuesString+"."))}return createChainableTypeChecker(validate)}function createObjectOfTypeChecker(typeChecker){function validate(props,propName,componentName,location,propFullName){if(typeof typeChecker!=="function")return new PropTypeError("Property `"+propFullName+"` of component `"+componentName+"` has invalid PropType notation inside objectOf.");var propValue=props[propName],propType=getPropType(propValue);if(propType!=="object")return new PropTypeError("Invalid "+location+" `"+propFullName+"` of type "+("`"+propType+"` supplied to `"+componentName+"`, expected an object."));for(var key in propValue)if(has(propValue,key)){var error=typeChecker(propValue,key,componentName,location,propFullName+"."+key,ReactPropTypesSecret);if(error instanceof Error)return error}return null}return createChainableTypeChecker(validate)}function createUnionTypeChecker(arrayOfTypeCheckers){if(!Array.isArray(arrayOfTypeCheckers))return printWarning("Invalid argument supplied to oneOfType, expected an instance of array."),emptyFunctionThatReturnsNull;for(var i=0;i<arrayOfTypeCheckers.length;i++){var checker=arrayOfTypeCheckers[i];if(typeof checker!=="function")return printWarning("Invalid argument supplied to oneOfType. Expected an array of check functions, but received "+getPostfixForTypeWarning(checker)+" at index "+i+"."),emptyFunctionThatReturnsNull}function validate(props,propName,componentName,location,propFullName){var expectedTypes=[];for(var i=0;i<arrayOfTypeCheckers.length;i++){var checker=arrayOfTypeCheckers[i],checkerResult=checker(props,propName,componentName,location,propFullName,ReactPropTypesSecret);if(checkerResult==null)return null;if(checkerResult.data&&has(checkerResult.data,"expectedType"))expectedTypes.push(checkerResult.data.expectedType)}var expectedTypesMessage=expectedTypes.length>0?", expected one of type ["+expectedTypes.join(", ")+"]":"";return new PropTypeError("Invalid "+location+" `"+propFullName+"` supplied to "+("`"+componentName+"`"+expectedTypesMessage+"."))}return createChainableTypeChecker(validate)}function createNodeChecker(){function validate(props,propName,componentName,location,propFullName){if(!isNode(props[propName]))return new PropTypeError("Invalid "+location+" `"+propFullName+"` supplied to "+("`"+componentName+"`, expected a ReactNode."));return null}return createChainableTypeChecker(validate)}function invalidValidatorError(componentName,location,propFullName,key,type){return new PropTypeError((componentName||"React class")+": "+location+" type `"+propFullName+"."+key+"` is invalid; it must be a function, usually from the `prop-types` package, but received `"+type+"`.")}function createShapeTypeChecker(shapeTypes){function validate(props,propName,componentName,location,propFullName){var propValue=props[propName],propType=getPropType(propValue);if(propType!=="object")return new PropTypeError("Invalid "+location+" `"+propFullName+"` of type `"+propType+"` "+("supplied to `"+componentName+"`, expected `object`."));for(var key in shapeTypes){var checker=shapeTypes[key];if(typeof checker!=="function")return invalidValidatorError(componentName,location,propFullName,key,getPreciseType(checker));var error=checker(propValue,key,componentName,location,propFullName+"."+key,ReactPropTypesSecret);if(error)return error}return null}return createChainableTypeChecker(validate)}function createStrictShapeTypeChecker(shapeTypes){function validate(props,propName,componentName,location,propFullName){var propValue=props[propName],propType=getPropType(propValue);if(propType!=="object")return new PropTypeError("Invalid "+location+" `"+propFullName+"` of type `"+propType+"` "+("supplied to `"+componentName+"`, expected `object`."));var allKeys=assign({},props[propName],shapeTypes);for(var key in allKeys){var checker=shapeTypes[key];if(has(shapeTypes,key)&&typeof checker!=="function")return invalidValidatorError(componentName,location,propFullName,key,getPreciseType(checker));if(!checker)return new PropTypeError("Invalid "+location+" `"+propFullName+"` key `"+key+"` supplied to `"+componentName+"`.\nBad object: "+JSON.stringify(props[propName],null," ")+`
2
+ import{clsx_default,helpersRegistry,parse_default,formatRgb,SX_PROP,catalogFromManifest,helperSourcePath}from"./chunk-tdsk5wxa.js";import{require_react_is_development,require_object_assign,require_emotion_serialize_development_cjs,$_default,import_emotion_react_development_cjs,$_default2,$_default3}from"./chunk-jfx9xjmr.js";import{resolveColors,DEFAULT_TYPESET_NAME,typesetScale}from"./chunk-40xgcth8.js";import{_objectWithoutPropertiesLoose,_extends,_assertThisInitialized,_setPrototypeOf}from"./chunk-h6gchare.js";import{resolveProviderSrcDir}from"./chunk-fjbzk4sw.js";import{require_react_jsx_runtime_development}from"./chunk-jb21jkp1.js";import{require_react_development,require_react_dom}from"./chunk-3e8vez4d.js";import{__toESM,__commonJS}from"./chunk-2smsg2ct.js";import{MUI_VERSION}from"./chunk-mzhdrawd.js";var require_ReactPropTypesSecret=__commonJS(function(exports,module){var ReactPropTypesSecret="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED";module.exports=ReactPropTypesSecret});var require_has=__commonJS(function(exports,module){module.exports=Function.call.bind(Object.prototype.hasOwnProperty)});var require_checkPropTypes=__commonJS(function(exports,module){var printWarning=function(){};ReactPropTypesSecret=require_ReactPropTypesSecret(),loggedTypeFailures={},has=require_has(),printWarning=function(text){var message="Warning: "+text;if(typeof console<"u")console.error(message);try{throw Error(message)}catch(x){}};var ReactPropTypesSecret,loggedTypeFailures,has;function checkPropTypes(typeSpecs,values,location,componentName,getStack){for(var typeSpecName in typeSpecs)if(has(typeSpecs,typeSpecName)){var error;try{if(typeof typeSpecs[typeSpecName]!=="function"){var err=Error((componentName||"React class")+": "+location+" type `"+typeSpecName+"` is invalid; it must be a function, usually from the `prop-types` package, but received `"+typeof typeSpecs[typeSpecName]+"`.This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.");throw err.name="Invariant Violation",err}error=typeSpecs[typeSpecName](values,typeSpecName,componentName,location,null,ReactPropTypesSecret)}catch(ex){error=ex}if(error&&!(error instanceof Error))printWarning((componentName||"React class")+": type specification of "+location+" `"+typeSpecName+"` is invalid; the type checker function must return `null` or an `Error` but returned a "+typeof error+". You may have forgotten to pass an argument to the type checker creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and shape all require an argument).");if(error instanceof Error&&!(error.message in loggedTypeFailures)){loggedTypeFailures[error.message]=!0;var stack=getStack?getStack():"";printWarning("Failed "+location+" type: "+error.message+(stack!=null?stack:""))}}}checkPropTypes.resetWarningCache=function(){loggedTypeFailures={}};module.exports=checkPropTypes});var require_factoryWithTypeCheckers=__commonJS(function(exports,module){var ReactIs=__toESM(require_react_is_development()),assign=require_object_assign(),ReactPropTypesSecret=require_ReactPropTypesSecret(),has=require_has(),checkPropTypes=require_checkPropTypes(),printWarning=function(){};printWarning=function(text){var message="Warning: "+text;if(typeof console<"u")console.error(message);try{throw Error(message)}catch(x){}};function emptyFunctionThatReturnsNull(){return null}module.exports=function(isValidElement,throwOnDirectAccess){var ITERATOR_SYMBOL=typeof Symbol==="function"&&Symbol.iterator,FAUX_ITERATOR_SYMBOL="@@iterator";function getIteratorFn(maybeIterable){var iteratorFn=maybeIterable&&(ITERATOR_SYMBOL&&maybeIterable[ITERATOR_SYMBOL]||maybeIterable[FAUX_ITERATOR_SYMBOL]);if(typeof iteratorFn==="function")return iteratorFn}var ANONYMOUS="<<anonymous>>",ReactPropTypes={array:createPrimitiveTypeChecker("array"),bigint:createPrimitiveTypeChecker("bigint"),bool:createPrimitiveTypeChecker("boolean"),func:createPrimitiveTypeChecker("function"),number:createPrimitiveTypeChecker("number"),object:createPrimitiveTypeChecker("object"),string:createPrimitiveTypeChecker("string"),symbol:createPrimitiveTypeChecker("symbol"),any:createAnyTypeChecker(),arrayOf:createArrayOfTypeChecker,element:createElementTypeChecker(),elementType:createElementTypeTypeChecker(),instanceOf:createInstanceTypeChecker,node:createNodeChecker(),objectOf:createObjectOfTypeChecker,oneOf:createEnumTypeChecker,oneOfType:createUnionTypeChecker,shape:createShapeTypeChecker,exact:createStrictShapeTypeChecker};function is(x,y){if(x===y)return x!==0||1/x===1/y;else return x!==x&&y!==y}function PropTypeError(message,data){this.message=message,this.data=data&&typeof data==="object"?data:{},this.stack=""}PropTypeError.prototype=Error.prototype;function createChainableTypeChecker(validate){var manualPropTypeCallCache={},manualPropTypeWarningCount=0;function checkType(isRequired,props,propName,componentName,location,propFullName,secret){if(componentName=componentName||ANONYMOUS,propFullName=propFullName||propName,secret!==ReactPropTypesSecret){if(throwOnDirectAccess){var err=Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use `PropTypes.checkPropTypes()` to call them. Read more at http://fb.me/use-check-prop-types");throw err.name="Invariant Violation",err}else if(typeof console<"u"){var cacheKey=componentName+":"+propName;if(!manualPropTypeCallCache[cacheKey]&&manualPropTypeWarningCount<3)printWarning("You are manually calling a React.PropTypes validation function for the `"+propFullName+"` prop on `"+componentName+"`. This is deprecated and will throw in the standalone `prop-types` package. You may be seeing this warning due to a third-party PropTypes library. See https://fb.me/react-warning-dont-call-proptypes for details."),manualPropTypeCallCache[cacheKey]=!0,manualPropTypeWarningCount++}}if(props[propName]==null){if(isRequired){if(props[propName]===null)return new PropTypeError("The "+location+" `"+propFullName+"` is marked as required "+("in `"+componentName+"`, but its value is `null`."));return new PropTypeError("The "+location+" `"+propFullName+"` is marked as required in "+("`"+componentName+"`, but its value is `undefined`."))}return null}else return validate(props,propName,componentName,location,propFullName)}var chainedCheckType=checkType.bind(null,!1);return chainedCheckType.isRequired=checkType.bind(null,!0),chainedCheckType}function createPrimitiveTypeChecker(expectedType){function validate(props,propName,componentName,location,propFullName,secret){var propValue=props[propName],propType=getPropType(propValue);if(propType!==expectedType){var preciseType=getPreciseType(propValue);return new PropTypeError("Invalid "+location+" `"+propFullName+"` of type "+("`"+preciseType+"` supplied to `"+componentName+"`, expected ")+("`"+expectedType+"`."),{expectedType})}return null}return createChainableTypeChecker(validate)}function createAnyTypeChecker(){return createChainableTypeChecker(emptyFunctionThatReturnsNull)}function createArrayOfTypeChecker(typeChecker){function validate(props,propName,componentName,location,propFullName){if(typeof typeChecker!=="function")return new PropTypeError("Property `"+propFullName+"` of component `"+componentName+"` has invalid PropType notation inside arrayOf.");var propValue=props[propName];if(!Array.isArray(propValue)){var propType=getPropType(propValue);return new PropTypeError("Invalid "+location+" `"+propFullName+"` of type "+("`"+propType+"` supplied to `"+componentName+"`, expected an array."))}for(var i=0;i<propValue.length;i++){var error=typeChecker(propValue,i,componentName,location,propFullName+"["+i+"]",ReactPropTypesSecret);if(error instanceof Error)return error}return null}return createChainableTypeChecker(validate)}function createElementTypeChecker(){function validate(props,propName,componentName,location,propFullName){var propValue=props[propName];if(!isValidElement(propValue)){var propType=getPropType(propValue);return new PropTypeError("Invalid "+location+" `"+propFullName+"` of type "+("`"+propType+"` supplied to `"+componentName+"`, expected a single ReactElement."))}return null}return createChainableTypeChecker(validate)}function createElementTypeTypeChecker(){function validate(props,propName,componentName,location,propFullName){var propValue=props[propName];if(!ReactIs.isValidElementType(propValue)){var propType=getPropType(propValue);return new PropTypeError("Invalid "+location+" `"+propFullName+"` of type "+("`"+propType+"` supplied to `"+componentName+"`, expected a single ReactElement type."))}return null}return createChainableTypeChecker(validate)}function createInstanceTypeChecker(expectedClass){function validate(props,propName,componentName,location,propFullName){if(!(props[propName]instanceof expectedClass)){var expectedClassName=expectedClass.name||ANONYMOUS,actualClassName=getClassName(props[propName]);return new PropTypeError("Invalid "+location+" `"+propFullName+"` of type "+("`"+actualClassName+"` supplied to `"+componentName+"`, expected ")+("instance of `"+expectedClassName+"`."))}return null}return createChainableTypeChecker(validate)}function createEnumTypeChecker(expectedValues){if(!Array.isArray(expectedValues)){if(arguments.length>1)printWarning("Invalid arguments supplied to oneOf, expected an array, got "+arguments.length+" arguments. A common mistake is to write oneOf(x, y, z) instead of oneOf([x, y, z]).");else printWarning("Invalid argument supplied to oneOf, expected an array.");return emptyFunctionThatReturnsNull}function validate(props,propName,componentName,location,propFullName){var propValue=props[propName];for(var i=0;i<expectedValues.length;i++)if(is(propValue,expectedValues[i]))return null;var valuesString=JSON.stringify(expectedValues,function(key,value){var type=getPreciseType(value);if(type==="symbol")return String(value);return value});return new PropTypeError("Invalid "+location+" `"+propFullName+"` of value `"+String(propValue)+"` "+("supplied to `"+componentName+"`, expected one of "+valuesString+"."))}return createChainableTypeChecker(validate)}function createObjectOfTypeChecker(typeChecker){function validate(props,propName,componentName,location,propFullName){if(typeof typeChecker!=="function")return new PropTypeError("Property `"+propFullName+"` of component `"+componentName+"` has invalid PropType notation inside objectOf.");var propValue=props[propName],propType=getPropType(propValue);if(propType!=="object")return new PropTypeError("Invalid "+location+" `"+propFullName+"` of type "+("`"+propType+"` supplied to `"+componentName+"`, expected an object."));for(var key in propValue)if(has(propValue,key)){var error=typeChecker(propValue,key,componentName,location,propFullName+"."+key,ReactPropTypesSecret);if(error instanceof Error)return error}return null}return createChainableTypeChecker(validate)}function createUnionTypeChecker(arrayOfTypeCheckers){if(!Array.isArray(arrayOfTypeCheckers))return printWarning("Invalid argument supplied to oneOfType, expected an instance of array."),emptyFunctionThatReturnsNull;for(var i=0;i<arrayOfTypeCheckers.length;i++){var checker=arrayOfTypeCheckers[i];if(typeof checker!=="function")return printWarning("Invalid argument supplied to oneOfType. Expected an array of check functions, but received "+getPostfixForTypeWarning(checker)+" at index "+i+"."),emptyFunctionThatReturnsNull}function validate(props,propName,componentName,location,propFullName){var expectedTypes=[];for(var i=0;i<arrayOfTypeCheckers.length;i++){var checker=arrayOfTypeCheckers[i],checkerResult=checker(props,propName,componentName,location,propFullName,ReactPropTypesSecret);if(checkerResult==null)return null;if(checkerResult.data&&has(checkerResult.data,"expectedType"))expectedTypes.push(checkerResult.data.expectedType)}var expectedTypesMessage=expectedTypes.length>0?", expected one of type ["+expectedTypes.join(", ")+"]":"";return new PropTypeError("Invalid "+location+" `"+propFullName+"` supplied to "+("`"+componentName+"`"+expectedTypesMessage+"."))}return createChainableTypeChecker(validate)}function createNodeChecker(){function validate(props,propName,componentName,location,propFullName){if(!isNode(props[propName]))return new PropTypeError("Invalid "+location+" `"+propFullName+"` supplied to "+("`"+componentName+"`, expected a ReactNode."));return null}return createChainableTypeChecker(validate)}function invalidValidatorError(componentName,location,propFullName,key,type){return new PropTypeError((componentName||"React class")+": "+location+" type `"+propFullName+"."+key+"` is invalid; it must be a function, usually from the `prop-types` package, but received `"+type+"`.")}function createShapeTypeChecker(shapeTypes){function validate(props,propName,componentName,location,propFullName){var propValue=props[propName],propType=getPropType(propValue);if(propType!=="object")return new PropTypeError("Invalid "+location+" `"+propFullName+"` of type `"+propType+"` "+("supplied to `"+componentName+"`, expected `object`."));for(var key in shapeTypes){var checker=shapeTypes[key];if(typeof checker!=="function")return invalidValidatorError(componentName,location,propFullName,key,getPreciseType(checker));var error=checker(propValue,key,componentName,location,propFullName+"."+key,ReactPropTypesSecret);if(error)return error}return null}return createChainableTypeChecker(validate)}function createStrictShapeTypeChecker(shapeTypes){function validate(props,propName,componentName,location,propFullName){var propValue=props[propName],propType=getPropType(propValue);if(propType!=="object")return new PropTypeError("Invalid "+location+" `"+propFullName+"` of type `"+propType+"` "+("supplied to `"+componentName+"`, expected `object`."));var allKeys=assign({},props[propName],shapeTypes);for(var key in allKeys){var checker=shapeTypes[key];if(has(shapeTypes,key)&&typeof checker!=="function")return invalidValidatorError(componentName,location,propFullName,key,getPreciseType(checker));if(!checker)return new PropTypeError("Invalid "+location+" `"+propFullName+"` key `"+key+"` supplied to `"+componentName+"`.\nBad object: "+JSON.stringify(props[propName],null," ")+`
3
3
  Valid keys: `+JSON.stringify(Object.keys(shapeTypes),null," "));var error=checker(propValue,key,componentName,location,propFullName+"."+key,ReactPropTypesSecret);if(error)return error}return null}return createChainableTypeChecker(validate)}function isNode(propValue){switch(typeof propValue){case"number":case"string":case"undefined":return!0;case"boolean":return!propValue;case"object":if(Array.isArray(propValue))return propValue.every(isNode);if(propValue===null||isValidElement(propValue))return!0;var iteratorFn=getIteratorFn(propValue);if(iteratorFn){var iterator=iteratorFn.call(propValue),step;if(iteratorFn!==propValue.entries){while(!(step=iterator.next()).done)if(!isNode(step.value))return!1}else while(!(step=iterator.next()).done){var entry=step.value;if(entry){if(!isNode(entry[1]))return!1}}}else return!1;return!0;default:return!1}}function isSymbol(propType,propValue){if(propType==="symbol")return!0;if(!propValue)return!1;if(propValue["@@toStringTag"]==="Symbol")return!0;if(typeof Symbol==="function"&&propValue instanceof Symbol)return!0;return!1}function getPropType(propValue){var propType=typeof propValue;if(Array.isArray(propValue))return"array";if(propValue instanceof RegExp)return"object";if(isSymbol(propType,propValue))return"symbol";return propType}function getPreciseType(propValue){if(typeof propValue>"u"||propValue===null)return""+propValue;var propType=getPropType(propValue);if(propType==="object"){if(propValue instanceof Date)return"date";else if(propValue instanceof RegExp)return"regexp"}return propType}function getPostfixForTypeWarning(value){var type=getPreciseType(value);switch(type){case"array":case"object":return"an "+type;case"boolean":case"date":case"regexp":return"a "+type;default:return type}}function getClassName(propValue){if(!propValue.constructor||!propValue.constructor.name)return ANONYMOUS;return propValue.constructor.name}return ReactPropTypes.checkPropTypes=checkPropTypes,ReactPropTypes.resetWarningCache=checkPropTypes.resetWarningCache,ReactPropTypes.PropTypes=ReactPropTypes,ReactPropTypes}});var require_prop_types=__commonJS(function(exports,module){var ReactIs=__toESM(require_react_is_development());throwOnDirectAccess=!0,module.exports=require_factoryWithTypeCheckers()(ReactIs.isElement,throwOnDirectAccess);var throwOnDirectAccess});var require_react_is_development2=__commonJS(function(exports){(function(){function typeOf(object){if(typeof object==="object"&&object!==null){var $$typeof=object.$$typeof;switch($$typeof){case REACT_ELEMENT_TYPE:switch(object=object.type,object){case REACT_FRAGMENT_TYPE:case REACT_PROFILER_TYPE:case REACT_STRICT_MODE_TYPE:case REACT_SUSPENSE_TYPE:case REACT_SUSPENSE_LIST_TYPE:case REACT_VIEW_TRANSITION_TYPE:return object;default:switch(object=object&&object.$$typeof,object){case REACT_CONTEXT_TYPE:case REACT_FORWARD_REF_TYPE:case REACT_LAZY_TYPE:case REACT_MEMO_TYPE:return object;case REACT_CONSUMER_TYPE:return object;default:return $$typeof}}case REACT_PORTAL_TYPE:return $$typeof}}}var REACT_ELEMENT_TYPE=Symbol.for("react.transitional.element"),REACT_PORTAL_TYPE=Symbol.for("react.portal"),REACT_FRAGMENT_TYPE=Symbol.for("react.fragment"),REACT_STRICT_MODE_TYPE=Symbol.for("react.strict_mode"),REACT_PROFILER_TYPE=Symbol.for("react.profiler"),REACT_CONSUMER_TYPE=Symbol.for("react.consumer"),REACT_CONTEXT_TYPE=Symbol.for("react.context"),REACT_FORWARD_REF_TYPE=Symbol.for("react.forward_ref"),REACT_SUSPENSE_TYPE=Symbol.for("react.suspense"),REACT_SUSPENSE_LIST_TYPE=Symbol.for("react.suspense_list"),REACT_MEMO_TYPE=Symbol.for("react.memo"),REACT_LAZY_TYPE=Symbol.for("react.lazy"),REACT_VIEW_TRANSITION_TYPE=Symbol.for("react.view_transition"),REACT_CLIENT_REFERENCE=Symbol.for("react.client.reference");exports.ContextConsumer=REACT_CONSUMER_TYPE,exports.ContextProvider=REACT_CONTEXT_TYPE,exports.Element=REACT_ELEMENT_TYPE,exports.ForwardRef=REACT_FORWARD_REF_TYPE,exports.Fragment=REACT_FRAGMENT_TYPE,exports.Lazy=REACT_LAZY_TYPE,exports.Memo=REACT_MEMO_TYPE,exports.Portal=REACT_PORTAL_TYPE,exports.Profiler=REACT_PROFILER_TYPE,exports.StrictMode=REACT_STRICT_MODE_TYPE,exports.Suspense=REACT_SUSPENSE_TYPE,exports.SuspenseList=REACT_SUSPENSE_LIST_TYPE,exports.isContextConsumer=function(object){return typeOf(object)===REACT_CONSUMER_TYPE},exports.isContextProvider=function(object){return typeOf(object)===REACT_CONTEXT_TYPE},exports.isElement=function(object){return typeof object==="object"&&object!==null&&object.$$typeof===REACT_ELEMENT_TYPE},exports.isForwardRef=function(object){return typeOf(object)===REACT_FORWARD_REF_TYPE},exports.isFragment=function(object){return typeOf(object)===REACT_FRAGMENT_TYPE},exports.isLazy=function(object){return typeOf(object)===REACT_LAZY_TYPE},exports.isMemo=function(object){return typeOf(object)===REACT_MEMO_TYPE},exports.isPortal=function(object){return typeOf(object)===REACT_PORTAL_TYPE},exports.isProfiler=function(object){return typeOf(object)===REACT_PROFILER_TYPE},exports.isStrictMode=function(object){return typeOf(object)===REACT_STRICT_MODE_TYPE},exports.isSuspense=function(object){return typeOf(object)===REACT_SUSPENSE_TYPE},exports.isSuspenseList=function(object){return typeOf(object)===REACT_SUSPENSE_LIST_TYPE},exports.isValidElementType=function(type){return typeof type==="string"||typeof type==="function"||type===REACT_FRAGMENT_TYPE||type===REACT_PROFILER_TYPE||type===REACT_STRICT_MODE_TYPE||type===REACT_SUSPENSE_TYPE||type===REACT_SUSPENSE_LIST_TYPE||typeof type==="object"&&type!==null&&(type.$$typeof===REACT_LAZY_TYPE||type.$$typeof===REACT_MEMO_TYPE||type.$$typeof===REACT_CONTEXT_TYPE||type.$$typeof===REACT_CONSUMER_TYPE||type.$$typeof===REACT_FORWARD_REF_TYPE||type.$$typeof===REACT_CLIENT_REFERENCE||type.getModuleId!==void 0)?!0:!1},exports.typeOf=typeOf})()});import{dirname,join}from"path";import{fileURLToPath}from"url";var MUI_INTRO=["**This folder targets Material UI.** Components are real MUI: `Box`/`Stack`/`Container`/`Paper` for layout, `Card`/`CardContent`/`CardHeader`/`CardActions`, `Typography` (ALL text \u2014 pick `variant` for the type scale), `Button`/`IconButton`, `TextField`, `Chip`, `Divider`, `Avatar`, `List`/`ListItem`, `Table*`, `Tabs`/`Tab`, `Alert`, `Tooltip`, and the overlay surface `Dialog`/`Menu`/`Popover`/`Drawer`/`Snackbar` (rendered open + inline in design mode). Call `list_components` for the full set and per-component `example` props.","",'**Style through `sx`.** `update_props { style: { display: "flex", alignItems: "center", gap: 2, p: 3, color: "primary.main" } }` \u2014 an object of MUI system props, where spacing is theme units (`p: 2` = 16px). It merges shallowly; an inner `null` drops a key, `style: null` clears. `emit_code` emits `<Component sx={{\u2026}} />` importing from `@mui/material`; `emit_theme` emits a `createTheme(...)` module. Tailwind utility diagnostics do not apply here \u2014 style via `sx` plus the shared theme tokens from `get_theme`, which project onto MUI.',""];var sx={name:"sx",type:"SxProps | undefined",optional:!0,control:"string"},children={name:"children",type:"ReactNode",optional:!0,control:"string"},enumProp=(name,values,defaultValue)=>({name,type:values.map((v)=>`"${v}"`).join(" | "),optional:!0,control:"enum",enumValues:values,defaultValue});function ui(id,props,notes,example){return{id,category:"ui",source:"mui",props:[...props,sx],designModeNotes:notes,example}}var className={name:"className",type:"string | undefined",optional:!0,control:"string"};function helper(id,props,notes,example){return{id,category:"ui",source:"velloo",props:[...props,className],designModeNotes:notes,example}}var MUI_MANIFEST=[ui("Box",[children],"Generic layout primitive; style via sx."),ui("Stack",[children,enumProp("direction",["row","column"],"column")],"Flex layout; set spacing via sx or the spacing prop."),ui("Container",[children,enumProp("maxWidth",["xs","sm","md","lg","xl"],"lg")],"Centers + max-widths content."),ui("Paper",[children,enumProp("variant",["elevation","outlined"],"elevation")]),ui("Card",[children,enumProp("variant",["elevation","outlined"],"elevation")]),ui("CardContent",[children]),ui("CardHeader",[{name:"title",type:"ReactNode",optional:!0,control:"string"},{name:"subheader",type:"ReactNode",optional:!0,control:"string"}]),ui("CardActions",[children]),ui("Button",[children,enumProp("variant",["text","outlined","contained"],"text"),enumProp("color",["primary","secondary","success","error","inherit"],"primary"),enumProp("size",["small","medium","large"],"medium")],"Action button.",{variant:"contained",color:"primary",children:"Submit"}),ui("Typography",[children,enumProp("variant",["h1","h2","h3","h4","h5","h6","subtitle1","subtitle2","body1","body2","caption","overline"],"body1"),enumProp("color",["text.primary","text.secondary","primary","error"])],"All text. Pick variant for the type scale; this is MUI's Heading + Text.",{variant:"h4",children:"Team analytics"}),ui("TextField",[enumProp("variant",["outlined","filled","standard"],"outlined"),{name:"label",type:"string",optional:!0,control:"string"},{name:"placeholder",type:"string",optional:!0,control:"string"}]),ui("Chip",[{name:"label",type:"ReactNode",optional:!0,control:"string"},enumProp("variant",["filled","outlined"],"filled"),enumProp("color",["default","primary","success","warning","error"],"default"),enumProp("size",["small","medium"],"medium")]),ui("Divider",[]),ui("Avatar",[children,{name:"src",type:"string",optional:!0,control:"string"}]),ui("LinearProgress",[{name:"value",type:"number",optional:!0,control:"number"},enumProp("variant",["determinate","indeterminate"],"indeterminate")]),ui("AppBar",[children,enumProp("position",["fixed","static","sticky"],"fixed"),enumProp("color",["primary","default","transparent","inherit"],"primary")]),ui("Toolbar",[children]),ui("IconButton",[children,enumProp("size",["small","medium","large"],"medium")]),ui("Link",[children,{name:"href",type:"string",optional:!0,control:"string"}]),ui("List",[children]),ui("ListItem",[children]),ui("ListItemText",[{name:"primary",type:"ReactNode",optional:!0,control:"string"},{name:"secondary",type:"ReactNode",optional:!0,control:"string"}]),ui("Table",[children]),ui("TableHead",[children]),ui("TableBody",[children]),ui("TableRow",[children]),ui("TableCell",[children,enumProp("align",["left","center","right"],"left")]),ui("Tabs",[children,{name:"value",type:"number | string",optional:!0,control:"string"}]),ui("Tab",[{name:"label",type:"ReactNode",optional:!0,control:"string"}]),ui("Badge",[children,{name:"badgeContent",type:"ReactNode",optional:!0,control:"string"}]),ui("Checkbox",[{name:"checked",type:"boolean",optional:!0,control:"boolean"}]),ui("Switch",[{name:"checked",type:"boolean",optional:!0,control:"boolean"}]),ui("Select",[children,enumProp("variant",["outlined","filled","standard"],"outlined")]),ui("MenuItem",[children,{name:"value",type:"string | number",optional:!0,control:"string"}]),ui("Tooltip",[children,{name:"title",type:"ReactNode",optional:!0,control:"string"}]),ui("Alert",[children,enumProp("severity",["success","info","warning","error"],"success")]),ui("Dialog",[children,enumProp("maxWidth",["xs","sm","md","lg","xl"],"sm")],"Modal dialog surface \u2014 renders open + inline in design mode. Fill it with DialogTitle / DialogContent / DialogActions.",{maxWidth:"sm"}),ui("DialogTitle",[children],"The dialog's heading row."),ui("DialogContent",[children],"The dialog's body."),ui("DialogContentText",[children],"Secondary text inside DialogContent."),ui("DialogActions",[children],"The dialog's button row (right-aligned)."),ui("Menu",[children],"A menu surface holding MenuItems \u2014 renders open + inline in design mode."),ui("Popover",[children],"A popover surface \u2014 renders open + inline in design mode."),ui("Drawer",[children],"A side panel \u2014 renders inline as a fixed-width column in design mode."),ui("Snackbar",[children,{name:"message",type:"ReactNode",optional:!0,control:"string"}],"A toast \u2014 renders inline as a dark pill in design mode. Use `message` or children.",{message:"Saved"}),helper("Icon",[{name:"name",type:"string",optional:!1,control:"icon"},{name:"size",type:"number",optional:!0,control:"number"}],"A lucide icon \u2014 MUI has no bundled icon set. Set the pixel `size` prop (not Tailwind). `name` is a lucide id (PascalCase or kebab). Emits a `lucide-react` import.",{name:"ArrowRight",size:20}),helper("Image",[{name:"src",type:"string",optional:!1,control:"string"},{name:"alt",type:"string",optional:!1,control:"string"}],"An image. Use velloo assets (`/assets/\u2026`) or a URL."),helper("Placeholder",[{name:"label",type:"string",optional:!0,control:"string"}],"A labeled placeholder box for imagery you haven't authored yet (avatars, hero shots)."),helper("SVG",[{name:"content",type:"string",optional:!1,control:"string"},{name:"viewBox",type:"string",optional:!1,control:"string"}],"Raw inline SVG markup."),helper("Layer",[children],"An absolutely-positioned overlay layer for stacked composition."),helper("Gradient",[{name:"from",type:"string",optional:!0,control:"color"}],"A gradient fill block."),helper("Prose",[children,{name:"preset",type:"string",optional:!0,control:"string"},{name:"as",type:"string",optional:!0,control:"string"}],"A long-form content region. Everything inside \u2014 Typography, headings, lists, quotes, code, tables \u2014 picks up the theme typeset's proportions and vertical rhythm automatically. `preset` selects a named typeset (see set_typeset). Reach for this for articles, docs, and marketing copy instead of setting sizes block by block.",{as:"article"})];var React49=__toESM(require_react_development()),import_prop_types26=__toESM(require_prop_types());function composeClasses(slots,getUtilityClass,classes=void 0){let output={};for(let slotName in slots){let slot=slots[slotName],buffer="",start=!0;for(let i=0;i<slot.length;i+=1){let value=slot[i];if(value){if(buffer+=(start===!0?"":" ")+getUtilityClass(value),start=!1,classes&&classes[value])buffer+=" "+classes[value]}}output[slotName]=buffer}return output}function clamp(val,min=Number.MIN_SAFE_INTEGER,max=Number.MAX_SAFE_INTEGER){return Math.max(min,Math.min(val,max))}var clamp_default=clamp;function clampWrapper(value,min=0,max=1){if(value<min||value>max)console.error(`MUI: The value provided ${value} is out of range [${min}, ${max}].`);return clamp_default(value,min,max)}function hexToRgb(color){color=color.slice(1);let re=new RegExp(`.{1,${color.length>=6?2:1}}`,"g"),colors=color.match(re);if(colors&&colors[0].length===1)colors=colors.map((n)=>n+n);if(color.length!==color.trim().length)console.error(`MUI: The color: "${color}" is invalid. Make sure the color input doesn't contain leading/trailing space.`);return colors?`rgb${colors.length===4?"a":""}(${colors.map((n,index)=>index<3?parseInt(n,16):Math.round(parseInt(n,16)/255*1000)/1000).join(", ")})`:""}function decomposeColor(color){if(color.type)return color;if(color.charAt(0)==="#")return decomposeColor(hexToRgb(color));let marker=color.indexOf("("),type=color.substring(0,marker);if(!["rgb","rgba","hsl","hsla","color"].includes(type))throw Error(`MUI: Unsupported \`${color}\` color.
4
4
  The following formats are supported: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla(), color().`);let values=color.substring(marker+1,color.length-1),colorSpace;if(type==="color"){if(values=values.split(" "),colorSpace=values.shift(),values.length===4&&values[3].charAt(0)==="/")values[3]=values[3].slice(1);if(!["srgb","display-p3","a98-rgb","prophoto-rgb","rec-2020"].includes(colorSpace))throw Error(`MUI: unsupported \`${colorSpace}\` color space.
5
5
  The following color spaces are supported: srgb, display-p3, a98-rgb, prophoto-rgb, rec-2020.`)}else values=values.split(",");return values=values.map((value)=>parseFloat(value)),{type,values,colorSpace}}var colorChannel=(color)=>{let decomposedColor=decomposeColor(color);return decomposedColor.values.slice(0,3).map((val,idx)=>decomposedColor.type.includes("hsl")&&idx!==0?`${val}%`:val).join(" ")},private_safeColorChannel=(color,warning)=>{try{return colorChannel(color)}catch(error){if(warning)console.warn(warning);return color}};function recomposeColor(color){let{type,colorSpace}=color,{values}=color;if(type.includes("rgb"))values=values.map((n,i)=>i<3?parseInt(n,10):n);else if(type.includes("hsl"))values[1]=`${values[1]}%`,values[2]=`${values[2]}%`;if(type.includes("color"))values=`${colorSpace} ${values.join(" ")}`;else values=`${values.join(", ")}`;return`${type}(${values})`}function hslToRgb(color){color=decomposeColor(color);let{values}=color,h=values[0],s=values[1]/100,l=values[2]/100,a=s*Math.min(l,1-l),f=(n,k=(n+h/30)%12)=>l-a*Math.max(Math.min(k-3,9-k,1),-1),type="rgb",rgb=[Math.round(f(0)*255),Math.round(f(8)*255),Math.round(f(4)*255)];if(color.type==="hsla")type+="a",rgb.push(values[3]);return recomposeColor({type,values:rgb})}function getLuminance(color){color=decomposeColor(color);let rgb=color.type==="hsl"||color.type==="hsla"?decomposeColor(hslToRgb(color)).values:color.values;return rgb=rgb.map((val)=>{if(color.type!=="color")val/=255;return val<=0.03928?val/12.92:((val+0.055)/1.055)**2.4}),Number((0.2126*rgb[0]+0.7152*rgb[1]+0.0722*rgb[2]).toFixed(3))}function getContrastRatio(foreground,background){let lumA=getLuminance(foreground),lumB=getLuminance(background);return(Math.max(lumA,lumB)+0.05)/(Math.min(lumA,lumB)+0.05)}function alpha(color,value){if(color=decomposeColor(color),value=clampWrapper(value),color.type==="rgb"||color.type==="hsl")color.type+="a";if(color.type==="color")color.values[3]=`/${value}`;else color.values[3]=value;return recomposeColor(color)}function private_safeAlpha(color,value,warning){try{return alpha(color,value)}catch(error){if(warning)console.warn(warning);return color}}function darken(color,coefficient){if(color=decomposeColor(color),coefficient=clampWrapper(coefficient),color.type.includes("hsl"))color.values[2]*=1-coefficient;else if(color.type.includes("rgb")||color.type.includes("color"))for(let i=0;i<3;i+=1)color.values[i]*=1-coefficient;return recomposeColor(color)}function private_safeDarken(color,coefficient,warning){try{return darken(color,coefficient)}catch(error){if(warning)console.warn(warning);return color}}function lighten(color,coefficient){if(color=decomposeColor(color),coefficient=clampWrapper(coefficient),color.type.includes("hsl"))color.values[2]+=(100-color.values[2])*coefficient;else if(color.type.includes("rgb"))for(let i=0;i<3;i+=1)color.values[i]+=(255-color.values[i])*coefficient;else if(color.type.includes("color"))for(let i=0;i<3;i+=1)color.values[i]+=(1-color.values[i])*coefficient;return recomposeColor(color)}function private_safeLighten(color,coefficient,warning){try{return lighten(color,coefficient)}catch(error){if(warning)console.warn(warning);return color}}function emphasize(color,coefficient=0.15){return getLuminance(color)>0.5?darken(color,coefficient):lighten(color,coefficient)}function private_safeEmphasize(color,coefficient,warning){try{return emphasize(color,coefficient)}catch(error){if(warning)console.warn(warning);return color}}var React27=__toESM(require_react_development());function capitalize(string){if(typeof string!=="string")throw Error("MUI: `capitalize(string)` expects a string argument.");return string.charAt(0).toUpperCase()+string.slice(1)}var React=__toESM(require_react_development()),import_react_is=__toESM(require_react_is_development2());function isPlainObject(item){if(typeof item!=="object"||item===null)return!1;let prototype=Object.getPrototypeOf(item);return(prototype===null||prototype===Object.prototype||Object.getPrototypeOf(prototype)===null)&&!(Symbol.toStringTag in item)&&!(Symbol.iterator in item)}function deepClone(source){if(React.isValidElement(source)||import_react_is.isValidElementType(source)||!isPlainObject(source))return source;let output={};return Object.keys(source).forEach((key)=>{output[key]=deepClone(source[key])}),output}function deepmerge(target,source,options={clone:!0}){let output=options.clone?{...target}:target;if(isPlainObject(target)&&isPlainObject(source))Object.keys(source).forEach((key)=>{if(React.isValidElement(source[key])||import_react_is.isValidElementType(source[key]))output[key]=source[key];else if(isPlainObject(source[key])&&Object.prototype.hasOwnProperty.call(target,key)&&isPlainObject(target[key]))output[key]=deepmerge(target[key],source[key],options);else if(options.clone)output[key]=isPlainObject(source[key])?deepClone(source[key]):source[key];else output[key]=source[key]});return output}function merge(acc,item){if(!item)return acc;return deepmerge(acc,item,{clone:!1})}var merge_default=merge;var import_prop_types=__toESM(require_prop_types()),responsivePropType=import_prop_types.default.oneOfType([import_prop_types.default.number,import_prop_types.default.string,import_prop_types.default.object,import_prop_types.default.array]),responsivePropType_default=responsivePropType;function sortContainerQueries(theme,css){if(!theme.containerQueries)return css;let sorted=Object.keys(css).filter((key)=>key.startsWith("@container")).sort((a,b)=>{let regex=/min-width:\s*([0-9.]+)/;return+(a.match(regex)?.[1]||0)-+(b.match(regex)?.[1]||0)});if(!sorted.length)return css;return sorted.reduce((acc,key)=>{let value=css[key];return delete acc[key],acc[key]=value,acc},{...css})}function isCqShorthand(breakpointKeys,value){return value==="@"||value.startsWith("@")&&(breakpointKeys.some((key)=>value.startsWith(`@${key}`))||!!value.match(/^@\d/))}function getContainerQuery(theme,shorthand){let matches=shorthand.match(/^@([^/]+)?\/?(.+)?$/);if(!matches)throw Error(`MUI: The provided shorthand ${`(${shorthand})`} is invalid. The format should be \`@<breakpoint | number>\` or \`@<breakpoint | number>/<container>\`.
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{registry2,loadManifest2}from"./chunk-hcb68zt7.js";import"./chunk-jb21jkp1.js";import{snapshotVersion2,entryCssPath2,componentsDir2}from"./chunk-cvn689d5.js";export{componentsDir2 as componentsDir,entryCssPath2 as entryCssPath,loadManifest2 as loadManifest,registry2 as registry,snapshotVersion2 as snapshotVersion};
package/cli.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
- import"./chunk-s23gtejf.js";import{COMMANDS}from"./chunk-1yhc252b.js";import{TOOL_VERSION}from"./chunk-65wb0g7d.js";import{maybeNotifyAboutUpdate}from"./chunk-cep3ktr3.js";import{defineCommand,runMain}from"./chunk-2smsg2ct.js";var main=defineCommand({meta:{name:"velloo",version:TOOL_VERSION,description:"Local, agent-driven canvas for redesigning an existing React screen against the running app, then sharing the result with a team or external reviewer."},subCommands:COMMANDS});await runMain(main);var command=process.argv[2];if(!["mcp","__daemon","__update_check","run","upgrade"].includes(command??""))await maybeNotifyAboutUpdate();
3
+ import"./chunk-s23gtejf.js";import{COMMANDS}from"./chunk-4fj5tahv.js";import{TOOL_VERSION}from"./chunk-dg6z4vdd.js";import{maybeNotifyAboutUpdate}from"./chunk-xt5ayg7g.js";import{defineCommand,runMain}from"./chunk-2smsg2ct.js";var main=defineCommand({meta:{name:"velloo",version:TOOL_VERSION,description:"Open-source, local-first canvas for agent-driven design."},subCommands:COMMANDS});await runMain(main);var command=process.argv[2];if(!["mcp","__daemon","__update_check","run","upgrade"].includes(command??""))await maybeNotifyAboutUpdate();
package/launcher.cjs CHANGED
@@ -54,7 +54,7 @@ if (process.platform === "win32" && process.argv.length === 3 && process.argv[2]
54
54
  // npm rewrote this launcher's package in place, so re-entering by the same
55
55
  // path runs the NEW velloo — which is the one that must migrate the design
56
56
  // folder, since only it knows the format it migrated towards.
57
- const migrate = spawnSync(process.execPath, [__filename, "upgrade", "--folder-only"], {
57
+ const migrate = spawnSync(process.execPath, [__filename, "upgrade", "--design-only"], {
58
58
  stdio: "inherit",
59
59
  });
60
60
  process.exit(migrate.status == null ? 1 : migrate.status);
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "velloo",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "description": "Local-first, code-shaped design canvas — your AI agent designs with your real components, in your repo",
6
6
  "license": "Apache-2.0",
7
- "homepage": "https://github.com/velloo-design/velloo#readme",
7
+ "homepage": "https://velloo.design",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "git+https://github.com/velloo-design/velloo.git"
@@ -26,7 +26,7 @@
26
26
  "bun"
27
27
  ],
28
28
  "bin": {
29
- "velloo": "./launcher.cjs"
29
+ "velloo": "launcher.cjs"
30
30
  },
31
31
  "engines": {
32
32
  "node": ">=18"
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  import { BoardGroupSchema } from "./board.ts";
3
3
  import { ExtensionSchema } from "./extension.ts";
4
4
  import { CURRENT_SCHEMA_VERSION } from "./migrate.ts";
5
- import { FeedbackPrefsSchema } from "./repo.ts";
5
+ import { DesignNameSchema, FeedbackPrefsSchema } from "./repo.ts";
6
6
 
7
7
  export const ViewportPresetSchema = z.object({
8
8
  name: z.string().min(1),
@@ -82,6 +82,13 @@ export const ConfigSchema = z
82
82
  .object({
83
83
  schemaVersion: z.literal(CURRENT_SCHEMA_VERSION),
84
84
  toolVersion: z.string().min(1),
85
+ /**
86
+ * The design's name — what commands, `velloo.json`'s `defaultDesign`, the
87
+ * canvas title and agents call it. Lives here, not in the manifest, so a
88
+ * design carries its identity wherever it is stored. Unique among the
89
+ * designs of one checkout.
90
+ */
91
+ name: DesignNameSchema,
85
92
  /**
86
93
  * Stable folder identity for velloo-cloud (a UUID). Published share links
87
94
  * carry it server-side, so every clone of the folder finds its links (and
@@ -77,9 +77,11 @@ export {
77
77
  export { pascalizeIconName } from "./icon-name.ts";
78
78
  export { type ResourceId, ResourceIdSchema } from "./ids.ts";
79
79
  export {
80
+ APP_PATH_PREFIX,
80
81
  CURRENT_SCHEMA_VERSION,
81
82
  FOLDER_MIGRATIONS,
82
83
  type FolderMigration,
84
+ type MigrationContext,
83
85
  type MigrationRun,
84
86
  planMigration,
85
87
  schemaVersionOf,
@@ -97,11 +99,17 @@ export {
97
99
  type SnippetInstance,
98
100
  } from "./node.ts";
99
101
  export {
102
+ DesignNameSchema,
103
+ designNameIssue,
100
104
  type FeedbackPrefs,
101
105
  FeedbackPrefsSchema,
106
+ isDesignName,
107
+ type NormalizedRepoManifest,
108
+ normalizeRepoManifest,
102
109
  REPO_MANIFEST_FILE,
103
110
  type RepoManifest,
104
111
  RepoManifestSchema,
112
+ toDesignName,
105
113
  } from "./repo.ts";
106
114
  export { type Screen, ScreenSchema } from "./screen.ts";
107
115
  export { type Snippet, type SnippetParam, SnippetParamSchema, SnippetSchema } from "./snippet.ts";
@@ -24,9 +24,14 @@
24
24
  * `letterSpacing` records are gone and `typography` parses strictly, so
25
25
  * a v2 theme file is now a hard validation failure rather than dead
26
26
  * weight — hence the version gate.
27
+ * 4 — designs carry their own `name` (formerly the `velloo.json` project
28
+ * key or a local record's `projectName`), and app-relative paths use the
29
+ * `app:` prefix instead of `project:`.
27
30
  */
28
31
 
29
- export const CURRENT_SCHEMA_VERSION = 3;
32
+ import { isDesignName, toDesignName } from "./repo.ts";
33
+
34
+ export const CURRENT_SCHEMA_VERSION = 4;
30
35
 
31
36
  /**
32
37
  * Read the format version off a raw (unvalidated) config object. Historical
@@ -41,19 +46,32 @@ export function schemaVersionOf(rawConfig: unknown): number {
41
46
 
42
47
  type RawObject = Record<string, unknown>;
43
48
 
49
+ /**
50
+ * Facts a pure migration can't read for itself. The CLI's upgrade supplies
51
+ * them from the files around the folder.
52
+ */
53
+ export interface MigrationContext {
54
+ /** The design's name as its registration recorded it. */
55
+ name?: string | undefined;
56
+ }
57
+
44
58
  export interface FolderMigration {
45
59
  /** Migrates from exactly this version to `from + 1`. */
46
60
  from: number;
47
61
  /** One-line, user-facing description (printed by `velloo upgrade`). */
48
62
  summary: string;
49
63
  /** Transform the raw config.json object (already shallow-cloned). */
50
- config?(raw: RawObject): RawObject;
64
+ config?(raw: RawObject, context: MigrationContext): RawObject;
51
65
  /** Transform one annotation entry from a `screens/<id>.annotations.json` sidecar. */
52
66
  annotation?(raw: RawObject): RawObject;
53
67
  /** Transform one `theme/<name>.json` document. */
54
68
  theme?(raw: RawObject): RawObject;
55
69
  }
56
70
 
71
+ /** Prefix of a path resolved from the design's application root. */
72
+ export const APP_PATH_PREFIX = "app:";
73
+ const LEGACY_APP_PREFIX = "project:";
74
+
57
75
  /** Library id assigned to a legacy single-library config when it is promoted. */
58
76
  const LEGACY_LIBRARY_KEY = "default";
59
77
 
@@ -194,6 +212,41 @@ export const FOLDER_MIGRATIONS: FolderMigration[] = [
194
212
  return { ...raw, typography: next };
195
213
  },
196
214
  },
215
+ {
216
+ from: 3,
217
+ summary: "the design's name moves into its config; `project:` paths become `app:`",
218
+ config(raw, context) {
219
+ const out: RawObject = { ...raw, schemaVersion: 4 };
220
+ if (typeof out.name !== "string" || !isDesignName(out.name)) {
221
+ out.name = (context.name && toDesignName(context.name)) ?? "design";
222
+ }
223
+ const toApp = (path: unknown) =>
224
+ typeof path === "string" && path.startsWith(LEGACY_APP_PREFIX)
225
+ ? `${APP_PATH_PREFIX}${path.slice(LEGACY_APP_PREFIX.length)}`
226
+ : path;
227
+ const hostApp = asObject(out.hostApp);
228
+ if (hostApp) out.hostApp = { ...hostApp, root: toApp(hostApp.root) };
229
+ const hostApps = asObject(out.hostApps);
230
+ if (hostApps) {
231
+ out.hostApps = Object.fromEntries(
232
+ Object.entries(hostApps).map(([key, app]) => {
233
+ const entry = asObject(app);
234
+ return [key, entry ? { ...entry, root: toApp(entry.root) } : app];
235
+ }),
236
+ );
237
+ }
238
+ const libraries = asObject(out.libraries);
239
+ if (libraries) {
240
+ out.libraries = Object.fromEntries(
241
+ Object.entries(libraries).map(([key, lib]) => {
242
+ const entry = asObject(lib);
243
+ return [key, entry ? { ...entry, componentsPath: toApp(entry.componentsPath) } : lib];
244
+ }),
245
+ );
246
+ }
247
+ return out;
248
+ },
249
+ },
197
250
  ];
198
251
 
199
252
  export interface MigrationRun {
@@ -216,7 +269,7 @@ export interface MigrationRun {
216
269
  * (version > current) — the caller should tell the user to upgrade velloo —
217
270
  * or when the chain has a gap (a bug in this module).
218
271
  */
219
- export function planMigration(rawConfig: unknown): MigrationRun {
272
+ export function planMigration(rawConfig: unknown, context: MigrationContext = {}): MigrationRun {
220
273
  const from = schemaVersionOf(rawConfig);
221
274
  if (from > CURRENT_SCHEMA_VERSION) {
222
275
  throw new Error(
@@ -231,7 +284,7 @@ export function planMigration(rawConfig: unknown): MigrationRun {
231
284
  }
232
285
  let config = { ...((rawConfig ?? {}) as RawObject) };
233
286
  for (const step of steps) {
234
- if (step.config) config = step.config(config);
287
+ if (step.config) config = step.config(config, context);
235
288
  }
236
289
  // Even a no-step run normalizes the version field so `upgrade` is idempotent.
237
290
  config.schemaVersion = CURRENT_SCHEMA_VERSION;
@@ -18,35 +18,117 @@ export const FeedbackPrefsSchema = z.object({
18
18
 
19
19
  export type FeedbackPrefs = z.infer<typeof FeedbackPrefsSchema>;
20
20
 
21
- const PROJECT_NAME = /^[a-z0-9][a-z0-9._-]*$/i;
21
+ const MAX_DESIGN_NAME = 80;
22
22
 
23
23
  /**
24
- * The repo-root `velloo.json`. It names a repo's design folders so a monorepo
25
- * can hold several, and carries the handful of preferences that belong to the
26
- * repo rather than to any one design folder — feedback consent is answered
27
- * once per person, not once per canvas.
28
- *
29
- * Design settings still live in each folder's `.design/config.json`; nothing
30
- * here duplicates that contract.
24
+ * Why `name` can't name a design, or null when it can. Almost anything goes —
25
+ * spaces, emoji, any script. The limits are the ones a name typed as a command
26
+ * argument needs: no path separator (a bare argument with one is read as a
27
+ * path), no control characters, nothing that is only whitespace or a dot
28
+ * path, and no padding a shell would silently strip.
29
+ */
30
+ export function designNameIssue(name: string): string | null {
31
+ if (name.trim() === "") return "a design name can't be empty";
32
+ if (name !== name.trim()) return "a design name can't start or end with spaces";
33
+ if (name === "." || name === "..") return `"${name}" can't be a design name`;
34
+ if (/[/\\]/.test(name)) return "a design name can't contain / or \\";
35
+ if (/\p{Cc}/u.test(name)) return "a design name can't contain control characters";
36
+ if ([...name].length > MAX_DESIGN_NAME)
37
+ return `a design name can't be longer than ${MAX_DESIGN_NAME} characters`;
38
+ return null;
39
+ }
40
+
41
+ export function isDesignName(name: string): boolean {
42
+ return designNameIssue(name) === null;
43
+ }
44
+
45
+ /** A Zod string that must be a design name, with the specific reason when it isn't. */
46
+ export const DesignNameSchema = z.string().superRefine((name, ctx) => {
47
+ const issue = designNameIssue(name);
48
+ if (issue) ctx.addIssue({ code: "custom", message: issue });
49
+ });
50
+
51
+ /**
52
+ * Coerce free text (a directory name, an app name) into a valid design name,
53
+ * or null when nothing usable is left.
54
+ */
55
+ export function toDesignName(text: string): string | null {
56
+ const cleaned = [...text.replace(/[/\\\p{Cc}]+/gu, " ").trim()]
57
+ .slice(0, MAX_DESIGN_NAME)
58
+ .join("")
59
+ .trim();
60
+ return cleaned && isDesignName(cleaned) ? cleaned : null;
61
+ }
62
+
63
+ /**
64
+ * The repo-root `velloo.json`. It lists a repo's designs so a monorepo can
65
+ * hold several, and carries the handful of preferences that belong to the
66
+ * repo rather than to any one design — feedback consent is answered once per
67
+ * person, not once per canvas.
31
68
  *
32
- * Every project is a path to a design folder inside the repository. A design
69
+ * Only locations live here: each design's name and settings are in its own
70
+ * `.design/config.json`, so nothing here can drift from the design itself.
71
+ * Every entry is a path to a design folder inside the repository. A design
33
72
  * kept outside it is recorded only on the machine that has it, never here.
34
73
  */
35
74
  export const RepoManifestSchema = z
36
75
  .object({
37
76
  $schema: z.string().optional(),
38
- projects: z.record(
39
- z.string().regex(PROJECT_NAME, "project names are letters/digits plus . _ -"),
40
- z.string().min(1),
41
- ),
42
- defaultProject: z.string().optional(),
77
+ designs: z.array(z.string().min(1)),
78
+ /** The name of the design a bare command resolves to when nothing else picks one. */
79
+ defaultDesign: DesignNameSchema.optional(),
43
80
  feedback: FeedbackPrefsSchema.optional(),
44
81
  })
45
- .refine((m) => !m.defaultProject || m.defaultProject in m.projects, {
46
- message: "defaultProject must name an entry in projects",
82
+ .refine((m) => new Set(m.designs).size === m.designs.length, {
83
+ message: "designs lists the same path twice",
47
84
  });
48
85
 
49
86
  export type RepoManifest = z.infer<typeof RepoManifestSchema>;
50
87
 
51
88
  /** Filename of the repo-root manifest, resolved by walking up from a folder. */
52
89
  export const REPO_MANIFEST_FILE = "velloo.json";
90
+
91
+ export interface NormalizedRepoManifest {
92
+ /** The manifest in the current shape, ready for {@link RepoManifestSchema}. */
93
+ manifest: unknown;
94
+ /**
95
+ * Names the pre-v4 `projects` map gave each path. A folder not yet migrated
96
+ * has no `name` in its config, so these stand in until `velloo upgrade`
97
+ * writes them there.
98
+ */
99
+ legacyNames: Record<string, string>;
100
+ /** True when the file was in the pre-v4 shape and should be rewritten. */
101
+ legacy: boolean;
102
+ }
103
+
104
+ /**
105
+ * Read either manifest shape. Before designs carried their own names the file
106
+ * was `{ projects: { name: path }, defaultProject }`; the schema would silently
107
+ * drop those keys, so they are converted here, before parsing.
108
+ */
109
+ export function normalizeRepoManifest(raw: unknown): NormalizedRepoManifest {
110
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
111
+ return { manifest: raw, legacyNames: {}, legacy: false };
112
+ }
113
+ const { projects, defaultProject, ...rest } = raw as Record<string, unknown>;
114
+ if (projects === undefined || "designs" in rest) {
115
+ return { manifest: raw, legacyNames: {}, legacy: false };
116
+ }
117
+ const legacyNames: Record<string, string> = {};
118
+ const designs: unknown[] = [];
119
+ if (typeof projects === "object" && projects !== null && !Array.isArray(projects)) {
120
+ for (const [name, path] of Object.entries(projects)) {
121
+ designs.push(path);
122
+ if (typeof path === "string") legacyNames[path] = name;
123
+ }
124
+ }
125
+ return {
126
+ manifest: {
127
+ ...rest,
128
+ designs,
129
+ ...(defaultProject !== undefined ? { defaultDesign: defaultProject } : {}),
130
+ },
131
+ legacyNames,
132
+ legacy: true,
133
+ };
134
+ }