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',
optional: false,
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: []
},
@ -49,10 +53,19 @@ export const stepperMorfo = {
optional: false,
states: ['complete', 'current', 'incomplete'],
data: [
{ attr: 'data-state', values: ['complete', 'current', 'incomplete'] },
{ attr: 'data-current', severity: 'optional' },
{ attr: 'data-complete', severity: 'optional' },
{ attr: 'data-incomplete', 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: []
},
@ -109,7 +122,16 @@ export const stepperMorfo = {
defaultElement: 'div',
optional: true,
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') }]
},
{
@ -122,8 +144,19 @@ export const stepperMorfo = {
optional: true,
states: ['complete', 'current', 'incomplete'],
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: []
},
@ -136,7 +169,13 @@ export const stepperMorfo = {
role: 'tabpanel',
optional: true,
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: []
},
{
@ -145,7 +184,7 @@ export const stepperMorfo = {
kind: 'public',
defaultElement: 'div',
optional: true,
data: [],
data: [{ attr: 'data-state', value: v.propRef('state'), emit: 'value' }],
aria: []
},
{

@ -73,12 +73,18 @@ export class StepperProvider {
private constructor(opts: StepperOpts) {
this.opts = opts;
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', {
id: opts.id,
ref: opts.ref,
owner: this,
context: StepperProvider.ctx
context: StepperProvider.ctx,
syncAttrs: true
});
}
@ -125,9 +131,7 @@ export class StepperProvider {
readonly props = $derived.by(() =>
this.runtimePart.assert({
...this.runtimePart.props,
dir: this.opts.dir.current,
'data-orientation': this.opts.orientation.current,
'data-linear': boolToEmptyStrOrUndef(this.opts.linear.current)
dir: this.opts.dir.current
} as const)
);
}
@ -201,7 +205,15 @@ export class StepperItemProvider {
id: opts.id,
ref: opts.ref,
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
@ -219,12 +231,7 @@ export class StepperItemProvider {
readonly props = $derived.by(() =>
this.runtimePart.assert({
...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)
...this.runtimePart.props
} as const)
);
}
@ -351,7 +358,14 @@ export class StepperIndicatorProvider {
this.runtimePart = this.item.provider.runtime.part('indicator', {
id: opts.id,
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(() =>
this.runtimePart.assert({
...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)
...this.runtimePart.props
} as const)
);
}
@ -391,19 +400,21 @@ export class StepperSeparatorProvider {
this.runtimePart = this.provider.runtime.part('separator', {
id: opts.id,
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(() =>
this.runtimePart.assert({
...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
...this.runtimePart.props
} as const)
);
}
@ -432,7 +443,11 @@ export class StepperContentProvider {
this.runtimePart = this.provider.runtime.part('content', {
id: opts.id,
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()
const item = StepperItemProvider.get();
@ -446,9 +461,7 @@ export class StepperContentProvider {
readonly props = $derived.by(() =>
this.runtimePart.assert({
...this.runtimePart.props,
role: 'tabpanel' as const,
tabindex: this.isCurrent ? 0 : -1,
'data-state': this.stepState
tabindex: this.isCurrent ? 0 : -1
} as const)
);
}
@ -472,7 +485,11 @@ export class StepperCompletedContentProvider {
this.runtimePart = this.provider.runtime.part('completed-content', {
id: opts.id,
ref: opts.ref,
owner: this
owner: this,
props: {
state: () => 'completed'
},
syncAttrs: true
});
}
@ -481,8 +498,7 @@ export class StepperCompletedContentProvider {
readonly props = $derived.by(() =>
this.runtimePart.assert({
...this.runtimePart.props,
'data-state': 'completed' as const
...this.runtimePart.props
} as const)
);
}

Loading…
Cancel
Save

Powered by TurnKey Linux.