All Downloads are FREE. Search and download functionalities are using the official Maven repository.

package.dist.index.js Maven / Gradle / Ivy

The newest version!
'use strict';

var anatomy$1 = require('@zag-js/anatomy');
var domEvent = require('@zag-js/dom-event');
var domQuery = require('@zag-js/dom-query');
var formUtils = require('@zag-js/form-utils');
var core = require('@zag-js/core');
var utils = require('@zag-js/utils');
var types = require('@zag-js/types');

// src/rating-group.anatomy.ts
var anatomy = anatomy$1.createAnatomy("rating-group").parts("root", "label", "item", "control");
var parts = anatomy.build();
var dom = domQuery.createScope({
  getRootId: (ctx) => ctx.ids?.root ?? `rating:${ctx.id}`,
  getLabelId: (ctx) => ctx.ids?.label ?? `rating:${ctx.id}:label`,
  getHiddenInputId: (ctx) => ctx.ids?.hiddenInput ?? `rating:${ctx.id}:input`,
  getControlId: (ctx) => ctx.ids?.control ?? `rating:${ctx.id}:control`,
  getItemId: (ctx, id) => ctx.ids?.item?.(id) ?? `rating:${ctx.id}:item:${id}`,
  getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
  getControlEl: (ctx) => dom.getById(ctx, dom.getControlId(ctx)),
  getRadioEl: (ctx, value = ctx.value) => {
    const selector = `[role=radio][aria-posinset='${Math.ceil(value)}']`;
    return domQuery.query(dom.getControlEl(ctx), selector);
  },
  getHiddenInputEl: (ctx) => dom.getById(ctx, dom.getHiddenInputId(ctx)),
  dispatchChangeEvent: (ctx) => {
    const inputEl = dom.getHiddenInputEl(ctx);
    if (!inputEl) return;
    formUtils.dispatchInputValueEvent(inputEl, { value: ctx.value });
  }
});

