docs: function CSelect(rawCases) {
  	return new Type("select", function makeSelect(ctx) {
  		var {value, updateTo, problems} = ctx;
  		var cases = processCases(ctx, rawCases);
  		var defaultCase =
  			cases.find(x => x.isDefault) ||
  			findCaseWithBestMode(cases) ||
  			cases[0];
  		var userSelected = value != undefined
  		if (!userSelected)
  			value = csel(defaultCase.name);
  		function retract() {
  			updateTo(undefined);
  		}
  		var {$case: caseName, $detail: detail} = value;
  		function getCase(name) {
  			return cases.find(x => x.name === name);
  		}
  		function updateCase(newCaseName) {
  			updateTo(csel(newCaseName));
  		}
  		function updateDetail(newDetail) {
  			updateTo(csel(caseName, newDetail));
  		}
  		var currentCase = getCase(caseName);
  		if (currentCase == undefined)
  			currentCase = {
  				name: caseName,
  				label: `unknown option: ${caseName}`,
  				type: CUnit(),
  				mode: "error"
  			};
  		var {mode, messages = []} = currentCase;
  		messages = messages.map(m => problems.add(m));
  		var detailNode = currentCase.type.makeNode({...ctx, value: detail, updateTo: updateDetail});
  		return new SelectNode({cases, caseName, currentCase, userSelected, retract, mode, messages, detailNode, updateCase});
  	});
  }