diff --git a/.changeset/new-moons-double.md b/.changeset/new-moons-double.md new file mode 100644 index 0000000000..d6bb77f2d2 --- /dev/null +++ b/.changeset/new-moons-double.md @@ -0,0 +1,28 @@ +--- +"@zag-js/color-picker": patch +"@zag-js/number-input": patch +"@zag-js/date-picker": patch +"@zag-js/file-upload": patch +"@zag-js/radio-group": patch +"@zag-js/hover-card": patch +"@zag-js/pagination": patch +"@zag-js/tags-input": patch +"@zag-js/accordion": patch +"@zag-js/pin-input": patch +"@zag-js/carousel": patch +"@zag-js/checkbox": patch +"@zag-js/editable": patch +"@zag-js/splitter": patch +"@zag-js/popover": patch +"@zag-js/tooltip": patch +"@zag-js/avatar": patch +"@zag-js/dialog": patch +"@zag-js/select": patch +"@zag-js/slider": patch +"@zag-js/switch": patch +"@zag-js/toast": patch +"@zag-js/menu": patch +"@zag-js/tabs": patch +--- + +Fix issue where `dir` attribute was not applied to all element parts diff --git a/packages/machines/accordion/src/accordion.connect.ts b/packages/machines/accordion/src/accordion.connect.ts index 58a7544a66..3ccf75d212 100644 --- a/packages/machines/accordion/src/accordion.connect.ts +++ b/packages/machines/accordion/src/accordion.connect.ts @@ -34,6 +34,7 @@ export function connect(state: State, send: Send, normalize rootProps: normalize.element({ ...parts.root.attrs, + dir: state.context.dir, id: dom.getRootId(state.context), "data-orientation": state.context.orientation, }), @@ -71,6 +72,7 @@ export function connect(state: State, send: Send, normalize const itemState = getItemState(props) return normalize.element({ ...parts.itemIndicator.attrs, + dir: state.context.dir, "aria-hidden": true, "data-state": itemState.isOpen ? "open" : "closed", "data-disabled": dataAttr(itemState.isDisabled), @@ -86,6 +88,7 @@ export function connect(state: State, send: Send, normalize return normalize.button({ ...parts.itemTrigger.attrs, type: "button", + dir: state.context.dir, id: dom.getItemTriggerId(state.context, value), "aria-controls": dom.getItemContentId(state.context, value), "aria-expanded": itemState.isOpen, diff --git a/packages/machines/avatar/src/avatar.connect.ts b/packages/machines/avatar/src/avatar.connect.ts index be03419e7f..e0d4971cdb 100644 --- a/packages/machines/avatar/src/avatar.connect.ts +++ b/packages/machines/avatar/src/avatar.connect.ts @@ -24,6 +24,7 @@ export function connect(state: State, send: Send, normalize rootProps: normalize.element({ ...parts.root.attrs, + dir: state.context.dir, id: dom.getRootId(state.context), style: { display: "grid", @@ -34,6 +35,7 @@ export function connect(state: State, send: Send, normalize imageProps: normalize.img({ ...parts.image.attrs, + dir: state.context.dir, id: dom.getImageId(state.context), "data-state": isLoaded ? "visible" : "hidden", onLoad() { @@ -50,6 +52,7 @@ export function connect(state: State, send: Send, normalize fallbackProps: normalize.element({ ...parts.fallback.attrs, + dir: state.context.dir, id: dom.getFallbackId(state.context), hidden: !showFallback, "data-state": isLoaded ? "hidden" : "visible", diff --git a/packages/machines/avatar/src/avatar.types.ts b/packages/machines/avatar/src/avatar.types.ts index 70140a7fcd..78cf12504f 100644 --- a/packages/machines/avatar/src/avatar.types.ts +++ b/packages/machines/avatar/src/avatar.types.ts @@ -1,5 +1,5 @@ import type { StateMachine as S } from "@zag-js/core" -import type { CommonProperties, Context, PropTypes, RequiredBy } from "@zag-js/types" +import type { CommonProperties, Context, DirectionProperty, PropTypes, RequiredBy } from "@zag-js/types" /* ----------------------------------------------------------------------------- * Callback details @@ -13,7 +13,7 @@ export interface StatusChangeDetails { * Machine context * -----------------------------------------------------------------------------*/ -interface PublicContext extends CommonProperties { +interface PublicContext extends CommonProperties, DirectionProperty { /** * Functional called when the image loading status changes. */ diff --git a/packages/machines/carousel/src/carousel.connect.ts b/packages/machines/carousel/src/carousel.connect.ts index 13ef665e7b..e623362c6e 100644 --- a/packages/machines/carousel/src/carousel.connect.ts +++ b/packages/machines/carousel/src/carousel.connect.ts @@ -100,13 +100,13 @@ export function connect(state: State, send: Send, normalize return normalize.element({ ...parts.item.attrs, id: dom.getItemId(state.context, index), + dir: state.context.dir, "data-current": dataAttr(sliderState.isCurrent), "data-inview": dataAttr(sliderState.isInView), role: "group", "aria-roledescription": "slide", "data-orientation": state.context.orientation, "aria-label": sliderState.valueText, - dir: state.context.dir, style: { position: "relative", flex: "0 0 var(--slide-size)", diff --git a/packages/machines/checkbox/src/checkbox.connect.ts b/packages/machines/checkbox/src/checkbox.connect.ts index 78dc88b180..03ce12fbd8 100644 --- a/packages/machines/checkbox/src/checkbox.connect.ts +++ b/packages/machines/checkbox/src/checkbox.connect.ts @@ -87,6 +87,7 @@ export function connect(state: State, send: Send, normalize indicatorProps: normalize.element({ ...parts.indicator.attrs, ...dataAttrs, + dir: state.context.dir, hidden: !isIndeterminate && !state.context.checked, }), diff --git a/packages/machines/color-picker/src/color-picker.connect.ts b/packages/machines/color-picker/src/color-picker.connect.ts index d95b93396c..70ff0d6b64 100644 --- a/packages/machines/color-picker/src/color-picker.connect.ts +++ b/packages/machines/color-picker/src/color-picker.connect.ts @@ -408,6 +408,7 @@ export function connect(state: State, send: Send, normalize return normalize.input({ ...parts.channelInput.attrs, + dir: state.context.dir, type: isTextField ? "text" : "number", "data-channel": channel, "aria-label": channel, @@ -461,6 +462,7 @@ export function connect(state: State, send: Send, normalize eyeDropperTriggerProps: normalize.button({ ...parts.eyeDropperTrigger.attrs, type: "button", + dir: state.context.dir, disabled: isDisabled, "data-disabled": dataAttr(isDisabled), "aria-label": "Pick a color from the screen", @@ -481,6 +483,7 @@ export function connect(state: State, send: Send, normalize return normalize.button({ ...parts.swatchTrigger.attrs, disabled: isDisabled, + dir: state.context.dir, type: "button", "data-value": color.toString("hex"), onClick() { @@ -499,6 +502,7 @@ export function connect(state: State, send: Send, normalize const color = colorValue.toFormat(value.getFormat()) return normalize.element({ ...parts.swatch.attrs, + dir: state.context.dir, "data-state": colorValue.isEqual(value) ? "selected" : "unselected", "data-value": color.toString("hex"), style: { diff --git a/packages/machines/date-picker/src/date-picker.connect.ts b/packages/machines/date-picker/src/date-picker.connect.ts index 7c96855407..d9f77c7120 100644 --- a/packages/machines/date-picker/src/date-picker.connect.ts +++ b/packages/machines/date-picker/src/date-picker.connect.ts @@ -261,6 +261,7 @@ export function connect(state: State, send: Send, normalize rootProps: normalize.element({ ...parts.root.attrs, + dir: state.context.dir, id: dom.getRootId(state.context), "data-state": isOpen ? "open" : "closed", "data-disabled": dataAttr(disabled), @@ -269,6 +270,7 @@ export function connect(state: State, send: Send, normalize labelProps: normalize.label({ ...parts.label.attrs, + dir: state.context.dir, htmlFor: dom.getInputId(state.context), "data-state": isOpen ? "open" : "closed", "data-disabled": dataAttr(disabled), @@ -277,17 +279,20 @@ export function connect(state: State, send: Send, normalize controlProps: normalize.element({ ...parts.control.attrs, + dir: state.context.dir, id: dom.getControlId(state.context), "data-disabled": dataAttr(disabled), }), rangeTextProps: normalize.element({ ...parts.rangeText.attrs, + dir: state.context.dir, }), contentProps: normalize.element({ ...parts.content.attrs, hidden: !isOpen, + dir: state.context.dir, "data-state": isOpen ? "open" : "closed", id: dom.getContentId(state.context), role: "application", @@ -424,6 +429,7 @@ export function connect(state: State, send: Send, normalize ...parts.tableCellTrigger.attrs, id: dom.getCellTriggerId(state.context, value.toString()), role: "button", + dir: state.context.dir, tabIndex: cellState.isFocused ? 0 : -1, "aria-label": cellState.ariaLabel, "aria-disabled": ariaAttr(!cellState.isSelectable), @@ -458,6 +464,7 @@ export function connect(state: State, send: Send, normalize const cellState = getMonthTableCellState(props) return normalize.element({ ...parts.tableCell.attrs, + dir: state.context.dir, colSpan: columns, role: "gridcell", "aria-selected": ariaAttr(cellState.isSelected), @@ -471,6 +478,7 @@ export function connect(state: State, send: Send, normalize const cellState = getMonthTableCellState(props) return normalize.element({ ...parts.tableCellTrigger.attrs, + dir: state.context.dir, role: "button", id: dom.getCellTriggerId(state.context, value.toString()), "data-selected": dataAttr(cellState.isSelected), @@ -494,6 +502,7 @@ export function connect(state: State, send: Send, normalize const cellState = getYearTableCellState(props) return normalize.element({ ...parts.tableCell.attrs, + dir: state.context.dir, colSpan: columns, role: "gridcell", "aria-selected": ariaAttr(cellState.isSelected), @@ -507,6 +516,7 @@ export function connect(state: State, send: Send, normalize const cellState = getYearTableCellState(props) return normalize.element({ ...parts.tableCellTrigger.attrs, + dir: state.context.dir, role: "button", id: dom.getCellTriggerId(state.context, value.toString()), "data-selected": dataAttr(cellState.isSelected), @@ -528,6 +538,7 @@ export function connect(state: State, send: Send, normalize const { view = "day" } = props return normalize.button({ ...parts.nextTrigger.attrs, + dir: state.context.dir, id: dom.getNextTriggerId(state.context, view), type: "button", "aria-label": getPrevTriggerLabel(view), @@ -542,6 +553,7 @@ export function connect(state: State, send: Send, normalize const { view = "day" } = props return normalize.button({ ...parts.prevTrigger.attrs, + dir: state.context.dir, id: dom.getPrevTriggerId(state.context, view), type: "button", "aria-label": getNextTriggerLabel(view), @@ -555,6 +567,7 @@ export function connect(state: State, send: Send, normalize clearTriggerProps: normalize.button({ ...parts.clearTrigger.attrs, id: dom.getClearTriggerId(state.context), + dir: state.context.dir, type: "button", "aria-label": "Clear dates", hidden: !state.context.value.length, @@ -566,6 +579,7 @@ export function connect(state: State, send: Send, normalize triggerProps: normalize.button({ ...parts.trigger.attrs, id: dom.getTriggerId(state.context), + dir: state.context.dir, type: "button", "aria-label": isOpen ? "Close calendar" : "Open calendar", "data-state": isOpen ? "open" : "closed", @@ -582,6 +596,7 @@ export function connect(state: State, send: Send, normalize return normalize.button({ ...parts.viewTrigger.attrs, "data-view": view, + dir: state.context.dir, id: dom.getViewTriggerId(state.context, view), type: "button", disabled, @@ -598,6 +613,7 @@ export function connect(state: State, send: Send, normalize return normalize.element({ ...parts.viewControl.attrs, "data-view": view, + dir: state.context.dir, }) }, diff --git a/packages/machines/dialog/src/dialog.connect.ts b/packages/machines/dialog/src/dialog.connect.ts index 24b36c55da..6f2a5e303f 100644 --- a/packages/machines/dialog/src/dialog.connect.ts +++ b/packages/machines/dialog/src/dialog.connect.ts @@ -19,6 +19,7 @@ export function connect(state: State, send: Send, normalize triggerProps: normalize.button({ ...parts.trigger.attrs, + dir: state.context.dir, id: dom.getTriggerId(state.context), "aria-haspopup": "dialog", type: "button", @@ -32,6 +33,7 @@ export function connect(state: State, send: Send, normalize backdropProps: normalize.element({ ...parts.backdrop.attrs, + dir: state.context.dir, hidden: !isOpen, id: dom.getBackdropId(state.context), "data-state": isOpen ? "open" : "closed", @@ -39,6 +41,7 @@ export function connect(state: State, send: Send, normalize positionerProps: normalize.element({ ...parts.positioner.attrs, + dir: state.context.dir, hidden: !isOpen, id: dom.getPositionerId(state.context), "data-state": isOpen ? "open" : "closed", @@ -49,6 +52,7 @@ export function connect(state: State, send: Send, normalize contentProps: normalize.element({ ...parts.content.attrs, + dir: state.context.dir, role: state.context.role, hidden: !isOpen, id: dom.getContentId(state.context), @@ -62,16 +66,19 @@ export function connect(state: State, send: Send, normalize titleProps: normalize.element({ ...parts.title.attrs, + dir: state.context.dir, id: dom.getTitleId(state.context), }), descriptionProps: normalize.element({ ...parts.description.attrs, + dir: state.context.dir, id: dom.getDescriptionId(state.context), }), closeTriggerProps: normalize.button({ ...parts.closeTrigger.attrs, + dir: state.context.dir, id: dom.getCloseTriggerId(state.context), type: "button", onClick(event) { diff --git a/packages/machines/editable/src/editable.connect.ts b/packages/machines/editable/src/editable.connect.ts index 08857ce1a7..348ed126de 100644 --- a/packages/machines/editable/src/editable.connect.ts +++ b/packages/machines/editable/src/editable.connect.ts @@ -25,27 +25,20 @@ export function connect(state: State, send: Send, normalize isEditing, isValueEmpty: isValueEmpty, value: state.context.value, - - setValue(value: string) { + setValue(value) { send({ type: "SET_VALUE", value }) }, - clearValue() { send({ type: "SET_VALUE", value: "" }) }, - edit() { if (!isInteractive) return send("EDIT") }, - /** - * Function to exit edit mode, and discard any changes - */ cancel() { if (!isInteractive) return send("CANCEL") }, - submit() { if (!isInteractive) return send("SUBMIT") @@ -54,11 +47,13 @@ export function connect(state: State, send: Send, normalize rootProps: normalize.element({ ...parts.root.attrs, id: dom.getRootId(state.context), + dir: state.context.dir, }), areaProps: normalize.element({ ...parts.area.attrs, id: dom.getAreaId(state.context), + dir: state.context.dir, style: autoResize ? { display: "inline-grid" } : undefined, "data-focus": dataAttr(isEditing), "data-disabled": dataAttr(isDisabled), @@ -68,6 +63,7 @@ export function connect(state: State, send: Send, normalize labelProps: normalize.label({ ...parts.label.attrs, id: dom.getLabelId(state.context), + dir: state.context.dir, htmlFor: dom.getInputId(state.context), "data-focus": dataAttr(isEditing), "data-invalid": dataAttr(isInvalid), @@ -81,6 +77,7 @@ export function connect(state: State, send: Send, normalize inputProps: normalize.input({ ...parts.input.attrs, + dir: state.context.dir, "aria-label": translations.input, name: state.context.name, form: state.context.form, @@ -129,6 +126,7 @@ export function connect(state: State, send: Send, normalize previewProps: normalize.element({ id: dom.getPreviewId(state.context), ...parts.preview.attrs, + dir: state.context.dir, "data-placeholder-shown": dataAttr(isValueEmpty), "aria-readonly": ariaAttr(isReadOnly), "data-readonly": dataAttr(isDisabled), @@ -163,6 +161,7 @@ export function connect(state: State, send: Send, normalize editTriggerProps: normalize.button({ ...parts.editTrigger.attrs, id: dom.getEditTriggerId(state.context), + dir: state.context.dir, "aria-label": translations.edit, hidden: isEditing, type: "button", @@ -176,10 +175,12 @@ export function connect(state: State, send: Send, normalize controlProps: normalize.element({ id: dom.getControlId(state.context), ...parts.control.attrs, + dir: state.context.dir, }), submitTriggerProps: normalize.button({ ...parts.submitTrigger.attrs, + dir: state.context.dir, id: dom.getSubmitTriggerId(state.context), "aria-label": translations.submit, hidden: !isEditing, @@ -193,6 +194,7 @@ export function connect(state: State, send: Send, normalize cancelTriggerProps: normalize.button({ ...parts.cancelTrigger.attrs, + dir: state.context.dir, "aria-label": translations.cancel, id: dom.getCancelTriggerId(state.context), hidden: !isEditing, diff --git a/packages/machines/file-upload/src/file-upload.connect.ts b/packages/machines/file-upload/src/file-upload.connect.ts index 7447bc807e..a5e44a7d9f 100644 --- a/packages/machines/file-upload/src/file-upload.connect.ts +++ b/packages/machines/file-upload/src/file-upload.connect.ts @@ -166,6 +166,7 @@ export function connect(state: State, send: Send, normalize const { file } = props return normalize.element({ ...parts.itemName.attrs, + dir: state.context.dir, id: dom.getItemNameId(state.context, file.name), "data-disabled": dataAttr(disabled), }) @@ -175,6 +176,7 @@ export function connect(state: State, send: Send, normalize const { file } = props return normalize.element({ ...parts.itemSizeText.attrs, + dir: state.context.dir, id: dom.getItemSizeTextId(state.context, file.name), "data-disabled": dataAttr(disabled), }) @@ -188,6 +190,7 @@ export function connect(state: State, send: Send, normalize } return normalize.img({ ...parts.itemPreview.attrs, + dir: state.context.dir, alt: `Preview of ${file.name}`, src: url, id: dom.getItemPreviewId(state.context, file.name), @@ -199,6 +202,7 @@ export function connect(state: State, send: Send, normalize const { file } = props return normalize.button({ ...parts.itemDeleteTrigger.attrs, + dir: state.context.dir, type: "button", disabled, "data-disabled": dataAttr(disabled), diff --git a/packages/machines/hover-card/src/hover-card.connect.ts b/packages/machines/hover-card/src/hover-card.connect.ts index cb7cebc296..a4303e9c88 100644 --- a/packages/machines/hover-card/src/hover-card.connect.ts +++ b/packages/machines/hover-card/src/hover-card.connect.ts @@ -1,4 +1,4 @@ -import { getPlacementStyles, type PositioningOptions } from "@zag-js/popper" +import { getPlacementStyles } from "@zag-js/popper" import type { NormalizeProps, PropTypes } from "@zag-js/types" import { parts } from "./hover-card.anatomy" import { dom } from "./hover-card.dom" @@ -14,32 +14,32 @@ export function connect(state: State, send: Send, normalize return { isOpen, - open() { send("OPEN") }, - close() { send("CLOSE") }, - - reposition(options: Partial = {}) { + reposition(options = {}) { send({ type: "SET_POSITIONING", options }) }, arrowProps: normalize.element({ id: dom.getArrowId(state.context), ...parts.arrow.attrs, + dir: state.context.dir, style: popperStyles.arrow, }), arrowTipProps: normalize.element({ ...parts.arrowTip.attrs, + dir: state.context.dir, style: popperStyles.arrowTip, }), triggerProps: normalize.element({ ...parts.trigger.attrs, + dir: state.context.dir, "data-placement": state.context.currentPlacement, id: dom.getTriggerId(state.context), "data-state": isOpen ? "open" : "closed", @@ -71,6 +71,7 @@ export function connect(state: State, send: Send, normalize contentProps: normalize.element({ ...parts.content.attrs, + dir: state.context.dir, id: dom.getContentId(state.context), hidden: !isOpen, "data-state": isOpen ? "open" : "closed", diff --git a/packages/machines/menu/src/menu.connect.ts b/packages/machines/menu/src/menu.connect.ts index ec5710f088..bfcbe8d9b4 100644 --- a/packages/machines/menu/src/menu.connect.ts +++ b/packages/machines/menu/src/menu.connect.ts @@ -126,6 +126,7 @@ export function connect(state: State, send: Send, normalize contextTriggerProps: normalize.element({ ...parts.contextTrigger.attrs, + dir: state.context.dir, id: dom.getContextTriggerId(state.context), onPointerDown(event) { if (event.pointerType === "mouse") return @@ -236,6 +237,7 @@ export function connect(state: State, send: Send, normalize indicatorProps: normalize.element({ ...parts.indicator.attrs, + dir: state.context.dir, "data-state": isOpen ? "open" : "closed", }), @@ -249,11 +251,13 @@ export function connect(state: State, send: Send, normalize arrowProps: normalize.element({ id: dom.getArrowId(state.context), ...parts.arrow.attrs, + dir: state.context.dir, style: popperStyles.arrow, }), arrowTipProps: normalize.element({ ...parts.arrowTip.attrs, + dir: state.context.dir, style: popperStyles.arrowTip, }), @@ -340,6 +344,7 @@ export function connect(state: State, send: Send, normalize separatorProps: normalize.element({ ...parts.separator.attrs, role: "separator", + dir: state.context.dir, "aria-orientation": "horizontal", }), getItemState, @@ -358,6 +363,7 @@ export function connect(state: State, send: Send, normalize "data-type": type, "data-name": name, ...parts.optionItem.attrs, + dir: state.context.dir, "data-value": option.value, role: `menuitem${type}`, "aria-checked": !!itemState.isChecked, @@ -384,6 +390,7 @@ export function connect(state: State, send: Send, normalize const itemState = getOptionItemState(props) return normalize.element({ ...parts.optionItemIndicator.attrs, + dir: state.context.dir, "data-disabled": dataAttr(itemState.isDisabled), "data-highlighted": dataAttr(itemState.isHighlighted), "data-state": itemState.isChecked ? "checked" : "unchecked", @@ -405,6 +412,7 @@ export function connect(state: State, send: Send, normalize getItemGroupLabelProps(props) { return normalize.element({ id: dom.getGroupLabelId(state.context, props.htmlFor), + dir: state.context.dir, ...parts.itemGroupLabel.attrs, }) }, @@ -413,6 +421,7 @@ export function connect(state: State, send: Send, normalize return normalize.element({ id: dom.getGroupId(state.context, props.id), ...parts.itemGroup.attrs, + dir: state.context.dir, "aria-labelledby": dom.getGroupLabelId(state.context, props.id), role: "group", }) diff --git a/packages/machines/number-input/src/number-input.connect.ts b/packages/machines/number-input/src/number-input.connect.ts index b4481ce651..0c9f6d0ef4 100644 --- a/packages/machines/number-input/src/number-input.connect.ts +++ b/packages/machines/number-input/src/number-input.connect.ts @@ -26,31 +26,24 @@ export function connect(state: State, send: Send, normalize isValueEmpty, value: state.context.formattedValue, valueAsNumber: state.context.valueAsNumber, - - setValue(value: string | number) { + setValue(value) { send({ type: "VALUE.SET", value: value.toString() }) }, - clearValue() { send("VALUE.CLEAR") }, - increment() { send("VALUE.INCREMENT") }, - decrement() { send("VALUE.DECREMENT") }, - setToMax() { send({ type: "VALUE.SET", value: state.context.max }) }, - setToMin() { send({ type: "VALUE.SET", value: state.context.min }) }, - focus() { dom.getInputEl(state.context)?.focus() }, @@ -230,6 +223,7 @@ export function connect(state: State, send: Send, normalize scrubberProps: normalize.element({ ...parts.scrubber.attrs, + dir: state.context.dir, "data-disabled": dataAttr(isDisabled), id: dom.getScrubberId(state.context), role: "presentation", diff --git a/packages/machines/pagination/src/pagination.connect.ts b/packages/machines/pagination/src/pagination.connect.ts index 30a183da76..53eb501f4a 100644 --- a/packages/machines/pagination/src/pagination.connect.ts +++ b/packages/machines/pagination/src/pagination.connect.ts @@ -29,19 +29,15 @@ export function connect(state: State, send: Send, normalize pageRange, isFirstPage, isLastPage, - slice(data) { return data.slice(pageRange.start, pageRange.end) }, - setCount(count) { send({ type: "SET_COUNT", count }) }, - setPageSize(size) { send({ type: "SET_PAGE_SIZE", size }) }, - setPage(page) { send({ type: "SET_PAGE", page }) }, @@ -49,6 +45,7 @@ export function connect(state: State, send: Send, normalize rootProps: normalize.element({ id: dom.getRootId(state.context), ...parts.root.attrs, + dir: state.context.dir, "aria-label": translations.rootLabel, }), @@ -56,6 +53,7 @@ export function connect(state: State, send: Send, normalize return normalize.element({ id: dom.getEllipsisId(state.context, props.index), ...parts.ellipsis.attrs, + dir: state.context.dir, }) }, @@ -66,6 +64,7 @@ export function connect(state: State, send: Send, normalize return normalize.element({ id: dom.getItemId(state.context, index), ...parts.item.attrs, + dir: state.context.dir, "data-index": index, "data-selected": dataAttr(isCurrentPage), "aria-current": isCurrentPage ? "page" : undefined, @@ -80,6 +79,7 @@ export function connect(state: State, send: Send, normalize prevTriggerProps: normalize.element({ id: dom.getPrevTriggerId(state.context), ...parts.prevTrigger.attrs, + dir: state.context.dir, "data-disabled": dataAttr(isFirstPage), "aria-label": translations.prevTriggerLabel, onClick() { @@ -91,6 +91,7 @@ export function connect(state: State, send: Send, normalize nextTriggerProps: normalize.element({ id: dom.getNextTriggerId(state.context), ...parts.nextTrigger.attrs, + dir: state.context.dir, "data-disabled": dataAttr(isLastPage), "aria-label": translations.nextTriggerLabel, onClick() { diff --git a/packages/machines/pin-input/src/pin-input.connect.ts b/packages/machines/pin-input/src/pin-input.connect.ts index 5fc7bbe44e..1a34271fb6 100644 --- a/packages/machines/pin-input/src/pin-input.connect.ts +++ b/packages/machines/pin-input/src/pin-input.connect.ts @@ -19,27 +19,23 @@ export function connect(state: State, send: Send, normalize } return { + focus, value: state.context.value, valueAsString: state.context.valueAsString, isValueComplete: isValueComplete, - setValue(value) { if (!Array.isArray(value)) { invariant("[pin-input/setValue] value must be an array") } send({ type: "VALUE.SET", value }) }, - clearValue() { send({ type: "VALUE.CLEAR" }) }, - setValueAtIndex(index, value) { send({ type: "VALUE.SET", value, index }) }, - focus, - rootProps: normalize.element({ dir: state.context.dir, ...parts.root.attrs, diff --git a/packages/machines/popover/src/popover.connect.ts b/packages/machines/popover/src/popover.connect.ts index 4e8d148299..1c91ab5a3e 100644 --- a/packages/machines/popover/src/popover.connect.ts +++ b/packages/machines/popover/src/popover.connect.ts @@ -1,5 +1,4 @@ import { dataAttr } from "@zag-js/dom-query" -import type { PositioningOptions } from "@zag-js/popper" import { getPlacementStyles } from "@zag-js/popper" import type { NormalizeProps, PropTypes } from "@zag-js/types" import { parts } from "./popover.anatomy" @@ -21,37 +20,38 @@ export function connect(state: State, send: Send, normalize return { portalled, isOpen, - open() { send("OPEN") }, - close() { send("CLOSE") }, - - reposition(options: Partial = {}) { + reposition(options = {}) { send({ type: "SET_POSITIONING", options }) }, arrowProps: normalize.element({ id: dom.getArrowId(state.context), ...parts.arrow.attrs, + dir: state.context.dir, style: popperStyles.arrow, }), arrowTipProps: normalize.element({ ...parts.arrowTip.attrs, + dir: state.context.dir, style: popperStyles.arrowTip, }), anchorProps: normalize.element({ ...parts.anchor.attrs, + dir: state.context.dir, id: dom.getAnchorId(state.context), }), triggerProps: normalize.button({ ...parts.trigger.attrs, + dir: state.context.dir, type: "button", "data-placement": currentPlacement, id: dom.getTriggerId(state.context), @@ -69,17 +69,20 @@ export function connect(state: State, send: Send, normalize indicatorProps: normalize.element({ ...parts.indicator.attrs, + dir: state.context.dir, "data-state": isOpen ? "open" : "closed", }), positionerProps: normalize.element({ id: dom.getPositionerId(state.context), ...parts.positioner.attrs, + dir: state.context.dir, style: popperStyles.floating, }), contentProps: normalize.element({ ...parts.content.attrs, + dir: state.context.dir, id: dom.getContentId(state.context), tabIndex: -1, role: "dialog", @@ -94,15 +97,18 @@ export function connect(state: State, send: Send, normalize titleProps: normalize.element({ ...parts.title.attrs, id: dom.getTitleId(state.context), + dir: state.context.dir, }), descriptionProps: normalize.element({ ...parts.description.attrs, id: dom.getDescriptionId(state.context), + dir: state.context.dir, }), closeTriggerProps: normalize.button({ ...parts.closeTrigger.attrs, + dir: state.context.dir, id: dom.getCloseTriggerId(state.context), type: "button", "aria-label": "close", diff --git a/packages/machines/popover/src/popover.types.ts b/packages/machines/popover/src/popover.types.ts index 6f4a96f224..148b1bca73 100644 --- a/packages/machines/popover/src/popover.types.ts +++ b/packages/machines/popover/src/popover.types.ts @@ -1,7 +1,7 @@ import type { StateMachine as S } from "@zag-js/core" import type { DismissableElementHandlers } from "@zag-js/dismissable" import type { Placement, PositioningOptions } from "@zag-js/popper" -import type { CommonProperties, Context, MaybeElement, PropTypes, RequiredBy } from "@zag-js/types" +import type { CommonProperties, Context, DirectionProperty, MaybeElement, PropTypes, RequiredBy } from "@zag-js/types" /* ----------------------------------------------------------------------------- * Callback details @@ -26,7 +26,7 @@ type ElementIds = Partial<{ arrow: string }> -interface PublicContext extends DismissableElementHandlers, CommonProperties { +interface PublicContext extends DismissableElementHandlers, CommonProperties, DirectionProperty { /** * The ids of the elements in the popover. Useful for composition. */ diff --git a/packages/machines/radio-group/src/radio-group.connect.ts b/packages/machines/radio-group/src/radio-group.connect.ts index e9d59b62ce..4f3556979b 100644 --- a/packages/machines/radio-group/src/radio-group.connect.ts +++ b/packages/machines/radio-group/src/radio-group.connect.ts @@ -44,18 +44,14 @@ export function connect(state: State, send: Send, normalize } return { + focus, value: state.context.value, - - setValue(value: string) { + setValue(value) { send({ type: "SET_VALUE", value, isTrusted: false }) }, - clearValue() { send({ type: "SET_VALUE", value: null, isTrusted: false }) }, - - focus, - getItemState, rootProps: normalize.element({ diff --git a/packages/machines/select/src/select.connect.ts b/packages/machines/select/src/select.connect.ts index 63677f408d..f07dc0acca 100644 --- a/packages/machines/select/src/select.connect.ts +++ b/packages/machines/select/src/select.connect.ts @@ -201,6 +201,7 @@ export function connect(state: State, send: Send, normalize value: state.context.value, isDragging, isFocused, - setValue(value) { send({ type: "SET_VALUE", value: value }) }, - getThumbValue(index) { return sliderValue[index] }, - setThumbValue(index, value) { send({ type: "SET_VALUE", index, value }) }, - getValuePercent: getValuePercentFn, - getPercentValue: getPercentValueFn, - getThumbPercent(index) { return getValuePercentFn(sliderValue[index]) }, - setThumbPercent(index, percent) { const value = getPercentValueFn(percent) send({ type: "SET_VALUE", index, value }) }, - getThumbMin(index) { return getRangeAtIndex(state.context, index).min }, - getThumbMax(index) { return getRangeAtIndex(state.context, index).max }, - increment(index) { send({ type: "INCREMENT", index }) }, - decrement(index) { send({ type: "DECREMENT", index }) }, - focus() { if (!isInteractive) return send({ type: "FOCUS", index: 0 }) diff --git a/packages/machines/splitter/src/splitter.connect.ts b/packages/machines/splitter/src/splitter.connect.ts index 84a0c06eee..2fb5b4c1d3 100644 --- a/packages/machines/splitter/src/splitter.connect.ts +++ b/packages/machines/splitter/src/splitter.connect.ts @@ -31,24 +31,20 @@ export function connect(state: State, send: Send, normalize return { isFocused, isDragging, + getResizeTriggerState, bounds: getHandleBounds(state.context), - setToMinSize(id) { const panel = panels.find((panel) => panel.id === id) send({ type: "SET_PANEL_SIZE", id, size: panel?.minSize, src: "setToMinSize" }) }, - setToMaxSize(id) { const panel = panels.find((panel) => panel.id === id) send({ type: "SET_PANEL_SIZE", id, size: panel?.maxSize, src: "setToMaxSize" }) }, - setSize(id, size) { send({ type: "SET_PANEL_SIZE", id, size }) }, - getResizeTriggerState, - rootProps: normalize.element({ ...parts.root.attrs, "data-orientation": state.context.orientation, diff --git a/packages/machines/switch/src/switch.connect.ts b/packages/machines/switch/src/switch.connect.ts index 47a82638b6..a70612b250 100644 --- a/packages/machines/switch/src/switch.connect.ts +++ b/packages/machines/switch/src/switch.connect.ts @@ -23,11 +23,9 @@ export function connect(state: State, send: Send, normalize isChecked, isDisabled, isFocused, - - setChecked(checked: boolean) { + setChecked(checked) { send({ type: "CHECKED.SET", checked, isTrusted: false }) }, - toggleChecked() { send({ type: "CHECKED.TOGGLE", checked: isChecked, isTrusted: false }) }, @@ -35,6 +33,7 @@ export function connect(state: State, send: Send, normalize rootProps: normalize.label({ ...parts.root.attrs, ...dataAttrs, + dir: state.context.dir, id: dom.getRootId(state.context), htmlFor: dom.getHiddenInputId(state.context), onPointerMove() { @@ -66,12 +65,14 @@ export function connect(state: State, send: Send, normalize labelProps: normalize.element({ ...parts.label.attrs, ...dataAttrs, + dir: state.context.dir, id: dom.getLabelId(state.context), }), thumbProps: normalize.element({ ...parts.thumb.attrs, ...dataAttrs, + dir: state.context.dir, id: dom.getThumbId(state.context), "aria-hidden": true, }), @@ -79,6 +80,7 @@ export function connect(state: State, send: Send, normalize controlProps: normalize.element({ ...parts.control.attrs, ...dataAttrs, + dir: state.context.dir, id: dom.getControlId(state.context), "aria-hidden": true, }), diff --git a/packages/machines/tabs/src/tabs.connect.ts b/packages/machines/tabs/src/tabs.connect.ts index d008564da3..2938c0d1ef 100644 --- a/packages/machines/tabs/src/tabs.connect.ts +++ b/packages/machines/tabs/src/tabs.connect.ts @@ -21,20 +21,16 @@ export function connect(state: State, send: Send, normalize value: state.context.value, focusedValue: state.context.focusedValue, previousValues: Array.from(state.context.previousValues), - setValue(value) { send({ type: "SET_VALUE", value }) }, - clearValue() { send({ type: "CLEAR_VALUE" }) }, - setIndicatorRect(value) { const id = dom.getTriggerId(state.context, value) send({ type: "SET_INDICATOR_RECT", id }) }, - getTriggerState, rootProps: normalize.element({ @@ -151,6 +147,7 @@ export function connect(state: State, send: Send, normalize indicatorProps: normalize.element({ id: dom.getIndicatorId(state.context), ...parts.indicator.attrs, + dir: state.context.dir, "data-orientation": state.context.orientation, style: { "--transition-duration": "150ms", diff --git a/packages/machines/tags-input/src/tags-input.connect.ts b/packages/machines/tags-input/src/tags-input.connect.ts index bd64dad851..006fc1a4b1 100644 --- a/packages/machines/tags-input/src/tags-input.connect.ts +++ b/packages/machines/tags-input/src/tags-input.connect.ts @@ -34,39 +34,31 @@ export function connect(state: State, send: Send, normalize valueAsString: state.context.valueAsString, count: state.context.count, isAtMax: state.context.isAtMax, - - setValue(value: string[]) { + setValue(value) { send({ type: "SET_VALUE", value }) }, - - clearValue(id?: string) { + clearValue(id) { if (id) { send({ type: "CLEAR_TAG", id }) } else { send("CLEAR_VALUE") } }, - - addValue(value: string) { + addValue(value) { send({ type: "ADD_TAG", value }) }, - - setValueAtIndex(index: number, value: string) { + setValueAtIndex(index, value) { send({ type: "SET_VALUE_AT_INDEX", index, value }) }, - - setInputValue(value: string) { + setInputValue(value) { send({ type: "SET_INPUT_VALUE", value }) }, - clearInputValue() { send({ type: "SET_INPUT_VALUE", value: "" }) }, - focus() { dom.getInputEl(state.context)?.focus() }, - getItemState, rootProps: normalize.element({ diff --git a/packages/machines/toast/src/toast-group.connect.ts b/packages/machines/toast/src/toast-group.connect.ts index ea12c33f54..4955505fba 100644 --- a/packages/machines/toast/src/toast-group.connect.ts +++ b/packages/machines/toast/src/toast-group.connect.ts @@ -126,6 +126,7 @@ export function groupConnect( const { placement, label = "Notifications" } = options return normalize.element({ ...parts.group.attrs, + dir: state.context.dir, tabIndex: -1, "aria-label": `${placement} ${label}`, id: dom.getGroupId(placement), diff --git a/packages/machines/tooltip/src/tooltip.connect.ts b/packages/machines/tooltip/src/tooltip.connect.ts index 4d31b813d5..9b6abe5103 100644 --- a/packages/machines/tooltip/src/tooltip.connect.ts +++ b/packages/machines/tooltip/src/tooltip.connect.ts @@ -1,5 +1,5 @@ import { dataAttr } from "@zag-js/dom-query" -import { getPlacementStyles, type PositioningOptions } from "@zag-js/popper" +import { getPlacementStyles } from "@zag-js/popper" import type { NormalizeProps, PropTypes } from "@zag-js/types" import { parts } from "./tooltip.anatomy" import { dom } from "./tooltip.dom" @@ -30,13 +30,14 @@ export function connect(state: State, send: Send, normalize close() { send("CLOSE") }, - reposition(options: Partial = {}) { + reposition(options = {}) { send({ type: "SET_POSITIONING", options }) }, triggerProps: normalize.button({ ...parts.trigger.attrs, id: triggerId, + dir: state.context.dir, "data-expanded": dataAttr(isOpen), "data-state": isOpen ? "open" : "closed", "aria-describedby": isOpen ? contentId : undefined, @@ -75,11 +76,13 @@ export function connect(state: State, send: Send, normalize arrowProps: normalize.element({ id: dom.getArrowId(state.context), ...parts.arrow.attrs, + dir: state.context.dir, style: popperStyles.arrow, }), arrowTipProps: normalize.element({ ...parts.arrowTip.attrs, + dir: state.context.dir, style: popperStyles.arrowTip, }), @@ -92,6 +95,7 @@ export function connect(state: State, send: Send, normalize contentProps: normalize.element({ ...parts.content.attrs, + dir: state.context.dir, hidden: !isOpen, "data-state": isOpen ? "open" : "closed", role: hasAriaLabel ? undefined : "tooltip",