|
|
|
@ -7,7 +7,7 @@ import { Soma } from '../../core/soma.svelte';
|
|
|
|
import { STEPPER_LANGS } from './langs';
|
|
|
|
import { STEPPER_LANGS } from './langs';
|
|
|
|
|
|
|
|
|
|
|
|
import { stepperMorfo } from '../../../morfo/components/stepper';
|
|
|
|
import { stepperMorfo } from '../../../morfo/components/stepper';
|
|
|
|
import type { SomaRuntimePart } from '../../runtime.svelte';
|
|
|
|
import type { SomaRuntime, SomaRuntimePart } from '../../runtime.svelte';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export type StepState = 'complete' | 'current' | 'incomplete';
|
|
|
|
export type StepState = 'complete' | 'current' | 'incomplete';
|
|
|
|
@ -27,6 +27,8 @@ interface StepperOpts
|
|
|
|
export class StepperProvider {
|
|
|
|
export class StepperProvider {
|
|
|
|
readonly opts: StepperOpts;
|
|
|
|
readonly opts: StepperOpts;
|
|
|
|
readonly runtimePart: SomaRuntimePart;
|
|
|
|
readonly runtimePart: SomaRuntimePart;
|
|
|
|
|
|
|
|
readonly soma: Soma;
|
|
|
|
|
|
|
|
readonly runtime: SomaRuntime;
|
|
|
|
static readonly ctx = context<StepperProvider>('Stepper');
|
|
|
|
static readonly ctx = context<StepperProvider>('Stepper');
|
|
|
|
static get(): StepperProvider | undefined {
|
|
|
|
static get(): StepperProvider | undefined {
|
|
|
|
return this.ctx.getOr(undefined) as StepperProvider | undefined;
|
|
|
|
return this.ctx.getOr(undefined) as StepperProvider | undefined;
|
|
|
|
@ -39,7 +41,6 @@ export class StepperProvider {
|
|
|
|
return new StepperProvider(opts);
|
|
|
|
return new StepperProvider(opts);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
readonly soma = Soma.get();
|
|
|
|
|
|
|
|
private _count = $state(0);
|
|
|
|
private _count = $state(0);
|
|
|
|
get count(): number {
|
|
|
|
get count(): number {
|
|
|
|
return this._count;
|
|
|
|
return this._count;
|
|
|
|
@ -72,9 +73,14 @@ export class StepperProvider {
|
|
|
|
|
|
|
|
|
|
|
|
private constructor(opts: StepperOpts) {
|
|
|
|
private constructor(opts: StepperOpts) {
|
|
|
|
this.opts = opts;
|
|
|
|
this.opts = opts;
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
this.soma = Soma.require();
|
|
|
|
.runtime(stepperMorfo, {})
|
|
|
|
this.runtime = this.soma.runtime(stepperMorfo, {});
|
|
|
|
.part('provider', { id: opts.id, ref: opts.ref, owner: this, context: StepperProvider.ctx });
|
|
|
|
this.runtimePart = this.runtime.part('provider', {
|
|
|
|
|
|
|
|
id: opts.id,
|
|
|
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
|
|
|
owner: this,
|
|
|
|
|
|
|
|
context: StepperProvider.ctx
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
get step(): number {
|
|
|
|
get step(): number {
|
|
|
|
@ -142,17 +148,19 @@ export class StepperListProvider {
|
|
|
|
|
|
|
|
|
|
|
|
private constructor(opts: StepperListOpts) {
|
|
|
|
private constructor(opts: StepperListOpts) {
|
|
|
|
this.opts = opts;
|
|
|
|
this.opts = opts;
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
|
|
|
.runtime(stepperMorfo, {})
|
|
|
|
|
|
|
|
.part('list', { id: opts.id, ref: opts.ref, owner: this });
|
|
|
|
|
|
|
|
this.provider = StepperProvider.require();
|
|
|
|
this.provider = StepperProvider.require();
|
|
|
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('list', {
|
|
|
|
|
|
|
|
id: opts.id,
|
|
|
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
|
|
|
owner: this
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
readonly props = $derived.by(() =>
|
|
|
|
readonly props = $derived.by(() =>
|
|
|
|
this.runtimePart.assert({
|
|
|
|
this.runtimePart.assert({
|
|
|
|
...this.runtimePart.props,
|
|
|
|
...this.runtimePart.props,
|
|
|
|
role: 'tablist' as const,
|
|
|
|
role: 'tablist' as const,
|
|
|
|
'aria-label': this.opts.ariaLabel.current || this.provider.soma?.langs.ts(STEPPER_LANGS.LIST),
|
|
|
|
'aria-label': this.opts.ariaLabel.current || this.provider.soma.langs.ts(STEPPER_LANGS.LIST),
|
|
|
|
'aria-orientation': this.provider.opts.orientation.current,
|
|
|
|
'aria-orientation': this.provider.opts.orientation.current,
|
|
|
|
'data-orientation': this.provider.opts.orientation.current
|
|
|
|
'data-orientation': this.provider.opts.orientation.current
|
|
|
|
} as const)
|
|
|
|
} as const)
|
|
|
|
@ -189,10 +197,13 @@ export class StepperItemProvider {
|
|
|
|
|
|
|
|
|
|
|
|
private constructor(opts: StepperItemOpts) {
|
|
|
|
private constructor(opts: StepperItemOpts) {
|
|
|
|
this.opts = opts;
|
|
|
|
this.opts = opts;
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
|
|
|
.runtime(stepperMorfo, {})
|
|
|
|
|
|
|
|
.part('item', { id: opts.id, ref: opts.ref, owner: this, context: StepperItemProvider.ctx });
|
|
|
|
|
|
|
|
this.provider = StepperProvider.require();
|
|
|
|
this.provider = StepperProvider.require();
|
|
|
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('item', {
|
|
|
|
|
|
|
|
id: opts.id,
|
|
|
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
|
|
|
owner: this,
|
|
|
|
|
|
|
|
context: StepperItemProvider.ctx
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Track count: increment on mount, decrement on unmount
|
|
|
|
// Track count: increment on mount, decrement on unmount
|
|
|
|
this.provider.incrementCount();
|
|
|
|
this.provider.incrementCount();
|
|
|
|
@ -240,11 +251,13 @@ export class StepperTriggerProvider {
|
|
|
|
|
|
|
|
|
|
|
|
private constructor(opts: StepperTriggerOpts) {
|
|
|
|
private constructor(opts: StepperTriggerOpts) {
|
|
|
|
this.opts = opts;
|
|
|
|
this.opts = opts;
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
|
|
|
.runtime(stepperMorfo, {})
|
|
|
|
|
|
|
|
.part('trigger', { id: opts.id, ref: opts.ref, owner: this });
|
|
|
|
|
|
|
|
this.provider = StepperProvider.require();
|
|
|
|
this.provider = StepperProvider.require();
|
|
|
|
this.item = StepperItemProvider.require();
|
|
|
|
this.item = StepperItemProvider.require();
|
|
|
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('trigger', {
|
|
|
|
|
|
|
|
id: opts.id,
|
|
|
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
|
|
|
owner: this
|
|
|
|
|
|
|
|
});
|
|
|
|
this.item.triggerId.current = opts.id.current;
|
|
|
|
this.item.triggerId.current = opts.id.current;
|
|
|
|
|
|
|
|
|
|
|
|
// Register in trigger registry for keyboard nav
|
|
|
|
// Register in trigger registry for keyboard nav
|
|
|
|
@ -335,10 +348,12 @@ export class StepperIndicatorProvider {
|
|
|
|
|
|
|
|
|
|
|
|
private constructor(opts: StepperIndicatorOpts) {
|
|
|
|
private constructor(opts: StepperIndicatorOpts) {
|
|
|
|
this.opts = opts;
|
|
|
|
this.opts = opts;
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
|
|
|
.runtime(stepperMorfo, {})
|
|
|
|
|
|
|
|
.part('indicator', { id: opts.id, ref: opts.ref, owner: this });
|
|
|
|
|
|
|
|
this.item = StepperItemProvider.require();
|
|
|
|
this.item = StepperItemProvider.require();
|
|
|
|
|
|
|
|
this.runtimePart = this.item.provider.runtime.part('indicator', {
|
|
|
|
|
|
|
|
id: opts.id,
|
|
|
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
|
|
|
owner: this
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Proxy to `item.stepState` so the wrapper snippet doesn't need `ctx.get()`. */
|
|
|
|
/** Proxy to `item.stepState` so the wrapper snippet doesn't need `ctx.get()`. */
|
|
|
|
@ -372,11 +387,13 @@ export class StepperSeparatorProvider {
|
|
|
|
|
|
|
|
|
|
|
|
private constructor(opts: StepperSeparatorOpts) {
|
|
|
|
private constructor(opts: StepperSeparatorOpts) {
|
|
|
|
this.opts = opts;
|
|
|
|
this.opts = opts;
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
|
|
|
.runtime(stepperMorfo, {})
|
|
|
|
|
|
|
|
.part('separator', { id: opts.id, ref: opts.ref, owner: this });
|
|
|
|
|
|
|
|
this.item = StepperItemProvider.require();
|
|
|
|
this.item = StepperItemProvider.require();
|
|
|
|
this.provider = StepperProvider.require();
|
|
|
|
this.provider = this.item.provider;
|
|
|
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('separator', {
|
|
|
|
|
|
|
|
id: opts.id,
|
|
|
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
|
|
|
owner: this
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
readonly props = $derived.by(() =>
|
|
|
|
readonly props = $derived.by(() =>
|
|
|
|
@ -412,10 +429,12 @@ export class StepperContentProvider {
|
|
|
|
|
|
|
|
|
|
|
|
private constructor(opts: StepperContentOpts) {
|
|
|
|
private constructor(opts: StepperContentOpts) {
|
|
|
|
this.opts = opts;
|
|
|
|
this.opts = opts;
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
|
|
|
.runtime(stepperMorfo, {})
|
|
|
|
|
|
|
|
.part('content', { id: opts.id, ref: opts.ref, owner: this });
|
|
|
|
|
|
|
|
this.provider = StepperProvider.require();
|
|
|
|
this.provider = StepperProvider.require();
|
|
|
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('content', {
|
|
|
|
|
|
|
|
id: opts.id,
|
|
|
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
|
|
|
owner: this
|
|
|
|
|
|
|
|
});
|
|
|
|
// 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();
|
|
|
|
if (item) item.contentId.current = opts.id.current;
|
|
|
|
if (item) item.contentId.current = opts.id.current;
|
|
|
|
@ -450,10 +469,12 @@ export class StepperCompletedContentProvider {
|
|
|
|
|
|
|
|
|
|
|
|
private constructor(opts: StepperCompletedContentOpts) {
|
|
|
|
private constructor(opts: StepperCompletedContentOpts) {
|
|
|
|
this.opts = opts;
|
|
|
|
this.opts = opts;
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
|
|
|
.runtime(stepperMorfo, {})
|
|
|
|
|
|
|
|
.part('completed-content', { id: opts.id, ref: opts.ref, owner: this });
|
|
|
|
|
|
|
|
this.provider = StepperProvider.require();
|
|
|
|
this.provider = StepperProvider.require();
|
|
|
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('completed-content', {
|
|
|
|
|
|
|
|
id: opts.id,
|
|
|
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
|
|
|
owner: this
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Proxy to `provider.isCompleted` so the wrapper doesn't need `ctx.get()`. */
|
|
|
|
/** Proxy to `provider.isCompleted` so the wrapper doesn't need `ctx.get()`. */
|
|
|
|
@ -487,10 +508,12 @@ export class StepperPrevTriggerProvider {
|
|
|
|
|
|
|
|
|
|
|
|
private constructor(opts: StepperPrevTriggerOpts) {
|
|
|
|
private constructor(opts: StepperPrevTriggerOpts) {
|
|
|
|
this.opts = opts;
|
|
|
|
this.opts = opts;
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
|
|
|
.runtime(stepperMorfo, {})
|
|
|
|
|
|
|
|
.part('prev-trigger', { id: opts.id, ref: opts.ref, owner: this });
|
|
|
|
|
|
|
|
this.provider = StepperProvider.require();
|
|
|
|
this.provider = StepperProvider.require();
|
|
|
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('prev-trigger', {
|
|
|
|
|
|
|
|
id: opts.id,
|
|
|
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
|
|
|
owner: this
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
readonly isDisabled = $derived.by(() => this.opts.disabled.current || !this.provider.hasPrevStep);
|
|
|
|
readonly isDisabled = $derived.by(() => this.opts.disabled.current || !this.provider.hasPrevStep);
|
|
|
|
@ -531,10 +554,12 @@ export class StepperNextTriggerProvider {
|
|
|
|
|
|
|
|
|
|
|
|
private constructor(opts: StepperNextTriggerOpts) {
|
|
|
|
private constructor(opts: StepperNextTriggerOpts) {
|
|
|
|
this.opts = opts;
|
|
|
|
this.opts = opts;
|
|
|
|
this.runtimePart = Soma.require()
|
|
|
|
|
|
|
|
.runtime(stepperMorfo, {})
|
|
|
|
|
|
|
|
.part('next-trigger', { id: opts.id, ref: opts.ref, owner: this });
|
|
|
|
|
|
|
|
this.provider = StepperProvider.require();
|
|
|
|
this.provider = StepperProvider.require();
|
|
|
|
|
|
|
|
this.runtimePart = this.provider.runtime.part('next-trigger', {
|
|
|
|
|
|
|
|
id: opts.id,
|
|
|
|
|
|
|
|
ref: opts.ref,
|
|
|
|
|
|
|
|
owner: this
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
readonly isDisabled = $derived.by(() => this.opts.disabled.current || !this.provider.hasNextStep);
|
|
|
|
readonly isDisabled = $derived.by(() => this.opts.disabled.current || !this.provider.hasNextStep);
|
|
|
|
|