@fuaran-ui/ops 0.2.0 → 0.4.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
@@ -1,4 +1,4 @@
1
- import { defaults, projectSelectionField, controlValueDefaults } from '@fuaran-ui/schema';
1
+ import { FORM_FIELD_KIND_NAMES, NODE_KIND_GROUPS, defaults, projectSelectionField, controlValueDefaults } from '@fuaran-ui/schema';
2
2
 
3
3
  // src/encode.ts
4
4
  var assertNever = (x) => {
@@ -935,6 +935,25 @@ var formFieldKind = (autoBind, k) => {
935
935
  if (k.constraints.step !== void 0) fields.push(["step", num(k.constraints.step)]);
936
936
  return caseObj("Date", fields);
937
937
  }
938
+ case "DateRange": {
939
+ const staticPair = (p) => jObject([
940
+ ["from", str(p[0])],
941
+ ["to", str(p[1])]
942
+ ]);
943
+ const fields = [
944
+ ...handlerField("onChange", k.onChange),
945
+ ...valueField(
946
+ k.value,
947
+ controlValueDefaults.dateRange,
948
+ (v) => v.kind === "Static" ? staticPair(v.value) : binding(v, staticPair)
949
+ ),
950
+ ["variant", str(k.variant)]
951
+ ];
952
+ if (k.constraints.min !== void 0) fields.push(["min", str(k.constraints.min)]);
953
+ if (k.constraints.max !== void 0) fields.push(["max", str(k.constraints.max)]);
954
+ if (k.constraints.step !== void 0) fields.push(["step", num(k.constraints.step)]);
955
+ return caseObj("DateRange", fields);
956
+ }
938
957
  default:
939
958
  return assertNever(k);
940
959
  }
@@ -1071,6 +1090,16 @@ var cellKindErased = (k) => {
1071
1090
  ["labelFn", CLOSURE],
1072
1091
  ["toneFn", CLOSURE]
1073
1092
  ]);
1093
+ // Phase 750 — the declarative pill. `default` is omitted-when-`Default` (the Phase
1094
+ // 460 discipline); `jObject` Ordinal-sorts, so push order is irrelevant.
1095
+ case "TonedPill": {
1096
+ const fields = [
1097
+ ["field", str(k.field)],
1098
+ ["map", jObject(Object.entries(k.map).map(([v, t]) => [v, str(t)]))]
1099
+ ];
1100
+ if (k.defaultTone !== "Default") fields.push(["default", str(k.defaultTone)]);
1101
+ return caseObj("TonedPill", fields);
1102
+ }
1074
1103
  case "Progress":
1075
1104
  return caseObj("Progress", [
1076
1105
  ["fractionFn", CLOSURE],
@@ -2995,14 +3024,18 @@ var EMPHASIS_ALIASES = {
2995
3024
  Subtle: "Quiet",
2996
3025
  Muted: "Quiet"
2997
3026
  };
3027
+ var TONE_NAMES = [
3028
+ "Default",
3029
+ "Subdued",
3030
+ "Brand",
3031
+ "Success",
3032
+ "Warning",
3033
+ "Critical",
3034
+ "Info"
3035
+ ];
2998
3036
  var decodeTone = (p, j) => {
2999
3037
  if (j.kind === "JString" && j.value in TONE_ALIASES) return ok(TONE_ALIASES[j.value]);
3000
- return bareEnum(
3001
- p,
3002
- j,
3003
- ["Default", "Subdued", "Brand", "Success", "Warning", "Critical", "Info"],
3004
- "ToneVariant"
3005
- );
3038
+ return bareEnum(p, j, TONE_NAMES, "ToneVariant");
3006
3039
  };
3007
3040
  var decodeWeight = (p, j) => (
3008
3041
  // StyleWeight deliberately not aliased — `Bold`/`Heavy` is font-weight intent, but
@@ -4337,6 +4370,41 @@ var decodeBindingFloatPair = (p, j) => {
4337
4370
  }
4338
4371
  return decodeBinding(p, j, parseStaticFloatPair, [0, 0]);
4339
4372
  };
4373
+ var parseStaticStringPair = (p, v) => {
4374
+ const ordered = (a, b) => a > b ? makeError(
4375
+ "WRONG_TYPE",
4376
+ p,
4377
+ `date-range start '${a}' is after end '${b}' \u2014 a DateRange pair is ordered (from <= to); ISO-8601 strings of one variant compare lexicographically, so swap the two values`,
4378
+ 'ordered ISO-8601 pair ({"from": <iso>, "to": <iso>} with from <= to)'
4379
+ ) : ok([a, b]);
4380
+ if (v.kind === "JObject") {
4381
+ const from = v.fields.get("from");
4382
+ const to = v.fields.get("to");
4383
+ if (from !== void 0 && to !== void 0) {
4384
+ const a = requireString(`${p}.from`, from);
4385
+ if (!a.ok) return a;
4386
+ const b = requireString(`${p}.to`, to);
4387
+ if (!b.ok) return b;
4388
+ return ordered(a.value, b.value);
4389
+ }
4390
+ return wrongType(p, "object with from and to ISO-8601 strings");
4391
+ }
4392
+ if (v.kind === "JArray" && v.items.length === 2) {
4393
+ const a = requireString(`${p}[0]`, v.items[0]);
4394
+ if (!a.ok) return a;
4395
+ const b = requireString(`${p}[1]`, v.items[1]);
4396
+ if (!b.ok) return b;
4397
+ return ordered(a.value, b.value);
4398
+ }
4399
+ return wrongType(p, "date-range pair ({from, to} object or [from, to] array)");
4400
+ };
4401
+ var decodeBindingStringPair = (p, j) => {
4402
+ if (j.kind === "JObject" && j.fields.get("$type") === void 0 && j.fields.get("from") !== void 0 && j.fields.get("to") !== void 0) {
4403
+ const parsed = parseStaticStringPair(p, j);
4404
+ return parsed.ok ? ok({ kind: "Static", value: parsed.value }) : parsed;
4405
+ }
4406
+ return decodeBinding(p, j, parseStaticStringPair, ["", ""]);
4407
+ };
4340
4408
  var parseStaticStringList = (p, v) => {
4341
4409
  if (v.kind === "JNull") return ok([]);
4342
4410
  if (v.kind === "JString" && v.value === OPAQUE2) return ok([OPAQUE2]);
@@ -5184,6 +5252,7 @@ var decodeDisplayKind = (path, j) => {
5184
5252
  );
5185
5253
  }
5186
5254
  };
5255
+ var WRONG_FORM_FIELD_KIND_HINT = FORM_FIELD_KIND_NAMES.join(" | ");
5187
5256
  var decodeFormFieldKind = (autoBind, path, j) => {
5188
5257
  const fo = requireObject(path, j);
5189
5258
  if (!fo.ok) return fo;
@@ -5333,12 +5402,35 @@ var decodeFormFieldKind = (autoBind, path, j) => {
5333
5402
  }
5334
5403
  });
