
package.dist.index.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of steps Show documentation
Show all versions of steps Show documentation
Core logic for the steps widget implemented as a state machine
The newest version!
'use strict';
var anatomy$1 = require('@zag-js/anatomy');
var domQuery = require('@zag-js/dom-query');
var utils = require('@zag-js/utils');
var core = require('@zag-js/core');
var types = require('@zag-js/types');
// src/steps.anatomy.ts
var anatomy = anatomy$1.createAnatomy("steps").parts(
"root",
"list",
"item",
"trigger",
"indicator",
"separator",
"content",
"nextTrigger",
"prevTrigger",
"progress"
);
var parts = anatomy.build();
var dom = domQuery.createScope({
getRootId: (ctx) => ctx.ids?.root ?? `steps:${ctx.id}`,
getListId: (ctx) => ctx.ids?.list ?? `steps:${ctx.id}:list`,
getTriggerId: (ctx, index) => ctx.ids?.triggerId?.(index) ?? `steps:${ctx.id}:trigger:${index}`,
getContentId: (ctx, index) => ctx.ids?.contentId?.(index) ?? `steps:${ctx.id}:content:${index}`
});
// src/steps.connect.ts
function connect(state, send, normalize) {
const step = state.context.step;
const count = state.context.count;
const percent = state.context.percent;
const hasNextStep = state.context.hasNextStep;
const hasPrevStep = state.context.hasPrevStep;
const getItemState = (props2) => ({
triggerId: dom.getTriggerId(state.context, props2.index),
contentId: dom.getContentId(state.context, props2.index),
current: props2.index === step,
completed: props2.index < step,
incomplete: props2.index > step,
index: props2.index,
first: props2.index === 0,
last: props2.index === count - 1
});
const goToNextStep = () => {
send({ type: "STEP.NEXT", src: "next.trigger.click" });
};
const goToPrevStep = () => {
send({ type: "STEP.PREV", src: "prev.trigger.click" });
};
const resetStep = () => {
send({ type: "STEP.RESET", src: "reset.trigger.click" });
};
const setStep = (value) => {
send({ type: "STEP.SET", value, src: "api.setValue" });
};
return {
value: step,
count,
percent,
hasNextStep,
hasPrevStep,
goToNextStep,
goToPrevStep,
resetStep,
getItemState,
setStep,
getRootProps() {
return normalize.element({
...parts.root.attrs,
id: dom.getRootId(state.context),
dir: state.context.dir,
"data-orientation": state.context.orientation,
style: {
"--percent": `${percent}%`
}
});
},
getListProps() {
const arr = utils.fromLength(state.context.count);
const triggerIds = arr.map((_, index) => dom.getTriggerId(state.context, index));
return normalize.element({
...parts.list.attrs,
dir: state.context.dir,
id: dom.getListId(state.context),
role: "tablist",
"aria-owns": triggerIds.join(" "),
"aria-orientation": state.context.orientation,
"data-orientation": state.context.orientation
});
},
getItemProps(props2) {
const itemState = getItemState(props2);
return normalize.element({
...parts.item.attrs,
dir: state.context.dir,
"aria-current": itemState.current ? "step" : void 0,
"data-orientation": state.context.orientation
});
},
getTriggerProps(props2) {
const itemState = getItemState(props2);
return normalize.button({
...parts.trigger.attrs,
id: itemState.triggerId,
role: "tab",
dir: state.context.dir,
tabIndex: !state.context.linear || itemState.current ? 0 : -1,
"aria-selected": itemState.current,
"aria-controls": itemState.contentId,
"data-state": itemState.current ? "open" : "closed",
"data-orientation": state.context.orientation,
"data-complete": domQuery.dataAttr(itemState.completed),
"data-current": domQuery.dataAttr(itemState.current),
"data-incomplete": domQuery.dataAttr(itemState.incomplete),
onClick(event) {
if (event.defaultPrevented) return;
if (state.context.linear) return;
send({ type: "STEP.SET", value: props2.index, src: "trigger.click" });
}
});
},
getContentProps(props2) {
const itemState = getItemState(props2);
return normalize.element({
...parts.content.attrs,
dir: state.context.dir,
id: itemState.contentId,
role: "tabpanel",
tabIndex: 0,
hidden: !itemState.current,
"data-state": itemState.current ? "open" : "closed",
"data-orientation": state.context.orientation,
"aria-labelledby": itemState.triggerId
});
},
getIndicatorProps(props2) {
const itemState = getItemState(props2);
return normalize.element({
...parts.indicator.attrs,
dir: state.context.dir,
"aria-hidden": true,
"data-complete": domQuery.dataAttr(itemState.completed),
"data-current": domQuery.dataAttr(itemState.current),
"data-incomplete": domQuery.dataAttr(itemState.incomplete)
});
},
getSeparatorProps(props2) {
const itemState = getItemState(props2);
return normalize.element({
...parts.separator.attrs,
dir: state.context.dir,
"data-orientation": state.context.orientation,
"data-complete": domQuery.dataAttr(itemState.completed),
"data-current": domQuery.dataAttr(itemState.current),
"data-incomplete": domQuery.dataAttr(itemState.incomplete)
});
},
getNextTriggerProps() {
return normalize.button({
...parts.nextTrigger.attrs,
dir: state.context.dir,
type: "button",
disabled: !hasNextStep,
onClick(event) {
if (event.defaultPrevented) return;
goToNextStep();
}
});
},
getPrevTriggerProps() {
return normalize.button({
dir: state.context.dir,
...parts.prevTrigger.attrs,
type: "button",
disabled: !hasPrevStep,
onClick(event) {
if (event.defaultPrevented) return;
goToPrevStep();
}
});
},
getProgressProps() {
return normalize.element({
dir: state.context.dir,
...parts.progress.attrs,
role: "progressbar",
"aria-valuenow": percent,
"aria-valuemin": 0,
"aria-valuemax": 100,
"aria-valuetext": `${percent}% complete`,
"data-complete": domQuery.dataAttr(percent === 100)
});
}
};
}
function machine(userContext) {
const ctx = utils.compact(userContext);
return core.createMachine(
{
id: "steps",
initial: "idle",
context: {
step: 0,
count: 1,
linear: false,
orientation: "horizontal",
...ctx
},
computed: {
percent: (ctx2) => ctx2.step / ctx2.count * 100,
hasNextStep: (ctx2) => ctx2.step < ctx2.count,
hasPrevStep: (ctx2) => ctx2.step > 0
},
states: {
idle: {
on: {
"STEP.SET": {
actions: "setStep"
},
"STEP.NEXT": {
actions: "goToNextStep"
},
"STEP.PREV": {
actions: "goToPrevStep"
},
"STEP.RESET": {
actions: "resetStep"
}
}
}
}
},
{
actions: {
goToNextStep(ctx2) {
const value = Math.min(ctx2.step + 1, ctx2.count);
set.value(ctx2, value);
},
goToPrevStep(ctx2) {
const value = Math.max(ctx2.step - 1, 0);
set.value(ctx2, value);
},
resetStep(ctx2) {
set.value(ctx2, 0);
},
setStep(ctx2, event) {
const value = event.value;
const inRange = value >= 0 && value < ctx2.count;
if (!inRange) throw new RangeError(`Index ${value} is out of bounds`);
set.value(ctx2, value);
}
}
}
);
}
var set = {
value(ctx, step) {
if (utils.isEqual(ctx.step, step)) return;
ctx.step = step;
ctx.onStepChange?.({ step });
}
};
var props = types.createProps()([
"count",
"dir",
"getRootNode",
"id",
"ids",
"linear",
"onStepChange",
"onStepComplete",
"orientation",
"step"
]);
var splitProps = utils.createSplitProps(props);
exports.anatomy = anatomy;
exports.connect = connect;
exports.machine = machine;
exports.props = props;
exports.splitProps = splitProps;
© 2015 - 2025 Weber Informatics LLC | Privacy Policy