# `MaterialInput`

> Contract 2.0.0 · package sha256 `a857eca95b35921109faf997094bb4192f12527d9d0fcd4be7e97f06425bad6e` · generated from `configurator-runtime.d.ts` by `services/onsite-scripter/scripts/build-contract-docs.mjs`; edit the source, not this file.

Type · `import type { MaterialInput } from '@holostep-configurators/runtime-client/contract';` · stable · since 2.0.0 · section 8. Materials and textures

A MaterialSpec, however complete, merges field by field (RFC 7396) over what the part wears
(authored maps such as baked AO stay). A Material handle, a stored MaterialNode
(`materialNodeId`), a worn handle's read form (`materialId`) or a SceneSpec material (`ref`) replaces it: to switch a whole look, wear a
Material from [`materials.create(spec)`](Materials.create.md). A MaterialNode worn here replaces, the GLB's maps
included; the same node selected with [`select()`](Writer.select.md) lies over the GLB's material instead, keeping
the maps it doesn't set ([`IMaterialNode`](IMaterialNode.md)).

Inherited from [`MaterialSpec`](MaterialSpec.md): [`$schema`](MaterialSpec._schema.md), [`name`](MaterialSpec.name.md), [`baseColor`](MaterialSpec.baseColor.md), [`alpha`](MaterialSpec.alpha.md), [`alphaMode`](MaterialSpec.alphaMode.md), [`alphaCutoff`](MaterialSpec.alphaCutoff.md), [`metallic`](MaterialSpec.metallic.md), [`roughness`](MaterialSpec.roughness.md), [`emissive`](MaterialSpec.emissive.md), [`emissiveStrength`](MaterialSpec.emissiveStrength.md), [`normalScale`](MaterialSpec.normalScale.md), [`occlusionStrength`](MaterialSpec.occlusionStrength.md), [`ior`](MaterialSpec.ior.md), [`specular`](MaterialSpec.specular.md), [`sheen`](MaterialSpec.sheen.md), [`clearcoat`](MaterialSpec.clearcoat.md), [`transmission`](MaterialSpec.transmission.md), [`side`](MaterialSpec.side.md), [`lighting`](MaterialSpec.lighting.md), [`exactColor`](MaterialSpec.exactColor.md), [`variant`](MaterialSpec.variant.md), [`maps`](MaterialSpec.maps.md), [`labs`](MaterialSpec.labs.md).

Inherited from [`Material`](Material.md): [`id`](Material.id.md), [`spec`](Material.spec.md), [`disposed`](Material.disposed.md), [`dispose`](Material.dispose.md).

## Declaration

```ts
export type MaterialInput = MaterialSpec | Material | {
  materialNodeId: string;
} | {
  materialId: string;
} | {
  ref: string;
};
```

## Example

Imports: values (`has`, `validate`, the `Holo*Error` classes, the pure helpers) from `@holostep-configurators/runtime-client`, types from `@holostep-configurators/runtime-client/contract`, `/math` and `/testing` names from those entries; `boot` from the runtime module the root's `loadRuntimeAtFloor` resolves to. A type your page defines is your app's: declare it there, never import it from the package.

Compiled under the contract's strict settings (`examples/declaration/08-MaterialInput.ts`):

```ts
import type { Session } from '@holostep-configurators/runtime-client/contract';
declare const session: Session;
declare const signal: AbortSignal;
declare const sofa: string; // a ModelNode's nodeId
// a look-only preview of a stored MaterialNode; an id it doesn't hold is reported, not silent
const r = await session.node(sofa).set({ material: { materialNodeId: 'linen' } });
const missing = r.problems.find((p) => p.code === 'unsupported-spec');
if (missing) console.warn(missing.message, missing.didYouMean);
```

## Generic-API test (spec 3.1)

| Rule | Result |
| --- | --- |
| 1. Neutral name | pass: `MaterialInput` names no product |
| 2. A precedent | not recorded: no ledger row (coverage.json) names this member or its owner |
| 3. Two apps, or labs | not recorded: no ledger row names this member or its owner |
| 4. The cheaper fix first | not recorded per member (Appendix B decides it per need) |