5335
5404
  }
5336
- default:
5337
- return unknownDuCase(
5338
- path,
5339
- d.value,
5340
- "Text | Number | Checkbox | Choice | Range | RangedNumber | SegmentedChoice | TextArea | Date"
5405
+ case "DateRange": {
5406
+ const value = valueOr(
5407
+ decodeBindingStringPair,
5408
+ controlValueDefaults.dateRange,
5409
+ "Binding<[from, to]> ISO-8601 pair value"
5341
5410
  );
5411
+ if (!value.ok) return value;
5412
+ const variant = reqField(path, f, "variant", "DateVariant", decodeDateVariant);
5413
+ if (!variant.ok) return variant;
5414
+ const min = optField(path, f, "min", requireString);
5415
+ if (!min.ok) return min;
5416
+ const max = optField(path, f, "max", requireString);
5417
+ if (!max.ok) return max;
5418
+ const step = optField(path, f, "step", requireFloat);
5419
+ if (!step.ok) return step;
5420
+ return ok({
5421
+ kind: "DateRange",
5422
+ value: value.value,
5423
+ ...onChangeField,
5424
+ variant: variant.value,
5425
+ constraints: {
5426
+ ...min.value !== void 0 ? { min: min.value } : {},
5427
+ ...max.value !== void 0 ? { max: max.value } : {},
5428
+ ...step.value !== void 0 ? { step: step.value } : {}
5429
+ }
5430
+ });
5431
+ }
5432
+ default:
5433
+ return unknownDuCase(path, d.value, WRONG_FORM_FIELD_KIND_HINT);
5342
5434
  }
5343
5435
  };
5344
5436
  var decodeFormField = (path, j) => {
@@ -5541,6 +5633,56 @@ var decodeInputKind = (path, j) => {
5541
5633
  return unknownDuCase(path, d.value, "Form | Filters | Button | FileUpload | Select");
5542
5634
  }
5543
5635
  };