// src/rating-group.connect.ts
function connect(state, send, normalize) {
  const interactive = state.context.isInteractive;
  const disabled = state.context.isDisabled;
  const readOnly = state.context.readOnly;
  const value = state.context.value;
  const hoveredValue = state.context.hoveredValue;
  const translations = state.context.translations;
  function getItemState(props2) {
    const value2 = state.context.isHovering ? state.context.hoveredValue : state.context.value;
    const equal = Math.ceil(value2) === props2.index;
    const highlighted = props2.index <= value2 || equal;
    const half = equal && Math.abs(value2 - props2.index) === 0.5;
    return {
      highlighted,
      half,
      checked: equal || state.context.value === -1 && props2.index === 1
    };
  }
  return {
    hovering: state.context.isHovering,
    value,
    hoveredValue,
    count: state.context.count,
    items: Array.from({ length: state.context.count }).map((_, index) => index + 1),
    setValue(value2) {
      send({ type: "SET_VALUE", value: value2 });
    },
    clearValue() {
      send("CLEAR_VALUE");
    },
    getRootProps() {
      return normalize.element({
        ...parts.root.attrs,
        dir: state.context.dir,
        id: dom.getRootId(state.context)
      });
    },
    getHiddenInputProps() {
      return normalize.input({
        name: state.context.name,
        form: state.context.form,
        type: "text",
        hidden: true,
        disabled,
        readOnly,
        required: state.context.required,
        id: dom.getHiddenInputId(state.context),
        defaultValue: state.context.value
      });
    },
    getLabelProps() {
      return normalize.label({
        ...parts.label.attrs,
        dir: state.context.dir,
        id: dom.getLabelId(state.context),
        "data-disabled": domQuery.dataAttr(disabled),
        htmlFor: dom.getHiddenInputId(state.context),
        onClick(event) {
          if (event.defaultPrevented) return;
          if (!interactive) return;
          event.preventDefault();
          const radioEl = dom.getRadioEl(state.context, 1);
          radioEl?.focus({ preventScroll: true });
        }
      });
    },
    getControlProps() {
      return normalize.element({
        id: dom.getControlId(state.context),
        ...parts.control.attrs,
        dir: state.context.dir,
        role: "radiogroup",
        "aria-orientation": "horizontal",
        "aria-labelledby": dom.getLabelId(state.context),
        "aria-readonly": domQuery.ariaAttr(readOnly),
        "data-readonly": domQuery.dataAttr(readOnly),
        "data-disabled": domQuery.dataAttr(disabled),
        onPointerMove(event) {
          if (!interactive) return;
          if (event.pointerType === "touch") return;
          send("GROUP_POINTER_OVER");
        },
        onPointerLeave(event) {
          if (!interactive) return;
          if (event.pointerType === "touch") return;
          send("GROUP_POINTER_LEAVE");
        }
      });
    },
    getItemState,
    getItemProps(props2) {
      const { index } = props2;
      const itemState = getItemState(props2);
      const valueText = translations.ratingValueText(index);
      return normalize.element({
        ...parts.item.attrs,
        dir: state.context.dir,
        id: dom.getItemId(state.context, index.toString()),
        role: "radio",
        tabIndex: (() => {
          if (readOnly) return itemState.checked ? 0 : void 0;
          if (disabled) return void 0;
          return itemState.checked ? 0 : -1;
        })(),
        "aria-roledescription": "rating",
        "aria-label": valueText,
        "aria-disabled": disabled,
        "data-disabled": domQuery.dataAttr(disabled),
        "data-readonly": domQuery.dataAttr(readOnly),
        "aria-setsize": state.context.count,
        "aria-checked": itemState.checked,
        "data-checked": domQuery.dataAttr(itemState.checked),
        "aria-posinset": index,
        "data-highlighted": domQuery.dataAttr(itemState.highlighted),
        "data-half": domQuery.dataAttr(itemState.half),
        onPointerDown(event) {
          if (!interactive) return;
          if (!domEvent.isLeftClick(event)) return;
          event.preventDefault();
        },
        onPointerMove(event) {
          if (!interactive) return;
          const point = domEvent.getEventPoint(event);
          const relativePoint = domEvent.getRelativePoint(point, event.currentTarget);
          const percentX = relativePoint.getPercentValue({
            orientation: "horizontal",
            dir: state.context.dir
          });
          const isMidway = percentX < 0.5;
          send({ type: "POINTER_OVER", index, isMidway });
        },
        onKeyDown(event) {
          if (event.defaultPrevented) return;
          if (!interactive) return;
          const keyMap = {
            ArrowLeft() {
              send("ARROW_LEFT");
            },
            ArrowRight() {
              send("ARROW_RIGHT");
            },
            ArrowUp() {
              send("ARROW_LEFT");
            },
            ArrowDown() {
              send("ARROW_RIGHT");
            },
            Space() {
              send({ type: "SPACE", value: index });
            },
            Home() {
              send("HOME");
            },
            End() {
              send("END");
            }
          };
          const key = domEvent.getEventKey(event, state.context);
          const exec = keyMap[key];
          if (exec) {
            event.preventDefault();
            exec(event);
          }
        },
        onClick() {
          if (!interactive) return;
          send({ type: "CLICK", value: index });
        },
        onFocus() {
          if (!interactive) return;
          send("FOCUS");
        },
        onBlur() {
          if (!interactive) return;
          send("BLUR");
        }
      });
    }
  };
}
function machine(userContext) {
  const ctx = utils.compact(userContext);
  return core.createMachine(
    {
      id: "rating",
      initial: "idle",
      context: {
        name: "rating",
        count: 5,
        dir: "ltr",
        value: -1,
        readOnly: false,
        disabled: false,
        ...ctx,
        hoveredValue: -1,
        fieldsetDisabled: false,
        translations: {
          ratingValueText: (index) => `${index} stars`,
          ...ctx.translations
        }
      },
      created: ["roundValueIfNeeded"],
      watch: {
        allowHalf: ["roundValueIfNeeded"]
      },
      computed: {
        isDisabled: (ctx2) => !!ctx2.disabled || ctx2.fieldsetDisabled,
        isInteractive: (ctx2) => !(ctx2.isDisabled || ctx2.readOnly),
        isHovering: (ctx2) => ctx2.hoveredValue > -1
      },
      activities: ["trackFormControlState"],
      on: {
        SET_VALUE: {
          actions: ["setValue"]
        },
        CLEAR_VALUE: {
          actions: ["clearValue"]
        }
      },
      states: {
        idle: {
          entry: "clearHoveredValue",
          on: {
            GROUP_POINTER_OVER: "hover",
            FOCUS: "focus",
            CLICK: {
              actions: ["setValue", "focusActiveRadio"]
            }
          }
        },
        focus: {
          on: {
            POINTER_OVER: {
              actions: "setHoveredValue"
            },
            GROUP_POINTER_LEAVE: {
              actions: "clearHoveredValue"
            },
            BLUR: "idle",
            SPACE: {
              guard: "isValueEmpty",
              actions: ["setValue"]
            },
            CLICK: {
              actions: ["setValue", "focusActiveRadio"]
            },
            ARROW_LEFT: {
              actions: ["setPrevValue", "focusActiveRadio"]
            },
            ARROW_RIGHT: {
              actions: ["setNextValue", "focusActiveRadio"]
            },
            HOME: {
              actions: ["setValueToMin", "focusActiveRadio"]
            },
            END: {
              actions: ["setValueToMax", "focusActiveRadio"]
            }
          }
        },
        hover: {
          on: {
            POINTER_OVER: {
              actions: "setHoveredValue"
            },
            GROUP_POINTER_LEAVE: [
              {
                guard: "isRadioFocused",
                target: "focus",
                actions: "clearHoveredValue"
              },
              {
                target: "idle",
                actions: "clearHoveredValue"
              }
            ],
            CLICK: {
              actions: ["setValue", "focusActiveRadio"]
            }
          }
        }
      }
    },
    {
      guards: {
        isInteractive: (ctx2) => !(ctx2.disabled || ctx2.readOnly),
        isHoveredValueEmpty: (ctx2) => ctx2.hoveredValue === -1,
        isValueEmpty: (ctx2) => ctx2.value <= 0,
        isRadioFocused: (ctx2) => !!dom.getControlEl(ctx2)?.contains(dom.getActiveElement(ctx2))
      },
      activities: {
        trackFormControlState(ctx2, _evt, { initialContext }) {
          return formUtils.trackFormControl(dom.getHiddenInputEl(ctx2), {
            onFieldsetDisabledChange(disabled) {
              ctx2.fieldsetDisabled = disabled;
            },
            onFormReset() {
              set.value(ctx2, initialContext.value);
            }
          });
        }
      },
      actions: {
        clearHoveredValue(ctx2) {
          set.hoveredValue(ctx2, -1);
        },
        focusActiveRadio(ctx2) {
          domQuery.raf(() => dom.getRadioEl(ctx2)?.focus());
        },
        setPrevValue(ctx2) {
          const factor = ctx2.allowHalf ? 0.5 : 1;
          set.value(ctx2, Math.max(0, ctx2.value - factor));
        },
        setNextValue(ctx2) {
          const factor = ctx2.allowHalf ? 0.5 : 1;
          const value = ctx2.value === -1 ? 0 : ctx2.value;
          set.value(ctx2, Math.min(ctx2.count, value + factor));
        },
        setValueToMin(ctx2) {
          set.value(ctx2, 1);
        },
        setValueToMax(ctx2) {
          set.value(ctx2, ctx2.count);
        },
        setValue(ctx2, evt) {
          const value = ctx2.hoveredValue === -1 ? evt.value : ctx2.hoveredValue;
          set.value(ctx2, value);
        },
        clearValue(ctx2) {
          set.value(ctx2, -1);
        },
        setHoveredValue(ctx2, evt) {
          const half = ctx2.allowHalf && evt.isMidway;
          const factor = half ? 0.5 : 0;
          set.hoveredValue(ctx2, evt.index - factor);
        },
        roundValueIfNeeded(ctx2) {
          if (ctx2.allowHalf) return;
          ctx2.value = Math.round(ctx2.value);
        }
      }
    }
  );
}
var invoke = {
  change: (ctx) => {
    ctx.onValueChange?.({ value: ctx.value });
    dom.dispatchChangeEvent(ctx);
  },
  hoverChange: (ctx) => {
    ctx.onHoverChange?.({ hoveredValue: ctx.hoveredValue });
  }
};
var set = {
  value: (ctx, value) => {
    if (utils.isEqual(ctx.value, value)) return;
    ctx.value = value;
    invoke.change(ctx);
  },
  hoveredValue: (ctx, value) => {
    if (utils.isEqual(ctx.hoveredValue, value)) return;
    ctx.hoveredValue = value;
    invoke.hoverChange(ctx);
  }
};
var props = types.createProps()([
  "allowHalf",
  "autoFocus",
  "count",
  "dir",
  "disabled",
  "form",
  "getRootNode",
  "id",
  "ids",
  "name",
  "onHoverChange",
  "onValueChange",
  "required",
  "readOnly",
  "translations",
  "value"
]);
var splitProps = utils.createSplitProps(props);
var itemProps = types.createProps()(["index"]);
var splitItemProps = utils.createSplitProps(itemProps);

exports.anatomy = anatomy;
exports.connect = connect;
exports.itemProps = itemProps;
exports.machine = machine;
exports.props = props;
exports.splitItemProps = splitItemProps;
exports.splitProps = splitProps;




© 2015 - 2025 Weber Informatics LLC | Privacy Policy