buildComponentLibrary discovers a component's public surface from the build config, never from the component. Every defineProps form I tried produces an empty properties map — except one, which produces names that cannot work.
Measured on @stacksjs/stx 0.2.343, with each component built alone.
| source | emitted properties |
|---|---|
const props = defineProps<{ label?: string }>() | {} |
const props = withDefaults(defineProps<{ label?: string }>(), { label: 'Hello' }) | {} |
const props = defineProps({ label: { type: String, default: 'Hello' } }) | {} |
const { label } = defineProps(['label']) | {} |
const { label = 'Hello', count = 0 } = defineProps<{ label?: string, count?: number }>() | see below |
The last one is the problem, because it looks like it works:
"properties": {
"label = 'Hello'": { "type": "object", "reflect": true },
"count = 0": { "type": "object", "reflect": true }
}The whole initialiser is taken as the property name. custom-elements.json then documents the attributes as label-hello and count-0, every type is object rather than string/number, and nothing a page writes as label="x" ever reaches the element.
What it costs
The public surface has to be restated in the build config:
components: [{
file: 'activity-card.stx',
properties: { activity: { type: 'string', default: '', reflect: true } },
}]That half works well — declared properties produce a correct manifest and correct attribute handling. But it leaves two lists to keep in step, and the failure when they drift is silent: the generated render reads an undefined identifier and the component renders an empty attribute.
A sharp edge that follows from it
When properties are declared, the compiler emits its own prologue:
const { activity, format } = this._props();So a component that also destructures defineProps redeclares those names and the build fails with a bare failed to compile render (Parse error) naming the file but not the line or the identifier. It took a while to find, because the same component compiles fine with no properties declared — the error only appears once you declare the surface, which is the opposite of where you look.
Two things would help on their own:
- say which identifier collided, rather than
Parse error - read
defineProps(any form) and treat an explicitpropertiesentry as an override
Why it matters here
The point of authoring a web component in stx rather than in hand-written JS is that the component is the single description of itself. Having to declare the surface somewhere else gives up a good part of that.
Happy to send a PR for the destructure-with-defaults parse if the shape above looks right.