5636
+ var decodeToneMap = (path, j) => {
5637
+ const fo = requireObject(path, j);
5638
+ if (!fo.ok) return fo;
5639
+ const out = {};
5640
+ for (const [k, v] of fo.value) {
5641
+ const entryPath = `${path}.${k}`;
5642
+ const t = decodeTone(entryPath, v);
5643
+ if (!t.ok) {
5644
+ if (t.error.code !== "UNKNOWN_DU_CASE") return t;
5645
+ const got = v.kind === "JString" ? v.value : "";
5646
+ return makeError(
5647
+ "UNKNOWN_DU_CASE",
5648
+ entryPath,
5649
+ `tone-map value '${got}' for '${k}' is not a ToneVariant`,
5650
+ TONE_NAMES.join(" | ")
5651
+ );
5652
+ }
5653
+ out[k] = t.value;
5654
+ }
5655
+ return ok(out);
5656
+ };
5657
+ var TONE_MAP_KEYS = ["map", "toneMap", "tones"];
5658
+ var decodeTonedPill = (path, f) => {
5659
+ const field2 = reqField(
5660
+ path,
5661
+ f,
5662
+ "field",
5663
+ "TonedPill row-field name (drives the label and the map key)",
5664
+ requireString
5665
+ );
5666
+ if (!field2.ok) return field2;
5667
+ const map = reqFieldAliased(
5668
+ path,
5669
+ f,
5670
+ "map",
5671
+ ["toneMap", "tones"],
5672
+ "TonedPill value\u2192ToneVariant map",
5673
+ decodeToneMap
5674
+ );
5675
+ if (!map.ok) return map;
5676
+ const defaultTone = optField(path, f, "default", decodeTone);
5677
+ if (!defaultTone.ok) return defaultTone;
5678
+ const k = {
5679
+ kind: "TonedPill",
5680
+ field: field2.value,
5681
+ map: map.value,
5682
+ defaultTone: defaultTone.value ?? "Default"
5683
+ };
5684
+ return ok(k);
5685
+ };
5544
5686
  var decodeCellKindErased = (path, j) => {
5545
5687
  const fo = requireObject(path, j);
5546
5688
  if (!fo.ok) return fo;
@@ -5593,6 +5735,8 @@ var decodeCellKindErased = (path, j) => {
5593
5735
  return ok(k);
5594
5736
  }
5595
5737
  case "Pill": {
5738
+ if (TONE_MAP_KEYS.some((key) => tryField(f, key) !== void 0))
5739
+ return decodeTonedPill(path, f);
5596
5740
  const k = {
5597
5741
  kind: "Pill",
5598
5742
  label: () => ({ kind: "Literal", value: CLOSURE2 }),
@@ -5600,6 +5744,8 @@ var decodeCellKindErased = (path, j) => {
5600
5744
  };
5601
5745
  return ok(k);
5602
5746
  }
5747
+ case "TonedPill":
5748
+ return decodeTonedPill(path, f);
5603
5749
  case "Progress": {
5604
5750
  const k = { kind: "Progress", fraction: () => 0 };
5605
5751
  return ok(k);
@@ -5615,7 +5761,7 @@ var decodeCellKindErased = (path, j) => {
5615
5761
  return unknownDuCase(
5616
5762
  path,
5617
5763
  d.value,
5618
- "Text | Numeric | Date | Editable | Checkbox | Button | ButtonGroup | Link | Pill | Progress | Custom"
5764
+ "Text | Numeric | Date | Editable | Checkbox | Button | ButtonGroup | Link | Pill | TonedPill | Progress | Custom"
5619
5765
  );
5620
5766
  }
5621
5767
  };
@@ -6300,6 +6446,13 @@ var decodeEffectClass = (path, j) => {
6300
6446
  );
6301
6447
  return ok({ hostEffect: host.value, determinism: det.value });
6302
6448
  };
6449
+ var WRONG_NODE_KIND_HINT = (() => {
6450
+ const primitives = NODE_KIND_GROUPS.filter((g) => g.label !== "Structural").map(
6451
+ (g) => `${"AEIOU".includes(g.label[0]) ? "an" : "a"} ${g.label} primitive (${g.kinds.join(" | ")})`
6452
+ ).join(", ");
6453
+ const structural = NODE_KIND_GROUPS.find((g) => g.label === "Structural")?.kinds ?? [];
6454
+ return `${primitives}, or ${structural.join(" | ")}`;
6455
+ })();
6303
6456
  var decodeNodeKind = (path, j) => {
6304
6457
  const fo = requireObject(path, j);
6305
6458
  if (!fo.ok) return fo;
@@ -6554,7 +6707,7 @@ var decodeNodeKind = (path, j) => {
6554
6707
  "WRONG_NODE_KIND",
6555
6708
  `${path}.$type`,
6556
6709
  `unknown NodeKind discriminator '${d.value}'`,
6557
- "a Layout primitive (Box | SplitPanel | Tabs | Stepper | SummaryList | Disclosure | Modal | ScrollArea), a Display primitive (Heading | Markdown | Metric | Badge | Sparkline | Callout | Progress | Skeleton | LabelValueRow | Link | Image | List | Toast), an Input primitive (Form | Filters | Button | FileUpload | Select), a Visualisation primitive (DataGrid | Chart | Map), or Custom | ErrorBoundary | FragmentDecl | FragmentRef | Mount"
6710
+ WRONG_NODE_KIND_HINT
6558
6711
  );
6559
6712
  }
6560
6713
  };