@fuaran-ui/ops 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -383,6 +383,9 @@ var binding = (b, staticEnc = objValue) => {
383
383
  }
384
384
  case "Computed":
385
385
  return caseObj("Computed", [["fn", CLOSURE]]);
386
+ // No wire fields: the instant is host-furnished at resolve time.
387
+ case "Now":
388
+ return caseObj("Now", []);
386
389
  case "I18n": {
387
390
  const fields = [];
388
391
  if (b.args !== void 0) {
@@ -425,7 +428,10 @@ var binding = (b, staticEnc = objValue) => {
425
428
  return caseObj("Transform", [
426
429
  ...paramFields,
427
430
  ["pipeline", jArray(b.pipeline.map(transformStep))],
428
- ["source", dataSource(b.source)]
431
+ [
432
+ "source",
433
+ b.source.kind === "Data" ? dataSource(b.source.source) : binding(b.source.binding, jsonValue)
434
+ ]
429
435
  ]);
430
436
  }
431
437
  case "Invoke":
@@ -459,11 +465,12 @@ var action = (a) => {
459
465
  ]);
460
466
  case "Navigate":
461
467
  return caseObj("Navigate", [["route", str(a.route)]]);
462
- case "SetState":
463
- return caseObj("SetState", [
464
- ["key", str(a.key)],
465
- ["value", jsonValue(a.value)]
466
- ]);
468
+ case "SetState": {
469
+ const fields = [["key", str(a.key)]];
470
+ if (a.value !== void 0) fields.push(["value", jsonValue(a.value)]);
471
+ if (a.valueFrom !== void 0) fields.push(["valueFrom", binding(a.valueFrom, jsonValue)]);
472
+ return caseObj("SetState", fields);
473
+ }
467
474
  case "AiTool":
468
475
  return caseObj("AiTool", [
469
476
  ["args", jsonValue(a.args)],
@@ -519,6 +526,13 @@ var cellFormat = (f) => {
519
526
  return caseObj("SignificantDigits", [["digits", num(f.digits)]]);
520
527
  case "Date":
521
528
  return caseObj("Date", [["format", str(f.format)]]);
529
+ case "Duration":
530
+ return caseObj("Duration", [
531
+ ["style", str(f.style)],
532
+ ["unit", str(f.unit)]
533
+ ]);
534
+ case "RelativeTime":
535
+ return caseObj("RelativeTime", [["unit", str(f.unit)]]);
522
536
  case "Custom":
523
537
  return caseObj("Custom", [["fn", CLOSURE]]);
524
538
  default:
@@ -537,6 +551,11 @@ var formatIntent = (f) => {
537
551
  return caseObj("Date", [["dateStyle", str(f.dateStyle)]]);
538
552
  case "RelativeTime":
539
553
  return caseObj("RelativeTime", [["unit", str(f.unit)]]);
554
+ case "Duration":
555
+ return caseObj("Duration", [
556
+ ["style", str(f.style)],
557
+ ["unit", str(f.unit)]
558
+ ]);
540
559
  default:
541
560
  return assertNever(f);
542
561
  }
@@ -632,6 +651,7 @@ var linkSpec = (s) => {
632
651
  ];
633
652
  if (s.rel !== void 0) fields.push(["rel", str(s.rel)]);
634
653
  if (s.target !== void 0) fields.push(["target", str(s.target)]);
654
+ if (s.protection !== void 0) fields.push(["protection", str(s.protection)]);
635
655
  return jObject(fields);
636
656
  };
637
657
  var imageSpec = (s) => jObject([
@@ -669,6 +689,13 @@ var mathSpec = (s) => jObject([
669
689
  ]);
670
690
  var sparklineSpec = (s) => jObject([["source", binding(s.source, staticFloatSeq)]]);
671
691
  var skeletonSpec = (s) => jObject([["rows", num(s.rows)]]);
692
+ var iconSpec = (s) => {
693
+ const fields = [["icon", str(s.icon)]];
694
+ if (s.label !== void 0) fields.push(["label", str(s.label)]);
695
+ if (s.size !== "Medium") fields.push(["size", str(s.size)]);
696
+ pushToneOptional(fields, s.tone);
697
+ return jObject(fields);
698
+ };
672
699
  var calloutSpec = (s) => {
673
700
  const fields = [
674
701
  ["body", textSource(s.body)],
@@ -712,6 +739,8 @@ var drawStyle = (s) => {
712
739
  if (s.emphasis !== void 0) fields.push(["emphasis", str(s.emphasis)]);
713
740
  if (s.fontFamily !== void 0) fields.push(["fontFamily", str(s.fontFamily)]);
714
741
  if (s.markId !== void 0) fields.push(["markId", str(s.markId)]);
742
+ if (s.rotation !== void 0) fields.push(["rotation", num(s.rotation)]);
743
+ if (s.tip !== void 0) fields.push(["tip", textSource(s.tip)]);
715
744
  return jObject(fields);
716
745
  };
717
746
  var curveCommand = (c) => {
@@ -828,6 +857,8 @@ var displayKind = (d) => {
828
857
  return hoistSpec("Progress", progressSpec(d.spec));
829
858
  case "Skeleton":
830
859
  return hoistSpec("Skeleton", skeletonSpec(d.spec));
860
+ case "Icon":
861
+ return hoistSpec("Icon", iconSpec(d.spec));
831
862
  case "LabelValueRow":
832
863
  return hoistSpec("LabelValueRow", labelValueRowSpec(d.spec));
833
864
  case "Fact":
@@ -877,6 +908,11 @@ var formFieldKind = (autoBind, k) => {
877
908
  ...handlerField("onToggle", k.onToggle),
878
909
  ...valueField(k.value, controlValueDefaults.checkbox, (v) => binding(v))
879
910
  ]);
911
+ case "Toggle":
912
+ return caseObj("Toggle", [
913
+ ...handlerField("onToggle", k.onToggle),
914
+ ...valueField(k.value, controlValueDefaults.checkbox, (v) => binding(v))
915
+ ]);
880
916
  case "Choice":
881
917
  return caseObj("Choice", [
882
918
  ...handlerField("onChange", k.onChange),
@@ -1130,8 +1166,14 @@ var columnErased = (c) => {
1130
1166
  pushColumnWidthOptional(fields, "width", c.width);
1131
1167
  if (c.value !== void 0) fields.push(["value", CLOSURE]);
1132
1168
  if (c.field !== void 0) fields.push(["field", str(c.field)]);
1169
+ if (c.sortable !== void 0) fields.push(["sortable", bool(c.sortable)]);
1170
+ if (c.editable !== void 0) fields.push(["editable", bool(c.editable)]);
1133
1171
  return jObject(fields);
1134
1172
  };
1173
+ var defaultSortJson = (d) => jObject([
1174
+ ["column", intLit(d.column)],
1175
+ ["direction", str(d.direction)]
1176
+ ]);
1135
1177
  var gridSpec = (s) => {
1136
1178
  const fields = [
1137
1179
  ["columns", jArray(s.columns.map(columnErased))],
@@ -1143,14 +1185,22 @@ var gridSpec = (s) => {
1143
1185
  if (s.onRowClick !== void 0) fields.push(["onRowClick", CLOSURE]);
1144
1186
  if (s.rowKey !== void 0) fields.push(["rowKey", CLOSURE]);
1145
1187
  if (s.rowKeyField !== void 0) fields.push(["rowKeyField", str(s.rowKeyField)]);
1146
- if (s.staticRows !== void 0)
1147
- fields.push([
1148
- "staticRows",
1149
- jObject([
1150
- ["headers", jArray(s.staticRows.headers.map(textSource))],
1151
- ["rows", jArray(s.staticRows.rows.map((row) => jArray(row.map(textSource))))]
1152
- ])
1153
- ]);
1188
+ if (s.sortStateKey !== void 0) fields.push(["sortStateKey", str(s.sortStateKey)]);
1189
+ if (s.pageSize !== void 0) fields.push(["pageSize", num(s.pageSize)]);
1190
+ if (s.pageStateKey !== void 0) fields.push(["pageStateKey", str(s.pageStateKey)]);
1191
+ if (s.defaultSort !== void 0) fields.push(["defaultSort", defaultSortJson(s.defaultSort)]);
1192
+ if (s.editStateKey !== void 0) fields.push(["editStateKey", str(s.editStateKey)]);
1193
+ if (s.staticRows !== void 0) {
1194
+ const sr = s.staticRows;
1195
+ const srFields = [
1196
+ ["headers", jArray(sr.headers.map(textSource))],
1197
+ ["rows", jArray(sr.rows.map((row) => jArray(row.map(textSource))))]
1198
+ ];
1199
+ if (sr.sortable !== void 0) srFields.push(["sortable", bool(sr.sortable)]);
1200
+ if (sr.defaultSort !== void 0)
1201
+ srFields.push(["defaultSort", defaultSortJson(sr.defaultSort)]);
1202
+ fields.push(["staticRows", jObject(srFields)]);
1203
+ }
1154
1204
  return jObject(fields);
1155
1205
  };
1156
1206
  var chartSpec = (s) => {
@@ -1163,6 +1213,13 @@ var chartSpec = (s) => {
1163
1213
  ["yFields", jArray(s.yFields.map(str))]
1164
1214
  ];
1165
1215
  if (s.title !== void 0) fields.push(["title", textSource(s.title)]);
1216
+ if (s.valueFormat !== void 0) fields.push(["valueFormat", formatIntent(s.valueFormat)]);
1217
+ if (s.xTitle !== void 0) fields.push(["xTitle", textSource(s.xTitle)]);
1218
+ if (s.yTitle !== void 0) fields.push(["yTitle", textSource(s.yTitle)]);
1219
+ if (s.subtitle !== void 0) fields.push(["subtitle", textSource(s.subtitle)]);
1220
+ if (s.legendPosition !== void 0) fields.push(["legendPosition", str(s.legendPosition)]);
1221
+ if (s.dataLabels !== void 0) fields.push(["dataLabels", str(s.dataLabels)]);
1222
+ if (s.xScale !== void 0) fields.push(["xScale", str(s.xScale)]);
1166
1223
  if (s.onPointClick !== void 0) fields.push(["onPointClick", CLOSURE]);
1167
1224
  return jObject(fields);
1168
1225
  };
@@ -1442,7 +1499,10 @@ var nodeKind = (k) => {
1442
1499
  )
1443
1500
  ],
1444
1501
  ["default", node(k.spec.default)],
1445
- ["stateKey", str(k.spec.stateKey)]
1502
+ // Phase 768 collapse rule — State(key, no default) keeps the compact
1503
+ // canonical `stateKey` spelling (existing fixtures stay byte-identical);
1504
+ // any other selector encodes as `on`.
1505
+ k.spec.on.kind === "State" && k.spec.on.defaultValue === void 0 ? ["stateKey", str(k.spec.on.key)] : ["on", binding(k.spec.on, str)]
1446
1506
  ]);
1447
1507
  case "FragmentDecl": {
1448
1508
  const fields = [
@@ -3078,12 +3138,23 @@ var decodeTextAnchor = (p, j) => bareEnum(p, j, ["Start", "Middle", "End"], "Tex
3078
3138
  var decodeStyleRole = (p, j) => bareEnum(p, j, ["None", "Eyebrow", "Data", "Lede", "Caption"], "StyleRole");
3079
3139
  var decodeFontVoice = (p, j) => bareEnum(p, j, ["Default", "Display", "Structural"], "FontVoice");
3080
3140
  var decodeChartKind = (p, j) => bareEnum(p, j, ["Line", "Bar", "Area", "Pie", "Scatter", "Heatmap"], "ChartKind");
3141
+ var decodeChartLegendPosition = (p, j) => bareEnum(p, j, ["Top", "Right", "Bottom", "None"], "ChartLegendPosition");
3142
+ var decodeChartDataLabels = (p, j) => bareEnum(p, j, ["Off", "Ends"], "ChartDataLabels");
3143
+ var decodeChartXScale = (p, j) => bareEnum(p, j, ["Category", "Temporal"], "ChartXScale");
3081
3144
  var decodeFileReadEncoding = (p, j) => bareEnum(p, j, ["Text", "Base64", "DataUrl"], "FileReadEncoding");
3082
3145
  var decodeAriaRole = (p, j) => {
3083
3146
  if (j.kind !== "JString") return wrongType(p, "JSON string (ARIA role)");
3084
3147
  return ok(j.value);
3085
3148
  };
3086
3149
  var decodeLiveRegion = (p, j) => bareEnum(p, j, ["polite", "assertive", "off"], "LiveRegionKind");
3150
+ var decodeDurationUnit = (p, j) => bareEnum(p, j, ["Seconds", "Minutes", "Hours"], "DurationUnit");
3151
+ var decodeDurationStyle = (p, j) => bareEnum(p, j, ["Compact", "Clock", "Long"], "DurationStyle");
3152
+ var decodeRelativeTimeUnit = (p, j) => bareEnum(
3153
+ p,
3154
+ j,
3155
+ ["Second", "Minute", "Hour", "Day", "Week", "Month", "Year"],
3156
+ "RelativeTimeUnit"
3157
+ );
3087
3158
  var decodeCellFormat = (path, j) => {
3088
3159
  const fo = requireObject(path, j);
3089
3160
  if (!fo.ok) return fo;
@@ -3118,13 +3189,24 @@ var decodeCellFormat = (path, j) => {
3118
3189
  const r = reqField(path, f, "format", "format string", requireString);
3119
3190
  return r.ok ? ok({ kind: "Date", format: r.value }) : r;
3120
3191
  }
3192
+ case "Duration": {
3193
+ const unit = reqField(path, f, "unit", "DurationUnit string", decodeDurationUnit);
3194
+ if (!unit.ok) return unit;
3195
+ const style = reqField(path, f, "style", "DurationStyle string", decodeDurationStyle);
3196
+ if (!style.ok) return style;
3197
+ return ok({ kind: "Duration", unit: unit.value, style: style.value });
3198
+ }
3199
+ case "RelativeTime": {
3200
+ const r = reqField(path, f, "unit", "RelativeTimeUnit string", decodeRelativeTimeUnit);
3201
+ return r.ok ? ok({ kind: "RelativeTime", unit: r.value }) : r;
3202
+ }
3121
3203
  case "Custom":
3122
3204
  return ok({ kind: "Custom", format: () => CLOSURE2 });
3123
3205
  default:
3124
3206
  return unknownDuCase(
3125
3207
  path,
3126
3208
  d.value,
3127
- "None | Number | Currency | Percent | SignificantDigits | Date | Custom"
3209
+ "None | Number | Currency | Percent | SignificantDigits | Date | Duration | RelativeTime | Custom"
3128
3210
  );
3129
3211
  }
3130
3212
  };
@@ -3162,22 +3244,22 @@ var decodeFormat = (path, j) => {
3162
3244
  return r.ok ? ok({ kind: "Date", dateStyle: r.value }) : r;
3163
3245
  }
3164
3246
  case "RelativeTime": {
3165
- const r = reqField(
3166
- path,
3167
- f,
3168
- "unit",
3169
- "RelativeTimeUnit string",
3170
- (p, v) => bareEnum(
3171
- p,
3172
- v,
3173
- ["Second", "Minute", "Hour", "Day", "Week", "Month", "Year"],
3174
- "RelativeTimeUnit"
3175
- )
3176
- );
3247
+ const r = reqField(path, f, "unit", "RelativeTimeUnit string", decodeRelativeTimeUnit);
3177
3248
  return r.ok ? ok({ kind: "RelativeTime", unit: r.value }) : r;
3178
3249
  }
3250
+ case "Duration": {
3251
+ const unit = reqField(path, f, "unit", "DurationUnit string", decodeDurationUnit);
3252
+ if (!unit.ok) return unit;
3253
+ const style = reqField(path, f, "style", "DurationStyle string", decodeDurationStyle);
3254
+ if (!style.ok) return style;
3255
+ return ok({ kind: "Duration", unit: unit.value, style: style.value });
3256
+ }
3179
3257
  default:
3180
- return unknownDuCase(path, d.value, "Number | Currency | Percent | Date | RelativeTime");
3258
+ return unknownDuCase(
3259
+ path,
3260
+ d.value,
3261
+ "Number | Currency | Percent | Date | RelativeTime | Duration"
3262
+ );
3181
3263
  }
3182
3264
  };
3183
3265
  var decodeLocaleSource = (path, j) => {
@@ -4164,6 +4246,13 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
4164
4246
  }
4165
4247
  case "Computed":
4166
4248
  return ok({ kind: "Computed", compute: () => void 0 });
4249
+ // The projection decodes to the IDENTITY (the Phase 427 Selection fix
4250
+ // replayed): the host-furnished instant is already the wire-shaped string,
4251
+ // so a decoded reader receives it as-is. A value-discarding placeholder
4252
+ // here would make every decoded `Now` resolve to nothing even when the
4253
+ // host furnishes the instant.
4254
+ case "Now":
4255
+ return ok({ kind: "Now", project: (iso) => iso });
4167
4256
  case "I18n": {
4168
4257
  const key = reqField(path, f, "key", "i18n key string", requireString);
4169
4258
  if (!key.ok) return key;
@@ -4224,8 +4313,35 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
4224
4313
  if (!srcJ.ok) return srcJ;
4225
4314
  const pipeJ = requireField(path, f, "pipeline", "Transform pipeline array");
4226
4315
  if (!pipeJ.ok) return pipeJ;
4227
- const src = decodeDataSource(srcJ.value);
4228
- if (!src.ok) return makeError("WRONG_TYPE", `${path}.source`, src.error);
4316
+ const liveTagAst = srcJ.value.kind === "JObject" ? srcJ.value.fields.get("$type") : void 0;
4317
+ const liveTag = liveTagAst !== void 0 && liveTagAst.kind === "JString" && (liveTagAst.value === "State" || liveTagAst.value === "Selection" || liveTagAst.value === "Query") ? liveTagAst.value : void 0;
4318
+ const hasCarried = srcJ.value.kind === "JObject" && srcJ.value.fields.has("defaultValue");
4319
+ let source;
4320
+ if (liveTag === void 0 || liveTag === "State" && !hasCarried) {
4321
+ const src = decodeDataSource(normaliseTransformSource(srcJ.value));
4322
+ if (!src.ok) return makeError("WRONG_TYPE", `${path}.source`, src.error);
4323
+ source = { kind: "Data", source: src.value };
4324
+ } else {
4325
+ const b2 = decodeBinding(`${path}.source`, srcJ.value, decodeJVal, void 0);
4326
+ if (!b2.ok) return b2;
4327
+ if (liveTag === "State") {
4328
+ const snap = decodeDataSource(normaliseTransformSource(srcJ.value));
4329
+ if (!snap.ok) return makeError("WRONG_TYPE", `${path}.source`, snap.error);
4330
+ source = {
4331
+ kind: "Live",
4332
+ binding: b2.value,
4333
+ initial: snap.value
4334
+ };
4335
+ } else {
4336
+ const dv = srcJ.value.kind === "JObject" ? srcJ.value.fields.get("defaultValue") : void 0;
4337
+ const snap = dv !== void 0 ? decodeDataSource(normaliseTransformSource(dv)) : void 0;
4338
+ source = {
4339
+ kind: "Live",
4340
+ binding: b2.value,
4341
+ initial: snap !== void 0 && snap.ok ? snap.value : { kind: "Embedded", table: { schema: [], columns: [] } }
4342
+ };
4343
+ }
4344
+ }
4229
4345
  const pipe = decodePipelineCore(pipeJ.value);
4230
4346
  if (!pipe.ok) return makeError("WRONG_TYPE", `${path}.pipeline`, pipe.error);
4231
4347
  const paramsField = tryField(f, "params");
@@ -4276,7 +4392,7 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
4276
4392
  }
4277
4393
  const b = {
4278
4394
  kind: "Transform",
4279
- source: src.value,
4395
+ source,
4280
4396
  pipeline: pipe.value,
4281
4397
  ...params !== void 0 ? { params } : {}
4282
4398
  };
@@ -4311,6 +4427,62 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
4311
4427
  );
4312
4428
  }
4313
4429
  };
4430
+ var normaliseTransformSource = (j) => {
4431
+ let unwrapped = j;
4432
+ if (j.kind === "JObject") {
4433
+ const t = j.fields.get("$type");
4434
+ if (t !== void 0 && t.kind === "JString" && (t.value === "State" || t.value === "Static" || t.value === "Bound")) {
4435
+ const inner = j.fields.get("defaultValue") ?? j.fields.get("value");
4436
+ if (inner !== void 0) unwrapped = inner;
4437
+ }
4438
+ }
4439
+ if (unwrapped.kind === "JArray" && unwrapped.items.length > 0 && unwrapped.items[0].kind === "JObject") {
4440
+ const rows = unwrapped.items;
4441
+ const first = unwrapped.items[0];
4442
+ const keys = [...first.fields.keys()].sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
4443
+ const cols = /* @__PURE__ */ new Map();
4444
+ for (const k of keys) {
4445
+ const cells = rows.map((row) => {
4446
+ if (row.kind !== "JObject") return { kind: "JNull" };
4447
+ return row.fields.get(k) ?? { kind: "JNull" };
4448
+ });
4449
+ cols.set(k, { kind: "JArray", items: cells });
4450
+ }
4451
+ return {
4452
+ kind: "JObject",
4453
+ fields: /* @__PURE__ */ new Map([["columns", { kind: "JObject", fields: cols }]])
4454
+ };
4455
+ }
4456
+ return unwrapped;
4457
+ };
4458
+ var liveValueToTable = (v) => {
4459
+ if (v === void 0) return { ok: false, error: "Transform live source resolved to no value" };
4460
+ let text;
4461
+ try {
4462
+ text = JSON.stringify(v);
4463
+ } catch {
4464
+ return {
4465
+ ok: false,
4466
+ error: "Transform live source resolved to a value with no JSON representation"
4467
+ };
4468
+ }
4469
+ if (text === void 0) {
4470
+ return { ok: false, error: "Transform live source resolved to no value" };
4471
+ }
4472
+ const parsed = parse(text);
4473
+ if (!parsed.ok) {
4474
+ return { ok: false, error: "Transform live source resolved to unreadable data" };
4475
+ }
4476
+ const src = decodeDataSource(normaliseTransformSource(parsed.value));
4477
+ if (!src.ok) return { ok: false, error: src.error };
4478
+ if (src.value.kind !== "Embedded") {
4479
+ return {
4480
+ ok: false,
4481
+ error: `Transform live source resolved to a 'ref' source ('${src.value.name}'), which is not host-resolved`
4482
+ };
4483
+ }
4484
+ return { ok: true, value: src.value.table };
4485
+ };
4314
4486
  var decodeBindingArgs = (path, j) => {
4315
4487
  const fo = requireObject(path, j);
4316
4488
  if (!fo.ok) return fo;
@@ -4575,9 +4747,32 @@ var decodeAction = (path, j) => {
4575
4747
  case "SetState": {
4576
4748
  const key = reqField(path, f, "key", "state key string", requireString);
4577
4749
  if (!key.ok) return key;
4578
- const valueJ = requireField(path, f, "value", "JsonValue value");
4579
- if (!valueJ.ok) return valueJ;
4580
- const value = decodeJVal(`${path}.value`, valueJ.value);
4750
+ const valueJ = tryField(f, "value");
4751
+ const fromJ = tryField(f, "valueFrom");
4752
+ if (valueJ !== void 0 && fromJ !== void 0) {
4753
+ return makeError(
4754
+ "WRONG_TYPE",
4755
+ `${path}.valueFrom`,
4756
+ "SetState carries both 'value' and 'valueFrom' \u2014 exactly one is allowed: 'value' is a literal JSON value written verbatim; 'valueFrom' derives the written value from a Binding at dispatch time; remove one"
4757
+ );
4758
+ }
4759
+ if (valueJ === void 0 && fromJ === void 0) {
4760
+ return makeError(
4761
+ "MISSING_FIELD",
4762
+ `${path}.value`,
4763
+ "missing required field 'value' \u2014 provide 'value' (a literal JSON value) or 'valueFrom' (a Binding evaluated at dispatch time)"
4764
+ );
4765
+ }
4766
+ if (fromJ !== void 0) {
4767
+ const from = decodeBinding(`${path}.valueFrom`, fromJ, decodeJVal, void 0);
4768
+ if (!from.ok) return from;
4769
+ return ok({
4770
+ kind: "SetState",
4771
+ key: key.value,
4772
+ valueFrom: from.value
4773
+ });
4774
+ }
4775
+ const value = decodeJVal(`${path}.value`, valueJ);
4581
4776
  return value.ok ? ok({ kind: "SetState", key: key.value, value: value.value }) : value;
4582
4777
  }
4583
4778
  case "AiTool": {
@@ -4786,14 +4981,18 @@ var decodeLinkSpec = (path, j) => {
4786
4981
  if (!rel.ok) return rel;
4787
4982
  const target = optField(path, f, "target", requireString);
4788
4983
  if (!target.ok) return target;
4984
+ const protection = optField(path, f, "protection", decodeLinkProtection);
4985
+ if (!protection.ok) return protection;
4789
4986
  return ok({
4790
4987
  href: href.value,
4791
4988
  label: label.value,
4792
4989
  download: download.value,
4793
4990
  ...rel.value !== void 0 ? { rel: rel.value } : {},
4794
- ...target.value !== void 0 ? { target: target.value } : {}
4991
+ ...target.value !== void 0 ? { target: target.value } : {},
4992
+ ...protection.value !== void 0 ? { protection: protection.value } : {}
4795
4993
  });
4796
4994
  };
4995
+ var decodeLinkProtection = (p, j) => bareEnum(p, j, ["email"], "LinkProtection");
4797
4996
  var decodeImageSpec = (path, j) => {
4798
4997
  const fo = requireObject(path, j);
4799
4998
  if (!fo.ok) return fo;
@@ -4900,6 +5099,28 @@ var decodeSkeletonSpec = (path, j) => {
4900
5099
  const rows = reqField(path, fo.value, "rows", "skeleton row count integer", requireInt);
4901
5100
  return rows.ok ? ok({ rows: rows.value }) : rows;
4902
5101
  };
5102
+ var decodeIconSize = (p, j) => bareEnum(p, j, ["Small", "Medium", "Large"], "IconSize");
5103
+ var decodeIconSpec = (path, j) => {
5104
+ const fo = requireObject(path, j);
5105
+ if (!fo.ok) return fo;
5106
+ const f = fo.value;
5107
+ const icon = reqField(path, f, "icon", "icon name string", requireString);
5108
+ if (!icon.ok) return icon;
5109
+ const sizeJ = tryField(f, "size");
5110
+ const size = sizeJ === void 0 ? ok("Medium") : decodeIconSize(`${path}.size`, sizeJ);
5111
+ if (!size.ok) return size;
5112
+ const toneJ = tryField(f, "tone");
5113
+ const tone = toneJ === void 0 ? ok("Default") : decodeTone(`${path}.tone`, toneJ);
5114
+ if (!tone.ok) return tone;
5115
+ const label = optField(path, f, "label", requireString);
5116
+ if (!label.ok) return label;
5117
+ return ok({
5118
+ icon: icon.value,
5119
+ size: size.value,
5120
+ tone: tone.value,
5121
+ ...label.value !== void 0 ? { label: label.value } : {}
5122
+ });
5123
+ };
4903
5124
  var decodeCalloutSpec = (path, j) => {
4904
5125
  const fo = requireObject(path, j);
4905
5126
  if (!fo.ok) return fo;
@@ -4990,6 +5211,10 @@ var decodeDrawStyle = (path, j) => {
4990
5211
  if (!fontFamily.ok) return fontFamily;
4991
5212
  const markId = optField(path, f, "markId", requireString);
4992
5213
  if (!markId.ok) return markId;
5214
+ const rotation = optField(path, f, "rotation", requireFloat);
5215
+ if (!rotation.ok) return rotation;
5216
+ const tip = optField(path, f, "tip", decodeTextSource);
5217
+ if (!tip.ok) return tip;
4993
5218
  return ok({
4994
5219
  ...fill.value !== void 0 ? { fill: fill.value } : {},
4995
5220
  ...stroke.value !== void 0 ? { stroke: stroke.value } : {},
@@ -4999,7 +5224,9 @@ var decodeDrawStyle = (path, j) => {
4999
5224
  ...fontSize.value !== void 0 ? { fontSize: fontSize.value } : {},
5000
5225
  ...emphasis.value !== void 0 ? { emphasis: emphasis.value } : {},
5001
5226
  ...fontFamily.value !== void 0 ? { fontFamily: fontFamily.value } : {},
5002
- ...markId.value !== void 0 ? { markId: markId.value } : {}
5227
+ ...markId.value !== void 0 ? { markId: markId.value } : {},
5228
+ ...rotation.value !== void 0 ? { rotation: rotation.value } : {},
5229
+ ...tip.value !== void 0 ? { tip: tip.value } : {}
5003
5230
  });
5004
5231
  };
5005
5232
  var decodeCurveCommand = (path, j) => {
@@ -5231,6 +5458,10 @@ var decodeDisplayKind = (path, j) => {
5231
5458
  const r = decodeSkeletonSpec(path, j);
5232
5459
  return r.ok ? ok({ kind: "Skeleton", spec: r.value }) : r;
5233
5460
  }
5461
+ case "Icon": {
5462
+ const r = decodeIconSpec(path, j);
5463
+ return r.ok ? ok({ kind: "Icon", spec: r.value }) : r;
5464
+ }
5234
5465
  case "LabelValueRow": {
5235
5466
  const r = decodeLabelValueRowSpec(path, j);
5236
5467
  return r.ok ? ok({ kind: "LabelValueRow", spec: r.value }) : r;
@@ -5309,6 +5540,14 @@ var decodeFormFieldKind = (autoBind, path, j) => {
5309
5540
  ...onToggleField
5310
5541
  }) : v;
5311
5542
  }
5543
+ case "Toggle": {
5544
+ const v = valueOr(decodeBinding, controlValueDefaults.checkbox, "Toggle value binding");
5545
+ return v.ok ? ok({
5546
+ kind: "Toggle",
5547
+ value: v.value,
5548
+ ...onToggleField
5549
+ }) : v;
5550
+ }
5312
5551
  case "Choice": {
5313
5552
  const options = reqField(
5314
5553
  path,
@@ -5706,7 +5945,7 @@ var decodeTonedPill = (path, f) => {
5706
5945
  };
5707
5946
  return ok(k);
5708
5947
  };
5709
- var decodeCellKindErased = (path, j) => {
5948
+ var decodeCellKindErased = (path, j, columnField) => {
5710
5949
  const fo = requireObject(path, j);
5711
5950
  if (!fo.ok) return fo;
5712
5951
  const f = fo.value;
@@ -5770,7 +6009,15 @@ var decodeCellKindErased = (path, j) => {
5770
6009
  case "TonedPill":
5771
6010
  return decodeTonedPill(path, f);
5772
6011
  case "Progress": {
5773
- const k = { kind: "Progress", fraction: () => 0 };
6012
+ const field2 = columnField;
6013
+ const k = {
6014
+ kind: "Progress",
6015
+ fraction: field2 === void 0 ? () => 0 : (row) => {
6016
+ const v = row !== null && typeof row === "object" ? row[field2] : void 0;
6017
+ const n = typeof v === "number" && Number.isFinite(v) ? v : 0;
6018
+ return Math.max(0, Math.min(1, n));
6019
+ }
6020
+ };
5774
6021
  return ok(k);
5775
6022
  }
5776
6023
  case "Custom": {
@@ -5788,13 +6035,78 @@ var decodeCellKindErased = (path, j) => {
5788
6035
  );
5789
6036
  }
5790
6037
  };
6038
+ var nearMiss = (path, found, canonical) => makeError(
6039
+ "WRONG_TYPE",
6040
+ `${path}.${found}`,
6041
+ `'${found}' is not part of the grid vocabulary \u2014 it would be ignored, not honoured`,
6042
+ canonical
6043
+ );
6044
+ var checkNearMisses = (path, f, candidates) => {
6045
+ for (const [name, canonical] of candidates) {
6046
+ if (tryField(f, name) !== void 0) return nearMiss(path, name, canonical);
6047
+ }
6048
+ return ok(void 0);
6049
+ };
6050
+ var COLUMN_NEAR_MISSES = [
6051
+ // Named by the census row itself. Deliberately NOT aliased to
6052
+ // `editable: false`: an inverting alias that guesses wrong makes a read-only
6053
+ // column editable.
6054
+ ["readOnly", "editable: false \u2014 the column flag NARROWS the grid's editable capability"]
6055
+ ];
6056
+ var GRID_NEAR_MISSES = [
6057
+ // The sharpest of them: a LITERAL page number is not expressible at all,
6058
+ // because the position lives in State so a control can move it. Ignoring it
6059
+ // is what produced the ×11 fake-affordance cluster.
6060
+ [
6061
+ "currentPage",
6062
+ 'pageStateKey \u2014 the page POSITION lives in State as {"page": N} so the pager can move it; a literal page number is not expressible'
6063
+ ],
6064
+ [
6065
+ "page",
6066
+ 'pageStateKey \u2014 the page POSITION lives in State as {"page": N} so the pager can move it; a literal page number is not expressible'
6067
+ ],
6068
+ [
6069
+ "pageIndex",
6070
+ 'pageStateKey \u2014 the page POSITION lives in State as {"page": N}, 1-based (not a zero-based index)'
6071
+ ],
6072
+ [
6073
+ "sortable",
6074
+ "sortStateKey on the grid + sortable on each COLUMN \u2014 grid-wide sortable is the staticRows spelling; a data-bound grid narrows per column"
6075
+ ],
6076
+ [
6077
+ "onEdit",
6078
+ "editStateKey \u2014 the edit DESTINATION is a State key on the grid; onEdit is a per-cell host closure and carries no destination across the wire"
6079
+ ],
6080
+ [
6081
+ "behaviour",
6082
+ "sibling fields on the grid (sortStateKey / pageStateKey / pageSize / editStateKey / defaultSort) \u2014 grid behaviour is not a nested record"
6083
+ ],
6084
+ [
6085
+ "behavior",
6086
+ "sibling fields on the grid (sortStateKey / pageStateKey / pageSize / editStateKey / defaultSort) \u2014 grid behaviour is not a nested record"
6087
+ ]
6088
+ ];
5791
6089
  var decodeColumnErased = (path, j) => {
5792
6090
  const fo = requireObject(path, j);
5793
6091
  if (!fo.ok) return fo;
5794
6092
  const f = fo.value;
5795
6093
  const format = optField(path, f, "format", decodeCellFormat);
5796
6094
  if (!format.ok) return format;
5797
- const kind = reqFieldAliased(path, f, "kind", ["type"], "CellKindErased", decodeCellKindErased);
6095
+ const fieldJ = tryField(f, "field");
6096
+ let field2;
6097
+ if (fieldJ !== void 0) {
6098
+ const fr = requireString(`${path}.field`, fieldJ);
6099
+ if (!fr.ok) return fr;
6100
+ field2 = fr.value;
6101
+ }
6102
+ const kind = reqFieldAliased(
6103
+ path,
6104
+ f,
6105
+ "kind",
6106
+ ["type"],
6107
+ "CellKindErased",
6108
+ (p, v) => decodeCellKindErased(p, v, field2)
6109
+ );
5798
6110
  if (!kind.ok) return kind;
5799
6111
  const label = reqFieldAliased(
5800
6112
  path,
@@ -5808,12 +6120,21 @@ var decodeColumnErased = (path, j) => {
5808
6120
  const width = optField(path, f, "width", decodeColumnWidth);
5809
6121
  if (!width.ok) return width;
5810
6122
  const hasValue = tryField(f, "value") !== void 0;
5811
- const fieldJ = tryField(f, "field");
5812
- let field2;
5813
- if (fieldJ !== void 0) {
5814
- const fr = requireString(`${path}.field`, fieldJ);
5815
- if (!fr.ok) return fr;
5816
- field2 = fr.value;
6123
+ const colNearMiss = checkNearMisses(path, f, COLUMN_NEAR_MISSES);
6124
+ if (!colNearMiss.ok) return colNearMiss;
6125
+ const colEditableJ = tryField(f, "editable");
6126
+ let colEditable;
6127
+ if (colEditableJ !== void 0) {
6128
+ const er = requireBool(`${path}.editable`, colEditableJ);
6129
+ if (!er.ok) return er;
6130
+ colEditable = er.value;
6131
+ }
6132
+ const sortableJ = tryField(f, "sortable");
6133
+ let sortable;
6134
+ if (sortableJ !== void 0) {
6135
+ const sr = requireBool(`${path}.sortable`, sortableJ);
6136
+ if (!sr.ok) return sr;
6137
+ sortable = sr.value;
5817
6138
  }
5818
6139
  return ok({
5819
6140
  format: format.value ?? { kind: "None" },
@@ -5821,9 +6142,27 @@ var decodeColumnErased = (path, j) => {
5821
6142
  label: label.value,
5822
6143
  width: width.value ?? { kind: "Auto" },
5823
6144
  ...hasValue ? { value: () => ({ kind: "Empty" }) } : {},
5824
- ...field2 !== void 0 ? { field: field2 } : {}
6145
+ ...field2 !== void 0 ? { field: field2 } : {},
6146
+ ...sortable !== void 0 ? { sortable } : {},
6147
+ ...colEditable !== void 0 ? { editable: colEditable } : {}
5825
6148
  });
5826
6149
  };
6150
+ var decodeSortDirection = (p, j) => bareEnum(p, j, ["asc", "desc"], "SortDirection");
6151
+ var decodeDefaultSort = (path, j) => {
6152
+ const fo = requireObject(path, j);
6153
+ if (!fo.ok) return fo;
6154
+ const f = fo.value;
6155
+ const columnJ = requireField(path, f, "column", "non-negative header index");
6156
+ if (!columnJ.ok) return columnJ;
6157
+ const cv = columnJ.value;
6158
+ if (cv.kind !== "JNumber" || cv.value < 0 || !Number.isInteger(cv.value))
6159
+ return wrongType(`${path}.column`, "JSON number (non-negative integer header index)");
6160
+ const directionJ = requireField(path, f, "direction", "asc | desc");
6161
+ if (!directionJ.ok) return directionJ;
6162
+ const direction = decodeSortDirection(`${path}.direction`, directionJ.value);
6163
+ if (!direction.ok) return direction;
6164
+ return ok({ column: cv.value, direction: direction.value });
6165
+ };
5827
6166
  var decodeStaticRows = (path, j) => {
5828
6167
  const fo = requireObject(path, j);
5829
6168
  if (!fo.ok) return fo;
@@ -5850,7 +6189,16 @@ var decodeStaticRows = (path, j) => {
5850
6189
  );
5851
6190
  });
5852
6191
  if (!rows.ok) return rows;
5853
- return ok({ headers: headers.value, rows: rows.value });
6192
+ const sortable = optField(path, f, "sortable", requireBool);
6193
+ if (!sortable.ok) return sortable;
6194
+ const defaultSort = optField(path, f, "defaultSort", decodeDefaultSort);
6195
+ if (!defaultSort.ok) return defaultSort;
6196
+ return ok({
6197
+ headers: headers.value,
6198
+ rows: rows.value,
6199
+ ...sortable.value !== void 0 ? { sortable: sortable.value } : {},
6200
+ ...defaultSort.value !== void 0 ? { defaultSort: defaultSort.value } : {}
6201
+ });
5854
6202
  };
5855
6203
  var decodeGridSpec = (path, j) => {
5856
6204
  const fo = requireObject(path, j);
@@ -5885,6 +6233,43 @@ var decodeGridSpec = (path, j) => {
5885
6233
  if (!rk.ok) return rk;
5886
6234
  rowKeyField = rk.value;
5887
6235
  }
6236
+ const sortStateKeyJ = tryField(f, "sortStateKey");
6237
+ let sortStateKey;
6238
+ if (sortStateKeyJ !== void 0) {
6239
+ const sk = requireString(`${path}.sortStateKey`, sortStateKeyJ);
6240
+ if (!sk.ok) return sk;
6241
+ sortStateKey = sk.value;
6242
+ }
6243
+ const pageSizeJ = tryField(f, "pageSize");
6244
+ let pageSize;
6245
+ if (pageSizeJ !== void 0) {
6246
+ if (pageSizeJ.kind !== "JNumber" || pageSizeJ.value < 1 || !Number.isInteger(pageSizeJ.value))
6247
+ return wrongType(`${path}.pageSize`, "JSON number (integer page size of 1 or more)");
6248
+ pageSize = pageSizeJ.value;
6249
+ }
6250
+ const defaultSortJ = tryField(f, "defaultSort");
6251
+ let defaultSort;
6252
+ if (defaultSortJ !== void 0) {
6253
+ const ds = decodeDefaultSort(`${path}.defaultSort`, defaultSortJ);
6254
+ if (!ds.ok) return ds;
6255
+ defaultSort = ds.value;
6256
+ }
6257
+ const gridNearMiss = checkNearMisses(path, f, GRID_NEAR_MISSES);
6258
+ if (!gridNearMiss.ok) return gridNearMiss;
6259
+ const editStateKeyJ = tryField(f, "editStateKey");
6260
+ let editStateKey;
6261
+ if (editStateKeyJ !== void 0) {
6262
+ const ek = requireString(`${path}.editStateKey`, editStateKeyJ);
6263
+ if (!ek.ok) return ek;
6264
+ editStateKey = ek.value;
6265
+ }
6266
+ const pageStateKeyJ = tryField(f, "pageStateKey");
6267
+ let pageStateKey;
6268
+ if (pageStateKeyJ !== void 0) {
6269
+ const pk = requireString(`${path}.pageStateKey`, pageStateKeyJ);
6270
+ if (!pk.ok) return pk;
6271
+ pageStateKey = pk.value;
6272
+ }
5888
6273
  const staticRowsJ = tryField(f, "staticRows");
5889
6274
  let staticRows;
5890
6275
  if (staticRowsJ !== void 0) {
@@ -5899,6 +6284,11 @@ var decodeGridSpec = (path, j) => {
5899
6284
  ...hasRowClick ? { onRowClick: () => placeholderAction } : {},
5900
6285
  ...hasRowKey ? { rowKey: () => CLOSURE2 } : {},
5901
6286
  ...rowKeyField !== void 0 ? { rowKeyField } : {},
6287
+ ...sortStateKey !== void 0 ? { sortStateKey } : {},
6288
+ ...pageSize !== void 0 ? { pageSize } : {},
6289
+ ...pageStateKey !== void 0 ? { pageStateKey } : {},
6290
+ ...defaultSort !== void 0 ? { defaultSort } : {},
6291
+ ...editStateKey !== void 0 ? { editStateKey } : {},
5902
6292
  ...staticRows !== void 0 ? { staticRows } : {}
5903
6293
  });
5904
6294
  };
@@ -5930,6 +6320,20 @@ var decodeChartSpec = (path, j) => {
5930
6320
  if (!yFields.ok) return yFields;
5931
6321
  const title = optField(path, f, "title", decodeTextSource);
5932
6322
  if (!title.ok) return title;
6323
+ const valueFormat = optField(path, f, "valueFormat", decodeFormat);
6324
+ if (!valueFormat.ok) return valueFormat;
6325
+ const xTitle = optField(path, f, "xTitle", decodeTextSource);
6326
+ if (!xTitle.ok) return xTitle;
6327
+ const yTitle = optField(path, f, "yTitle", decodeTextSource);
6328
+ if (!yTitle.ok) return yTitle;
6329
+ const subtitle = optField(path, f, "subtitle", decodeTextSource);
6330
+ if (!subtitle.ok) return subtitle;
6331
+ const legendPosition = optField(path, f, "legendPosition", decodeChartLegendPosition);
6332
+ if (!legendPosition.ok) return legendPosition;
6333
+ const dataLabels = optField(path, f, "dataLabels", decodeChartDataLabels);
6334
+ if (!dataLabels.ok) return dataLabels;
6335
+ const xScale = optField(path, f, "xScale", decodeChartXScale);
6336
+ if (!xScale.ok) return xScale;
5933
6337
  const hasPointClick = tryField(f, "onPointClick") !== void 0;
5934
6338
  const stacked = optField(path, f, "stacked", requireBool);
5935
6339
  if (!stacked.ok) return stacked;
@@ -5940,6 +6344,13 @@ var decodeChartSpec = (path, j) => {
5940
6344
  yFields: yFields.value,
5941
6345
  stacked: stacked.value ?? false,
5942
6346
  ...title.value !== void 0 ? { title: title.value } : {},
6347
+ ...valueFormat.value !== void 0 ? { valueFormat: valueFormat.value } : {},
6348
+ ...xTitle.value !== void 0 ? { xTitle: xTitle.value } : {},
6349
+ ...yTitle.value !== void 0 ? { yTitle: yTitle.value } : {},
6350
+ ...subtitle.value !== void 0 ? { subtitle: subtitle.value } : {},
6351
+ ...legendPosition.value !== void 0 ? { legendPosition: legendPosition.value } : {},
6352
+ ...dataLabels.value !== void 0 ? { dataLabels: dataLabels.value } : {},
6353
+ ...xScale.value !== void 0 ? { xScale: xScale.value } : {},
5943
6354
  ...hasPointClick ? { onPointClick: () => placeholderAction } : {}
5944
6355
  });
5945
6356
  };
@@ -6506,6 +6917,7 @@ var decodeNodeKind = (path, j) => {
6506
6917
  case "Callout":
6507
6918
  case "Progress":
6508
6919
  case "Skeleton":
6920
+ case "Icon":
6509
6921
  case "LabelValueRow":
6510
6922
  case "Fact":
6511
6923
  case "Link":
@@ -6578,8 +6990,22 @@ var decodeNodeKind = (path, j) => {
6578
6990
  return ok({ kind: "ErrorBoundary", spec: { child: child.value, fallback: fallback.value } });
6579
6991
  }
6580
6992
  case "Switch": {
6581
- const stateKey = reqField(path, f, "stateKey", "Switch stateKey string", requireString);
6582
- if (!stateKey.ok) return stateKey;
6993
+ const onJ = tryField(f, "on");
6994
+ const on = onJ !== void 0 ? decodeBinding(`${path}.on`, onJ) : (() => {
6995
+ const stateKey = reqField(
6996
+ path,
6997
+ f,
6998
+ "stateKey",
6999
+ "Switch stateKey string",
7000
+ requireString
7001
+ );
7002
+ return stateKey.ok ? ok({
7003
+ kind: "State",
7004
+ key: stateKey.value,
7005
+ defaultValue: void 0
7006
+ }) : stateKey;
7007
+ })();
7008
+ if (!on.ok) return on;
6583
7009
  const casesArr = reqField(path, f, "cases", "Switch cases array", requireArray);
6584
7010
  if (!casesArr.ok) return casesArr;
6585
7011
  const cases = traverseIndexed(casesArr.value, (i, item) => {
@@ -6597,7 +7023,7 @@ var decodeNodeKind = (path, j) => {
6597
7023
  if (!def.ok) return def;
6598
7024
  return ok({
6599
7025
  kind: "Switch",
6600
- spec: { stateKey: stateKey.value, cases: cases.value, default: def.value }
7026
+ spec: { on: on.value, cases: cases.value, default: def.value }
6601
7027
  });
6602
7028
  }
6603
7029
  case "FragmentDecl": {
@@ -7002,7 +7428,11 @@ var coerce = {
7002
7428
  emphasisFlag: (v) => viaAst(v, decodeEmphasisFlag),
7003
7429
  headingVariant: (v) => viaAst(v, decodeHeadingVariant),
7004
7430
  badgeVariant: (v) => viaAst(v, decodeBadgeVariant),
7005
- iconSource: (v) => viaAst(v, decodeIconSource)
7431
+ iconSource: (v) => viaAst(v, decodeIconSource),
7432
+ /** `Icon.Size : IconSize` (Phase 821) — the UpdateProp twin of `decodeIconSize`,
7433
+ * added with the standalone Icon display kind. */
7434
+ iconSize: (v) => viaAst(v, decodeIconSize),
7435
+ stringOption: (v) => viaAst(v, parseStaticStringOpt)
7006
7436
  };
7007
7437
  var invalidJson = (parseMessage) => makeError(
7008
7438
  "INVALID_JSON",
@@ -7240,6 +7670,37 @@ var updateField = (field2, value, kind) => {
7240
7670
  }
7241
7671
  case "Skeleton":
7242
7672
  return field2 === "Rows" ? patch(coerce.int(value), (x) => disp({ kind: "Skeleton", spec: { rows: x } })) : { tag: "unknownField" };
7673
+ case "Icon": {
7674
+ const s = d.spec;
7675
+ switch (field2) {
7676
+ case "Icon":
7677
+ return patch(
7678
+ coerce.string(value),
7679
+ (x) => disp({ kind: "Icon", spec: { ...s, icon: x } })
7680
+ );
7681
+ case "Size":
7682
+ return patch(
7683
+ coerce.iconSize(value),
7684
+ (x) => disp({ kind: "Icon", spec: { ...s, size: x } })
7685
+ );
7686
+ case "Tone":
7687
+ return patch(
7688
+ coerce.tone(value),
7689
+ (x) => disp({ kind: "Icon", spec: { ...s, tone: x } })
7690
+ );
7691
+ case "Label": {
7692
+ return patch(coerce.stringOption(value), (x) => {
7693
+ const { label: _label, ...rest } = s;
7694
+ return disp({
7695
+ kind: "Icon",
7696
+ spec: { ...rest, ...x !== void 0 ? { label: x } : {} }
7697
+ });
7698
+ });
7699
+ }
7700
+ default:
7701
+ return { tag: "unknownField" };
7702
+ }
7703
+ }
7243
7704
  case "Callout": {
7244
7705
  const s = d.spec;
7245
7706
  switch (field2) {
@@ -8047,6 +8508,168 @@ var apply = (tree, op) => {
8047
8508
  return { ok: true, value: { newTree: r.value, emittedTelemetry: telem } };
8048
8509
  };
8049
8510
 
8511
+ // src/placement.ts
8512
+ var derivedFreshIds = (oldId, taken) => {
8513
+ for (let n = 1; ; n += 1) {
8514
+ const candidate = n === 1 ? `${oldId}-copy` : `${oldId}-copy-${n}`;
8515
+ if (!taken(candidate)) return candidate;
8516
+ }
8517
+ };
8518
+ var sequentialFreshIds = (prefix) => {
8519
+ let counter = 0;
8520
+ return (_oldId, taken) => {
8521
+ for (; ; ) {
8522
+ counter += 1;
8523
+ const candidate = `${prefix}-${counter}`;
8524
+ if (!taken(candidate)) return candidate;
8525
+ }
8526
+ };
8527
+ };
8528
+ var ok3 = (value) => ({ ok: true, value });
8529
+ var err = (error) => ({ ok: false, error });
8530
+ var idOf2 = (n) => n.id;
8531
+ var sameOrder = (a, b) => a.length === b.length && a.every((id, i) => id === b[i]);
8532
+ var containerChildren = (root, parentId) => {
8533
+ const parent = findNode(parentId, root);
8534
+ if (parent === void 0) return err({ kind: "ParentNotFound", parentId });
8535
+ const children = layoutChildren(parent);
8536
+ if (children === void 0) return err({ kind: "ChildlessKind", parentId });
8537
+ return ok3(children.map(idOf2));
8538
+ };
8539
+ var reposition = (order, moved, placement) => {
8540
+ const rest = order.filter((id) => id !== moved);
8541
+ const anchored = (anchor, offset) => {
8542
+ const i = rest.findIndex((id) => id === anchor);
8543
+ if (i < 0) return err({ kind: "UnknownAnchor", anchor });
8544
+ const at = i + offset;
8545
+ return ok3([...rest.slice(0, at), moved, ...rest.slice(at)]);
8546
+ };
8547
+ switch (placement.kind) {
8548
+ case "Last":
8549
+ return ok3([...rest, moved]);
8550
+ case "First":
8551
+ return ok3([moved, ...rest]);
8552
+ case "Before":
8553
+ return anchored(placement.anchor, 0);
8554
+ case "After":
8555
+ return anchored(placement.anchor, 1);
8556
+ }
8557
+ };
8558
+ var structurallyPresent = (nodeId, root) => idOf2(root) === nodeId || findLayoutParent(nodeId, root) !== void 0;
8559
+ var firstSharedId = (root, incoming) => {
8560
+ const existing = new Set(allNodeIds(root));
8561
+ return allNodeIds(incoming).find((id) => existing.has(id));
8562
+ };
8563
+ var canPlace = (root, moved, target) => {
8564
+ const r = root;
8565
+ if (!structurallyPresent(moved, r)) return err({ kind: "NodeNotFound", nodeId: moved });
8566
+ if (target.parentId === moved) return err({ kind: "MoveIntoSelf", nodeId: moved });
8567
+ if (isAncestor(moved, target.parentId, r))
8568
+ return err({ kind: "MoveIntoDescendant", nodeId: moved, parentId: target.parentId });
8569
+ const siblings = containerChildren(r, target.parentId);
8570
+ if (!siblings.ok) return siblings;
8571
+ const membership = [...siblings.value.filter((id) => id !== moved), moved];
8572
+ const placed = reposition(membership, moved, target.placement);
8573
+ return placed.ok ? ok3(void 0) : placed;
8574
+ };
8575
+ var placeOp = (root, child, target) => {
8576
+ const r = root;
8577
+ const siblings = containerChildren(r, target.parentId);
8578
+ if (!siblings.ok) return siblings;
8579
+ const dup = firstSharedId(r, child);
8580
+ if (dup !== void 0) return err({ kind: "DuplicateId", nodeId: dup });
8581
+ const childId = idOf2(child);
8582
+ const appended = [...siblings.value, childId];
8583
+ const wanted = reposition(appended, childId, target.placement);
8584
+ if (!wanted.ok) return wanted;
8585
+ const insert = { kind: "InsertChild", parentId: target.parentId, child };
8586
+ return ok3(
8587
+ sameOrder(wanted.value, appended) ? insert : {
8588
+ kind: "Batch",
8589
+ ops: [
8590
+ insert,
8591
+ { kind: "ReorderChildren", parentId: target.parentId, newOrder: wanted.value }
8592
+ ]
8593
+ }
8594
+ );
8595
+ };
8596
+ var moveOp = (root, moved, target) => {
8597
+ const legal = canPlace(root, moved, target);
8598
+ if (!legal.ok) return legal;
8599
+ const siblings = containerChildren(root, target.parentId);
8600
+ if (!siblings.ok) return siblings;
8601
+ const appended = [...siblings.value.filter((id) => id !== moved), moved];
8602
+ const wanted = reposition(appended, moved, target.placement);
8603
+ if (!wanted.ok) return wanted;
8604
+ const move = { kind: "MoveNode", target: moved, newParentId: target.parentId };
8605
+ return ok3(
8606
+ sameOrder(wanted.value, appended) ? move : {
8607
+ kind: "Batch",
8608
+ ops: [
8609
+ move,
8610
+ { kind: "ReorderChildren", parentId: target.parentId, newOrder: wanted.value }
8611
+ ]
8612
+ }
8613
+ );
8614
+ };
8615
+ var nudgeOp = (root, nodeId, delta) => {
8616
+ const r = root;
8617
+ if (idOf2(r) === nodeId) return err({ kind: "CannotNudgeRoot", nodeId });
8618
+ const parent = findLayoutParent(nodeId, r);
8619
+ if (parent === void 0) return err({ kind: "NodeNotFound", nodeId });
8620
+ const ids = (layoutChildren(parent) ?? []).map(idOf2);
8621
+ const index = ids.findIndex((id) => id === nodeId);
8622
+ const swapWith = index + delta;
8623
+ if (swapWith < 0 || swapWith >= ids.length)
8624
+ return err({ kind: "NudgeOutOfRange", nodeId, delta });
8625
+ const reordered = ids.map(
8626
+ (id, i) => i === index ? ids[swapWith] : i === swapWith ? ids[index] : id
8627
+ );
8628
+ return ok3({ kind: "ReorderChildren", parentId: idOf2(parent), newOrder: reordered });
8629
+ };
8630
+ var mapImmediate = (n, f) => {
8631
+ let cur = n;
8632
+ const count = childSlots(n).length;
8633
+ for (let i = 0; i < count; i += 1) {
8634
+ const slot = childSlots(cur)[i];
8635
+ const mapped = f(slot.child);
8636
+ if (mapped !== slot.child) cur = slot.rebuild(mapped);
8637
+ }
8638
+ return cur;
8639
+ };
8640
+ var remapForInsert = (freshIds, targetRoot, incoming) => {
8641
+ const existing = new Set(allNodeIds(targetRoot));
8642
+ const taken = /* @__PURE__ */ new Set([...existing, ...allNodeIds(incoming)]);
8643
+ const rename = /* @__PURE__ */ new Map();
8644
+ for (const oldId of allNodeIds(incoming)) {
8645
+ if (existing.has(oldId)) {
8646
+ const fresh = freshIds(oldId, (candidate) => taken.has(candidate));
8647
+ taken.add(fresh);
8648
+ rename.set(oldId, fresh);
8649
+ }
8650
+ }
8651
+ if (rename.size === 0) return incoming;
8652
+ const rewrite = (node2) => {
8653
+ const withChildren = mapImmediate(node2, rewrite);
8654
+ const fresh = rename.get(withChildren.id);
8655
+ return fresh === void 0 ? withChildren : { ...withChildren, id: fresh };
8656
+ };
8657
+ return rewrite(incoming);
8658
+ };
8659
+ var duplicateOpWith = (freshIds, root, source, target) => {
8660
+ const r = root;
8661
+ const sub = findNode(source, r);
8662
+ if (sub === void 0) return err({ kind: "NodeNotFound", nodeId: source });
8663
+ return placeOp(root, remapForInsert(freshIds, r, sub), target);
8664
+ };
8665
+ var duplicateOp = (root, source, target) => duplicateOpWith(derivedFreshIds, root, source, target);
8666
+ var pasteOpWith = (freshIds, targetRoot, incoming, target) => placeOp(
8667
+ targetRoot,
8668
+ remapForInsert(freshIds, targetRoot, incoming),
8669
+ target
8670
+ );
8671
+ var pasteOp = (targetRoot, incoming, target) => pasteOpWith(derivedFreshIds, targetRoot, incoming, target);
8672
+
8050
8673
  // src/dag.ts
8051
8674
  var str2 = (s) => {
8052
8675
  let out = '"';
@@ -9138,6 +9761,6 @@ var validateAnswerDocument = (json) => {
9138
9761
  return validateAnswerAt("$.answer", contract.value, answer.value);
9139
9762
  };
9140
9763
 
9141
- export { ELICITATION_KEY, ELICITATION_VERSION, PAYLOAD_KEY, PROFILE_KEY, REQUIRED_PROFILE_KEY, apply, cellString, coerce, coreV1, decodeDagRecord, decodeElicitation, decodeElicitationOutcome, decodeEnvelope, decodeEnvelopeAst, decodeNode, decodeNodeTolerant, decodeOp, decodeTolerant, encodeCell, encodeColExpr, encodeDagRecord, encodeDataSource, encodeElicitation, encodeElicitationOutcome, encodeEnvelope2 as encodeEnvelope, encodeNode, encodeOp, encodePipeline, evalErrorString, evalPipeline, evalPipelineInEnv, evalPipelineWith, evalPipelineWithInEnv, evalSource, field as jsonField, merge3Way, negotiate, negotiateEnvelope, noResolve, parse, pipelineParams, reencodeNode, renderAstCanonical, renderProfile, stepParams, tryParseProfile, validateAnswer, validateAnswerAt, validateAnswerDocument };
9764
+ export { ELICITATION_KEY, ELICITATION_VERSION, PAYLOAD_KEY, PROFILE_KEY, REQUIRED_PROFILE_KEY, apply, canPlace, cellString, coerce, coreV1, decodeDagRecord, decodeElicitation, decodeElicitationOutcome, decodeEnvelope, decodeEnvelopeAst, decodeNode, decodeNodeTolerant, decodeOp, decodeTolerant, derivedFreshIds, duplicateOp, duplicateOpWith, encodeCell, encodeColExpr, encodeDagRecord, encodeDataSource, encodeElicitation, encodeElicitationOutcome, encodeEnvelope2 as encodeEnvelope, encodeNode, encodeOp, encodePipeline, evalErrorString, evalPipeline, evalPipelineInEnv, evalPipelineWith, evalPipelineWithInEnv, evalSource, field as jsonField, liveValueToTable, merge3Way, moveOp, negotiate, negotiateEnvelope, noResolve, nudgeOp, parse, pasteOp, pasteOpWith, pipelineParams, placeOp, reencodeNode, renderAstCanonical, renderProfile, sequentialFreshIds, stepParams, tryParseProfile, validateAnswer, validateAnswerAt, validateAnswerDocument };
9142
9765
  //# sourceMappingURL=index.js.map
9143
9766
  //# sourceMappingURL=index.js.map