Drive Stepper state attrs from Soma runtime

active-uix
dev 5 months ago
parent 72c195d1c6
commit c5595dda71

@ -17,8 +17,12 @@ export const stepperMorfo = {
defaultElement: 'div', defaultElement: 'div',
optional: false, optional: false,
data: [ data: [
{ attr: 'data-orientation', values: ['horizontal', 'vertical'] }, {
{ attr: 'data-linear', severity: 'optional' } attr: 'data-orientation',
values: ['horizontal', 'vertical'],
value: v.propRef('orientation')
},
{ attr: 'data-linear', value: v.propRef('linear'), severity: 'optional' }
], ],
aria: [] aria: []
}, },
@ -49,10 +53,19 @@ export const stepperMorfo = {
optional: false, optional: false,
states: ['complete', 'current', 'incomplete'], states: ['complete', 'current', 'incomplete'],
data: [ data: [
{ attr: 'data-state', values: ['complete', 'current', 'incomplete'] }, {
{ attr: 'data-current', severity: 'optional' }, attr: 'data-state',
{ attr: 'data-complete', severity: 'optional' }, values: ['complete', 'current', 'incomplete'],
{ attr: 'data-incomplete', severity: 'optional' } value: v.propRef('state')
},
{
attr: 'data-orientation',
values: ['horizontal', 'vertical'],
value: v.propRef('orientation')
},
{ attr: 'data-current', value: v.propRef('current'), severity: 'optional' },
{ attr: 'data-complete', value: v.propRef('complete'), severity: 'optional' },
{ attr: 'data-incomplete', value: v.propRef('incomplete'), severity: 'optional' }
], ],
aria: [] aria: []
}, },
@ -109,7 +122,16 @@ export const stepperMorfo = {
defaultElement: 'div', defaultElement: 'div',
optional: true, optional: true,
states: ['complete', 'current', 'incomplete'], states: ['complete', 'current', 'incomplete'],
data: [{ attr: 'data-state', values: ['complete', 'current', 'incomplete'] }], data: [
{
attr: 'data-state',
values: ['complete', 'current', 'incomplete'],
value: v.propRef('state')
},
{ attr: 'data-current', value: v.propRef('current'), severity: 'optional' },
{ attr: 'data-complete', value: v.propRef('complete'), severity: 'optional' },
{ attr: 'data-incomplete', value: v.propRef('incomplete'), severity: 'optional' }
],
aria: [{ attr: 'aria-hidden', value: v.literal('true') }] aria: [{ attr: 'aria-hidden', value: v.literal('true') }]
}, },
{ {
@ -122,8 +144,19 @@ export const stepperMorfo = {
optional: true, optional: true,
states: ['complete', 'current', 'incomplete'], states: ['complete', 'current', 'incomplete'],
data: [ data: [
{ attr: 'data-state', values: ['complete', 'current', 'incomplete'] }, {
{ attr: 'data-complete', severity: 'optional' } attr: 'data-state',
values: ['complete', 'current', 'incomplete'],
value: v.propRef('state')
},
{
attr: 'data-orientation',
values: ['horizontal', 'vertical'],
value: v.propRef('orientation')
},
{ attr: 'data-current', value: v.propRef('current'), severity: 'optional' },
{ attr: 'data-complete', value: v.propRef('complete'), severity: 'optional' },
{ attr: 'data-incomplete', value: v.propRef('incomplete'), severity: 'optional' }
], ],
aria: [] aria: []
}, },
@ -136,7 +169,13 @@ export const stepperMorfo = {
role: 'tabpanel', role: 'tabpanel',
optional: true, optional: true,
states: ['complete', 'current', 'incomplete'], states: ['complete', 'current', 'incomplete'],
data: [{ attr: 'data-state', values: ['complete', 'current', 'incomplete'] }], data: [
{
attr: 'data-state',
values: ['complete', 'current', 'incomplete'],
value: v.propRef('state')
}
],
aria: [] aria: []
}, },
{ {
@ -145,7 +184,7 @@ export const stepperMorfo = {
kind: 'public', kind: 'public',
defaultElement: 'div', defaultElement: 'div',
optional: true, optional: true,
data: [], data: [{ attr: 'data-state', value: v.propRef('state'), emit: 'value' }],
aria: [] aria: []
}, },
{ {

@ -73,12 +73,18 @@ export class StepperProvider {
private constructor(opts: StepperOpts) { private constructor(opts: StepperOpts) {
this.opts = opts; this.opts = opts;
this.soma = Soma.require(); this.soma = Soma.require();
this.runtime = this.soma.runtime(stepperMorfo, {}); this.runtime = this.soma.runtime(stepperMorfo, {
props: {
orientation: () => this.opts.orientation.current,
linear: () => this.opts.linear.current
}
});
this.runtimePart = this.runtime.part('provider', { this.runtimePart = this.runtime.part('provider', {
id: opts.id, id: opts.id,
ref: opts.ref, ref: opts.ref,
owner: this, owner: this,
context: StepperProvider.ctx context: StepperProvider.ctx,
syncAttrs: true
}); });
} }
@ -125,9 +131,7 @@ export class StepperProvider {
readonly props = $derived.by(() => readonly props = $derived.by(() =>
this.runtimePart.assert({ this.runtimePart.assert({
...this.runtimePart.props, ...this.runtimePart.props,
dir: this.opts.dir.current, dir: this.opts.dir.current
'data-orientation': this.opts.orientation.current,
'data-linear': boolToEmptyStrOrUndef(this.opts.linear.current)
} as const) } as const)
); );
} }
@ -201,7 +205,15 @@ export class StepperItemProvider {
id: opts.id, id: opts.id,
ref: opts.ref, ref: opts.ref,
owner: this, owner: this,
context: StepperItemProvider.ctx context: StepperItemProvider.ctx,
props: {
state: () => this.stepState,
orientation: () => this.provider.opts.orientation.current,
current: () => this.isCurrent,
complete: () => this.isComplete,
incomplete: () => this.isIncomplete
},
syncAttrs: true
}); });
// Track count: increment on mount, decrement on unmount // Track count: increment on mount, decrement on unmount
@ -219,12 +231,7 @@ export class StepperItemProvider {
readonly props = $derived.by(() => readonly props = $derived.by(() =>
this.runtimePart.assert({ this.runtimePart.assert({
...this.runtimePart.props, ...this.runtimePart.props
'data-state': this.stepState,
'data-orientation': this.provider.opts.orientation.current,
'data-current': boolToEmptyStrOrUndef(this.isCurrent),
'data-complete': boolToEmptyStrOrUndef(this.isComplete),
'data-incomplete': boolToEmptyStrOrUndef(this.isIncomplete)
} as const) } as const)
); );
} }
@ -351,7 +358,14 @@ export class StepperIndicatorProvider {
this.runtimePart = this.item.provider.runtime.part('indicator', { this.runtimePart = this.item.provider.runtime.part('indicator', {
id: opts.id, id: opts.id,
ref: opts.ref, ref: opts.ref,
owner: this owner: this,
props: {
state: () => this.item.stepState,
current: () => this.item.isCurrent,
complete: () => this.item.isComplete,
incomplete: () => this.item.isIncomplete
},
syncAttrs: true
}); });
} }
@ -360,12 +374,7 @@ export class StepperIndicatorProvider {
readonly props = $derived.by(() => readonly props = $derived.by(() =>
this.runtimePart.assert({ this.runtimePart.assert({
...this.runtimePart.props, ...this.runtimePart.props
'aria-hidden': true as const,
'data-state': this.item.stepState,
'data-current': boolToEmptyStrOrUndef(this.item.isCurrent),
'data-complete': boolToEmptyStrOrUndef(this.item.isComplete),
'data-incomplete': boolToEmptyStrOrUndef(this.item.isIncomplete)
} as const) } as const)
); );
} }
@ -391,19 +400,21 @@ export class StepperSeparatorProvider {
this.runtimePart = this.provider.runtime.part('separator', { this.runtimePart = this.provider.runtime.part('separator', {
id: opts.id, id: opts.id,
ref: opts.ref, ref: opts.ref,
owner: this owner: this,
props: {
state: () => this.item.stepState,
orientation: () => this.provider.opts.orientation.current,
current: () => this.item.isCurrent,
complete: () => this.item.isComplete,
incomplete: () => this.item.isIncomplete
},
syncAttrs: true
}); });
} }
readonly props = $derived.by(() => readonly props = $derived.by(() =>
this.runtimePart.assert({ this.runtimePart.assert({
...this.runtimePart.props, ...this.runtimePart.props
role: 'separator' as const,
'data-state': this.item.stepState,
'data-current': boolToEmptyStrOrUndef(this.item.isCurrent),
'data-complete': boolToEmptyStrOrUndef(this.item.isComplete),
'data-incomplete': boolToEmptyStrOrUndef(this.item.isIncomplete),
'data-orientation': this.provider.opts.orientation.current
} as const) } as const)
); );
} }
@ -432,7 +443,11 @@ export class StepperContentProvider {
this.runtimePart = this.provider.runtime.part('content', { this.runtimePart = this.provider.runtime.part('content', {
id: opts.id, id: opts.id,
ref: opts.ref, ref: opts.ref,
owner: this owner: this,
props: {
state: () => this.stepState
},
syncAttrs: true
}); });
// Content can be inside or outside an Item — use get() not require() // Content can be inside or outside an Item — use get() not require()
const item = StepperItemProvider.get(); const item = StepperItemProvider.get();
@ -446,9 +461,7 @@ export class StepperContentProvider {
readonly props = $derived.by(() => readonly props = $derived.by(() =>
this.runtimePart.assert({ this.runtimePart.assert({
...this.runtimePart.props, ...this.runtimePart.props,
role: 'tabpanel' as const, tabindex: this.isCurrent ? 0 : -1
tabindex: this.isCurrent ? 0 : -1,
'data-state': this.stepState
} as const) } as const)
); );
} }
@ -472,7 +485,11 @@ export class StepperCompletedContentProvider {
this.runtimePart = this.provider.runtime.part('completed-content', { this.runtimePart = this.provider.runtime.part('completed-content', {
id: opts.id, id: opts.id,
ref: opts.ref, ref: opts.ref,
owner: this owner: this,
props: {
state: () => 'completed'
},
syncAttrs: true
}); });
} }
@ -481,8 +498,7 @@ export class StepperCompletedContentProvider {
readonly props = $derived.by(() => readonly props = $derived.by(() =>
this.runtimePart.assert({ this.runtimePart.assert({
...this.runtimePart.props, ...this.runtimePart.props
'data-state': 'completed' as const
} as const) } as const)
); );
} }

Loading…
Cancel
Save

Powered by TurnKey Linux.