@instruments/materialgraph 3.0.1 → 3.1.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/client.d.ts CHANGED
@@ -177,7 +177,7 @@ export declare class MaterialGraphClient {
177
177
  * materials catalog, never silently dropped from the page.
178
178
  *
179
179
  * `filters`/`optionalFilters`/`orderBy`/`colors` are sent as URL-encoded
180
- * JSON; `attributes`/`include`/`words` as comma-separated lists — the server
180
+ * JSON; `attributes`/`observations`/`include`/`words` as comma-separated lists — the server
181
181
  * validates, this method does not duplicate that check.
182
182
  */
183
183
  listVariants(input: ListVariantsInput, signal?: AbortSignal): Promise<ListVariantsOutput>;
package/client.js CHANGED
@@ -181,6 +181,9 @@ export class MaterialGraphClient {
181
181
  blocks: options?.blocks !== undefined && options.blocks.length > 0
182
182
  ? options.blocks.join(",")
183
183
  : undefined,
184
+ observations: options?.observations !== undefined && options.observations.length > 0
185
+ ? options.observations.join(",")
186
+ : undefined,
184
187
  ifc: options?.ifc === true ? "true" : undefined,
185
188
  }, signal, { variantId });
186
189
  }
@@ -249,7 +252,7 @@ export class MaterialGraphClient {
249
252
  * materials catalog, never silently dropped from the page.
250
253
  *
251
254
  * `filters`/`optionalFilters`/`orderBy`/`colors` are sent as URL-encoded
252
- * JSON; `attributes`/`include`/`words` as comma-separated lists — the server
255
+ * JSON; `attributes`/`observations`/`include`/`words` as comma-separated lists — the server
253
256
  * validates, this method does not duplicate that check.
254
257
  */
255
258
  async listVariants(input, signal) {
@@ -269,6 +272,9 @@ export class MaterialGraphClient {
269
272
  : undefined,
270
273
  limit: input.limit,
271
274
  name: input.name,
275
+ observations: input.observations !== undefined && input.observations.length > 0
276
+ ? input.observations.join(",")
277
+ : undefined,
272
278
  optionalFilters: input.optionalFilters
273
279
  ? JSON.stringify(input.optionalFilters)
274
280
  : undefined,
@@ -0,0 +1,94 @@
1
+ /**
2
+ * The ColorScope shapes `resolveColor` returns, as they arrive on the wire.
3
+ * They mirror `@materialinstruments/colorscope` (14.x) rather than importing
4
+ * it: the published SDK carries no dependency, and ColorScope is private.
5
+ */
6
+ import type { OpenEnum } from "./types.js";
7
+ /** A color in OKLab: lightness 0 to 1, and the green-red and blue-yellow axes. */
8
+ export type OKLab = {
9
+ L: number;
10
+ a: number;
11
+ b: number;
12
+ };
13
+ /** A region of color: chroma, hue (null for neutrals) and lightness bounds. */
14
+ export type ColorRegion = {
15
+ chroma: [number, number];
16
+ hue: [number, number] | null;
17
+ lightness: [number, number];
18
+ };
19
+ /** One of ColorScope's fifteen color families. */
20
+ export type ColorFamilyId = OpenEnum<"beige" | "black" | "blue" | "brown" | "cream" | "gray" | "green" | "orange" | "pink" | "purple" | "red" | "taupe" | "teal" | "white" | "yellow">;
21
+ /** A named color a resolution lands on, and how close the input is to it. */
22
+ export type ColorResolutionMatch = {
23
+ band: OpenEnum<"inside" | "near" | "far">;
24
+ family: ColorFamilyId;
25
+ hex: string;
26
+ id: string;
27
+ name: string;
28
+ range: ColorRegion;
29
+ };
30
+ /** What ColorScope makes of a color name: resolved to a color, or why not. */
31
+ export type ColorResolution = {
32
+ kind: "resolved";
33
+ confidence: number;
34
+ input: string;
35
+ principal: ColorResolutionMatch;
36
+ others: ColorResolutionMatch[];
37
+ reference?: {
38
+ brand: string;
39
+ code?: string;
40
+ hex: string;
41
+ id: string;
42
+ libraryId: string;
43
+ name: string;
44
+ };
45
+ source: OpenEnum<"composed" | "family" | "hex" | "name" | "reference" | "semantic">;
46
+ } | {
47
+ kind: "unresolved";
48
+ input: string;
49
+ reason: OpenEnum<"ambiguous-modifier" | "contradictory-modifiers" | "empty-range" | "unknown-term" | "unrepresentable-color" | "unsupported-base">;
50
+ terms: string[];
51
+ };
52
+ type SelectedTarget = OKLab & {
53
+ hasSelection: true;
54
+ label: string;
55
+ previewColors: string[];
56
+ };
57
+ /** The color a search matches against, by kind of selection. */
58
+ export type MatchTarget = {
59
+ type: "none";
60
+ hasSelection: false;
61
+ } | (SelectedTarget & {
62
+ type: "oklab";
63
+ }) | (SelectedTarget & {
64
+ type: "palette";
65
+ colors: {
66
+ hex: string;
67
+ oklab: OKLab;
68
+ }[];
69
+ logic: OpenEnum<"all" | "any">;
70
+ }) | (SelectedTarget & {
71
+ type: "image";
72
+ colors: {
73
+ hex: string;
74
+ oklab: OKLab | null;
75
+ proportion: number;
76
+ }[];
77
+ }) | (SelectedTarget & {
78
+ type: "gradient";
79
+ startColor: {
80
+ hex: string;
81
+ oklab: OKLab;
82
+ };
83
+ endColor: {
84
+ hex: string;
85
+ oklab: OKLab;
86
+ };
87
+ }) | (SelectedTarget & {
88
+ type: "range";
89
+ representative: {
90
+ hex: string;
91
+ };
92
+ range: ColorRegion[];
93
+ });
94
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -7,7 +7,7 @@
7
7
  * `__tests__/contract-parity.test.ts` keeps the mirror honest against the
8
8
  * server types.
9
9
  */
10
- import type { ListVariantsNotApplicable, ListVariantsSpecifications, SampleSubject } from "./list-variants-types.js";
10
+ import type { ListVariantsNotApplicable, ListVariantsSpecifications, SampleSubject, VariantObservations } from "./list-variants-types.js";
11
11
  import type { VariantColorPalette } from "./material-block-types.js";
12
12
  /** The detail to add under `specifications`; absent, the answer is the compact item alone. */
13
13
  export type GetVariantOptions = {
@@ -15,6 +15,8 @@ export type GetVariantOptions = {
15
15
  attributes?: readonly string[];
16
16
  /** Canonical block ids, returned whole, e.g. `["acoustic"]`. */
17
17
  blocks?: readonly string[];
18
+ /** Observation attribute ids, e.g. `["sample_size"]`, returned under `observations` by channel. */
19
+ observations?: readonly string[];
18
20
  /** Add `ifc`: the IFC 4.3 manufacturer property set and classification references. */
19
21
  ifc?: boolean;
20
22
  };
@@ -98,6 +100,8 @@ export type GetVariantOutput = {
98
100
  variantLabel: string | null;
99
101
  /** Requested blocks or attributes the variant's product type does not carry. */
100
102
  notApplicable?: ListVariantsNotApplicable;
103
+ /** Present when `observations` was asked for and the variant has any. */
104
+ observations?: VariantObservations;
101
105
  /** Present when `ifc` was asked for. */
102
106
  ifc?: GetVariantIfc;
103
107
  product: {
package/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export type { DiscoveryReference, DiscoveryTerms, InterpretDiscoveryTermsInput, ColorlessVariantsResult, VariantSibling, } from "./discovery-context-types.js";
2
2
  export { MaterialGraphClient, DEFAULT_BASE_URL } from "./client.js";
3
3
  export type { MaterialGraphClientOptions } from "./client.js";
4
- export type { FilterOp, FilterTermCondition, FilterNumericCondition, FilterPresenceCondition, FilterAnyFieldCondition, FilterCondition, FilterGroups, OptionalFilterGroups, OrderByEntry, ListVariantsInclude, ListVariantsCollapse, ColorRegion, ColorRangeCondition, ListVariantsInput, ListVariantsPreference, ListVariantsSpecifications, ListVariantsNotApplicable, SampleSubject, ListVariantsItem, ListVariantsOutput, VariantCard, } from "./list-variants-types.js";
4
+ export type { FilterOp, FilterTermCondition, FilterNumericCondition, FilterPresenceCondition, FilterAnyFieldCondition, FilterCondition, FilterGroups, OptionalFilterGroups, OrderByEntry, ListVariantsInclude, ListVariantsCollapse, ColorRegion, ColorRangeCondition, ListVariantsInput, ListVariantsPreference, ListVariantsSpecifications, ListVariantsNotApplicable, SampleSizeObservation, VariantObservations, SampleSubject, ListVariantsItem, ListVariantsOutput, VariantCard, } from "./list-variants-types.js";
5
5
  export type { ListVariantFacetsInput, VariantFacetValue, CategoricalVariantFacet, BooleanVariantFacet, NumericVariantFacet, VariantFacet, ListVariantFacetsOutput, } from "./list-variant-facets-types.js";
6
6
  export type { SearchVariantsSelection, SearchVariantsInput, SearchVariantsUnderstood, SearchVariantsReading, SearchVariantsSuggestion, SearchVariantsChoice, SearchVariantsOutput, } from "./search-variants-types.js";
7
7
  export type { ListEnumValuesOptions, EnumValueMatch, EnumValueItem, ListEnumValuesResult, } from "./list-enum-values-types.js";
@@ -27,7 +27,7 @@ export type { ColorsTransport } from "./colors-client.js";
27
27
  export type { CategoryTier, CategoryColor, CategoryColorProfile, CategoryColorProfilesResponse, ColorProfilesParams, } from "./color-profiles-types.js";
28
28
  export type { DeclaredProvenance, DeclaredAssociationSubject, DeclaredAssociation, DeclaredAssociationsResponse, AssociatedOptions, ApplicabilitySubject, ApplicabilityCoverageState, ApplicabilityCoverage, ApplicabilityFact, ApplicabilitySourceEntry, UnresolvedApplicabilityEndpoint, ApplicabilityResponse, ApplicabilityOptions, } from "./association-types.js";
29
29
  export type { BrandsOptions, BrandItem, ListBrandsPage, } from "./brand-types.js";
30
- export type { VariantAssetAvailability, VariantImageRole, VariantImagePresentation, VariantDocumentType, VariantAssetKind, VariantAssetItem, VariantDocumentCoverageState, VariantAssetPageInfo, ListVariantAssetsOptions, VariantAssetPage, MaterialDocumentStatus, MaterialDocumentCoverageState, MaterialDocumentScope, MaterialDocumentSource, MaterialDocumentProjectionItem, MaterialDocumentCoverageSource, MaterialDocumentCoverage, MaterialDocumentCoverageSummary, MaterialDocumentPageOptions, MaterialDocumentPage, } from "./material-asset-types.js";
30
+ export type { VariantAssetAvailability, VariantImageRole, VariantImagePresentation, VariantImageShows, VariantImageSurfaceMm, VariantDocumentType, VariantAssetKind, VariantAssetItem, VariantDocumentCoverageState, VariantAssetPageInfo, ListVariantAssetsOptions, VariantAssetPage, MaterialDocumentStatus, MaterialDocumentCoverageState, MaterialDocumentScope, MaterialDocumentSource, MaterialDocumentProjectionItem, MaterialDocumentCoverageSource, MaterialDocumentCoverage, MaterialDocumentCoverageSummary, MaterialDocumentPageOptions, MaterialDocumentPage, } from "./material-asset-types.js";
31
31
  export type { MaterialCoverageStatus, MaterialBlockStatus, MaterialBlockFieldStatus, MaterialBlockFieldValue, MaterialBlockProjectionField, MaterialBlockProjectionItem, MaterialBlockProjection, VariantColorPalette, } from "./material-block-types.js";
32
32
  export type { SchemaResource, SCHEMA_RESOURCE_OPERATION_IDS, SchemaResourceRequest, SchemaLifecycle, SchemaExternalMapping, SchemaMatchStrength, SchemaValueDictionaryTerm, SchemaValueDictionaryItem, SchemaResourceItemMap, SchemaResourceResponse, } from "./schema-resource-types.js";
33
33
  export type { NearestPaintsParams, NearestPaintCard, NearestPaintsHexResult, NearestPaintsOutput, } from "./nearest-paints-types.js";
@@ -145,6 +145,8 @@ export type ListVariantsInput = {
145
145
  * ambiguous matches are all returned rather than guessed between.
146
146
  */
147
147
  name?: string;
148
+ /** Observation attribute ids to add under each item's `observations`, e.g. `["sample_size"]`. */
149
+ observations?: string[];
148
150
  /** Rank only — never excludes. */
149
151
  optionalFilters?: OptionalFilterGroups;
150
152
  orderBy?: OrderByEntry[];
@@ -162,6 +164,23 @@ export type ListVariantsPreference = {
162
164
  };
163
165
  /** `{ [blockId]: { [attributeId]: value } }`. Null means the value is unknown. */
164
166
  export type ListVariantsSpecifications = Record<string, Record<string, unknown>>;
167
+ /** Material Bank's printed sample size. Any field may be absent; absent is unknown, never 0. */
168
+ export type SampleSizeObservation = {
169
+ /** The sample size as the channel printed it, verbatim. */
170
+ wording?: string;
171
+ /** The shorter side in millimeters. */
172
+ width_mm?: number;
173
+ /** The longer side in millimeters. */
174
+ length_mm?: number;
175
+ };
176
+ /**
177
+ * `{ [channel]: { [attributeId]: value } }`: the latest observation of each
178
+ * selected attribute for each channel (`no_channel` when none is named). An
179
+ * attribute with no observation is absent.
180
+ */
181
+ export type VariantObservations = Record<string, {
182
+ sample_size?: SampleSizeObservation;
183
+ } & Record<string, unknown>>;
165
184
  export type ListVariantsNotApplicable = {
166
185
  attributes?: string[];
167
186
  blocks?: string[];
@@ -210,6 +229,8 @@ export type ListVariantsItem = {
210
229
  /** The trimmed source variant label; null when unknown or for a paint color sample, whose own name identifies its color. Separate from surface finish, color family and derived color names. */
211
230
  variantLabel: string | null;
212
231
  notApplicable?: ListVariantsNotApplicable;
232
+ /** Present when `observations` was asked for and the variant has any. */
233
+ observations?: VariantObservations;
213
234
  preference?: ListVariantsPreference;
214
235
  product: {
215
236
  id: string;
@@ -20,6 +20,13 @@ export type VariantAssetAvailability = OpenEnum<"available" | "unknown" | "unava
20
20
  export type VariantImageRole = OpenEnum<"product" | "swatch" | "detail" | "scene" | "technical" | "color_chart" | "sample_collection" | "other" | "unknown">;
21
21
  /** How an image must be framed, a different question from what it shows. */
22
22
  export type VariantImagePresentation = OpenEnum<"edge_to_edge" | "packshot" | "cutout_margin" | "montage" | "unknown">;
23
+ /** What a photo shows of its material, so an app can place it at real size. */
24
+ export type VariantImageShows = OpenEnum<"sample" | "crop" | "laid_field" | "room" | "detail">;
25
+ /** The size of the surface in an image's frame, in millimeters. */
26
+ export type VariantImageSurfaceMm = {
27
+ width_mm: number;
28
+ height_mm: number;
29
+ };
23
30
  /** What a document is for; a document can carry more than one purpose. */
24
31
  export type VariantDocumentType = OpenEnum<"technical_data_sheet" | "product_sheet" | "technical_bulletin" | "sustainability_report" | "specification" | "installation_guide" | "care_maintenance_guide" | "operation_manual" | "warranty" | "parts_list" | "technical_drawing" | "test_report" | "certificate" | "declaration_of_performance" | "environmental_product_declaration" | "health_product_declaration" | "ingredient_disclosure" | "safety_data_sheet" | "brochure" | "catalog" | "color_finish_chart" | "other" | "unknown">;
25
32
  /** Every asset kind the registry knows. */
@@ -43,10 +50,16 @@ export type VariantAssetItem = {
43
50
  /** Images only; absent when unknown. */
44
51
  imageRole?: VariantImageRole;
45
52
  kind: VariantAssetKind;
53
+ /** Millimeters per pixel of this file. Images only; absent when unknown. */
54
+ mmPerPx?: number;
46
55
  /** Not on images; absent when unknown. */
47
56
  name?: string;
48
57
  /** Images only; absent when unknown. */
49
58
  presentation?: VariantImagePresentation;
59
+ /** What the photo shows of the material. Images only; absent when unknown. */
60
+ shows?: VariantImageShows;
61
+ /** The surface in frame: width and height times `mmPerPx`. Images only; absent when unknown. */
62
+ surfaceMm?: VariantImageSurfaceMm;
50
63
  url?: string;
51
64
  /** Images only; absent when unknown. */
52
65
  width?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instruments/materialgraph",
3
- "version": "3.0.1",
3
+ "version": "3.1.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -16,9 +16,6 @@
16
16
  "import": "./response-schemas.js"
17
17
  }
18
18
  },
19
- "dependencies": {
20
- "@materialinstruments/colorscope": "14.0.1"
21
- },
22
19
  "license": "Proprietary",
23
20
  "engines": {
24
21
  "node": ">=24.0.0"
@@ -1,9 +1,8 @@
1
- import type { MatchTarget } from "@materialinstruments/colorscope/match";
2
1
  /**
3
2
  * Color-name resolution (GET `/api/v1/search/colors/resolve`): the resolved
4
3
  * color, and whether the named paint is a variant in the catalog.
5
4
  */
6
- import type { ColorResolution } from "@materialinstruments/colorscope/naming";
5
+ import type { ColorResolution, MatchTarget } from "./color-wire-types.js";
7
6
  import type { VariantId } from "./identifiers.js";
8
7
  import type { SearchCatalogSubset } from "./search-catalog-subset-types.js";
9
8
  import type { OpenEnum } from "./types.js";