diff --git a/.changeset/slimy-ads-build.md b/.changeset/slimy-ads-build.md new file mode 100644 index 0000000000..2ef0d63ba6 --- /dev/null +++ b/.changeset/slimy-ads-build.md @@ -0,0 +1,10 @@ +--- +"@zag-js/slider": minor +--- + +Merge the slider and range slider machines into one to prevent duplication. + +Some notable changes: + +- `value` and `onValueChange` type has been updated to be `number[]` +- Update `api.getThumbProps(index)` to `api.getThumbProps({ index })` diff --git a/.xstate/slider.js b/.xstate/slider.js index 8589aaf5da..9249ca3aca 100644 --- a/.xstate/slider.js +++ b/.xstate/slider.js @@ -13,24 +13,28 @@ const fetchMachine = createMachine({ id: "slider", initial: "idle", context: { + "hasIndex": false, "isHorizontal": false, "isHorizontal": false, "isVertical": false, "isVertical": false }, - activities: ["trackFormControlState", "trackThumbSize"], + entry: ["coarseValue"], + activities: ["trackFormControlState", "trackThumbsSize"], on: { - SET_VALUE: { + SET_VALUE: [{ + cond: "hasIndex", + actions: "setValueAtIndex" + }, { actions: "setValue" - }, + }], INCREMENT: { - actions: "increment" + actions: "incrementAtIndex" }, DECREMENT: { - actions: "decrement" + actions: "decrementAtIndex" } }, - entry: ["checkValue"], on: { UPDATE_CONTEXT: { actions: "updateContext" @@ -41,59 +45,65 @@ const fetchMachine = createMachine({ on: { POINTER_DOWN: { target: "dragging", - actions: ["setPointerValue", "invokeOnChangeStart", "focusThumb"] + actions: ["setClosestThumbIndex", "setPointerValue", "focusActiveThumb"] + }, + FOCUS: { + target: "focus", + actions: "setFocusedIndex" }, - FOCUS: "focus", THUMB_POINTER_DOWN: { target: "dragging", - actions: ["invokeOnChangeStart", "focusThumb"] + actions: ["setFocusedIndex", "focusActiveThumb"] } } }, focus: { - entry: "focusThumb", + entry: "focusActiveThumb", on: { POINTER_DOWN: { target: "dragging", - actions: ["setPointerValue", "invokeOnChangeStart", "focusThumb"] + actions: ["setClosestThumbIndex", "setPointerValue", "focusActiveThumb"] }, THUMB_POINTER_DOWN: { target: "dragging", - actions: ["invokeOnChangeStart", "focusThumb"] + actions: ["setFocusedIndex", "focusActiveThumb"] }, ARROW_LEFT: { cond: "isHorizontal", - actions: "decrement" + actions: "decrementAtIndex" }, ARROW_RIGHT: { cond: "isHorizontal", - actions: "increment" + actions: "incrementAtIndex" }, ARROW_UP: { cond: "isVertical", - actions: "increment" + actions: "incrementAtIndex" }, ARROW_DOWN: { cond: "isVertical", - actions: "decrement" + actions: "decrementAtIndex" }, PAGE_UP: { - actions: "increment" + actions: "incrementAtIndex" }, PAGE_DOWN: { - actions: "decrement" + actions: "decrementAtIndex" }, HOME: { - actions: "setToMin" + actions: "setActiveThumbToMin" }, END: { - actions: "setToMax" + actions: "setActiveThumbToMax" }, - BLUR: "idle" + BLUR: { + target: "idle", + actions: "clearFocusedIndex" + } } }, dragging: { - entry: "focusThumb", + entry: "focusActiveThumb", activities: "trackPointerMove", on: { POINTER_UP: { @@ -115,6 +125,7 @@ const fetchMachine = createMachine({ }) }, guards: { + "hasIndex": ctx => ctx["hasIndex"], "isHorizontal": ctx => ctx["isHorizontal"], "isVertical": ctx => ctx["isVertical"] } diff --git a/e2e/slider.e2e.ts b/e2e/slider.e2e.ts index fd5ec06a79..3b604b34b9 100644 --- a/e2e/slider.e2e.ts +++ b/e2e/slider.e2e.ts @@ -1,9 +1,9 @@ import { expect, test } from "@playwright/test" -import { testid, a11y, rect } from "./__utils" +import { part, a11y, rect } from "./__utils" -const output = testid("output") -const thumb = testid("thumb") -const track = testid("track") +const output = part("output") +const thumb = part("thumb") +const track = part("track") test.describe("slider", () => { test.beforeEach(async ({ page }) => { diff --git a/examples/next-ts/CHANGELOG.md b/examples/next-ts/CHANGELOG.md index afeff01eb5..38b9ec0c00 100644 --- a/examples/next-ts/CHANGELOG.md +++ b/examples/next-ts/CHANGELOG.md @@ -23,7 +23,7 @@ - @zag-js/number-input@0.1.13 - @zag-js/pin-input@0.1.11 - @zag-js/popover@0.1.11 - - @zag-js/range-slider@0.1.11 + - @zag-js/slider@0.1.11 - @zag-js/rating@0.1.11 - @zag-js/slider@0.1.11 - @zag-js/splitter@0.1.11 diff --git a/examples/next-ts/package.json b/examples/next-ts/package.json index 37a5151b4f..57b440f2c4 100644 --- a/examples/next-ts/package.json +++ b/examples/next-ts/package.json @@ -55,14 +55,13 @@ "@zag-js/presence": "workspace:*", "@zag-js/pressable": "workspace:*", "@zag-js/radio-group": "workspace:*", - "@zag-js/range-slider": "workspace:*", + "@zag-js/slider": "workspace:*", "@zag-js/rating-group": "workspace:*", "@zag-js/react": "workspace:*", "@zag-js/rect-utils": "workspace:*", "@zag-js/remove-scroll": "workspace:*", "@zag-js/select": "workspace:*", "@zag-js/shared": "workspace:*", - "@zag-js/slider": "workspace:*", "@zag-js/splitter": "workspace:*", "@zag-js/store": "workspace:*", "@zag-js/switch": "workspace:*", @@ -92,4 +91,4 @@ "typescript": "5.2.2" }, "license": "MIT" -} \ No newline at end of file +} diff --git a/examples/next-ts/pages/range-slider.tsx b/examples/next-ts/pages/range-slider.tsx index 4c4ea2cd76..5fc64be298 100644 --- a/examples/next-ts/pages/range-slider.tsx +++ b/examples/next-ts/pages/range-slider.tsx @@ -1,6 +1,6 @@ -import * as slider from "@zag-js/range-slider" +import * as slider from "@zag-js/slider" import { normalizeProps, useMachine } from "@zag-js/react" -import { rangeSliderControls } from "@zag-js/shared" +import { sliderControls } from "@zag-js/shared" import serialize from "form-serialize" import { useId } from "react" import { StateVisualizer } from "../components/state-visualizer" @@ -8,7 +8,7 @@ import { Toolbar } from "../components/toolbar" import { useControls } from "../hooks/use-controls" export default function Page() { - const controls = useControls(rangeSliderControls) + const controls = useControls(sliderControls) const [state, send] = useMachine( slider.machine({ @@ -42,8 +42,8 @@ export default function Page() {
{api.value.map((_, index) => ( -
- +
+
))}
diff --git a/examples/next-ts/pages/slider.tsx b/examples/next-ts/pages/slider.tsx index 895184331d..9b44d72c97 100644 --- a/examples/next-ts/pages/slider.tsx +++ b/examples/next-ts/pages/slider.tsx @@ -14,6 +14,7 @@ export default function Page() { slider.machine({ id: useId(), name: "quantity", + value: [0], }), { context: controls.context, @@ -46,9 +47,11 @@ export default function Page() {
-
- -
+ {api.value.map((_, index) => ( +
+ +
+ ))}
* diff --git a/examples/nuxt-ts/package.json b/examples/nuxt-ts/package.json index 4b3a8e2872..72616140b9 100644 --- a/examples/nuxt-ts/package.json +++ b/examples/nuxt-ts/package.json @@ -54,13 +54,12 @@ "@zag-js/presence": "workspace:*", "@zag-js/pressable": "workspace:*", "@zag-js/radio-group": "workspace:*", - "@zag-js/range-slider": "workspace:*", + "@zag-js/slider": "workspace:*", "@zag-js/rating-group": "workspace:*", "@zag-js/rect-utils": "workspace:*", "@zag-js/remove-scroll": "workspace:*", "@zag-js/select": "workspace:*", "@zag-js/shared": "workspace:*", - "@zag-js/slider": "workspace:*", "@zag-js/splitter": "workspace:*", "@zag-js/store": "workspace:*", "@zag-js/switch": "workspace:*", @@ -83,4 +82,4 @@ "@types/node": "^20.8.4", "nuxt": "^3.7.3" } -} \ No newline at end of file +} diff --git a/examples/nuxt-ts/pages/range-slider.vue b/examples/nuxt-ts/pages/range-slider.vue index 927ae4609c..59df52a217 100644 --- a/examples/nuxt-ts/pages/range-slider.vue +++ b/examples/nuxt-ts/pages/range-slider.vue @@ -1,10 +1,10 @@ @@ -24,9 +24,9 @@ const api = computed(() =>
- +
diff --git a/website/data/snippets/vue-sfc/slider/tick-marks.mdx b/website/data/snippets/vue-sfc/slider/tick-marks.mdx index 927f6f9b54..a68aa44c70 100644 --- a/website/data/snippets/vue-sfc/slider/tick-marks.mdx +++ b/website/data/snippets/vue-sfc/slider/tick-marks.mdx @@ -6,8 +6,8 @@
-
- +
+
diff --git a/website/data/snippets/vue-sfc/slider/usage.mdx b/website/data/snippets/vue-sfc/slider/usage.mdx index 7494b49504..4dbb03ebfe 100644 --- a/website/data/snippets/vue-sfc/slider/usage.mdx +++ b/website/data/snippets/vue-sfc/slider/usage.mdx @@ -4,7 +4,7 @@ import * as slider from "@zag-js/slider"; import { normalizeProps, useMachine } from "@zag-js/vue"; import { computed } from "vue"; -const [state, send] = useMachine(slider.machine({ id: "1" })); +const [state, send] = useMachine(slider.machine({ id: "1", value: [0] })); const api = computed(() => slider.connect(state.value, send, normalizeProps)); @@ -12,14 +12,18 @@ const api = computed(() => slider.connect(state.value, send, normalizeProps));
- {{ api.value }} + {{ api.value.at(0) }}
-
- +
+
diff --git a/website/package.json b/website/package.json index 10e252cbb1..bcf5fef2b2 100644 --- a/website/package.json +++ b/website/package.json @@ -41,11 +41,10 @@ "@zag-js/popover": "workspace:*", "@zag-js/pressable": "workspace:*", "@zag-js/radio-group": "workspace:*", - "@zag-js/range-slider": "workspace:*", + "@zag-js/slider": "workspace:*", "@zag-js/rating-group": "workspace:*", "@zag-js/react": "workspace:*", "@zag-js/select": "workspace:*", - "@zag-js/slider": "workspace:*", "@zag-js/splitter": "workspace:*", "@zag-js/switch": "workspace:*", "@zag-js/tabs": "workspace:*",