@oods/component-contracts 0.3.1 → 0.3.3

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/README.md CHANGED
@@ -21,7 +21,7 @@ console.log(componentContracts.Button.accessibility);
21
21
 
22
22
  Use the contract when writing a component adapter. The `componentCapabilityBaseline` export and `@oods/component-contracts/registry/capabilities` contain the retained capability ledger. Its evidence is scoped to the recorded component scenarios; a declared obligation is not evidence that an arbitrary implementation meets it.
23
23
 
24
- Forge's mapped-component reports distinguish met, unmet and not-checked obligations. Read their reasons and source identities before using a report as evidence. The package does not certify an application, a third-party library or every possible component state.
24
+ OODS Foundry's mapped-component reports distinguish met, unmet and not-checked obligations. Read their reasons and source identities before using a report as evidence. The package does not certify an application, a third-party library or every possible component state.
25
25
 
26
26
  ## Limits
27
27
 
@@ -29,4 +29,4 @@ Use matching versions of the OODS packages. These packages are separate from the
29
29
 
30
30
  ## License
31
31
 
32
- Apache License 2.0. See [LICENSE](LICENSE) and [NOTICE](NOTICE). Generated output belongs to its user; installed package dependencies retain their own licenses.
32
+ Apache License 2.0. See [LICENSE](https://cdn.jsdelivr.net/npm/@oods/component-contracts@0.3.3/LICENSE) and [NOTICE](https://cdn.jsdelivr.net/npm/@oods/component-contracts@0.3.3/NOTICE). Generated output belongs to its user; installed package dependencies retain their own licenses.
package/dist/index.cjs CHANGED
@@ -15373,7 +15373,7 @@ var authoredContracts = {
15373
15373
  states: ["subtle", "solid"],
15374
15374
  tokenRoles: ["badge.background", "badge.border", "badge.text"],
15375
15375
  accessibility: ["false remains visible", "archive is the badge variant"],
15376
- compatibility: "Mirrors renderArchivePill over renderBadgePrimitive: label/text/status/state/isArchived/value label precedence, status/state/isArchived/value status precedence, Archive fallback and archive variant. Boolean false and true remain literal scalar labels/status metadata; absent flags remain absent and authored labels or children win. field binds isArchived. archivedAtField is consumed unbound because the HTML pill has no date term. Noninteractive; no archive or restore action."
15376
+ compatibility: "Mirrors renderArchivePill over renderBadgePrimitive: label/text/status/state/isArchived/value label precedence, status/state/isArchived/value status precedence, Archive fallback and archive variant. Boolean flags read Not archived / Archived while preserving their recorded status; absent flags remain absent and authored labels or children win. field binds isArchived. archivedAtField is consumed unbound because the HTML pill has no date term. Noninteractive; no archive or restore action."
15377
15377
  },
15378
15378
  ArchiveSummary: {
15379
15379
  id: "ArchiveSummary",
@@ -15412,22 +15412,17 @@ var authoredContracts = {
15412
15412
  AuditTimeline: {
15413
15413
  id: "AuditTimeline",
15414
15414
  version: COMPONENT_CONTRACT_VERSION,
15415
- props: [
15416
- "title",
15417
- "events",
15418
- "history",
15419
- "entries",
15420
- "auditLog",
15415
+ props: ["title", "events", "history", "entries", "auditLog", "maxVisible", "showFromState", "showActorId", "showReason"],
15416
+ directives: [
15417
+ "field",
15418
+ "historyField",
15419
+ "statesParameter",
15421
15420
  "auditLogField",
15422
15421
  "createdField",
15423
15422
  "updatedField",
15424
15423
  "eventField",
15425
15424
  "eventTimestampField",
15426
- "eventOptionsParameter",
15427
- "maxVisible",
15428
- "showFromState",
15429
- "showActorId",
15430
- "showReason"
15425
+ "eventOptionsParameter"
15431
15426
  ],
15432
15427
  slots: ["default"],
15433
15428
  events: [],
@@ -15539,18 +15534,8 @@ var authoredContracts = {
15539
15534
  CancellationSummary: {
15540
15535
  id: "CancellationSummary",
15541
15536
  version: COMPONENT_CONTRACT_VERSION,
15542
- props: [
15543
- "title",
15544
- "label",
15545
- "cancelAtPeriodEnd",
15546
- "requestedAt",
15547
- "reason",
15548
- "code",
15549
- "cancelAtPeriodEndField",
15550
- "requestedAtField",
15551
- "reasonField",
15552
- "codeField"
15553
- ],
15537
+ props: ["title", "label", "cancelAtPeriodEnd", "requestedAt", "reason", "code"],
15538
+ directives: ["field", "cancelAtPeriodEndField", "requestedAtField", "reasonField", "codeField"],
15554
15539
  slots: ["default"],
15555
15540
  events: [],
15556
15541
  states: ["scheduled", "not-scheduled"],
@@ -15841,7 +15826,9 @@ var authoredContracts = {
15841
15826
  "pageSizeOptions",
15842
15827
  "showPageSizeSelector",
15843
15828
  "showGotoPage",
15844
- "showItemRange",
15829
+ "showItemRange"
15830
+ ],
15831
+ directives: [
15845
15832
  "pageField",
15846
15833
  "pageSizeField",
15847
15834
  "totalItemsField",
@@ -15937,12 +15924,9 @@ var authoredContracts = {
15937
15924
  "label",
15938
15925
  "value",
15939
15926
  "emphasis",
15940
- "amountField",
15941
- "currencyField",
15942
- "intervalField",
15943
- "minorUnitsParameter",
15944
15927
  "minorUnits"
15945
15928
  ],
15929
+ directives: ["field", "amountField", "currencyField", "intervalField", "minorUnitsParameter"],
15946
15930
  slots: ["default"],
15947
15931
  events: [],
15948
15932
  states: ["priced", "missing-price"],
@@ -15959,7 +15943,7 @@ var authoredContracts = {
15959
15943
  states: ["populated", "empty"],
15960
15944
  tokenRoles: ["meta.text", "meta.label"],
15961
15945
  accessibility: ["model and interval have literal inline labels", "price metadata is noninteractive"],
15962
- compatibility: "Mirrors renderPriceCardMeta over renderMetaInline: title/label/heading/name (default Price), Model model/pricingModel and Interval interval/billingInterval inline terms. Children replace the entire body including its title. modelField and intervalField lower to their runtime keys. amountField, currencyField and minorUnitsParameter are consumed unbound because this HTML metadata renderer has no amount or currency term. Noninteractive."
15946
+ compatibility: "Mirrors renderPriceCardMeta over renderMetaInline: title/label/heading/name (default Price), Model model/pricingModel and Interval interval/billingInterval inline terms, their codes read as PriceSummary reads them (formatPriceCode: one_time reads One Time). Children replace the entire body including its title. modelField and intervalField lower to their runtime keys. amountField, currencyField and minorUnitsParameter are consumed unbound because this HTML metadata renderer has no amount or currency term. Noninteractive."
15963
15947
  },
15964
15948
  PriceSummary: {
15965
15949
  id: "PriceSummary",
@@ -15986,10 +15970,9 @@ var authoredContracts = {
15986
15970
  "text",
15987
15971
  "timezone",
15988
15972
  "now",
15989
- "fallbackField",
15990
- "timezoneParameter",
15991
15973
  "hideWhenEmpty"
15992
15974
  ],
15975
+ directives: ["field", "fallbackField", "timezoneParameter"],
15993
15976
  slots: ["default"],
15994
15977
  events: [],
15995
15978
  states: ["relative", "absolute", "empty"],
@@ -16032,12 +16015,9 @@ var authoredContracts = {
16032
16015
  "debounceMs",
16033
16016
  "debounce",
16034
16017
  "minQueryLength",
16035
- "disabled",
16036
- "placeholderParameter",
16037
- "debounceParameter",
16038
- "minQueryLengthParameter",
16039
- "clearableParameter"
16018
+ "disabled"
16040
16019
  ],
16020
+ directives: ["field", "placeholderParameter", "debounceParameter", "minQueryLengthParameter", "clearableParameter"],
16041
16021
  slots: [],
16042
16022
  events: ["valueChange", "update", "search", "clear"],
16043
16023
  states: ["empty", "valued", "disabled"],
@@ -16061,7 +16041,8 @@ var authoredContracts = {
16061
16041
  Stack: {
16062
16042
  id: "Stack",
16063
16043
  version: COMPONENT_CONTRACT_VERSION_1_1,
16064
- props: ["direction", "gap", "align", "justify", "wrap", "patternComponent", "fields"],
16044
+ props: ["direction", "gap", "align", "justify", "wrap"],
16045
+ directives: ["patternComponent", "fields"],
16065
16046
  slots: ["default"],
16066
16047
  events: [],
16067
16048
  states: ["row", "column", "wrapped"],
@@ -16083,11 +16064,10 @@ var authoredContracts = {
16083
16064
  "emphasis",
16084
16065
  "showIcon",
16085
16066
  "variant",
16086
- "statusField",
16087
- "domainField",
16088
16067
  "readOnly",
16089
16068
  "compact"
16090
16069
  ],
16070
+ directives: ["field", "statusField", "domainField"],
16091
16071
  slots: ["default"],
16092
16072
  events: [],
16093
16073
  states: ["subtle", "solid"],
@@ -16118,12 +16098,21 @@ var authoredContracts = {
16118
16098
  "stateHistory",
16119
16099
  "status",
16120
16100
  "allowedTransitions",
16121
- "historyField",
16122
- "statesParameter",
16123
16101
  "showActorId",
16124
16102
  "showReason",
16125
16103
  "maxVisible"
16126
16104
  ],
16105
+ directives: [
16106
+ "field",
16107
+ "historyField",
16108
+ "statesParameter",
16109
+ "auditLogField",
16110
+ "createdField",
16111
+ "updatedField",
16112
+ "eventField",
16113
+ "eventTimestampField",
16114
+ "eventOptionsParameter"
16115
+ ],
16127
16116
  slots: ["default"],
16128
16117
  events: [],
16129
16118
  states: ["populated", "empty"],
@@ -16348,7 +16337,7 @@ var viz_preview_samples_v1_default = {
16348
16337
  input: {
16349
16338
  name: "Example connected relationships",
16350
16339
  description: "Synthetic neighborhood edges illustrating relationships that share an endpoint; these are examples, not live graph data."},
16351
- svg: '<svg width="360" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" viewBox="0 0 360 200">\n<rect width="360" height="200" x="0" y="0" fill="#F9FAFC"></rect>\n<path d="M208.4 34Q249.7 88.3 221.2 150.3" fill="none" pointer-events="visible" stroke="rgb(88, 9, 24)" stroke-opacity="0.5" ecmeta_series_index="0" ecmeta_data_index="0" ecmeta_ssr_type="chart" class="oods-zr-0"></path>\n<path d="M221.2 150.3Q155.5 166.3 110.4 115.8" fill="none" pointer-events="visible" stroke="rgb(88, 9, 24)" stroke-opacity="0.5" ecmeta_series_index="0" ecmeta_data_index="1" ecmeta_ssr_type="chart" class="oods-zr-0"></path>\n<path d="M110.4 115.8Q176.1 99.8 221.2 150.3" fill="none" pointer-events="visible" stroke="rgb(88, 9, 24)" stroke-opacity="0.5" ecmeta_series_index="0" ecmeta_data_index="2" ecmeta_ssr_type="chart" class="oods-zr-0"></path>\n<path d="M1 0A1 1 0 1 1 1 -0.1A1 1 0 0 1 1 0" transform="matrix(5,0,0,5,110.3635,115.779)" fill="rgb(88, 9, 24)" ecmeta_series_index="0" ecmeta_data_index="0" ecmeta_ssr_type="chart" class="oods-zr-1"></path>\n<path d="M1 0A1 1 0 1 1 1 -0.1A1 1 0 0 1 1 0" transform="matrix(5,0,0,5,221.2255,150.2583)" fill="rgb(88, 9, 24)" ecmeta_series_index="0" ecmeta_data_index="1" ecmeta_ssr_type="chart" class="oods-zr-1"></path>\n<path d="M1 0A1 1 0 1 1 1 -0.1A1 1 0 0 1 1 0" transform="matrix(5,0,0,5,208.3976,33.9582)" fill="rgb(88, 9, 24)" ecmeta_series_index="0" ecmeta_data_index="2" ecmeta_ssr_type="chart" class="oods-zr-1"></path>\n<text dominant-baseline="central" text-anchor="start" style="font-size:12px;font-family:sans-serif;" transform="translate(120.3635 115.779)" fill="#1A1D23">example-document</text>\n<text dominant-baseline="central" text-anchor="start" style="font-size:12px;font-family:sans-serif;" transform="translate(231.2255 150.2583)" fill="#1A1D23">example-project</text>\n<text dominant-baseline="central" text-anchor="start" style="font-size:12px;font-family:sans-serif;" transform="translate(218.3976 33.9582)" fill="#1A1D23">example-team</text>\n<path d="M-108.1 -5l216.2 0l0 24l-216.2 0Z" transform="translate(180 13)" fill="rgb(0,0,0)" fill-opacity="0" stroke="#3c3c41" stroke-width="0" class="oods-zr-2"></path>\n<text dominant-baseline="central" text-anchor="middle" style="font-size:14px;font-family:sans-serif;font-weight:600;" xml:space="preserve" y="7" transform="translate(180 13)" fill="#1A1D23">Example connected relationships</text>\n<style ><![CDATA[\n.oods-zr-0:hover {\ncursor:pointer;\nstroke-width:4;\n}\n.oods-zr-1:hover {\ncursor:pointer;\nfill:rgba(96,9,26,1);\n}\n.oods-zr-2:hover {\npointer-events:none;\n}\n\n]]>\n\n</style>\n</svg>'}
16340
+ svg: '<svg width="360" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" viewBox="0 0 360 200" role="img" aria-label="Example connected relationships" aria-description="Synthetic neighborhood edges illustrating relationships that share an endpoint; these are examples, not live graph data."><title>Example connected relationships</title><desc>Synthetic neighborhood edges illustrating relationships that share an endpoint; these are examples, not live graph data.</desc>\n<rect width="360" height="200" x="0" y="0" fill="#F9FAFC"></rect>\n<path d="M208.4 34Q249.7 88.3 221.2 150.3" fill="none" pointer-events="visible" stroke="rgb(88, 9, 24)" stroke-opacity="0.5" ecmeta_series_index="0" ecmeta_data_index="0" ecmeta_ssr_type="chart" class="oods-zr-0"></path>\n<path d="M221.2 150.3Q155.5 166.3 110.4 115.8" fill="none" pointer-events="visible" stroke="rgb(88, 9, 24)" stroke-opacity="0.5" ecmeta_series_index="0" ecmeta_data_index="1" ecmeta_ssr_type="chart" class="oods-zr-0"></path>\n<path d="M110.4 115.8Q176.1 99.8 221.2 150.3" fill="none" pointer-events="visible" stroke="rgb(88, 9, 24)" stroke-opacity="0.5" ecmeta_series_index="0" ecmeta_data_index="2" ecmeta_ssr_type="chart" class="oods-zr-0"></path>\n<path d="M1 0A1 1 0 1 1 1 -0.1A1 1 0 0 1 1 0" transform="matrix(5,0,0,5,110.3635,115.779)" fill="rgb(88, 9, 24)" ecmeta_series_index="0" ecmeta_data_index="0" ecmeta_ssr_type="chart" class="oods-zr-1"></path>\n<path d="M1 0A1 1 0 1 1 1 -0.1A1 1 0 0 1 1 0" transform="matrix(5,0,0,5,221.2255,150.2583)" fill="rgb(88, 9, 24)" ecmeta_series_index="0" ecmeta_data_index="1" ecmeta_ssr_type="chart" class="oods-zr-1"></path>\n<path d="M1 0A1 1 0 1 1 1 -0.1A1 1 0 0 1 1 0" transform="matrix(5,0,0,5,208.3976,33.9582)" fill="rgb(88, 9, 24)" ecmeta_series_index="0" ecmeta_data_index="2" ecmeta_ssr_type="chart" class="oods-zr-1"></path>\n<text dominant-baseline="central" text-anchor="start" style="font-size:12px;font-family:sans-serif;" transform="translate(120.3635 115.779)" fill="#1A1D23">example-document</text>\n<text dominant-baseline="central" text-anchor="start" style="font-size:12px;font-family:sans-serif;" transform="translate(231.2255 150.2583)" fill="#1A1D23">example-project</text>\n<text dominant-baseline="central" text-anchor="start" style="font-size:12px;font-family:sans-serif;" transform="translate(218.3976 33.9582)" fill="#1A1D23">example-team</text>\n<path d="M-108.1 -5l216.2 0l0 24l-216.2 0Z" transform="translate(180 13)" fill="rgb(0,0,0)" fill-opacity="0" stroke="#3c3c41" stroke-width="0" class="oods-zr-2"></path>\n<text dominant-baseline="central" text-anchor="middle" style="font-size:14px;font-family:sans-serif;font-weight:600;" xml:space="preserve" y="7" transform="translate(180 13)" fill="#1A1D23">Example connected relationships</text>\n<style ><![CDATA[\n.oods-zr-0:hover {\ncursor:pointer;\nstroke-width:4;\n}\n.oods-zr-1:hover {\ncursor:pointer;\nfill:rgba(96,9,26,1);\n}\n.oods-zr-2:hover {\npointer-events:none;\n}\n\n]]>\n\n</style>\n</svg>'}
16352
16341
  }
16353
16342
  };
16354
16343
 
@@ -16396,7 +16385,7 @@ var authoredScenarios = [
16396
16385
  { id: "address-editor-fields-and-change", oodsComponentId: "AddressEditor", props: { title: "Shipping address", street: "1 Main St", city: "Springfield", region: "IL", postalCode: "62701" }, slots: {}, initialState: { street: "1 Main St" }, renderExpectation: { name: "change", trigger: "type into the City input", expected: "change emitted with the current street/city/region/postalCode record" }, assertions: ["title is a real h2 heading", "four labelled inputs are prefilled", "change carries the whole address record", "submitting is a no-op"] },
16397
16386
  { id: "address-summary-badge-role", oodsComponentId: "AddressSummaryBadge", props: { label: "Billing address", role: "billing" }, slots: {}, initialState: { status: "billing" }, renderExpectation: { name: "render", trigger: "mount", expected: "visible Billing address label with data-badge-status billing and the address variant" }, assertions: ["label is visible text", "data-badge-status is billing", "data-badge-variant is address", "badge is noninteractive"] },
16398
16387
  { id: "address-validation-timeline-events", oodsComponentId: "AddressValidationTimeline", props: { title: "Address checks", validations: [{ label: "Postal code verified", timestamp: "2026-09-05T12:00:00Z", detail: "Matched carrier database" }, "Geocoded"] }, slots: {}, initialState: { events: 2 }, renderExpectation: { name: "render", trigger: "mount", expected: "a log region titled Address checks with two ordered events, the first timestamped and detailed" }, assertions: ["region has role log and an h2 title", "events are ordered list items", "the timestamp is a time element", "scalar entries render as text"] },
16399
- { id: "archive-pill-false", oodsComponentId: "ArchivePill", props: { "isArchived": false }, slots: {}, initialState: { content: "populated" }, renderExpectation: { name: "render", trigger: "mount", expected: "false remains visible; archive is the badge variant" }, assertions: ["false remains visible", "archive is the badge variant"] },
16388
+ { id: "archive-pill-false", oodsComponentId: "ArchivePill", props: { "isArchived": false }, slots: {}, initialState: { content: "populated" }, renderExpectation: { name: "render", trigger: "mount", expected: "Not archived remains visible; machine status remains false; archive is the badge variant" }, assertions: ["Not archived remains visible; machine status remains false", "archive is the badge variant"] },
16400
16389
  { id: "archive-summary-false-and-reason", oodsComponentId: "ArchiveSummary", props: { "isArchived": false, "archivedAt": "2026-09-05T12:00:00Z", "reason": "Retention policy" }, slots: {}, initialState: { content: "populated" }, renderExpectation: { name: "render", trigger: "mount", expected: "No remains visible in its named term; archive date and reason remain associated terms" }, assertions: ["No remains visible in its named term", "archive date and reason remain associated terms"] },
16401
16390
  { id: "archived-row-presentation", oodsComponentId: "ArchivedRowOverlay", props: { "isArchived": true, "showBadge": true, "separateTab": true, "tabLabel": "Archived", "label": "Team subscription" }, slots: {}, initialState: {}, renderExpectation: { name: "render", trigger: "mount", expected: "Archived row stays accessible and its badge and tab label agree" }, assertions: ["Archived row stays accessible and its badge and tab label agree"] },
16402
16391
  { id: "audit-event-type-and-timestamp", oodsComponentId: "AuditEvent", props: { event: "user.updated", timestamp: "2026-09-05T12:00:00Z", detail: "Display name changed" }, slots: {}, initialState: { timestamped: true }, renderExpectation: { name: "render", trigger: "mount", expected: "one audit article with a machine-readable time, the event label and the detail" }, assertions: ["article carries data-event-type audit", "time element has a datetime", "label and detail are visible text"] },
@@ -16608,6 +16597,28 @@ function billingCycle(values) {
16608
16597
  const announcement = `${percent === void 0 ? "Progress unavailable" : `${percent}% complete`} \xB7 ${remainingDays === void 0 ? "Remaining days unavailable" : `${remainingDays} ${remainingDays === 1 ? "day" : "days"} remaining`}`;
16609
16598
  return { percent, remainingDays, announcement, ended };
16610
16599
  }
16600
+ var PERIOD_MONTHS = { monthly: 1, quarterly: 3, yearly: 12, annual: 12 };
16601
+ function billingPeriodEnd(start, interval) {
16602
+ const date = new Date(start);
16603
+ if (!Number.isFinite(date.getTime())) return void 0;
16604
+ if (interval === "weekly") return new Date(date.getTime() + 7 * 864e5).toISOString();
16605
+ const months = interval ? PERIOD_MONTHS[interval] : void 0;
16606
+ if (!months) return void 0;
16607
+ const end = new Date(date);
16608
+ end.setUTCDate(1);
16609
+ end.setUTCMonth(end.getUTCMonth() + months);
16610
+ end.setUTCDate(Math.min(date.getUTCDate(), new Date(Date.UTC(end.getUTCFullYear(), end.getUTCMonth() + 1, 0)).getUTCDate()));
16611
+ return end.toISOString();
16612
+ }
16613
+ function restartedBillingPeriod(at, interval) {
16614
+ return {
16615
+ current_period_start: at,
16616
+ current_period_end: billingPeriodEnd(at, interval),
16617
+ current_period_progress: void 0,
16618
+ next_payment_due_at: at,
16619
+ payment_status: "pending"
16620
+ };
16621
+ }
16611
16622
  var NO_NEXT_PAYMENT = "No payment scheduled";
16612
16623
  var NO_LAST_PAYMENT = "No previous payment";
16613
16624
  function billingDate(value) {
@@ -16667,9 +16678,13 @@ function recordCollectionEvents(record2, options = {}) {
16667
16678
  if (typeof at !== "string" || typeof state !== "string") return [];
16668
16679
  return [{ id: "state-" + index, title: String(entry.title ?? state.split(/[_-]/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ")), at, description: String(entry.reason ?? ""), kind: "state" }];
16669
16680
  }) : [];
16681
+ const recorded = Array.isArray(record2.payment_history) ? record2.payment_history : [];
16670
16682
  for (const source2 of options.payments ?? []) {
16671
16683
  const at = record2[source2.field];
16672
- if (typeof at === "string") events.push({ id: "payment-" + source2.field, title: source2.title, at, description: billingSummary(Number(record2.amount), String(record2.currency), options.minorUnits ?? 100, String(record2.billing_interval)), kind: "payment" });
16684
+ if (typeof at !== "string") continue;
16685
+ const paid = recorded.find((row) => row && typeof row === "object" && Date.parse(row.at) === Date.parse(at) && typeof row.amount === "number");
16686
+ const description = paid ? formatBillingAmount(paid.amount, String(paid.currency ?? record2.currency), options.minorUnits ?? 100) : billingSummary(Number(record2.amount), String(record2.currency), options.minorUnits ?? 100, String(record2.billing_interval));
16687
+ events.push({ id: "payment-" + source2.field, title: source2.title, at, description, kind: "payment" });
16673
16688
  }
16674
16689
  for (const source2 of [{ field: "created_at", title: "Created" }, { field: "last_event_at", title: String(record2.last_event ?? "Updated").replaceAll("_", " ") }, { field: "issued_at", title: "Issued" }, { field: "period_start", title: "Period started" }, { field: "ownership_transferred_at", title: "Ownership transferred" }]) {
16675
16690
  const at = record2[source2.field];
@@ -17031,6 +17046,7 @@ exports.billingDate = billingDate;
17031
17046
  exports.billingIntervalMessage = billingIntervalMessage;
17032
17047
  exports.billingPaymentRows = billingPaymentRows;
17033
17048
  exports.billingPaymentSummary = billingPaymentSummary;
17049
+ exports.billingPeriodEnd = billingPeriodEnd;
17034
17050
  exports.billingSummary = billingSummary;
17035
17051
  exports.chronologicalEvents = chronologicalEvents;
17036
17052
  exports.componentBehaviors = componentBehaviors;
@@ -17063,6 +17079,7 @@ exports.portedComponentContracts = portedComponentContracts;
17063
17079
  exports.portedScenarios = portedScenarios;
17064
17080
  exports.recipeItemLabels = recipeItemLabels;
17065
17081
  exports.recordCollectionEvents = recordCollectionEvents;
17082
+ exports.restartedBillingPeriod = restartedBillingPeriod;
17066
17083
  exports.sharedScenarios = sharedScenarios;
17067
17084
  exports.substitutionContractReport = substitutionContractReport;
17068
17085
  exports.summarizeSubstitutionReport = summarizeSubstitutionReport;
package/dist/index.d.cts CHANGED
@@ -20,6 +20,12 @@ type ComponentContract = {
20
20
  id: GovernedComponentId;
21
21
  version: '1.0.0' | '1.1.0';
22
22
  props: readonly string[];
23
+ /**
24
+ * s221-m02 (#2482 ruling 5): saved-schema composition directives the React and Vue components accept, which code
25
+ * generation consumes (a field binding, a pattern's parts) and the component reads no value from; listed apart from
26
+ * the props a consumer passes.
27
+ */
28
+ directives?: readonly string[];
23
29
  /** Public props needed to name or identify a field; substitution must preserve them. */
24
30
  requiredProps?: readonly string[];
25
31
  slots: readonly string[];
@@ -177,6 +183,25 @@ declare function billingCycle(values: BillingCycleValues): {
177
183
  announcement: string;
178
184
  ended: boolean;
179
185
  };
186
+ /**
187
+ * The end of a billing period that starts at `start` and lasts one `interval` (UTC). A month keeps the start's day, or
188
+ * the month's last day when it is shorter. An interval with no fixed length has no computable end: undefined.
189
+ */
190
+ declare function billingPeriodEnd(start: string, interval: string | undefined): string | undefined;
191
+ /**
192
+ * s220-m01 (#2461): Billable's billing-anchor reset (traits/financial/Billable.trait.yaml). When the terms an active
193
+ * record is billed at change (price, currency or interval), a new billing period starts at the change. Billable charges
194
+ * at a period's start (prepaid), so the new period's payment is due at once, and nothing has collected it: pending.
195
+ * Progress is left to the clock the period is measured by. Recorded payments are history and keep their own amounts.
196
+ * Before it, an edit to "€19.99 · yearly" kept the monthly period (77% complete, 7 days remaining, next payment in a month).
197
+ */
198
+ declare function restartedBillingPeriod(at: string, interval: string | undefined): {
199
+ current_period_start: string;
200
+ current_period_end: string | undefined;
201
+ current_period_progress: undefined;
202
+ next_payment_due_at: string;
203
+ payment_status: "pending";
204
+ };
180
205
  interface BillingPaymentValues {
181
206
  lastPayment?: string;
182
207
  nextPayment?: string;
@@ -3021,4 +3046,4 @@ declare function getBaselineCapability(componentId: string): {
3021
3046
  };
3022
3047
  } | undefined;
3023
3048
 
3024
- export { type AuditSummaryValues, BILLING_AMOUNT_ERROR, BILLING_INTERVALS, BILLING_INTERVAL_ERROR, BILLING_MINOR_UNITS, type BillingAmountResult, type BillingCycleValues, type BillingPaymentValues, COMPONENT_CLASSIFICATIONS, COMPONENT_CONTRACT_VERSION, COMPONENT_CONTRACT_VERSION_1_1, type CollectionEvent, type ComponentBehavior, type ComponentClassification, type ComponentContract, DEFAULT_COLOR_STATES, EMISSION_ELIGIBILITY_EVIDENCE_CLASSES, type EmissionEligibilityEvidence, type EmissionEligibilityEvidenceClass, type EvidenceResult, type EvidenceStatus, FOUNDATION_V1_EVIDENCE_CLASSES, type FoundationV1Evidence, type FoundationV1EvidenceClass, GOVERNED_DEFINITION, GOVERNED_SURFACES, type GeoFieldMappingValue, type GovernedComponentId, type GovernedLedgerRow, NO_LAST_PAYMENT, NO_NEXT_PAYMENT, NUCLEUS_COMPONENT_IDS, type NucleusComponentId, type ObligationStatus, PORTED_COMPONENT_IDS, type PortedComponentId, RESULT_STATES, RESULT_STATE_TONE, type ResultState, SEVERITY_TONES, type ScenarioTrigger, type SharedScenario, type SortIndicatorValues, type SortState, type SubstitutionContractReport, type SubstitutionObligation, type TraitEventKind, type TraitEventValues, UI_WORKFLOW_STATES, type UiWorkflowState, VIZ_CONTROL_IDS, VIZ_CONTROL_TITLES, VIZ_PREVIEW_TYPES, VIZ_SUMMARY_IDS, type VizChannel, type VizChartType, type VizColorBinding, type VizControlField, type VizControlId, type VizFieldBinding, type VizIntentFragment, type VizScale, type VizSummaryId, ariaSort, assertStaticSvg, auditSummary, billingAmountMessage, billingAmountText, billingCycle, billingDate, billingIntervalMessage, billingPaymentRows, billingPaymentSummary, billingSummary, chronologicalEvents, componentBehaviors, componentCapabilityBaseline, componentContracts, componentIntake, componentReconciliationProposal, currencyMinorUnits, dateTimeInputValue, defaultVizIntent, deriveStartingComponentCount, editVizIntent, evaluateEmissionEligibility, evaluateFoundationV1, formatBillingAmount, formatDateTime, formatPriceAmount, formatPriceCode, formatReadOnlyValue, formatRecordLabel, formatReferenceLabel, geoFieldMapping, getBaselineCapability, initialSort, isGovernedComponent, isVizIntentFragment, nextSort, parseBillingAmount, portedComponentContracts, portedScenarios, recipeItemLabels, recordCollectionEvents, sharedScenarios, substitutionContractReport, summarizeSubstitutionReport, summaryValue, svgCarriesTitle, traitEventRows, validMinorUnits, validateComponentIntakeDocument, vizControlFields, vizFieldValue, vizSummaryRows };
3049
+ export { type AuditSummaryValues, BILLING_AMOUNT_ERROR, BILLING_INTERVALS, BILLING_INTERVAL_ERROR, BILLING_MINOR_UNITS, type BillingAmountResult, type BillingCycleValues, type BillingPaymentValues, COMPONENT_CLASSIFICATIONS, COMPONENT_CONTRACT_VERSION, COMPONENT_CONTRACT_VERSION_1_1, type CollectionEvent, type ComponentBehavior, type ComponentClassification, type ComponentContract, DEFAULT_COLOR_STATES, EMISSION_ELIGIBILITY_EVIDENCE_CLASSES, type EmissionEligibilityEvidence, type EmissionEligibilityEvidenceClass, type EvidenceResult, type EvidenceStatus, FOUNDATION_V1_EVIDENCE_CLASSES, type FoundationV1Evidence, type FoundationV1EvidenceClass, GOVERNED_DEFINITION, GOVERNED_SURFACES, type GeoFieldMappingValue, type GovernedComponentId, type GovernedLedgerRow, NO_LAST_PAYMENT, NO_NEXT_PAYMENT, NUCLEUS_COMPONENT_IDS, type NucleusComponentId, type ObligationStatus, PORTED_COMPONENT_IDS, type PortedComponentId, RESULT_STATES, RESULT_STATE_TONE, type ResultState, SEVERITY_TONES, type ScenarioTrigger, type SharedScenario, type SortIndicatorValues, type SortState, type SubstitutionContractReport, type SubstitutionObligation, type TraitEventKind, type TraitEventValues, UI_WORKFLOW_STATES, type UiWorkflowState, VIZ_CONTROL_IDS, VIZ_CONTROL_TITLES, VIZ_PREVIEW_TYPES, VIZ_SUMMARY_IDS, type VizChannel, type VizChartType, type VizColorBinding, type VizControlField, type VizControlId, type VizFieldBinding, type VizIntentFragment, type VizScale, type VizSummaryId, ariaSort, assertStaticSvg, auditSummary, billingAmountMessage, billingAmountText, billingCycle, billingDate, billingIntervalMessage, billingPaymentRows, billingPaymentSummary, billingPeriodEnd, billingSummary, chronologicalEvents, componentBehaviors, componentCapabilityBaseline, componentContracts, componentIntake, componentReconciliationProposal, currencyMinorUnits, dateTimeInputValue, defaultVizIntent, deriveStartingComponentCount, editVizIntent, evaluateEmissionEligibility, evaluateFoundationV1, formatBillingAmount, formatDateTime, formatPriceAmount, formatPriceCode, formatReadOnlyValue, formatRecordLabel, formatReferenceLabel, geoFieldMapping, getBaselineCapability, initialSort, isGovernedComponent, isVizIntentFragment, nextSort, parseBillingAmount, portedComponentContracts, portedScenarios, recipeItemLabels, recordCollectionEvents, restartedBillingPeriod, sharedScenarios, substitutionContractReport, summarizeSubstitutionReport, summaryValue, svgCarriesTitle, traitEventRows, validMinorUnits, validateComponentIntakeDocument, vizControlFields, vizFieldValue, vizSummaryRows };
package/dist/index.d.ts CHANGED
@@ -20,6 +20,12 @@ type ComponentContract = {
20
20
  id: GovernedComponentId;
21
21
  version: '1.0.0' | '1.1.0';
22
22
  props: readonly string[];
23
+ /**
24
+ * s221-m02 (#2482 ruling 5): saved-schema composition directives the React and Vue components accept, which code
25
+ * generation consumes (a field binding, a pattern's parts) and the component reads no value from; listed apart from
26
+ * the props a consumer passes.
27
+ */
28
+ directives?: readonly string[];
23
29
  /** Public props needed to name or identify a field; substitution must preserve them. */
24
30
  requiredProps?: readonly string[];
25
31
  slots: readonly string[];
@@ -177,6 +183,25 @@ declare function billingCycle(values: BillingCycleValues): {
177
183
  announcement: string;
178
184
  ended: boolean;
179
185
  };
186
+ /**
187
+ * The end of a billing period that starts at `start` and lasts one `interval` (UTC). A month keeps the start's day, or
188
+ * the month's last day when it is shorter. An interval with no fixed length has no computable end: undefined.
189
+ */
190
+ declare function billingPeriodEnd(start: string, interval: string | undefined): string | undefined;
191
+ /**
192
+ * s220-m01 (#2461): Billable's billing-anchor reset (traits/financial/Billable.trait.yaml). When the terms an active
193
+ * record is billed at change (price, currency or interval), a new billing period starts at the change. Billable charges
194
+ * at a period's start (prepaid), so the new period's payment is due at once, and nothing has collected it: pending.
195
+ * Progress is left to the clock the period is measured by. Recorded payments are history and keep their own amounts.
196
+ * Before it, an edit to "€19.99 · yearly" kept the monthly period (77% complete, 7 days remaining, next payment in a month).
197
+ */
198
+ declare function restartedBillingPeriod(at: string, interval: string | undefined): {
199
+ current_period_start: string;
200
+ current_period_end: string | undefined;
201
+ current_period_progress: undefined;
202
+ next_payment_due_at: string;
203
+ payment_status: "pending";
204
+ };
180
205
  interface BillingPaymentValues {
181
206
  lastPayment?: string;
182
207
  nextPayment?: string;
@@ -3021,4 +3046,4 @@ declare function getBaselineCapability(componentId: string): {
3021
3046
  };
3022
3047
  } | undefined;
3023
3048
 
3024
- export { type AuditSummaryValues, BILLING_AMOUNT_ERROR, BILLING_INTERVALS, BILLING_INTERVAL_ERROR, BILLING_MINOR_UNITS, type BillingAmountResult, type BillingCycleValues, type BillingPaymentValues, COMPONENT_CLASSIFICATIONS, COMPONENT_CONTRACT_VERSION, COMPONENT_CONTRACT_VERSION_1_1, type CollectionEvent, type ComponentBehavior, type ComponentClassification, type ComponentContract, DEFAULT_COLOR_STATES, EMISSION_ELIGIBILITY_EVIDENCE_CLASSES, type EmissionEligibilityEvidence, type EmissionEligibilityEvidenceClass, type EvidenceResult, type EvidenceStatus, FOUNDATION_V1_EVIDENCE_CLASSES, type FoundationV1Evidence, type FoundationV1EvidenceClass, GOVERNED_DEFINITION, GOVERNED_SURFACES, type GeoFieldMappingValue, type GovernedComponentId, type GovernedLedgerRow, NO_LAST_PAYMENT, NO_NEXT_PAYMENT, NUCLEUS_COMPONENT_IDS, type NucleusComponentId, type ObligationStatus, PORTED_COMPONENT_IDS, type PortedComponentId, RESULT_STATES, RESULT_STATE_TONE, type ResultState, SEVERITY_TONES, type ScenarioTrigger, type SharedScenario, type SortIndicatorValues, type SortState, type SubstitutionContractReport, type SubstitutionObligation, type TraitEventKind, type TraitEventValues, UI_WORKFLOW_STATES, type UiWorkflowState, VIZ_CONTROL_IDS, VIZ_CONTROL_TITLES, VIZ_PREVIEW_TYPES, VIZ_SUMMARY_IDS, type VizChannel, type VizChartType, type VizColorBinding, type VizControlField, type VizControlId, type VizFieldBinding, type VizIntentFragment, type VizScale, type VizSummaryId, ariaSort, assertStaticSvg, auditSummary, billingAmountMessage, billingAmountText, billingCycle, billingDate, billingIntervalMessage, billingPaymentRows, billingPaymentSummary, billingSummary, chronologicalEvents, componentBehaviors, componentCapabilityBaseline, componentContracts, componentIntake, componentReconciliationProposal, currencyMinorUnits, dateTimeInputValue, defaultVizIntent, deriveStartingComponentCount, editVizIntent, evaluateEmissionEligibility, evaluateFoundationV1, formatBillingAmount, formatDateTime, formatPriceAmount, formatPriceCode, formatReadOnlyValue, formatRecordLabel, formatReferenceLabel, geoFieldMapping, getBaselineCapability, initialSort, isGovernedComponent, isVizIntentFragment, nextSort, parseBillingAmount, portedComponentContracts, portedScenarios, recipeItemLabels, recordCollectionEvents, sharedScenarios, substitutionContractReport, summarizeSubstitutionReport, summaryValue, svgCarriesTitle, traitEventRows, validMinorUnits, validateComponentIntakeDocument, vizControlFields, vizFieldValue, vizSummaryRows };
3049
+ export { type AuditSummaryValues, BILLING_AMOUNT_ERROR, BILLING_INTERVALS, BILLING_INTERVAL_ERROR, BILLING_MINOR_UNITS, type BillingAmountResult, type BillingCycleValues, type BillingPaymentValues, COMPONENT_CLASSIFICATIONS, COMPONENT_CONTRACT_VERSION, COMPONENT_CONTRACT_VERSION_1_1, type CollectionEvent, type ComponentBehavior, type ComponentClassification, type ComponentContract, DEFAULT_COLOR_STATES, EMISSION_ELIGIBILITY_EVIDENCE_CLASSES, type EmissionEligibilityEvidence, type EmissionEligibilityEvidenceClass, type EvidenceResult, type EvidenceStatus, FOUNDATION_V1_EVIDENCE_CLASSES, type FoundationV1Evidence, type FoundationV1EvidenceClass, GOVERNED_DEFINITION, GOVERNED_SURFACES, type GeoFieldMappingValue, type GovernedComponentId, type GovernedLedgerRow, NO_LAST_PAYMENT, NO_NEXT_PAYMENT, NUCLEUS_COMPONENT_IDS, type NucleusComponentId, type ObligationStatus, PORTED_COMPONENT_IDS, type PortedComponentId, RESULT_STATES, RESULT_STATE_TONE, type ResultState, SEVERITY_TONES, type ScenarioTrigger, type SharedScenario, type SortIndicatorValues, type SortState, type SubstitutionContractReport, type SubstitutionObligation, type TraitEventKind, type TraitEventValues, UI_WORKFLOW_STATES, type UiWorkflowState, VIZ_CONTROL_IDS, VIZ_CONTROL_TITLES, VIZ_PREVIEW_TYPES, VIZ_SUMMARY_IDS, type VizChannel, type VizChartType, type VizColorBinding, type VizControlField, type VizControlId, type VizFieldBinding, type VizIntentFragment, type VizScale, type VizSummaryId, ariaSort, assertStaticSvg, auditSummary, billingAmountMessage, billingAmountText, billingCycle, billingDate, billingIntervalMessage, billingPaymentRows, billingPaymentSummary, billingPeriodEnd, billingSummary, chronologicalEvents, componentBehaviors, componentCapabilityBaseline, componentContracts, componentIntake, componentReconciliationProposal, currencyMinorUnits, dateTimeInputValue, defaultVizIntent, deriveStartingComponentCount, editVizIntent, evaluateEmissionEligibility, evaluateFoundationV1, formatBillingAmount, formatDateTime, formatPriceAmount, formatPriceCode, formatReadOnlyValue, formatRecordLabel, formatReferenceLabel, geoFieldMapping, getBaselineCapability, initialSort, isGovernedComponent, isVizIntentFragment, nextSort, parseBillingAmount, portedComponentContracts, portedScenarios, recipeItemLabels, recordCollectionEvents, restartedBillingPeriod, sharedScenarios, substitutionContractReport, summarizeSubstitutionReport, summaryValue, svgCarriesTitle, traitEventRows, validMinorUnits, validateComponentIntakeDocument, vizControlFields, vizFieldValue, vizSummaryRows };
package/dist/index.js CHANGED
@@ -15371,7 +15371,7 @@ var authoredContracts = {
15371
15371
  states: ["subtle", "solid"],
15372
15372
  tokenRoles: ["badge.background", "badge.border", "badge.text"],
15373
15373
  accessibility: ["false remains visible", "archive is the badge variant"],
15374
- compatibility: "Mirrors renderArchivePill over renderBadgePrimitive: label/text/status/state/isArchived/value label precedence, status/state/isArchived/value status precedence, Archive fallback and archive variant. Boolean false and true remain literal scalar labels/status metadata; absent flags remain absent and authored labels or children win. field binds isArchived. archivedAtField is consumed unbound because the HTML pill has no date term. Noninteractive; no archive or restore action."
15374
+ compatibility: "Mirrors renderArchivePill over renderBadgePrimitive: label/text/status/state/isArchived/value label precedence, status/state/isArchived/value status precedence, Archive fallback and archive variant. Boolean flags read Not archived / Archived while preserving their recorded status; absent flags remain absent and authored labels or children win. field binds isArchived. archivedAtField is consumed unbound because the HTML pill has no date term. Noninteractive; no archive or restore action."
15375
15375
  },
15376
15376
  ArchiveSummary: {
15377
15377
  id: "ArchiveSummary",
@@ -15410,22 +15410,17 @@ var authoredContracts = {
15410
15410
  AuditTimeline: {
15411
15411
  id: "AuditTimeline",
15412
15412
  version: COMPONENT_CONTRACT_VERSION,
15413
- props: [
15414
- "title",
15415
- "events",
15416
- "history",
15417
- "entries",
15418
- "auditLog",
15413
+ props: ["title", "events", "history", "entries", "auditLog", "maxVisible", "showFromState", "showActorId", "showReason"],
15414
+ directives: [
15415
+ "field",
15416
+ "historyField",
15417
+ "statesParameter",
15419
15418
  "auditLogField",
15420
15419
  "createdField",
15421
15420
  "updatedField",
15422
15421
  "eventField",
15423
15422
  "eventTimestampField",
15424
- "eventOptionsParameter",
15425
- "maxVisible",
15426
- "showFromState",
15427
- "showActorId",
15428
- "showReason"
15423
+ "eventOptionsParameter"
15429
15424
  ],
15430
15425
  slots: ["default"],
15431
15426
  events: [],
@@ -15537,18 +15532,8 @@ var authoredContracts = {
15537
15532
  CancellationSummary: {
15538
15533
  id: "CancellationSummary",
15539
15534
  version: COMPONENT_CONTRACT_VERSION,
15540
- props: [
15541
- "title",
15542
- "label",
15543
- "cancelAtPeriodEnd",
15544
- "requestedAt",
15545
- "reason",
15546
- "code",
15547
- "cancelAtPeriodEndField",
15548
- "requestedAtField",
15549
- "reasonField",
15550
- "codeField"
15551
- ],
15535
+ props: ["title", "label", "cancelAtPeriodEnd", "requestedAt", "reason", "code"],
15536
+ directives: ["field", "cancelAtPeriodEndField", "requestedAtField", "reasonField", "codeField"],
15552
15537
  slots: ["default"],
15553
15538
  events: [],
15554
15539
  states: ["scheduled", "not-scheduled"],
@@ -15839,7 +15824,9 @@ var authoredContracts = {
15839
15824
  "pageSizeOptions",
15840
15825
  "showPageSizeSelector",
15841
15826
  "showGotoPage",
15842
- "showItemRange",
15827
+ "showItemRange"
15828
+ ],
15829
+ directives: [
15843
15830
  "pageField",
15844
15831
  "pageSizeField",
15845
15832
  "totalItemsField",
@@ -15935,12 +15922,9 @@ var authoredContracts = {
15935
15922
  "label",
15936
15923
  "value",
15937
15924
  "emphasis",
15938
- "amountField",
15939
- "currencyField",
15940
- "intervalField",
15941
- "minorUnitsParameter",
15942
15925
  "minorUnits"
15943
15926
  ],
15927
+ directives: ["field", "amountField", "currencyField", "intervalField", "minorUnitsParameter"],
15944
15928
  slots: ["default"],
15945
15929
  events: [],
15946
15930
  states: ["priced", "missing-price"],
@@ -15957,7 +15941,7 @@ var authoredContracts = {
15957
15941
  states: ["populated", "empty"],
15958
15942
  tokenRoles: ["meta.text", "meta.label"],
15959
15943
  accessibility: ["model and interval have literal inline labels", "price metadata is noninteractive"],
15960
- compatibility: "Mirrors renderPriceCardMeta over renderMetaInline: title/label/heading/name (default Price), Model model/pricingModel and Interval interval/billingInterval inline terms. Children replace the entire body including its title. modelField and intervalField lower to their runtime keys. amountField, currencyField and minorUnitsParameter are consumed unbound because this HTML metadata renderer has no amount or currency term. Noninteractive."
15944
+ compatibility: "Mirrors renderPriceCardMeta over renderMetaInline: title/label/heading/name (default Price), Model model/pricingModel and Interval interval/billingInterval inline terms, their codes read as PriceSummary reads them (formatPriceCode: one_time reads One Time). Children replace the entire body including its title. modelField and intervalField lower to their runtime keys. amountField, currencyField and minorUnitsParameter are consumed unbound because this HTML metadata renderer has no amount or currency term. Noninteractive."
15961
15945
  },
15962
15946
  PriceSummary: {
15963
15947
  id: "PriceSummary",
@@ -15984,10 +15968,9 @@ var authoredContracts = {
15984
15968
  "text",
15985
15969
  "timezone",
15986
15970
  "now",
15987
- "fallbackField",
15988
- "timezoneParameter",
15989
15971
  "hideWhenEmpty"
15990
15972
  ],
15973
+ directives: ["field", "fallbackField", "timezoneParameter"],
15991
15974
  slots: ["default"],
15992
15975
  events: [],
15993
15976
  states: ["relative", "absolute", "empty"],
@@ -16030,12 +16013,9 @@ var authoredContracts = {
16030
16013
  "debounceMs",
16031
16014
  "debounce",
16032
16015
  "minQueryLength",
16033
- "disabled",
16034
- "placeholderParameter",
16035
- "debounceParameter",
16036
- "minQueryLengthParameter",
16037
- "clearableParameter"
16016
+ "disabled"
16038
16017
  ],
16018
+ directives: ["field", "placeholderParameter", "debounceParameter", "minQueryLengthParameter", "clearableParameter"],
16039
16019
  slots: [],
16040
16020
  events: ["valueChange", "update", "search", "clear"],
16041
16021
  states: ["empty", "valued", "disabled"],
@@ -16059,7 +16039,8 @@ var authoredContracts = {
16059
16039
  Stack: {
16060
16040
  id: "Stack",
16061
16041
  version: COMPONENT_CONTRACT_VERSION_1_1,
16062
- props: ["direction", "gap", "align", "justify", "wrap", "patternComponent", "fields"],
16042
+ props: ["direction", "gap", "align", "justify", "wrap"],
16043
+ directives: ["patternComponent", "fields"],
16063
16044
  slots: ["default"],
16064
16045
  events: [],
16065
16046
  states: ["row", "column", "wrapped"],
@@ -16081,11 +16062,10 @@ var authoredContracts = {
16081
16062
  "emphasis",
16082
16063
  "showIcon",
16083
16064
  "variant",
16084
- "statusField",
16085
- "domainField",
16086
16065
  "readOnly",
16087
16066
  "compact"
16088
16067
  ],
16068
+ directives: ["field", "statusField", "domainField"],
16089
16069
  slots: ["default"],
16090
16070
  events: [],
16091
16071
  states: ["subtle", "solid"],
@@ -16116,12 +16096,21 @@ var authoredContracts = {
16116
16096
  "stateHistory",
16117
16097
  "status",
16118
16098
  "allowedTransitions",
16119
- "historyField",
16120
- "statesParameter",
16121
16099
  "showActorId",
16122
16100
  "showReason",
16123
16101
  "maxVisible"
16124
16102
  ],
16103
+ directives: [
16104
+ "field",
16105
+ "historyField",
16106
+ "statesParameter",
16107
+ "auditLogField",
16108
+ "createdField",
16109
+ "updatedField",
16110
+ "eventField",
16111
+ "eventTimestampField",
16112
+ "eventOptionsParameter"
16113
+ ],
16125
16114
  slots: ["default"],
16126
16115
  events: [],
16127
16116
  states: ["populated", "empty"],
@@ -16346,7 +16335,7 @@ var viz_preview_samples_v1_default = {
16346
16335
  input: {
16347
16336
  name: "Example connected relationships",
16348
16337
  description: "Synthetic neighborhood edges illustrating relationships that share an endpoint; these are examples, not live graph data."},
16349
- svg: '<svg width="360" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" viewBox="0 0 360 200">\n<rect width="360" height="200" x="0" y="0" fill="#F9FAFC"></rect>\n<path d="M208.4 34Q249.7 88.3 221.2 150.3" fill="none" pointer-events="visible" stroke="rgb(88, 9, 24)" stroke-opacity="0.5" ecmeta_series_index="0" ecmeta_data_index="0" ecmeta_ssr_type="chart" class="oods-zr-0"></path>\n<path d="M221.2 150.3Q155.5 166.3 110.4 115.8" fill="none" pointer-events="visible" stroke="rgb(88, 9, 24)" stroke-opacity="0.5" ecmeta_series_index="0" ecmeta_data_index="1" ecmeta_ssr_type="chart" class="oods-zr-0"></path>\n<path d="M110.4 115.8Q176.1 99.8 221.2 150.3" fill="none" pointer-events="visible" stroke="rgb(88, 9, 24)" stroke-opacity="0.5" ecmeta_series_index="0" ecmeta_data_index="2" ecmeta_ssr_type="chart" class="oods-zr-0"></path>\n<path d="M1 0A1 1 0 1 1 1 -0.1A1 1 0 0 1 1 0" transform="matrix(5,0,0,5,110.3635,115.779)" fill="rgb(88, 9, 24)" ecmeta_series_index="0" ecmeta_data_index="0" ecmeta_ssr_type="chart" class="oods-zr-1"></path>\n<path d="M1 0A1 1 0 1 1 1 -0.1A1 1 0 0 1 1 0" transform="matrix(5,0,0,5,221.2255,150.2583)" fill="rgb(88, 9, 24)" ecmeta_series_index="0" ecmeta_data_index="1" ecmeta_ssr_type="chart" class="oods-zr-1"></path>\n<path d="M1 0A1 1 0 1 1 1 -0.1A1 1 0 0 1 1 0" transform="matrix(5,0,0,5,208.3976,33.9582)" fill="rgb(88, 9, 24)" ecmeta_series_index="0" ecmeta_data_index="2" ecmeta_ssr_type="chart" class="oods-zr-1"></path>\n<text dominant-baseline="central" text-anchor="start" style="font-size:12px;font-family:sans-serif;" transform="translate(120.3635 115.779)" fill="#1A1D23">example-document</text>\n<text dominant-baseline="central" text-anchor="start" style="font-size:12px;font-family:sans-serif;" transform="translate(231.2255 150.2583)" fill="#1A1D23">example-project</text>\n<text dominant-baseline="central" text-anchor="start" style="font-size:12px;font-family:sans-serif;" transform="translate(218.3976 33.9582)" fill="#1A1D23">example-team</text>\n<path d="M-108.1 -5l216.2 0l0 24l-216.2 0Z" transform="translate(180 13)" fill="rgb(0,0,0)" fill-opacity="0" stroke="#3c3c41" stroke-width="0" class="oods-zr-2"></path>\n<text dominant-baseline="central" text-anchor="middle" style="font-size:14px;font-family:sans-serif;font-weight:600;" xml:space="preserve" y="7" transform="translate(180 13)" fill="#1A1D23">Example connected relationships</text>\n<style ><![CDATA[\n.oods-zr-0:hover {\ncursor:pointer;\nstroke-width:4;\n}\n.oods-zr-1:hover {\ncursor:pointer;\nfill:rgba(96,9,26,1);\n}\n.oods-zr-2:hover {\npointer-events:none;\n}\n\n]]>\n\n</style>\n</svg>'}
16338
+ svg: '<svg width="360" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" viewBox="0 0 360 200" role="img" aria-label="Example connected relationships" aria-description="Synthetic neighborhood edges illustrating relationships that share an endpoint; these are examples, not live graph data."><title>Example connected relationships</title><desc>Synthetic neighborhood edges illustrating relationships that share an endpoint; these are examples, not live graph data.</desc>\n<rect width="360" height="200" x="0" y="0" fill="#F9FAFC"></rect>\n<path d="M208.4 34Q249.7 88.3 221.2 150.3" fill="none" pointer-events="visible" stroke="rgb(88, 9, 24)" stroke-opacity="0.5" ecmeta_series_index="0" ecmeta_data_index="0" ecmeta_ssr_type="chart" class="oods-zr-0"></path>\n<path d="M221.2 150.3Q155.5 166.3 110.4 115.8" fill="none" pointer-events="visible" stroke="rgb(88, 9, 24)" stroke-opacity="0.5" ecmeta_series_index="0" ecmeta_data_index="1" ecmeta_ssr_type="chart" class="oods-zr-0"></path>\n<path d="M110.4 115.8Q176.1 99.8 221.2 150.3" fill="none" pointer-events="visible" stroke="rgb(88, 9, 24)" stroke-opacity="0.5" ecmeta_series_index="0" ecmeta_data_index="2" ecmeta_ssr_type="chart" class="oods-zr-0"></path>\n<path d="M1 0A1 1 0 1 1 1 -0.1A1 1 0 0 1 1 0" transform="matrix(5,0,0,5,110.3635,115.779)" fill="rgb(88, 9, 24)" ecmeta_series_index="0" ecmeta_data_index="0" ecmeta_ssr_type="chart" class="oods-zr-1"></path>\n<path d="M1 0A1 1 0 1 1 1 -0.1A1 1 0 0 1 1 0" transform="matrix(5,0,0,5,221.2255,150.2583)" fill="rgb(88, 9, 24)" ecmeta_series_index="0" ecmeta_data_index="1" ecmeta_ssr_type="chart" class="oods-zr-1"></path>\n<path d="M1 0A1 1 0 1 1 1 -0.1A1 1 0 0 1 1 0" transform="matrix(5,0,0,5,208.3976,33.9582)" fill="rgb(88, 9, 24)" ecmeta_series_index="0" ecmeta_data_index="2" ecmeta_ssr_type="chart" class="oods-zr-1"></path>\n<text dominant-baseline="central" text-anchor="start" style="font-size:12px;font-family:sans-serif;" transform="translate(120.3635 115.779)" fill="#1A1D23">example-document</text>\n<text dominant-baseline="central" text-anchor="start" style="font-size:12px;font-family:sans-serif;" transform="translate(231.2255 150.2583)" fill="#1A1D23">example-project</text>\n<text dominant-baseline="central" text-anchor="start" style="font-size:12px;font-family:sans-serif;" transform="translate(218.3976 33.9582)" fill="#1A1D23">example-team</text>\n<path d="M-108.1 -5l216.2 0l0 24l-216.2 0Z" transform="translate(180 13)" fill="rgb(0,0,0)" fill-opacity="0" stroke="#3c3c41" stroke-width="0" class="oods-zr-2"></path>\n<text dominant-baseline="central" text-anchor="middle" style="font-size:14px;font-family:sans-serif;font-weight:600;" xml:space="preserve" y="7" transform="translate(180 13)" fill="#1A1D23">Example connected relationships</text>\n<style ><![CDATA[\n.oods-zr-0:hover {\ncursor:pointer;\nstroke-width:4;\n}\n.oods-zr-1:hover {\ncursor:pointer;\nfill:rgba(96,9,26,1);\n}\n.oods-zr-2:hover {\npointer-events:none;\n}\n\n]]>\n\n</style>\n</svg>'}
16350
16339
  }
16351
16340
  };
16352
16341
 
@@ -16394,7 +16383,7 @@ var authoredScenarios = [
16394
16383
  { id: "address-editor-fields-and-change", oodsComponentId: "AddressEditor", props: { title: "Shipping address", street: "1 Main St", city: "Springfield", region: "IL", postalCode: "62701" }, slots: {}, initialState: { street: "1 Main St" }, renderExpectation: { name: "change", trigger: "type into the City input", expected: "change emitted with the current street/city/region/postalCode record" }, assertions: ["title is a real h2 heading", "four labelled inputs are prefilled", "change carries the whole address record", "submitting is a no-op"] },
16395
16384
  { id: "address-summary-badge-role", oodsComponentId: "AddressSummaryBadge", props: { label: "Billing address", role: "billing" }, slots: {}, initialState: { status: "billing" }, renderExpectation: { name: "render", trigger: "mount", expected: "visible Billing address label with data-badge-status billing and the address variant" }, assertions: ["label is visible text", "data-badge-status is billing", "data-badge-variant is address", "badge is noninteractive"] },
16396
16385
  { id: "address-validation-timeline-events", oodsComponentId: "AddressValidationTimeline", props: { title: "Address checks", validations: [{ label: "Postal code verified", timestamp: "2026-09-05T12:00:00Z", detail: "Matched carrier database" }, "Geocoded"] }, slots: {}, initialState: { events: 2 }, renderExpectation: { name: "render", trigger: "mount", expected: "a log region titled Address checks with two ordered events, the first timestamped and detailed" }, assertions: ["region has role log and an h2 title", "events are ordered list items", "the timestamp is a time element", "scalar entries render as text"] },
16397
- { id: "archive-pill-false", oodsComponentId: "ArchivePill", props: { "isArchived": false }, slots: {}, initialState: { content: "populated" }, renderExpectation: { name: "render", trigger: "mount", expected: "false remains visible; archive is the badge variant" }, assertions: ["false remains visible", "archive is the badge variant"] },
16386
+ { id: "archive-pill-false", oodsComponentId: "ArchivePill", props: { "isArchived": false }, slots: {}, initialState: { content: "populated" }, renderExpectation: { name: "render", trigger: "mount", expected: "Not archived remains visible; machine status remains false; archive is the badge variant" }, assertions: ["Not archived remains visible; machine status remains false", "archive is the badge variant"] },
16398
16387
  { id: "archive-summary-false-and-reason", oodsComponentId: "ArchiveSummary", props: { "isArchived": false, "archivedAt": "2026-09-05T12:00:00Z", "reason": "Retention policy" }, slots: {}, initialState: { content: "populated" }, renderExpectation: { name: "render", trigger: "mount", expected: "No remains visible in its named term; archive date and reason remain associated terms" }, assertions: ["No remains visible in its named term", "archive date and reason remain associated terms"] },
16399
16388
  { id: "archived-row-presentation", oodsComponentId: "ArchivedRowOverlay", props: { "isArchived": true, "showBadge": true, "separateTab": true, "tabLabel": "Archived", "label": "Team subscription" }, slots: {}, initialState: {}, renderExpectation: { name: "render", trigger: "mount", expected: "Archived row stays accessible and its badge and tab label agree" }, assertions: ["Archived row stays accessible and its badge and tab label agree"] },
16400
16389
  { id: "audit-event-type-and-timestamp", oodsComponentId: "AuditEvent", props: { event: "user.updated", timestamp: "2026-09-05T12:00:00Z", detail: "Display name changed" }, slots: {}, initialState: { timestamped: true }, renderExpectation: { name: "render", trigger: "mount", expected: "one audit article with a machine-readable time, the event label and the detail" }, assertions: ["article carries data-event-type audit", "time element has a datetime", "label and detail are visible text"] },
@@ -16606,6 +16595,28 @@ function billingCycle(values) {
16606
16595
  const announcement = `${percent === void 0 ? "Progress unavailable" : `${percent}% complete`} \xB7 ${remainingDays === void 0 ? "Remaining days unavailable" : `${remainingDays} ${remainingDays === 1 ? "day" : "days"} remaining`}`;
16607
16596
  return { percent, remainingDays, announcement, ended };
16608
16597
  }
16598
+ var PERIOD_MONTHS = { monthly: 1, quarterly: 3, yearly: 12, annual: 12 };
16599
+ function billingPeriodEnd(start, interval) {
16600
+ const date = new Date(start);
16601
+ if (!Number.isFinite(date.getTime())) return void 0;
16602
+ if (interval === "weekly") return new Date(date.getTime() + 7 * 864e5).toISOString();
16603
+ const months = interval ? PERIOD_MONTHS[interval] : void 0;
16604
+ if (!months) return void 0;
16605
+ const end = new Date(date);
16606
+ end.setUTCDate(1);
16607
+ end.setUTCMonth(end.getUTCMonth() + months);
16608
+ end.setUTCDate(Math.min(date.getUTCDate(), new Date(Date.UTC(end.getUTCFullYear(), end.getUTCMonth() + 1, 0)).getUTCDate()));
16609
+ return end.toISOString();
16610
+ }
16611
+ function restartedBillingPeriod(at, interval) {
16612
+ return {
16613
+ current_period_start: at,
16614
+ current_period_end: billingPeriodEnd(at, interval),
16615
+ current_period_progress: void 0,
16616
+ next_payment_due_at: at,
16617
+ payment_status: "pending"
16618
+ };
16619
+ }
16609
16620
  var NO_NEXT_PAYMENT = "No payment scheduled";
16610
16621
  var NO_LAST_PAYMENT = "No previous payment";
16611
16622
  function billingDate(value) {
@@ -16665,9 +16676,13 @@ function recordCollectionEvents(record2, options = {}) {
16665
16676
  if (typeof at !== "string" || typeof state !== "string") return [];
16666
16677
  return [{ id: "state-" + index, title: String(entry.title ?? state.split(/[_-]/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ")), at, description: String(entry.reason ?? ""), kind: "state" }];
16667
16678
  }) : [];
16679
+ const recorded = Array.isArray(record2.payment_history) ? record2.payment_history : [];
16668
16680
  for (const source2 of options.payments ?? []) {
16669
16681
  const at = record2[source2.field];
16670
- if (typeof at === "string") events.push({ id: "payment-" + source2.field, title: source2.title, at, description: billingSummary(Number(record2.amount), String(record2.currency), options.minorUnits ?? 100, String(record2.billing_interval)), kind: "payment" });
16682
+ if (typeof at !== "string") continue;
16683
+ const paid = recorded.find((row) => row && typeof row === "object" && Date.parse(row.at) === Date.parse(at) && typeof row.amount === "number");
16684
+ const description = paid ? formatBillingAmount(paid.amount, String(paid.currency ?? record2.currency), options.minorUnits ?? 100) : billingSummary(Number(record2.amount), String(record2.currency), options.minorUnits ?? 100, String(record2.billing_interval));
16685
+ events.push({ id: "payment-" + source2.field, title: source2.title, at, description, kind: "payment" });
16671
16686
  }
16672
16687
  for (const source2 of [{ field: "created_at", title: "Created" }, { field: "last_event_at", title: String(record2.last_event ?? "Updated").replaceAll("_", " ") }, { field: "issued_at", title: "Issued" }, { field: "period_start", title: "Period started" }, { field: "ownership_transferred_at", title: "Ownership transferred" }]) {
16673
16688
  const at = record2[source2.field];
@@ -16995,4 +17010,4 @@ function getBaselineCapability(componentId) {
16995
17010
  return componentCapabilityBaseline.rows.find((row) => row.id === componentId);
16996
17011
  }
16997
17012
 
16998
- export { BILLING_AMOUNT_ERROR, BILLING_INTERVALS, BILLING_INTERVAL_ERROR, BILLING_MINOR_UNITS, COMPONENT_CLASSIFICATIONS, COMPONENT_CONTRACT_VERSION, COMPONENT_CONTRACT_VERSION_1_1, DEFAULT_COLOR_STATES, EMISSION_ELIGIBILITY_EVIDENCE_CLASSES, FOUNDATION_V1_EVIDENCE_CLASSES, GOVERNED_DEFINITION, GOVERNED_SURFACES, NO_LAST_PAYMENT, NO_NEXT_PAYMENT, NUCLEUS_COMPONENT_IDS, PORTED_COMPONENT_IDS, RESULT_STATES, RESULT_STATE_TONE, SEVERITY_TONES, UI_WORKFLOW_STATES, VIZ_CONTROL_IDS, VIZ_CONTROL_TITLES, VIZ_PREVIEW_TYPES, VIZ_SUMMARY_IDS, ariaSort, assertStaticSvg, auditSummary, billingAmountMessage, billingAmountText, billingCycle, billingDate, billingIntervalMessage, billingPaymentRows, billingPaymentSummary, billingSummary, chronologicalEvents, componentBehaviors, componentCapabilityBaseline, componentContracts, componentIntake, componentReconciliationProposal, currencyMinorUnits, dateTimeInputValue, defaultVizIntent, deriveStartingComponentCount, editVizIntent, evaluateEmissionEligibility, evaluateFoundationV1, formatBillingAmount, formatDateTime, formatPriceAmount, formatPriceCode, formatReadOnlyValue, formatRecordLabel, formatReferenceLabel, geoFieldMapping, getBaselineCapability, initialSort, isGovernedComponent, isVizIntentFragment, nextSort, parseBillingAmount, portedComponentContracts, portedScenarios, recipeItemLabels, recordCollectionEvents, sharedScenarios, substitutionContractReport, summarizeSubstitutionReport, summaryValue, svgCarriesTitle, traitEventRows, validMinorUnits, validateComponentIntakeDocument, vizControlFields, vizFieldValue, vizSummaryRows };
17013
+ export { BILLING_AMOUNT_ERROR, BILLING_INTERVALS, BILLING_INTERVAL_ERROR, BILLING_MINOR_UNITS, COMPONENT_CLASSIFICATIONS, COMPONENT_CONTRACT_VERSION, COMPONENT_CONTRACT_VERSION_1_1, DEFAULT_COLOR_STATES, EMISSION_ELIGIBILITY_EVIDENCE_CLASSES, FOUNDATION_V1_EVIDENCE_CLASSES, GOVERNED_DEFINITION, GOVERNED_SURFACES, NO_LAST_PAYMENT, NO_NEXT_PAYMENT, NUCLEUS_COMPONENT_IDS, PORTED_COMPONENT_IDS, RESULT_STATES, RESULT_STATE_TONE, SEVERITY_TONES, UI_WORKFLOW_STATES, VIZ_CONTROL_IDS, VIZ_CONTROL_TITLES, VIZ_PREVIEW_TYPES, VIZ_SUMMARY_IDS, ariaSort, assertStaticSvg, auditSummary, billingAmountMessage, billingAmountText, billingCycle, billingDate, billingIntervalMessage, billingPaymentRows, billingPaymentSummary, billingPeriodEnd, billingSummary, chronologicalEvents, componentBehaviors, componentCapabilityBaseline, componentContracts, componentIntake, componentReconciliationProposal, currencyMinorUnits, dateTimeInputValue, defaultVizIntent, deriveStartingComponentCount, editVizIntent, evaluateEmissionEligibility, evaluateFoundationV1, formatBillingAmount, formatDateTime, formatPriceAmount, formatPriceCode, formatReadOnlyValue, formatRecordLabel, formatReferenceLabel, geoFieldMapping, getBaselineCapability, initialSort, isGovernedComponent, isVizIntentFragment, nextSort, parseBillingAmount, portedComponentContracts, portedScenarios, recipeItemLabels, recordCollectionEvents, restartedBillingPeriod, sharedScenarios, substitutionContractReport, summarizeSubstitutionReport, summaryValue, svgCarriesTitle, traitEventRows, validMinorUnits, validateComponentIntakeDocument, vizControlFields, vizFieldValue, vizSummaryRows };
package/package.json CHANGED
@@ -1,11 +1,22 @@
1
1
  {
2
2
  "name": "@oods/component-contracts",
3
- "version": "0.3.1",
4
- "description": "Versioned OODS component identities, semantic contracts, shared scenarios, and readiness predicates.",
3
+ "version": "0.3.3",
4
+ "description": "Component contracts for OODS Foundry: each component's identity, props, events, states, token roles and accessibility obligations, with shared formatting helpers.",
5
+ "homepage": "https://oods-foundry.com/",
6
+ "bugs": {
7
+ "email": "derek@derekn.com"
8
+ },
9
+ "keywords": [
10
+ "oods",
11
+ "oods-foundry",
12
+ "component-contracts",
13
+ "design-system",
14
+ "accessibility"
15
+ ],
5
16
  "type": "module",
6
17
  "license": "Apache-2.0",
7
18
  "engines": {
8
- "node": ">=20.11.1"
19
+ "node": ">=22.0.0"
9
20
  },
10
21
  "files": [
11
22
  "dist",