diff --git a/.eslintrc b/.eslintrc index 6b70425072..e23755388f 100644 --- a/.eslintrc +++ b/.eslintrc @@ -45,6 +45,7 @@ "import/no-named-as-default": "off", "prefer-object-spread": "off", "arrow-body-style": "off", + "import/namespace": "off", "@typescript-eslint/no-unused-vars": [ "error", { diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index e8404ece4f..7aa19a361a 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -71,4 +71,4 @@ jobs: uses: preactjs/compressed-size-action@v2 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" - pattern: "**/dist/**/*.prod.js" + pattern: "**/dist/**/*.mjs" diff --git a/.gitignore b/.gitignore index 4d82e17132..a1b79b5dd5 100644 --- a/.gitignore +++ b/.gitignore @@ -162,4 +162,5 @@ temp/ # End of https://www.toptal.com/developers/gitignore/api/node,yarn,jetbrains,visualstudiocode # System files -.DS_Store \ No newline at end of file +.DS_Store +.ultra.cache.json \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000000..801116a4cb --- /dev/null +++ b/.prettierrc @@ -0,0 +1,10 @@ +{ + "bracketSpacing": true, + "jsxSingleQuote": false, + "printWidth": 120, + "proseWrap": "always", + "semi": false, + "singleQuote": false, + "tabWidth": 2, + "trailingComma": "all" +} diff --git a/.watchmanconfig b/.watchmanconfig index e69de29bb2..0967ef424b 100644 --- a/.watchmanconfig +++ b/.watchmanconfig @@ -0,0 +1 @@ +{} diff --git a/babel.config.js b/babel.config.js deleted file mode 100644 index 845eac9a8e..0000000000 --- a/babel.config.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = { - presets: [ - [ - "@babel/env", - { - bugfixes: true, - targets: { - browsers: "Chrome >= 74, Safari >= 13.1, iOS >= 13.3, Firefox >= 78, Edge >= 79", - node: 12, - }, - }, - ], - "@babel/preset-typescript", - ], - plugins: [["@babel/plugin-proposal-private-methods", { loose: false }], "@babel/plugin-proposal-class-properties"], -} diff --git a/examples/next-ts/.babelrc b/examples/next-ts/.babelrc deleted file mode 100644 index 20ffe5738a..0000000000 --- a/examples/next-ts/.babelrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "presets": ["next/babel"], - "plugins": [["@babel/plugin-transform-runtime", { "regenerator": true }]] -} diff --git a/examples/next-ts/components/state-visualizer.tsx b/examples/next-ts/components/state-visualizer.tsx index 739c3ef25d..9c79d6f16d 100644 --- a/examples/next-ts/components/state-visualizer.tsx +++ b/examples/next-ts/components/state-visualizer.tsx @@ -1,5 +1,5 @@ import { Machine } from "@ui-machines/core" -import { isDom } from "tiny-guard" +import { isDom } from "@ui-machines/utils" type StateVisualizerProps = { state: Record diff --git a/examples/next-ts/next.config.js b/examples/next-ts/next.config.js index ecf0f7a4b7..f501fc61de 100644 --- a/examples/next-ts/next.config.js +++ b/examples/next-ts/next.config.js @@ -1,2 +1,15 @@ -const withPreconstruct = require("@preconstruct/next") -module.exports = withPreconstruct({}) +module.exports = { + experimental: { + externalDir: true, + }, + webpack: (config) => { + config.module.rules.push({ + test: /\.m?js$/, + type: "javascript/auto", + resolve: { + fullySpecified: false, + }, + }) + return config + }, +} diff --git a/examples/next-ts/package.json b/examples/next-ts/package.json index 1f9283937a..68fde6dc1c 100644 --- a/examples/next-ts/package.json +++ b/examples/next-ts/package.json @@ -1,5 +1,5 @@ { - "name": "with-typescript", + "name": "next-ts", "version": "0.0.0", "private": true, "scripts": { @@ -12,23 +12,21 @@ "dependencies": { "@emotion/core": "^11.0.0", "@emotion/styled": "^11.3.0", - "@reach/auto-id": "^0.15.0", - "@reach/portal": "^0.16.0", + "@reach/auto-id": "^0.16.0", + "@reach/portal": "^0.16.2", "@ui-machines/core": "0.0.0", "@ui-machines/react": "0.0.0", - "next": "latest", + "next": "^12.0.4", "react": "^17.0.2", - "react-dom": "^17.0.1", + "react-dom": "^17.0.2", "react-spinners": "^0.11.0" }, "devDependencies": { - "@preconstruct/next": "^3.0.0", "@types/node": "16.9.1", "@types/react": "^17.0.20", "@types/react-dom": "^17.0.1", "eslint-plugin-react": "^7.24.0", "eslint-plugin-react-hooks": "^4.2.0", - "regenerator-runtime": "^0.13.9", "typescript": "4.4.3" }, "license": "MIT" diff --git a/examples/next-ts/pages/accordion.tsx b/examples/next-ts/pages/accordion.tsx index 772e884d7b..fec5496b84 100644 --- a/examples/next-ts/pages/accordion.tsx +++ b/examples/next-ts/pages/accordion.tsx @@ -1,5 +1,5 @@ +import { accordion } from "@ui-machines/accordion" import { useMachine } from "@ui-machines/react" -import { accordion } from "@ui-machines/web" import { StateVisualizer } from "components/state-visualizer" import { useControls } from "hooks/use-controls" import { useMount } from "hooks/use-mount" diff --git a/examples/next-ts/pages/combobox.tsx b/examples/next-ts/pages/combobox.tsx index c46fe5fbc1..362f7cec28 100644 --- a/examples/next-ts/pages/combobox.tsx +++ b/examples/next-ts/pages/combobox.tsx @@ -1,9 +1,7 @@ /* eslint-disable jsx-a11y/label-has-associated-control */ -import { combobox } from "@ui-machines/web" -import { useMachine } from "@ui-machines/react" - import * as styled from "@emotion/styled" - +import { combobox } from "@ui-machines/combobox" +import { useMachine } from "@ui-machines/react" import { StateVisualizer } from "components/state-visualizer" import { useMount } from "hooks/use-mount" import { comboboxData } from "../../../shared/data" diff --git a/examples/next-ts/pages/dialog.tsx b/examples/next-ts/pages/dialog.tsx index 8e6fc7c6e4..893fe1d10c 100644 --- a/examples/next-ts/pages/dialog.tsx +++ b/examples/next-ts/pages/dialog.tsx @@ -1,6 +1,6 @@ import { Portal } from "@reach/portal" +import { dialog } from "@ui-machines/dialog" import { useMachine, useSetup } from "@ui-machines/react" -import { dialog } from "@ui-machines/web" import { StateVisualizer } from "components/state-visualizer" import { useRef } from "react" diff --git a/examples/next-ts/pages/editable.tsx b/examples/next-ts/pages/editable.tsx index e0fb7f8274..f629ac7fe7 100644 --- a/examples/next-ts/pages/editable.tsx +++ b/examples/next-ts/pages/editable.tsx @@ -1,5 +1,5 @@ +import { editable } from "@ui-machines/editable" import { useMachine, useSetup } from "@ui-machines/react" -import { editable } from "@ui-machines/web" import { StateVisualizer } from "components/state-visualizer" import { useControls } from "hooks/use-controls" diff --git a/examples/next-ts/pages/menu.tsx b/examples/next-ts/pages/menu.tsx index 79a323e676..40899be343 100644 --- a/examples/next-ts/pages/menu.tsx +++ b/examples/next-ts/pages/menu.tsx @@ -1,6 +1,6 @@ import { Global } from "@emotion/react" import { useMachine } from "@ui-machines/react" -import { menu } from "@ui-machines/web" +import { menu } from "@ui-machines/menu" import { StateVisualizer } from "components/state-visualizer" import { useMount } from "hooks/use-mount" import { menuStyle } from "../../../shared/style" diff --git a/examples/next-ts/pages/nested-menu.tsx b/examples/next-ts/pages/nested-menu.tsx index 547f959f91..ced5d1ccd0 100644 --- a/examples/next-ts/pages/nested-menu.tsx +++ b/examples/next-ts/pages/nested-menu.tsx @@ -1,10 +1,12 @@ import { useMachine } from "@ui-machines/react" -import { menu, mergeProps } from "@ui-machines/web" +import { menu } from "@ui-machines/menu" +import { mergeProps } from "@ui-machines/core" // import { StateVisualizer } from "components/state-visualizer" import { useMount } from "hooks/use-mount" import { useEffect } from "react" -import { nextTick } from "tiny-fn" -import { Styles } from "./menu" +import { nextTick } from "@ui-machines/dom-utils" +import { menuStyle } from "../../../shared/style" +import { Global } from "@emotion/react" export default function Page() { const [state, send, machine] = useMachine(menu.machine) @@ -51,7 +53,8 @@ export default function Page() { const triggerItem2Props = mergeProps(sub.getItemProps({ id: sub2.triggerProps.id }), sub2.triggerProps) return ( - + <> + @@ -119,6 +122,6 @@ export default function Page() { {/* */} - + ) } diff --git a/examples/next-ts/pages/number-input.tsx b/examples/next-ts/pages/number-input.tsx index 9293866234..00033656a6 100644 --- a/examples/next-ts/pages/number-input.tsx +++ b/examples/next-ts/pages/number-input.tsx @@ -1,10 +1,10 @@ /* eslint-disable jsx-a11y/label-has-associated-control */ -import { mergeProps, numberInput } from "@ui-machines/web" +import { mergeProps } from "@ui-machines/core" +import { numberInput } from "@ui-machines/number-input" import { useMachine } from "@ui-machines/react" - import { StateVisualizer } from "components/state-visualizer" -import { useMount } from "hooks/use-mount" import { useControls } from "hooks/use-controls" +import { useMount } from "hooks/use-mount" export default function Page() { const controls = useControls({ diff --git a/examples/next-ts/pages/pin-input.tsx b/examples/next-ts/pages/pin-input.tsx index 94120347f4..cea8a429ad 100644 --- a/examples/next-ts/pages/pin-input.tsx +++ b/examples/next-ts/pages/pin-input.tsx @@ -1,10 +1,9 @@ -import { pinInput } from "@ui-machines/web" +import { Global } from "@emotion/react" +import { pinInput } from "@ui-machines/pin-input" import { useMachine } from "@ui-machines/react" - import { StateVisualizer } from "components/state-visualizer" -import { useMount } from "hooks/use-mount" import { useControls } from "hooks/use-controls" -import { Global } from "@emotion/react" +import { useMount } from "hooks/use-mount" import { pinInputStyle } from "../../../shared/style" export default function Page() { diff --git a/examples/next-ts/pages/popover.tsx b/examples/next-ts/pages/popover.tsx index 9a61e061ec..533dcbd8ce 100644 --- a/examples/next-ts/pages/popover.tsx +++ b/examples/next-ts/pages/popover.tsx @@ -1,7 +1,7 @@ import { Global } from "@emotion/react" import { Portal } from "@reach/portal" +import { popover } from "@ui-machines/popover" import { useMachine } from "@ui-machines/react" -import { popover } from "@ui-machines/web" import { StateVisualizer } from "components/state-visualizer" import { useControls } from "hooks/use-controls" import { useMount } from "hooks/use-mount" diff --git a/examples/next-ts/pages/range-slider.tsx b/examples/next-ts/pages/range-slider.tsx index a5ace0eceb..314201f99c 100644 --- a/examples/next-ts/pages/range-slider.tsx +++ b/examples/next-ts/pages/range-slider.tsx @@ -1,14 +1,12 @@ -import { rangeSlider } from "@ui-machines/web" -import { useMachine } from "@ui-machines/react" - -import serialize from "form-serialize" import * as styled from "@emotion/styled" - +import { rangeSlider } from "@ui-machines/range-slider" +import { useMachine } from "@ui-machines/react" import { StateVisualizer } from "components/state-visualizer" +import serialize from "form-serialize" import { useMount } from "hooks/use-mount" import { rangeSliderStyle } from "../../../shared/style" -const Styles = styled.default(`div`)(rangeSliderStyle as styled.CSSObject) +const Styles = styled.default(`div`)(rangeSliderStyle) export default function Page() { const [state, send] = useMachine( diff --git a/examples/next-ts/pages/rating.tsx b/examples/next-ts/pages/rating.tsx index 05c9d347dc..618a14b7e1 100644 --- a/examples/next-ts/pages/rating.tsx +++ b/examples/next-ts/pages/rating.tsx @@ -1,6 +1,5 @@ -import { rating } from "@ui-machines/web" +import { rating } from "@ui-machines/rating" import { useMachine } from "@ui-machines/react" - import { StateVisualizer } from "components/state-visualizer" import { useMount } from "hooks/use-mount" diff --git a/examples/next-ts/pages/slider.tsx b/examples/next-ts/pages/slider.tsx index c5395ca68d..b4e8603eb7 100644 --- a/examples/next-ts/pages/slider.tsx +++ b/examples/next-ts/pages/slider.tsx @@ -1,7 +1,7 @@ /* eslint-disable jsx-a11y/label-has-associated-control */ import * as styled from "@emotion/styled" import { useMachine } from "@ui-machines/react" -import { slider } from "@ui-machines/web" +import { slider } from "@ui-machines/slider" import { StateVisualizer } from "components/state-visualizer" import serialize from "form-serialize" import { useMount } from "hooks/use-mount" diff --git a/examples/next-ts/pages/split-view.tsx b/examples/next-ts/pages/split-view.tsx index 5b075a1408..9440af6188 100644 --- a/examples/next-ts/pages/split-view.tsx +++ b/examples/next-ts/pages/split-view.tsx @@ -1,8 +1,6 @@ -import { splitView } from "@ui-machines/web" -import { useMachine } from "@ui-machines/react" - import * as styled from "@emotion/styled" - +import { useMachine } from "@ui-machines/react" +import { splitView } from "@ui-machines/split-view" import { StateVisualizer } from "components/state-visualizer" import { useMount } from "hooks/use-mount" import { splitViewStyle } from "../../../shared/style" diff --git a/examples/next-ts/pages/tabs.tsx b/examples/next-ts/pages/tabs.tsx index 20ca8471f3..85aa24e956 100644 --- a/examples/next-ts/pages/tabs.tsx +++ b/examples/next-ts/pages/tabs.tsx @@ -1,8 +1,8 @@ -import { tabs } from "@ui-machines/web" import { useMachine } from "@ui-machines/react" +import { tabs } from "@ui-machines/tabs" import { StateVisualizer } from "components/state-visualizer" -import { useMount } from "hooks/use-mount" import { useControls } from "hooks/use-controls" +import { useMount } from "hooks/use-mount" const tabsData = [ { diff --git a/examples/next-ts/pages/tags-input.tsx b/examples/next-ts/pages/tags-input.tsx index 2f822cc9bc..dbd0539ab2 100644 --- a/examples/next-ts/pages/tags-input.tsx +++ b/examples/next-ts/pages/tags-input.tsx @@ -1,12 +1,10 @@ -import { tagsInput } from "@ui-machines/web" -import { useMachine } from "@ui-machines/react" - import * as styled from "@emotion/styled" - +import { useMachine } from "@ui-machines/react" +import { tagsInput } from "@ui-machines/tags-input" import { StateVisualizer } from "components/state-visualizer" +import { useControls } from "hooks/use-controls" import { useMount } from "hooks/use-mount" import { tagsInputStyle } from "../../../shared/style" -import { useControls } from "hooks/use-controls" const Styles = styled.default(`div`)(tagsInputStyle as styled.CSSObject) diff --git a/examples/next-ts/pages/toast.tsx b/examples/next-ts/pages/toast.tsx index 2aa05d814a..01681f80f9 100644 --- a/examples/next-ts/pages/toast.tsx +++ b/examples/next-ts/pages/toast.tsx @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ import { Global } from "@emotion/react" import { useActor, useMachine } from "@ui-machines/react" -import { toast, ToastMachine } from "@ui-machines/web" +import { toast, ToastMachine } from "@ui-machines/toast" import { StateVisualizer } from "components/state-visualizer" import { useMount } from "hooks/use-mount" import { useRef } from "react" @@ -19,7 +19,6 @@ const Toast = ({ actor }: { actor: ToastMachine }) => {
       
       

{ctx.title}

- {/* @ts-expect-error */}

{ctx.type === "loading" ? : null}

diff --git a/examples/next-ts/pages/tooltip.tsx b/examples/next-ts/pages/tooltip.tsx index 83f0cdb9f1..284a8f7b58 100644 --- a/examples/next-ts/pages/tooltip.tsx +++ b/examples/next-ts/pages/tooltip.tsx @@ -1,5 +1,5 @@ import { useMachine, useSetup } from "@ui-machines/react" -import { tooltip } from "@ui-machines/web" +import { tooltip } from "@ui-machines/tooltip" function Tooltip(props: { id?: string }) { const [state, send] = useMachine(tooltip.machine) diff --git a/examples/next-ts/tsconfig.json b/examples/next-ts/tsconfig.json index eaf14ae54c..2f275119c0 100644 --- a/examples/next-ts/tsconfig.json +++ b/examples/next-ts/tsconfig.json @@ -18,11 +18,8 @@ "strict": false, "target": "esnext", "baseUrl": ".", - "paths": { - "@ui-machines/core": ["../../packages/core/src"], - "@ui-machines/react": ["../../packages/frameworks/react/src"] - } + "incremental": true }, "exclude": ["node_modules"], - "include": ["**/*.ts", "**/*.tsx", "next-env.d.ts"] + "include": ["**/*.ts", "**/*.tsx", "next-env.d.ts", "next.config.js"] } diff --git a/examples/solid-ts/package.json b/examples/solid-ts/package.json index cdb68ffb8f..ffbe088157 100644 --- a/examples/solid-ts/package.json +++ b/examples/solid-ts/package.json @@ -2,6 +2,7 @@ "name": "solid-ts", "version": "0.0.0", "description": "", + "private": true, "scripts": { "clean": "echo 'clean'", "dev": "vite", diff --git a/examples/solid-ts/src/components/state-visualizer.tsx b/examples/solid-ts/src/components/state-visualizer.tsx index 74e8b572e0..b3f78673b3 100644 --- a/examples/solid-ts/src/components/state-visualizer.tsx +++ b/examples/solid-ts/src/components/state-visualizer.tsx @@ -1,4 +1,4 @@ -import { isDom } from "tiny-guard" +import { isDom } from "@ui-machines/utils" import { Machine } from "@ui-machines/core" type StateVisualizerProps = { diff --git a/examples/solid-ts/src/pages/accordion.tsx b/examples/solid-ts/src/pages/accordion.tsx index a73083638c..80600aa3a6 100644 --- a/examples/solid-ts/src/pages/accordion.tsx +++ b/examples/solid-ts/src/pages/accordion.tsx @@ -1,4 +1,4 @@ -import { accordion } from "@ui-machines/web" +import { accordion } from "@ui-machines/accordion" import { normalizeProps, useMachine, useSetup, SolidPropTypes } from "@ui-machines/solid" import { createMemo } from "solid-js" import { StateVisualizer } from "../components/state-visualizer" diff --git a/examples/solid-ts/src/pages/combobox.tsx b/examples/solid-ts/src/pages/combobox.tsx index 43c8621581..aa3b8cd8d2 100644 --- a/examples/solid-ts/src/pages/combobox.tsx +++ b/examples/solid-ts/src/pages/combobox.tsx @@ -1,4 +1,4 @@ -import { combobox } from "@ui-machines/web" +import { combobox } from "@ui-machines/combobox" import { normalizeProps, useMachine, useSetup, SolidPropTypes } from "@ui-machines/solid" import { createMemo, For } from "solid-js" diff --git a/examples/solid-ts/src/pages/editable.tsx b/examples/solid-ts/src/pages/editable.tsx index 3e51e7eda7..7c62d0d7c6 100644 --- a/examples/solid-ts/src/pages/editable.tsx +++ b/examples/solid-ts/src/pages/editable.tsx @@ -1,4 +1,4 @@ -import { editable } from "@ui-machines/web" +import { editable } from "@ui-machines/editable" import { normalizeProps, useMachine, useSetup, SolidPropTypes } from "@ui-machines/solid" import { createMemo } from "solid-js" import { StateVisualizer } from "../components/state-visualizer" diff --git a/examples/solid-ts/src/pages/menu.tsx b/examples/solid-ts/src/pages/menu.tsx index 5ac35ba36b..cc45376363 100644 --- a/examples/solid-ts/src/pages/menu.tsx +++ b/examples/solid-ts/src/pages/menu.tsx @@ -1,4 +1,4 @@ -import { menu } from "@ui-machines/web" +import { menu } from "@ui-machines/menu" import { normalizeProps, useMachine, useSetup, SolidPropTypes } from "@ui-machines/solid" import { createMemo } from "solid-js" diff --git a/examples/solid-ts/src/pages/number-input.tsx b/examples/solid-ts/src/pages/number-input.tsx index eaee0d638b..1c6ff48a97 100644 --- a/examples/solid-ts/src/pages/number-input.tsx +++ b/examples/solid-ts/src/pages/number-input.tsx @@ -1,8 +1,7 @@ -import { mergeProps, numberInput } from "@ui-machines/web" -import { normalizeProps, useMachine, useSetup, SolidPropTypes } from "@ui-machines/solid" - +import { mergeProps } from "@ui-machines/core" +import { numberInput } from "@ui-machines/number-input" +import { normalizeProps, SolidPropTypes, useMachine, useSetup } from "@ui-machines/solid" import { createMemo } from "solid-js" - import { StateVisualizer } from "../components/state-visualizer" export default function Page() { diff --git a/examples/solid-ts/src/pages/pin-input.tsx b/examples/solid-ts/src/pages/pin-input.tsx index 9c7fda4a34..2bf418e25c 100644 --- a/examples/solid-ts/src/pages/pin-input.tsx +++ b/examples/solid-ts/src/pages/pin-input.tsx @@ -1,4 +1,4 @@ -import { pinInput } from "@ui-machines/web" +import { pinInput } from "@ui-machines/pin-input" import { normalizeProps, useMachine, useSetup, SolidPropTypes } from "@ui-machines/solid" import { createMemo } from "solid-js" diff --git a/examples/solid-ts/src/pages/popover.tsx b/examples/solid-ts/src/pages/popover.tsx index be9cf2e547..bfd58b8883 100644 --- a/examples/solid-ts/src/pages/popover.tsx +++ b/examples/solid-ts/src/pages/popover.tsx @@ -1,4 +1,4 @@ -import { popover } from "@ui-machines/web" +import { popover } from "@ui-machines/popover" import { normalizeProps, useMachine, useSetup, SolidPropTypes } from "@ui-machines/solid" import { createMemo } from "solid-js" diff --git a/examples/solid-ts/src/pages/range-slider.tsx b/examples/solid-ts/src/pages/range-slider.tsx index e9f30aaefb..4641977681 100644 --- a/examples/solid-ts/src/pages/range-slider.tsx +++ b/examples/solid-ts/src/pages/range-slider.tsx @@ -1,4 +1,4 @@ -import { rangeSlider } from "@ui-machines/web" +import { rangeSlider } from "@ui-machines/range-slider" import { normalizeProps, useMachine, useSetup, SolidPropTypes } from "@ui-machines/solid" import { createMemo, For } from "solid-js" diff --git a/examples/solid-ts/src/pages/rating.tsx b/examples/solid-ts/src/pages/rating.tsx index 6398f90fdf..639d5cb382 100644 --- a/examples/solid-ts/src/pages/rating.tsx +++ b/examples/solid-ts/src/pages/rating.tsx @@ -1,4 +1,4 @@ -import { rating } from "@ui-machines/web" +import { rating } from "@ui-machines/rating" import { normalizeProps, useMachine, useSetup, SolidPropTypes } from "@ui-machines/solid" import { createMemo } from "solid-js" diff --git a/examples/solid-ts/src/pages/slider.tsx b/examples/solid-ts/src/pages/slider.tsx index eab9b582e6..8930b20a58 100644 --- a/examples/solid-ts/src/pages/slider.tsx +++ b/examples/solid-ts/src/pages/slider.tsx @@ -1,4 +1,4 @@ -import { slider } from "@ui-machines/web" +import { slider } from "@ui-machines/slider" import { normalizeProps, useMachine, useSetup, SolidPropTypes } from "@ui-machines/solid" import { createMemo } from "solid-js" diff --git a/examples/solid-ts/src/pages/split-view.tsx b/examples/solid-ts/src/pages/split-view.tsx index a04ff36cf1..3a49b419f1 100644 --- a/examples/solid-ts/src/pages/split-view.tsx +++ b/examples/solid-ts/src/pages/split-view.tsx @@ -1,4 +1,4 @@ -import { splitView } from "@ui-machines/web" +import { splitView } from "@ui-machines/split-view" import { normalizeProps, useMachine, useSetup, SolidPropTypes } from "@ui-machines/solid" import { createMemo } from "solid-js" diff --git a/examples/solid-ts/src/pages/tabs.tsx b/examples/solid-ts/src/pages/tabs.tsx index c625b2c15b..36ddb63140 100644 --- a/examples/solid-ts/src/pages/tabs.tsx +++ b/examples/solid-ts/src/pages/tabs.tsx @@ -1,4 +1,4 @@ -import { tabs } from "@ui-machines/web" +import { tabs } from "@ui-machines/tabs" import { normalizeProps, useMachine, useSetup, SolidPropTypes } from "@ui-machines/solid" import { createMemo } from "solid-js" diff --git a/examples/solid-ts/src/pages/tags-input.tsx b/examples/solid-ts/src/pages/tags-input.tsx index ab1ef70e3c..06171b4750 100644 --- a/examples/solid-ts/src/pages/tags-input.tsx +++ b/examples/solid-ts/src/pages/tags-input.tsx @@ -1,4 +1,4 @@ -import { tagsInput } from "@ui-machines/web" +import { tagsInput } from "@ui-machines/tags-input" import { normalizeProps, useMachine, useSetup, SolidPropTypes } from "@ui-machines/solid" import { createMemo } from "solid-js" diff --git a/examples/vue-ts/package.json b/examples/vue-ts/package.json index 42678d86f6..be906b3ccc 100644 --- a/examples/vue-ts/package.json +++ b/examples/vue-ts/package.json @@ -1,5 +1,5 @@ { - "name": "with-typescript-on-vue", + "name": "vue-ts", "version": "0.0.0", "private": true, "scripts": { @@ -34,28 +34,10 @@ "optimizeDeps": { "include": [ "@emotion/css", - "@vue/runtime-core", - "aria-hidden", - "focus-trap", "klona", "merge-anything", + "react", "scroll-into-view-if-needed", - "tiny-array", - "tiny-dom-event", - "tiny-dom-query", - "tiny-dom-query/focusable", - "tiny-dom-query/scrollable", - "tiny-dom-query/tabbable", - "tiny-fn", - "tiny-guard", - "tiny-nodelist", - "tiny-num", - "tiny-point/distance", - "tiny-point/dom", - "tiny-point/within", - "tiny-rect", - "tiny-rect/from-element", - "tiny-rect/operations", "valtio", "valtio/utils", "valtio/vanilla", diff --git a/examples/vue-ts/src/components/state-visualizer.tsx b/examples/vue-ts/src/components/state-visualizer.tsx index b6b823561c..56ccfc6047 100644 --- a/examples/vue-ts/src/components/state-visualizer.tsx +++ b/examples/vue-ts/src/components/state-visualizer.tsx @@ -1,11 +1,11 @@ -import { isDom } from "tiny-guard" +import { isDom } from "@ui-machines/utils" import { h, SetupContext } from "vue" export function StateVisualizer(props: { state: Record }, { attrs }: SetupContext) { const { state } = props return (
(config: T) {
                       type="checkbox"
                       checked={state.value[key] as boolean}
                       onInput={(e) => {
+                        //@ts-expect-error
                         state.value[key] = e.currentTarget.checked
                       }}
                     />
@@ -90,10 +91,10 @@ export function useControls(config: T) {
                       type="text"
                       placeholder={placeholder}
                       value={state.value[key] as string}
-                      //@ts-expect-error
-                      onKeydown={(e) => {
-                        if (e.key === "Enter") {
-                          state.value[key] = (e.target as HTMLInputElement).value
+                      onKeydown={(event) => {
+                        if (event.key === "Enter") {
+                          //@ts-expect-error
+                          state.value[key] = (event.target as HTMLInputElement).value
                         }
                       }}
                     />
@@ -110,11 +111,12 @@ export function useControls(config: T) {
                       id={label}
                       value={state.value[key] as string}
                       onChange={(e) => {
+                        //@ts-expect-error
                         state.value[key] = (e.target as HTMLSelectElement).value
                       }}
                     >
                       
-                      {options.map((option) => (
+                      {options.map((option: any) => (
                         
@@ -137,6 +139,7 @@ export function useControls(config: T) {
                       value={state.value[key] as number}
                       onKeydown={(e) => {
                         if (e.key === "Enter") {
+                          //@ts-expect-error
                           state.value[key] = (e.target as HTMLInputElement).valueAsNumber
                         }
                       }}
diff --git a/examples/vue-ts/src/hooks/use-id.ts b/examples/vue-ts/src/hooks/use-id.ts
index 044e7e0873..9323944320 100644
--- a/examples/vue-ts/src/hooks/use-id.ts
+++ b/examples/vue-ts/src/hooks/use-id.ts
@@ -1,38 +1,3 @@
-/**
- * Credit: https://github.com/reach/reach-ui/blob/develop/packages/auto-id/src/index.tsx
- *
- * Why does this hook exist?
- *   1. Accessibiliy APIs rely heavily on element IDs
- *   2. Requiring developers to put IDs on every Chakra component
- *      is cumbersome and error-prone.
- *   3. With a components model, we can generate IDs for them!
- *
- * Solutions to ID problem:
- * 1. Generate random IDs
- *    We did this before in prior projects
- *    Since then, we've learned some things about performance for
- *    components especially with SSR.
- *
- *    This may not be a good idea because during server rendering
- *    the IDs will be statically generated, and during client-side hydration,
- *    the IDs may not match, when booting up the Vue App. Vue will then
- *    go ahead and recreate the entire application.
- *
- * 2. Don't server render IDs. Instead patch on client `onMounted`
- *    In this approach, generated ID is an empty string on the first render.
- *    This way the client and server possess the same ID.
- *
- *    When the component is finally mounted, we patch the ID.
- *    This may cause a re-render on the client, but it shouldn't be a
- *    big problem, because:
- *
- *        1. Components using `useId` composable are small
- *        2. With solution 1, it would cause a re-render anyway.
- *        3. This patch only runs once. (Only when the `onMounted` life
- *           -cycle hook is called.)
- *
- */
-
 import { computed, onBeforeMount, onMounted, ref } from "vue"
 
 let serverHandoffComplete = false
diff --git a/examples/vue-ts/src/pages/accordion.tsx b/examples/vue-ts/src/pages/accordion.tsx
index 78e67045e1..e2a33954f0 100644
--- a/examples/vue-ts/src/pages/accordion.tsx
+++ b/examples/vue-ts/src/pages/accordion.tsx
@@ -1,4 +1,4 @@
-import { accordion } from "@ui-machines/web"
+import { accordion } from "@ui-machines/accordion"
 import { useMachine, normalizeProps, VuePropTypes } from "@ui-machines/vue"
 import { defineComponent, h, Fragment, computed, watch } from "vue"
 import { StateVisualizer } from "../components/state-visualizer"
diff --git a/examples/vue-ts/src/pages/combobox.tsx b/examples/vue-ts/src/pages/combobox.tsx
index e3c4c16a5c..9ee56bb621 100644
--- a/examples/vue-ts/src/pages/combobox.tsx
+++ b/examples/vue-ts/src/pages/combobox.tsx
@@ -1,4 +1,4 @@
-import { combobox } from "@ui-machines/web"
+import { combobox } from "@ui-machines/combobox"
 import { useMachine, normalizeProps, VuePropTypes } from "@ui-machines/vue"
 
 import { defineComponent, h, Fragment, computed } from "vue"
diff --git a/examples/vue-ts/src/pages/editable.tsx b/examples/vue-ts/src/pages/editable.tsx
index 2ee9eb547e..6c6df82283 100644
--- a/examples/vue-ts/src/pages/editable.tsx
+++ b/examples/vue-ts/src/pages/editable.tsx
@@ -1,4 +1,4 @@
-import { editable } from "@ui-machines/web"
+import { editable } from "@ui-machines/editable"
 import { useMachine, normalizeProps, VuePropTypes } from "@ui-machines/vue"
 
 import { defineComponent, h, Fragment, computed } from "vue"
diff --git a/examples/vue-ts/src/pages/menu.tsx b/examples/vue-ts/src/pages/menu.tsx
index d54ab0febe..47f337658f 100644
--- a/examples/vue-ts/src/pages/menu.tsx
+++ b/examples/vue-ts/src/pages/menu.tsx
@@ -1,4 +1,4 @@
-import { menu } from "@ui-machines/web"
+import { menu } from "@ui-machines/menu"
 import { useMachine, normalizeProps, VuePropTypes } from "@ui-machines/vue"
 
 import { defineComponent, h, Fragment, computed } from "vue"
diff --git a/examples/vue-ts/src/pages/number-input.tsx b/examples/vue-ts/src/pages/number-input.tsx
index 99ccabc812..693367c056 100644
--- a/examples/vue-ts/src/pages/number-input.tsx
+++ b/examples/vue-ts/src/pages/number-input.tsx
@@ -1,4 +1,5 @@
-import { mergeProps, numberInput } from "@ui-machines/web"
+import { numberInput } from "@ui-machines/number-input"
+import { mergeProps } from "@ui-machines/core"
 import { useMachine, normalizeProps, VuePropTypes } from "@ui-machines/vue"
 
 import { computed, nextTick, onMounted, ref, h, Fragment } from "vue"
diff --git a/examples/vue-ts/src/pages/pin-input.tsx b/examples/vue-ts/src/pages/pin-input.tsx
index 01ece36009..3b658e5676 100644
--- a/examples/vue-ts/src/pages/pin-input.tsx
+++ b/examples/vue-ts/src/pages/pin-input.tsx
@@ -1,4 +1,4 @@
-import { pinInput } from "@ui-machines/web"
+import { pinInput } from "@ui-machines/pin-input"
 import { useMachine, normalizeProps, VuePropTypes } from "@ui-machines/vue"
 
 import { computed, h, Fragment } from "vue"
diff --git a/examples/vue-ts/src/pages/popover.tsx b/examples/vue-ts/src/pages/popover.tsx
index a074fc36a3..464360c92e 100644
--- a/examples/vue-ts/src/pages/popover.tsx
+++ b/examples/vue-ts/src/pages/popover.tsx
@@ -1,4 +1,4 @@
-import { popover } from "@ui-machines/web"
+import { popover } from "@ui-machines/popover"
 import { useMachine, normalizeProps, VuePropTypes } from "@ui-machines/vue"
 
 import { computed, h, Fragment } from "vue"
diff --git a/examples/vue-ts/src/pages/range-slider.tsx b/examples/vue-ts/src/pages/range-slider.tsx
index e2eb3aa335..62378f4666 100644
--- a/examples/vue-ts/src/pages/range-slider.tsx
+++ b/examples/vue-ts/src/pages/range-slider.tsx
@@ -1,4 +1,4 @@
-import { rangeSlider } from "@ui-machines/web"
+import { rangeSlider } from "@ui-machines/range-slider"
 import { useMachine, normalizeProps, VuePropTypes } from "@ui-machines/vue"
 
 import { computed, h, Fragment } from "vue"
diff --git a/examples/vue-ts/src/pages/rating.tsx b/examples/vue-ts/src/pages/rating.tsx
index 694c5f8382..bce9c3f7d2 100644
--- a/examples/vue-ts/src/pages/rating.tsx
+++ b/examples/vue-ts/src/pages/rating.tsx
@@ -1,4 +1,4 @@
-import { rating } from "@ui-machines/web"
+import { rating } from "@ui-machines/rating"
 import { useMachine, normalizeProps, VuePropTypes } from "@ui-machines/vue"
 
 import { computed, h, Fragment } from "vue"
diff --git a/examples/vue-ts/src/pages/slider.tsx b/examples/vue-ts/src/pages/slider.tsx
index b66101ccd0..75a4a60d93 100644
--- a/examples/vue-ts/src/pages/slider.tsx
+++ b/examples/vue-ts/src/pages/slider.tsx
@@ -1,4 +1,4 @@
-import { slider } from "@ui-machines/web"
+import { slider } from "@ui-machines/slider"
 import { useMachine, normalizeProps, VuePropTypes } from "@ui-machines/vue"
 
 import { computed, h, Fragment } from "vue"
diff --git a/examples/vue-ts/src/pages/split-view.tsx b/examples/vue-ts/src/pages/split-view.tsx
index c71d8e8952..919a60cfd1 100644
--- a/examples/vue-ts/src/pages/split-view.tsx
+++ b/examples/vue-ts/src/pages/split-view.tsx
@@ -1,4 +1,4 @@
-import { splitView } from "@ui-machines/web"
+import { splitView } from "@ui-machines/split-view"
 import { useMachine, normalizeProps, VuePropTypes } from "@ui-machines/vue"
 
 import { computed, h, Fragment } from "vue"
diff --git a/examples/vue-ts/src/pages/tabs.tsx b/examples/vue-ts/src/pages/tabs.tsx
index 00481f51cf..7f2e131ca2 100644
--- a/examples/vue-ts/src/pages/tabs.tsx
+++ b/examples/vue-ts/src/pages/tabs.tsx
@@ -1,4 +1,4 @@
-import { tabs } from "@ui-machines/web"
+import { tabs } from "@ui-machines/tabs"
 import { useMachine, normalizeProps, VuePropTypes } from "@ui-machines/vue"
 import { computed, h, Fragment } from "vue"
 import { defineComponent } from "@vue/runtime-core"
diff --git a/examples/vue-ts/src/pages/tags-input.tsx b/examples/vue-ts/src/pages/tags-input.tsx
index 3b91cafaa4..bb886dd5f6 100644
--- a/examples/vue-ts/src/pages/tags-input.tsx
+++ b/examples/vue-ts/src/pages/tags-input.tsx
@@ -1,4 +1,4 @@
-import { tagsInput } from "@ui-machines/web"
+import { tagsInput } from "@ui-machines/tags-input"
 import { useMachine, normalizeProps, VuePropTypes } from "@ui-machines/vue"
 
 import { computed, h, Fragment } from "vue"
diff --git a/examples/vue-ts/src/pages/toast.tsx b/examples/vue-ts/src/pages/toast.tsx
index d50d9c0720..68c0d2e90f 100644
--- a/examples/vue-ts/src/pages/toast.tsx
+++ b/examples/vue-ts/src/pages/toast.tsx
@@ -1,6 +1,6 @@
 import { computed, h, Fragment, defineComponent, ref, PropType } from "vue"
 import { useMachine, normalizeProps, useActor, VuePropTypes } from "@ui-machines/vue"
-import { toast, ToastMachine } from "@ui-machines/web"
+import { toast, ToastMachine } from "@ui-machines/toast"
 import { HollowDotsSpinner } from "epic-spinners"
 import { useMount } from "../hooks/use-mount"
 import { injectGlobal } from "@emotion/css"
diff --git a/examples/vue-ts/src/pages/tooltip.tsx b/examples/vue-ts/src/pages/tooltip.tsx
index 10ee384280..1c64014492 100644
--- a/examples/vue-ts/src/pages/tooltip.tsx
+++ b/examples/vue-ts/src/pages/tooltip.tsx
@@ -1,6 +1,6 @@
 import { defineComponent, computed, h, Fragment, PropType } from "vue"
 import { useMachine, normalizeProps, useSnapshot, VuePropTypes } from "@ui-machines/vue"
-import { tooltip } from "@ui-machines/web"
+import { tooltip } from "@ui-machines/tooltip"
 import { useMount } from "../hooks/use-mount"
 
 const Tooltip = defineComponent({
diff --git a/package.json b/package.json
index 4a317f4b96..4f6e752808 100644
--- a/package.json
+++ b/package.json
@@ -9,8 +9,16 @@
   "author": "Segun Adebayo ",
   "license": "MIT",
   "scripts": {
-    "build": "preconstruct build",
-    "clean": "yarn workspaces run clean",
+    "buildr": "esr scripts/build.ts",
+    "dev": "yarn buildr --dev",
+    "watch": "yarn buildr --dev --watch",
+    "build:bundle": "yarn buildr",
+    "prepare": "husky install && yarn dev",
+    "clean": "esr scripts/generate-typings.ts",
+    "build:types": "ultra -r --silent --concurrency 20 --filter \"@ui-machines/*\" \"tsc src/index.ts --declaration --emitDeclarationOnly --target es2018 --outDir dist --skipLibCheck --moduleResolution node --strict false\"",
+    "prebuild": "yarn clean && yarn build:types",
+    "build": "yarn build:bundle",
+    "build:ci": "yarn build:bundle",
     "start:react": "cd examples/next-ts && yarn dev",
     "start:vue": "cd examples/vue-ts && yarn dev",
     "start:solid": "cd examples/solid-ts && yarn dev",
@@ -19,22 +27,11 @@
     "cypress:run": "cypress run",
     "cypress:dev": "cypress open",
     "fix:pkgs": "manypkg fix",
-    "fix:preconstruct": "preconstruct fix",
     "gen:machine": "ts-node scripts/generate-machine.ts",
     "gen:util": "ts-node scripts/generate-util.ts",
-    "lint": "npm-run-all lint:**",
-    "lint:code": "eslint . --ext .js,.jsx,.ts,.tsx -c .eslintrc",
-    "lint:pkgs": "manypkg check",
-    "lint:types": "tsc --noEmit --incremental",
-    "lint:validate": "preconstruct validate",
-    "pkg": "manypkg run",
+    "lint": "eslint packages --ext .ts",
     "postinstall": "patch-package",
-    "prebuild": "yarn clean",
-    "prepare": "npm-run-all -s prepare:**",
-    "prepare:husky": "husky install",
-    "prepare:preconstruct": "preconstruct dev",
     "release": "changeset publish",
-    "start": "preconstruct watch",
     "test": "jest --maxWorkers=50%",
     "test:ci": "jest --runInBand"
   },
@@ -52,7 +49,6 @@
     "@commitlint/cli": "^12.1.4",
     "@commitlint/config-conventional": "^12.1.4",
     "@manypkg/cli": "^0.17.0",
-    "@preconstruct/cli": "^2.1.0",
     "@swc-node/jest": "^1.3.3",
     "@testing-library/cypress": "^8.0.1",
     "@testing-library/jest-dom": "^5.14.1",
@@ -63,11 +59,15 @@
     "@typescript-eslint/eslint-plugin": "^4.23.0",
     "@typescript-eslint/parser": "^4.23.0",
     "axe-core": "^4.3.3",
+    "chalk": "^4.1.2",
+    "chokidar": "^3.5.2",
     "commitlint": "^12.1.4",
     "cypress": "^8.5.0",
     "cypress-axe": "^0.13.0",
     "cypress-plugin-tab": "^1.0.5",
     "cypress-real-events": "^1.5.1",
+    "esbuild": "^0.13.14",
+    "esbuild-runner": "^2.2.1",
     "eslint": "^7.26.0",
     "eslint-config-prettier": "^8.3.0",
     "eslint-plugin-cypress": "^2.11.3",
@@ -77,6 +77,7 @@
     "eslint-plugin-prettier": "^3.4.0",
     "eslint-plugin-testing-library": "^4.4.0",
     "form-serialize": "^0.7.2",
+    "gzip-size": "6.0.0",
     "husky": "^6.0.0",
     "jest": "^26.6.3",
     "jest-environment-jsdom": "^26.6.2",
@@ -84,29 +85,22 @@
     "lint-staged": "^11.0.0",
     "lodash": "^4.17.21",
     "node-plop": "^0.26.2",
-    "npm-run-all": "^4.1.5",
     "patch-package": "^6.4.7",
     "prettier": "^2.3.0",
+    "pretty-bytes": "^5.6.0",
     "rimraf": "^3.0.2",
     "shelljs": "^0.8.4",
     "start-server-and-test": "^1.14.0",
-    "ts-node": "^9.1.1",
-    "typescript": "4.4.3"
-  },
-  "preconstruct": {
-    "packages": [
-      "packages/prop-types",
-      "packages/core",
-      "packages/machines",
-      "packages/frameworks/*"
-    ]
+    "typescript": "4.4.3",
+    "ultra-runner": "^3.10.5"
   },
   "workspaces": {
     "packages": [
-      "packages/prop-types",
       "packages/core",
-      "packages/machines",
+      "packages/machines/*",
       "packages/frameworks/*",
+      "packages/types",
+      "packages/utilities/*",
       "examples/*"
     ]
   },
@@ -118,17 +112,6 @@
       "prettier --write"
     ]
   },
-  "prettier": {
-    "bracketSpacing": true,
-    "jsxBracketSameLine": false,
-    "jsxSingleQuote": false,
-    "printWidth": 120,
-    "proseWrap": "always",
-    "semi": false,
-    "singleQuote": false,
-    "tabWidth": 2,
-    "trailingComma": "all"
-  },
   "commitlint": {
     "extends": [
       "@commitlint/config-conventional"
diff --git a/packages/core/package.json b/packages/core/package.json
index 21ac3002c2..4ce22b57d3 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -11,8 +11,9 @@
   "author": "Segun Adebayo ",
   "homepage": "https://github.com/chakra-ui/core#readme",
   "license": "MIT",
-  "main": "dist/ui-machines-core.cjs.js",
-  "module": "dist/ui-machines-core.esm.js",
+  "main": "dist/index.js",
+  "module": "dist/index.mjs",
+  "types": "dist/index.d.ts",
   "repository": "https://github.com/chakra-ui/core/tree/main/packages/machine",
   "sideEffects": false,
   "files": [
@@ -24,13 +25,8 @@
   "bugs": {
     "url": "https://github.com/chakra-ui/core/issues"
   },
-  "scripts": {
-    "clean": "rimraf dist"
-  },
   "dependencies": {
-    "klona": "^2.0.4",
-    "tiny-fn": "^0.0.2",
-    "tiny-guard": "^0.0.3",
-    "valtio": "^1.2.5"
+    "valtio": "^1.2.5",
+    "klona": "^2.0.4"
   }
 }
diff --git a/packages/core/src/action-utils.ts b/packages/core/src/action-utils.ts
index b4aaed9941..c2506cf087 100644
--- a/packages/core/src/action-utils.ts
+++ b/packages/core/src/action-utils.ts
@@ -1,4 +1,4 @@
-import { isObject, isString } from "tiny-guard"
+import { isObject, isString } from "@ui-machines/utils"
 import { Dict, StateMachine as S } from "./types"
 
 export function choose(
diff --git a/packages/core/src/create-proxy.ts b/packages/core/src/create-proxy.ts
index d64a7f258b..92044cb621 100644
--- a/packages/core/src/create-proxy.ts
+++ b/packages/core/src/create-proxy.ts
@@ -1,5 +1,5 @@
-import { cast } from "tiny-fn"
 import { proxy } from "valtio"
+import { cast } from "@ui-machines/utils"
 import { ActionTypes, Dict, StateMachine as S } from "./types"
 
 export function createProxy(
diff --git a/packages/core/src/delay-utils.ts b/packages/core/src/delay-utils.ts
index dcd05fcf8c..c9d5862d60 100644
--- a/packages/core/src/delay-utils.ts
+++ b/packages/core/src/delay-utils.ts
@@ -1,4 +1,4 @@
-import { isFunction, isNumber, isString } from "tiny-guard"
+import { isFunction, isNumber, isString } from "@ui-machines/utils"
 import { StateMachine as S } from "./types"
 
 /**
diff --git a/packages/core/src/guard-utils.ts b/packages/core/src/guard-utils.ts
index 7142d8ff16..41a7e5b24b 100644
--- a/packages/core/src/guard-utils.ts
+++ b/packages/core/src/guard-utils.ts
@@ -1,4 +1,4 @@
-import { isFunction, isObject, isString } from "tiny-guard"
+import { isFunction, isObject, isString } from "@ui-machines/utils"
 import { Dict, StateMachine as S } from "./types"
 
 function or(
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index 96d2d2543b..806abd0a0b 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -1,5 +1,6 @@
-export { ref, subscribe, snapshot } from "valtio/vanilla"
-export { guards } from "./guard-utils"
+export { proxy, ref, snapshot, subscribe } from "valtio/vanilla"
 export { choose } from "./action-utils"
+export { guards } from "./guard-utils"
 export * from "./machine"
+export { mergeProps } from "./merge-props"
 export type { StateMachine } from "./types"
diff --git a/packages/core/src/machine.ts b/packages/core/src/machine.ts
index 8ff52ca98d..b5105f0576 100644
--- a/packages/core/src/machine.ts
+++ b/packages/core/src/machine.ts
@@ -1,6 +1,5 @@
 import { klona } from "klona"
-import { cast, invariant, noop, runIfFn, warn } from "tiny-fn"
-import { isArray, isObject, isString } from "tiny-guard"
+import { cast, invariant, noop, runIfFn, warn, isArray, isObject, isString, uuid } from "@ui-machines/utils"
 import { derive, subscribeKey, underive } from "valtio/utils"
 import { ref, snapshot, subscribe } from "valtio/vanilla"
 import { determineActionsFn } from "./action-utils"
@@ -9,7 +8,7 @@ import { determineDelayFn } from "./delay-utils"
 import { determineGuardFn } from "./guard-utils"
 import { determineTransitionFn, toTransition } from "./transition-utils"
 import { ActionTypes, Dict, MachineStatus, MachineType, StateMachine as S, VoidFunction } from "./types"
-import { toArray, toEvent, uniqueId } from "./utils"
+import { toArray, toEvent } from "./utils"
 
 export class Machine<
   TContext extends Dict,
@@ -51,7 +50,7 @@ export class Machine<
     public config: S.MachineConfig,
     public options?: S.MachineOptions,
   ) {
-    this.id = config.id ?? `machine-${uniqueId()}`
+    this.id = config.id ?? `machine-${uuid()}`
     this.state = createProxy(config)
     this.guardMap = options?.guards ?? {}
     this.actionMap = options?.actions ?? {}
diff --git a/packages/machines/src/utils/merge-props.ts b/packages/core/src/merge-props.ts
similarity index 89%
rename from packages/machines/src/utils/merge-props.ts
rename to packages/core/src/merge-props.ts
index ebadd10dcf..be76f6bf4c 100644
--- a/packages/machines/src/utils/merge-props.ts
+++ b/packages/core/src/merge-props.ts
@@ -1,5 +1,4 @@
-import { merge } from "merge-anything"
-import { callAll } from "tiny-fn"
+import { callAll } from "@ui-machines/utils"
 
 interface Props {
   [key: string]: any
@@ -31,7 +30,7 @@ export function mergeProps(...args: T): UnionToIntersection(event: S.Event): T {
@@ -10,11 +10,3 @@ export function toArray(value: T | T[] | undefined): T[] {
   if (!value) return []
   return isArray(value) ? value : [value]
 }
-
-export const uniqueId = (() => {
-  let id = 0
-  return () => {
-    id++
-    return id.toString(16)
-  }
-})()
diff --git a/packages/frameworks/react/package.json b/packages/frameworks/react/package.json
index 2bde66365b..e278b1353b 100644
--- a/packages/frameworks/react/package.json
+++ b/packages/frameworks/react/package.json
@@ -11,8 +11,9 @@
   "author": "Segun Adebayo ",
   "homepage": "https://github.com/chakra-ui/ui-machines#readme",
   "license": "MIT",
-  "main": "dist/ui-machines-react.cjs.js",
-  "module": "dist/ui-machines-react.esm.js",
+  "main": "dist/index.js",
+  "module": "dist/index.mjs",
+  "types": "dist/index.d.ts",
   "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/frameworks/react",
   "sideEffects": false,
   "files": [
@@ -24,12 +25,8 @@
   "bugs": {
     "url": "https://github.com/chakra-ui/ui-machines/issues"
   },
-  "scripts": {
-    "clean": "rimraf dist"
-  },
   "dependencies": {
     "@ui-machines/core": "0.0.0",
-    "tiny-guard": "^0.0.3",
     "valtio": "^1.2.5"
   },
   "devDependencies": {
diff --git a/packages/frameworks/react/src/use-actor.ts b/packages/frameworks/react/src/use-actor.ts
index 512068311e..9954c601f8 100644
--- a/packages/frameworks/react/src/use-actor.ts
+++ b/packages/frameworks/react/src/use-actor.ts
@@ -1,4 +1,4 @@
-import type { Machine, StateMachine as S } from "@ui-machines/core"
+import { Machine, StateMachine as S } from "@ui-machines/core"
 import { useEffect, useLayoutEffect, useRef, useState } from "react"
 import { useConstant } from "./use-constant"
 
diff --git a/packages/frameworks/solid/package.json b/packages/frameworks/solid/package.json
index 4762f82b07..8d4cd99e2a 100644
--- a/packages/frameworks/solid/package.json
+++ b/packages/frameworks/solid/package.json
@@ -11,8 +11,9 @@
   "author": "Segun Adebayo ",
   "homepage": "https://github.com/chakra-ui/ui-machines#readme",
   "license": "MIT",
-  "main": "dist/ui-machines-solid.cjs.js",
-  "module": "dist/ui-machines-solid.esm.js",
+  "main": "dist/index.js",
+  "module": "dist/index.mjs",
+  "types": "dist/index.d.ts",
   "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/frameworks/solid",
   "sideEffects": false,
   "files": [
@@ -24,14 +25,9 @@
   "bugs": {
     "url": "https://github.com/chakra-ui/ui-machines/issues"
   },
-  "scripts": {
-    "clean": "rimraf dist"
-  },
   "dependencies": {
     "@ui-machines/core": "0.0.0",
-    "@ui-machines/prop-types": "0.0.0",
     "hyphenate-style-name": "^1.0.4",
-    "tiny-guard": "^0.0.3",
     "valtio": "^1.2.5"
   },
   "devDependencies": {
diff --git a/packages/frameworks/solid/src/cssify.ts b/packages/frameworks/solid/src/cssify.ts
index a433b696d1..a310aebddc 100644
--- a/packages/frameworks/solid/src/cssify.ts
+++ b/packages/frameworks/solid/src/cssify.ts
@@ -1,5 +1,5 @@
 import hyphenate from "hyphenate-style-name"
-import { isNumber, isString } from "tiny-guard"
+import { isNumber, isString } from "@ui-machines/utils"
 
 const format = (v: string) => (v.startsWith("--") ? v : hyphenate(v))
 
diff --git a/packages/frameworks/solid/src/normalize-props.ts b/packages/frameworks/solid/src/normalize-props.ts
index d5bb8abfa1..c8123670a3 100644
--- a/packages/frameworks/solid/src/normalize-props.ts
+++ b/packages/frameworks/solid/src/normalize-props.ts
@@ -1,5 +1,5 @@
-import { createNormalizer } from "@ui-machines/prop-types"
-import { isObject, isString } from "tiny-guard"
+import { createNormalizer } from "@ui-machines/types"
+import { isObject, isString } from "@ui-machines/utils"
 import { cssify } from "./cssify"
 
 const eventMap = {
diff --git a/packages/frameworks/svelte/package.json b/packages/frameworks/svelte/package.json
index 8ba375d1f8..df372d25b6 100644
--- a/packages/frameworks/svelte/package.json
+++ b/packages/frameworks/svelte/package.json
@@ -11,8 +11,9 @@
   "author": "Segun Adebayo ",
   "homepage": "https://github.com/chakra-ui/ui-machines#readme",
   "license": "MIT",
-  "main": "dist/ui-machines-svelte.cjs.js",
-  "module": "dist/ui-machines-svelte.esm.js",
+  "main": "dist/index.js",
+  "module": "dist/index.mjs",
+  "types": "dist/index.d.ts",
   "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/core/svelte",
   "sideEffects": false,
   "files": [
@@ -24,9 +25,6 @@
   "bugs": {
     "url": "https://github.com/chakra-ui/ui-machines/issues"
   },
-  "scripts": {
-    "clean": "rimraf dist"
-  },
   "dependencies": {
     "@ui-machines/core": "0.0.0"
   },
diff --git a/packages/frameworks/vue/package.json b/packages/frameworks/vue/package.json
index 5490fe171b..b00cd5717e 100644
--- a/packages/frameworks/vue/package.json
+++ b/packages/frameworks/vue/package.json
@@ -11,8 +11,9 @@
   "author": "Segun Adebayo ",
   "homepage": "https://github.com/chakra-ui/ui-machines#readme",
   "license": "MIT",
-  "main": "dist/ui-machines-vue.cjs.js",
-  "module": "dist/ui-machines-vue.esm.js",
+  "main": "dist/index.js",
+  "module": "dist/index.mjs",
+  "types": "dist/index.d.ts",
   "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/frameworks/vue",
   "sideEffects": false,
   "files": [
@@ -24,18 +25,15 @@
   "bugs": {
     "url": "https://github.com/chakra-ui/ui-machines/issues"
   },
-  "scripts": {
-    "clean": "rimraf dist"
-  },
   "dependencies": {
     "@ui-machines/core": "0.0.0",
-    "@ui-machines/prop-types": "0.0.0",
     "valtio": "^1.2.5"
   },
   "devDependencies": {
     "vue": "^3.0.5"
   },
   "peerDependencies": {
-    "vue": ">=3.0.5"
+    "vue": ">=3.0.0",
+    "@vue/runtime-dom": ">=3.2.0"
   }
 }
diff --git a/packages/frameworks/vue/src/normalize-props.ts b/packages/frameworks/vue/src/normalize-props.ts
index ad1d02ae24..5736c8cf53 100644
--- a/packages/frameworks/vue/src/normalize-props.ts
+++ b/packages/frameworks/vue/src/normalize-props.ts
@@ -1,4 +1,4 @@
-import { createNormalizer } from "@ui-machines/prop-types"
+import { createNormalizer } from "@ui-machines/types"
 
 type Dict = Record
 
diff --git a/packages/machines/accordion/README.md b/packages/machines/accordion/README.md
new file mode 100644
index 0000000000..8d20d47293
--- /dev/null
+++ b/packages/machines/accordion/README.md
@@ -0,0 +1,19 @@
+# @ui-machines/accordion
+
+Core logic for the accordion widget implemented as a state machine
+
+## Installation
+
+```sh
+yarn add  @ui-machines/accordion
+# or
+npm i  @ui-machines/accordion
+```
+
+## Contribution
+
+Yes please! See the [contributing guidelines](https://github.com/chakra-ui/ui-machines/blob/main/CONTRIBUTING.md) for details.
+
+## Licence
+
+This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ui-machines/blob/main/LICENSE).
diff --git a/packages/prop-types/package.json b/packages/machines/accordion/package.json
similarity index 54%
rename from packages/prop-types/package.json
rename to packages/machines/accordion/package.json
index 6c7bc77884..3de3765390 100644
--- a/packages/prop-types/package.json
+++ b/packages/machines/accordion/package.json
@@ -1,19 +1,23 @@
 {
-  "name": "@ui-machines/prop-types",
+  "name": "@ui-machines/accordion",
   "version": "0.0.0",
-  "description": "Shared typescript utility for prop definition",
+  "description": "Core logic for the accordion widget implemented as a state machine",
   "keywords": [
     "js",
-    "utils",
-    "prop-types"
+    "machine",
+    "xstate",
+    "statechart",
+    "component",
+    "chakra-ui",
+    "accordion"
   ],
   "author": "Segun Adebayo ",
   "homepage": "https://github.com/chakra-ui/ui-machines#readme",
   "license": "MIT",
-  "main": "dist/ui-machines-prop-types.cjs.js",
-  "module": "dist/ui-machines-prop-types.esm.js",
-  "types": "dist/ui-machines-prop-types.cjs.d.ts",
-  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/prop-types",
+  "main": "dist/index.js",
+  "types": "dist/index.d.ts",
+  "module": "dist/index.mjs",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/accordion",
   "sideEffects": false,
   "files": [
     "dist"
@@ -21,13 +25,10 @@
   "publishConfig": {
     "access": "public"
   },
-  "dependencies": {
-    "@types/react": "^17.0.20"
-  },
   "bugs": {
     "url": "https://github.com/chakra-ui/ui-machines/issues"
   },
-  "scripts": {
-    "clean": "rimraf dist"
+  "dependencies": {
+    "@ui-machines/core": "^0.0.0"
   }
 }
diff --git a/packages/machines/src/accordion/accordion.connect.ts b/packages/machines/accordion/src/accordion.connect.ts
similarity index 96%
rename from packages/machines/src/accordion/accordion.connect.ts
rename to packages/machines/accordion/src/accordion.connect.ts
index ccafb164b8..63592ba97e 100644
--- a/packages/machines/src/accordion/accordion.connect.ts
+++ b/packages/machines/accordion/src/accordion.connect.ts
@@ -1,6 +1,5 @@
-import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/prop-types"
-import type { EventKeyMap } from "../utils"
-import { dataAttr, getEventKey } from "../utils"
+import { dataAttr, getEventKey, EventKeyMap } from "@ui-machines/dom-utils"
+import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/types"
 import { dom } from "./accordion.dom"
 import type { AccordionItemProps, AccordionSend, AccordionState } from "./accordion.types"
 
diff --git a/packages/machines/src/accordion/accordion.dom.ts b/packages/machines/accordion/src/accordion.dom.ts
similarity index 89%
rename from packages/machines/src/accordion/accordion.dom.ts
rename to packages/machines/accordion/src/accordion.dom.ts
index bdd7c5effe..f441280993 100644
--- a/packages/machines/src/accordion/accordion.dom.ts
+++ b/packages/machines/accordion/src/accordion.dom.ts
@@ -1,5 +1,5 @@
-import { queryElements, nextById, prevById } from "../utils/nodelist"
-import { first, last } from "../utils/array"
+import { nextById, prevById, queryElements } from "@ui-machines/dom-utils"
+import { first, last } from "@ui-machines/utils"
 import type { AccordionMachineContext as Ctx } from "./accordion.types"
 
 export const dom = {
diff --git a/packages/machines/src/accordion/accordion.machine.ts b/packages/machines/accordion/src/accordion.machine.ts
similarity index 91%
rename from packages/machines/src/accordion/accordion.machine.ts
rename to packages/machines/accordion/src/accordion.machine.ts
index d1ab43db87..41f1f97ac2 100644
--- a/packages/machines/src/accordion/accordion.machine.ts
+++ b/packages/machines/accordion/src/accordion.machine.ts
@@ -1,7 +1,5 @@
+import { add, remove, toArray } from "@ui-machines/utils"
 import { createMachine, guards, ref } from "@ui-machines/core"
-import { uuid } from "../utils"
-import { add, remove, toArray } from "../utils/array"
-import { isArray } from "../utils/guard"
 import { dom } from "./accordion.dom"
 import { AccordionMachineContext, AccordionMachineState } from "./accordion.types"
 
@@ -14,7 +12,7 @@ export const accordionMachine = createMachine !!ctx.collapsible || !!ctx.multiple,
-      isExpanded: (ctx, evt) => (isArray(ctx.value) ? ctx.value.includes(evt.value) : ctx.value === evt.value),
+      isExpanded: (ctx, evt) => {
+        return Array.isArray(ctx.value) ? ctx.value.includes(evt.value) : ctx.value === evt.value
+      },
     },
     actions: {
       invokeOnChange(ctx) {
diff --git a/packages/machines/src/accordion/accordion.types.ts b/packages/machines/accordion/src/accordion.types.ts
similarity index 96%
rename from packages/machines/src/accordion/accordion.types.ts
rename to packages/machines/accordion/src/accordion.types.ts
index 3693f25ab0..8d9651267a 100644
--- a/packages/machines/src/accordion/accordion.types.ts
+++ b/packages/machines/accordion/src/accordion.types.ts
@@ -1,5 +1,5 @@
 import type { StateMachine as S } from "@ui-machines/core"
-import type { Context } from "../utils"
+import type { Context } from "@ui-machines/types"
 
 export type AccordionMachineContext = Context<{
   /**
diff --git a/packages/machines/src/accordion/index.ts b/packages/machines/accordion/src/index.ts
similarity index 100%
rename from packages/machines/src/accordion/index.ts
rename to packages/machines/accordion/src/index.ts
diff --git a/packages/machines/combobox/README.md b/packages/machines/combobox/README.md
new file mode 100644
index 0000000000..9179433610
--- /dev/null
+++ b/packages/machines/combobox/README.md
@@ -0,0 +1,19 @@
+# @ui-machines/combobox
+
+Core logic for the combobox widget implemented as a state machine
+
+## Installation
+
+```sh
+yarn add  @ui-machines/combobox
+# or
+npm i  @ui-machines/combobox
+```
+
+## Contribution
+
+Yes please! See the [contributing guidelines](https://github.com/chakra-ui/ui-machines/blob/main/CONTRIBUTING.md) for details.
+
+## Licence
+
+This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ui-machines/blob/main/LICENSE).
diff --git a/packages/machines/combobox/package.json b/packages/machines/combobox/package.json
new file mode 100644
index 0000000000..7320ef4756
--- /dev/null
+++ b/packages/machines/combobox/package.json
@@ -0,0 +1,35 @@
+{
+  "name": "@ui-machines/combobox",
+  "version": "0.0.0",
+  "description": "Core logic for the combobox widget implemented as a state machine",
+  "keywords": [
+    "js",
+    "machine",
+    "xstate",
+    "statechart",
+    "component",
+    "chakra-ui",
+    "combobox"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "types": "dist/index.d.ts",
+  "module": "dist/index.mjs",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/combobox",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  },
+  "dependencies": {
+    "@ui-machines/core": "^0.0.0",
+    "scroll-into-view-if-needed": "^2.2.28"
+  }
+}
diff --git a/packages/machines/src/combobox/combobox.connect.ts b/packages/machines/combobox/src/combobox.connect.ts
similarity index 97%
rename from packages/machines/src/combobox/combobox.connect.ts
rename to packages/machines/combobox/src/combobox.connect.ts
index d94b13f314..ebeca9ca7a 100644
--- a/packages/machines/src/combobox/combobox.connect.ts
+++ b/packages/machines/combobox/src/combobox.connect.ts
@@ -1,6 +1,5 @@
-import type { EventKeyMap } from "../utils"
-import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/prop-types"
-import { dataAttr, getEventKey, srOnlyStyle, validateBlur } from "../utils"
+import { dataAttr, EventKeyMap, getEventKey, srOnlyStyle, validateBlur } from "@ui-machines/dom-utils"
+import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/types"
 import { dom } from "./combobox.dom"
 import { ComboboxOptionProps, ComboboxSend, ComboboxState } from "./combobox.types"
 
diff --git a/packages/machines/src/combobox/combobox.dom.ts b/packages/machines/combobox/src/combobox.dom.ts
similarity index 93%
rename from packages/machines/src/combobox/combobox.dom.ts
rename to packages/machines/combobox/src/combobox.dom.ts
index 367408ae53..d38cdd85a6 100644
--- a/packages/machines/src/combobox/combobox.dom.ts
+++ b/packages/machines/combobox/src/combobox.dom.ts
@@ -1,5 +1,5 @@
-import { first, last } from "../utils/array"
-import { nextById, prevById, queryElements } from "../utils/nodelist"
+import { nextById, prevById, queryElements } from "@ui-machines/dom-utils"
+import { first, last } from "@ui-machines/utils"
 import type { ComboboxMachineContext as Ctx } from "./combobox.types"
 
 export const dom = {
diff --git a/packages/machines/src/combobox/combobox.machine.ts b/packages/machines/combobox/src/combobox.machine.ts
similarity index 95%
rename from packages/machines/src/combobox/combobox.machine.ts
rename to packages/machines/combobox/src/combobox.machine.ts
index 6ff9dd3220..7c18537833 100644
--- a/packages/machines/src/combobox/combobox.machine.ts
+++ b/packages/machines/combobox/src/combobox.machine.ts
@@ -1,8 +1,7 @@
 import { createMachine, guards, ref } from "@ui-machines/core"
+import { LiveRegion, nextTick, observeAttributes, trackPointerDown } from "@ui-machines/dom-utils"
+import { isApple, isFunction } from "@ui-machines/utils"
 import scrollIntoView from "scroll-into-view-if-needed"
-import { nextTick } from "tiny-fn"
-import { LiveRegion, observeAttributes, trackPointerDown, uuid } from "../utils"
-import { isApple, isFunction } from "../utils/guard"
 import { dom } from "./combobox.dom"
 import { ComboboxMachineContext, ComboboxMachineState } from "./combobox.types"
 
@@ -13,7 +12,7 @@ export const comboboxMachine = createMachine !!ctx.selectOnFocus,
     },
     activities: {
-      trackPointerDown,
+      trackPointerDown(ctx) {
+        return trackPointerDown(dom.getDoc(ctx), (el) => {
+          ctx.pointerdownNode = ref(el)
+        })
+      },
       scrollOptionIntoView(ctx) {
         const input = dom.getInputEl(ctx)
         const listbox = dom.getListboxEl(ctx)
         return observeAttributes(input, "aria-activedescendant", () => {
           const opt = dom.getActiveOptionEl(ctx)
           if (!opt) return
-          scrollIntoView(opt, {
-            boundary: listbox,
-            block: "nearest",
-            scrollMode: "if-needed",
-          })
+          scrollIntoView(opt, { boundary: listbox, block: "nearest", scrollMode: "if-needed" })
         })
       },
     },
diff --git a/packages/machines/src/combobox/combobox.types.ts b/packages/machines/combobox/src/combobox.types.ts
similarity index 88%
rename from packages/machines/src/combobox/combobox.types.ts
rename to packages/machines/combobox/src/combobox.types.ts
index 9567ba4a2a..22d4d7aad2 100644
--- a/packages/machines/src/combobox/combobox.types.ts
+++ b/packages/machines/combobox/src/combobox.types.ts
@@ -1,5 +1,6 @@
-import { StateMachine as S } from "@ui-machines/core"
-import { Context, LiveRegion } from "../utils"
+import type { StateMachine as S } from "@ui-machines/core"
+import type { LiveRegion } from "@ui-machines/dom-utils"
+import type { Context } from "@ui-machines/types"
 
 export type ComboboxMachineState = {
   value: "unknown" | "idle" | "focused" | "suggesting" | "navigating" | "interacting"
diff --git a/packages/machines/src/combobox/index.ts b/packages/machines/combobox/src/index.ts
similarity index 100%
rename from packages/machines/src/combobox/index.ts
rename to packages/machines/combobox/src/index.ts
diff --git a/packages/machines/dialog/README.md b/packages/machines/dialog/README.md
new file mode 100644
index 0000000000..0377aaf0f4
--- /dev/null
+++ b/packages/machines/dialog/README.md
@@ -0,0 +1,19 @@
+# @ui-machines/dialog
+
+Core logic for the dialog widget implemented as a state machine
+
+## Installation
+
+```sh
+yarn add  @ui-machines/dialog
+# or
+npm i  @ui-machines/dialog
+```
+
+## Contribution
+
+Yes please! See the [contributing guidelines](https://github.com/chakra-ui/ui-machines/blob/main/CONTRIBUTING.md) for details.
+
+## Licence
+
+This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ui-machines/blob/main/LICENSE).
diff --git a/packages/machines/dialog/package.json b/packages/machines/dialog/package.json
new file mode 100644
index 0000000000..0a1c606dc7
--- /dev/null
+++ b/packages/machines/dialog/package.json
@@ -0,0 +1,37 @@
+{
+  "name": "@ui-machines/dialog",
+  "version": "0.0.0",
+  "description": "Core logic for the dialog widget implemented as a state machine",
+  "keywords": [
+    "js",
+    "machine",
+    "xstate",
+    "statechart",
+    "component",
+    "chakra-ui",
+    "dialog"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "types": "dist/index.d.ts",
+  "module": "dist/index.mjs",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/dialog",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  },
+  "dependencies": {
+    "@ui-machines/core": "^0.0.0",
+    "aria-hidden": "^1.1.3",
+    "focus-trap": "^6.7.1",
+    "scroll-into-view-if-needed": "^2.2.28"
+  }
+}
diff --git a/packages/machines/src/dialog/dialog.connect.ts b/packages/machines/dialog/src/dialog.connect.ts
similarity index 96%
rename from packages/machines/src/dialog/dialog.connect.ts
rename to packages/machines/dialog/src/dialog.connect.ts
index d32d0b48a2..ce7972098a 100644
--- a/packages/machines/src/dialog/dialog.connect.ts
+++ b/packages/machines/dialog/src/dialog.connect.ts
@@ -1,6 +1,6 @@
 import { StateMachine as S } from "@ui-machines/core"
-import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/prop-types"
-import { ariaAttr } from "../utils"
+import { ariaAttr } from "@ui-machines/dom-utils"
+import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/types"
 import { dom } from "./dialog.dom"
 import { DialogMachineContext, DialogMachineState } from "./dialog.machine"
 
diff --git a/packages/machines/src/dialog/dialog.dom.ts b/packages/machines/dialog/src/dialog.dom.ts
similarity index 100%
rename from packages/machines/src/dialog/dialog.dom.ts
rename to packages/machines/dialog/src/dialog.dom.ts
diff --git a/packages/machines/src/dialog/dialog.machine.ts b/packages/machines/dialog/src/dialog.machine.ts
similarity index 88%
rename from packages/machines/src/dialog/dialog.machine.ts
rename to packages/machines/dialog/src/dialog.machine.ts
index af455d2384..54de6013f3 100644
--- a/packages/machines/src/dialog/dialog.machine.ts
+++ b/packages/machines/dialog/src/dialog.machine.ts
@@ -1,11 +1,8 @@
-import { createMachine, ref } from "@ui-machines/core"
+import { createMachine, ref, subscribe } from "@ui-machines/core"
+import { addDomEvent, nextTick, preventBodyScroll } from "@ui-machines/dom-utils"
+import { Context } from "@ui-machines/types"
 import { hideOthers } from "aria-hidden"
 import { createFocusTrap, FocusTrap } from "focus-trap"
-import { addDomEvent } from "tiny-dom-event"
-import { nextTick, noop } from "tiny-fn"
-import { subscribe } from "valtio"
-import { Context } from "../utils"
-import { preventBodyScroll } from "../utils/body-scroll-lock"
 import { dom } from "./dialog.dom"
 import { dialogStore } from "./dialog.store"
 
@@ -56,14 +53,10 @@ export const dialogMachine = createMachine {
-          if (!ctx.isTopMostDialog || !ctx.trapFocus) return noop
+          if (!ctx.isTopMostDialog || !ctx.trapFocus) return
           const el = dom.getContentEl(ctx)
           trap = createFocusTrap(el, {
             document: dom.getDoc(ctx),
@@ -140,7 +133,7 @@ export const dialogMachine = createMachine {
           ctx.hasTitle = !!dom.getTitleEl(ctx)
           ctx.hasDescription = !!dom.getDescriptionEl(ctx)
diff --git a/packages/machines/src/dialog/dialog.store.ts b/packages/machines/dialog/src/dialog.store.ts
similarity index 82%
rename from packages/machines/src/dialog/dialog.store.ts
rename to packages/machines/dialog/src/dialog.store.ts
index 73fc7474f8..2847e7b596 100644
--- a/packages/machines/src/dialog/dialog.store.ts
+++ b/packages/machines/dialog/src/dialog.store.ts
@@ -1,5 +1,4 @@
-import { last } from "tiny-array"
-import { proxy } from "valtio"
+import { proxy } from "@ui-machines/core"
 
 type StoreItem = { id: string; close: VoidFunction }
 
@@ -13,7 +12,8 @@ type Store = {
 export const dialogStore = proxy({
   value: [],
   isTopMost(id) {
-    return last(this.value)?.id === id
+    const lastModal = this.value[this.value.length - 1]
+    return lastModal?.id === id
   },
   add(item: StoreItem) {
     this.value.push(item)
diff --git a/packages/machines/src/dialog/index.ts b/packages/machines/dialog/src/index.ts
similarity index 100%
rename from packages/machines/src/dialog/index.ts
rename to packages/machines/dialog/src/index.ts
diff --git a/packages/machines/editable/README.md b/packages/machines/editable/README.md
new file mode 100644
index 0000000000..30840b4284
--- /dev/null
+++ b/packages/machines/editable/README.md
@@ -0,0 +1,19 @@
+# @ui-machines/editable
+
+Core logic for the editable widget implemented as a state machine
+
+## Installation
+
+```sh
+yarn add  @ui-machines/editable
+# or
+npm i  @ui-machines/editable
+```
+
+## Contribution
+
+Yes please! See the [contributing guidelines](https://github.com/chakra-ui/ui-machines/blob/main/CONTRIBUTING.md) for details.
+
+## Licence
+
+This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ui-machines/blob/main/LICENSE).
diff --git a/packages/machines/editable/package.json b/packages/machines/editable/package.json
new file mode 100644
index 0000000000..f7284f1fc7
--- /dev/null
+++ b/packages/machines/editable/package.json
@@ -0,0 +1,34 @@
+{
+  "name": "@ui-machines/editable",
+  "version": "0.0.0",
+  "description": "Core logic for the editable widget implemented as a state machine",
+  "keywords": [
+    "js",
+    "machine",
+    "xstate",
+    "statechart",
+    "component",
+    "chakra-ui",
+    "editable"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "types": "dist/index.d.ts",
+  "module": "dist/index.mjs",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/editable",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  },
+  "dependencies": {
+    "@ui-machines/core": "^0.0.0"
+  }
+}
diff --git a/packages/machines/src/editable/editable.connect.ts b/packages/machines/editable/src/editable.connect.ts
similarity index 95%
rename from packages/machines/src/editable/editable.connect.ts
rename to packages/machines/editable/src/editable.connect.ts
index 2bba3f4b0c..220421df63 100644
--- a/packages/machines/src/editable/editable.connect.ts
+++ b/packages/machines/editable/src/editable.connect.ts
@@ -1,6 +1,5 @@
-import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/prop-types"
-import { ariaAttr, validateBlur } from "../utils"
-import type { EventKeyMap } from "../utils/types"
+import { ariaAttr, EventKeyMap, validateBlur } from "@ui-machines/dom-utils"
+import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/types"
 import { dom } from "./editable.dom"
 import { EditableSend, EditableState } from "./editable.types"
 
diff --git a/packages/machines/src/editable/editable.dom.ts b/packages/machines/editable/src/editable.dom.ts
similarity index 100%
rename from packages/machines/src/editable/editable.dom.ts
rename to packages/machines/editable/src/editable.dom.ts
diff --git a/packages/machines/src/editable/editable.machine.ts b/packages/machines/editable/src/editable.machine.ts
similarity index 94%
rename from packages/machines/src/editable/editable.machine.ts
rename to packages/machines/editable/src/editable.machine.ts
index dfecefb8ee..75e7c961b0 100644
--- a/packages/machines/src/editable/editable.machine.ts
+++ b/packages/machines/editable/src/editable.machine.ts
@@ -1,6 +1,5 @@
 import { choose, createMachine, guards, ref } from "@ui-machines/core"
-import { nextTick } from "tiny-fn"
-import { trackPointerDown, uuid } from "../utils"
+import { nextTick, trackPointerDown } from "@ui-machines/dom-utils"
 import { dom } from "./editable.dom"
 import { EditableMachineContext, EditableMachineState } from "./editable.types"
 
@@ -13,7 +12,7 @@ export const editableMachine = createMachine ctx.activationMode === "focus",
     },
     activities: {
-      trackPointerDown,
+      trackPointerDown(ctx) {
+        return trackPointerDown(dom.getDoc(ctx), (el) => {
+          ctx.pointerdownNode = ref(el)
+        })
+      },
     },
     actions: {
       setId(ctx, evt) {
diff --git a/packages/machines/src/editable/editable.types.ts b/packages/machines/editable/src/editable.types.ts
similarity index 98%
rename from packages/machines/src/editable/editable.types.ts
rename to packages/machines/editable/src/editable.types.ts
index c59a9122a5..33769d733a 100644
--- a/packages/machines/src/editable/editable.types.ts
+++ b/packages/machines/editable/src/editable.types.ts
@@ -1,5 +1,5 @@
 import type { StateMachine as S } from "@ui-machines/core"
-import type { Context } from "../utils"
+import type { Context } from "@ui-machines/types"
 
 export type ActivationMode = "focus" | "dblclick" | "none"
 
diff --git a/packages/machines/src/editable/index.ts b/packages/machines/editable/src/index.ts
similarity index 100%
rename from packages/machines/src/editable/index.ts
rename to packages/machines/editable/src/index.ts
diff --git a/packages/machines/menu/README.md b/packages/machines/menu/README.md
new file mode 100644
index 0000000000..7c39991c07
--- /dev/null
+++ b/packages/machines/menu/README.md
@@ -0,0 +1,19 @@
+# @ui-machines/menu
+
+Core logic for the menu widget implemented as a state machine
+
+## Installation
+
+```sh
+yarn add  @ui-machines/menu
+# or
+npm i  @ui-machines/menu
+```
+
+## Contribution
+
+Yes please! See the [contributing guidelines](https://github.com/chakra-ui/ui-machines/blob/main/CONTRIBUTING.md) for details.
+
+## Licence
+
+This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ui-machines/blob/main/LICENSE).
diff --git a/packages/machines/menu/package.json b/packages/machines/menu/package.json
new file mode 100644
index 0000000000..cc6896f23d
--- /dev/null
+++ b/packages/machines/menu/package.json
@@ -0,0 +1,34 @@
+{
+  "name": "@ui-machines/menu",
+  "version": "0.0.0",
+  "description": "Core logic for the menu widget implemented as a state machine",
+  "keywords": [
+    "js",
+    "machine",
+    "xstate",
+    "statechart",
+    "component",
+    "chakra-ui",
+    "menu"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "types": "dist/index.d.ts",
+  "module": "dist/index.mjs",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/menu",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  },
+  "dependencies": {
+    "@ui-machines/core": "^0.0.0"
+  }
+}
diff --git a/packages/machines/src/menu/index.ts b/packages/machines/menu/src/index.ts
similarity index 100%
rename from packages/machines/src/menu/index.ts
rename to packages/machines/menu/src/index.ts
diff --git a/packages/machines/src/menu/menu.connect.ts b/packages/machines/menu/src/menu.connect.ts
similarity index 92%
rename from packages/machines/src/menu/menu.connect.ts
rename to packages/machines/menu/src/menu.connect.ts
index 46b775e979..a71b1734d8 100644
--- a/packages/machines/src/menu/menu.connect.ts
+++ b/packages/machines/menu/src/menu.connect.ts
@@ -1,10 +1,7 @@
-import { contains } from "tiny-dom-query"
-import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/prop-types"
-import { cast } from "tiny-fn"
-import { isLeftClick } from "tiny-guard"
-import { fromPointerEvent } from "tiny-point/dom"
-import type { EventKeyMap } from "../utils"
-import { dataAttr, getEventKey, validateBlur } from "../utils"
+import { contains, dataAttr, EventKeyMap, getEventKey, getNativeEvent, validateBlur } from "@ui-machines/dom-utils"
+import { getEventPoint } from "@ui-machines/rect-utils"
+import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/types"
+import { isLeftClick } from "@ui-machines/utils"
 import { dom } from "./menu.dom"
 import { MenuItemProps, MenuMachine, MenuOptionItemProps, MenuSend, MenuState } from "./menu.types"
 
@@ -33,7 +30,8 @@ export function menuConnect(
         send({ type: "ITEM_CLICK", target: event.currentTarget })
       },
       onPointerUp(event) {
-        if (!isLeftClick(cast(event)) || disabled) return
+        const evt = (event.nativeEvent ?? event) as PointerEvent
+        if (!isLeftClick(evt) || disabled) return
         event.currentTarget.click()
       },
       onPointerLeave(event) {
@@ -86,17 +84,19 @@ export function menuConnect(
         })
       },
       onPointerLeave(event) {
+        const evt = getNativeEvent(event)
         const disabled = dom.isTargetDisabled(event.currentTarget)
         if (disabled || !isSubmenu) return
         send({
           type: "TRIGGER_POINTERLEAVE",
           target: event.currentTarget,
-          point: fromPointerEvent(cast(event)),
+          point: getEventPoint(evt),
         })
       },
       onPointerDown(event) {
+        const evt = getNativeEvent(event)
         const disabled = dom.isTargetDisabled(event.currentTarget)
-        if (!isLeftClick(cast(event)) || disabled) return
+        if (!isLeftClick(evt) || disabled) return
         send({ type: "TRIGGER_CLICK", target: event.currentTarget })
       },
       onBlur() {
diff --git a/packages/machines/src/menu/menu.dom.ts b/packages/machines/menu/src/menu.dom.ts
similarity index 87%
rename from packages/machines/src/menu/menu.dom.ts
rename to packages/machines/menu/src/menu.dom.ts
index 721e95192f..2d3af98819 100644
--- a/packages/machines/src/menu/menu.dom.ts
+++ b/packages/machines/menu/src/menu.dom.ts
@@ -1,6 +1,5 @@
-import { first, last } from "tiny-array"
-import { isElement } from "tiny-guard"
-import { findByText, nextById, prevById, queryElements } from "../utils/nodelist"
+import { findByText, isHTMLElement, nextById, prevById, queryElements } from "@ui-machines/dom-utils"
+import { first, last } from "@ui-machines/utils"
 import { MenuMachineContext as Ctx } from "./menu.types"
 
 type HTMLEl = HTMLElement | null
@@ -28,7 +27,7 @@ export const dom = {
   getChildMenus: (ctx: Ctx) => {
     return Object.values(ctx.children)
       .map((child) => dom.getMenuEl(child.state.context))
-      .filter(isElement)
+      .filter(isHTMLElement)
   },
   getParentMenus: (ctx: Ctx) => {
     const menus: HTMLElement[] = []
@@ -42,6 +41,6 @@ export const dom = {
   },
 
   isTargetDisabled: (v: EventTarget | null) => {
-    return isElement(v) && v.dataset.disabled === ""
+    return isHTMLElement(v) && v.dataset.disabled === ""
   },
 }
diff --git a/packages/machines/src/menu/menu.machine.ts b/packages/machines/menu/src/menu.machine.ts
similarity index 94%
rename from packages/machines/src/menu/menu.machine.ts
rename to packages/machines/menu/src/menu.machine.ts
index 1200784872..cec16696e4 100644
--- a/packages/machines/src/menu/menu.machine.ts
+++ b/packages/machines/menu/src/menu.machine.ts
@@ -1,14 +1,6 @@
 import { createMachine, guards, ref } from "@ui-machines/core"
-import { addPointerEvent } from "tiny-dom-event"
-import { contains } from "tiny-dom-query"
-import { isFocusable } from "tiny-dom-query/focusable"
-import { nextTick } from "tiny-fn"
-import { fromPointerEvent } from "tiny-point/dom"
-import { withinPolygon } from "tiny-point/within"
-import { corners } from "tiny-rect"
-import { fromElement } from "tiny-rect/from-element"
-import { inset } from "tiny-rect/operations"
-import { trackPointerDown, uuid } from "../utils"
+import { addPointerEvent, contains, isFocusable, nextTick, trackPointerDown } from "@ui-machines/dom-utils"
+import { getEventPoint, withinPolygon, getElementRect, inset } from "@ui-machines/rect-utils"
 import { dom } from "./menu.dom"
 import { MenuMachineContext, MenuMachineState } from "./menu.types"
 
@@ -22,7 +14,7 @@ export const menuMachine = createMachine(
       pointerdownNode: null,
       orientation: "vertical",
       activeId: null,
-      uid: uuid(),
+      uid: "",
       parent: null,
       children: {},
       intentPolygon: null,
@@ -261,7 +253,11 @@ export const menuMachine = createMachine(
       },
     },
     activities: {
-      trackPointerDown,
+      trackPointerDown(ctx) {
+        return trackPointerDown(dom.getDoc(ctx), (el) => {
+          ctx.pointerdownNode = ref(el)
+        })
+      },
       trackPointerMove(ctx, _evt, { guards = {}, send }) {
         const { isWithinPolygon } = guards
         ctx.parent!.state.context.suspendPointer = true
@@ -269,7 +265,7 @@ export const menuMachine = createMachine(
         const doc = dom.getDoc(ctx)
         return addPointerEvent(doc, "pointermove", (e) => {
           const isMovingToSubmenu = isWithinPolygon(ctx, {
-            point: fromPointerEvent(e),
+            point: getEventPoint(e),
           })
           if (!isMovingToSubmenu) {
             send("CLOSE")
@@ -282,10 +278,10 @@ export const menuMachine = createMachine(
       setIntentPolygon(ctx, evt) {
         const menu = dom.getMenuEl(ctx)
         if (!menu) return
-        let menuRect = fromElement(menu)
+        let menuRect = getElementRect(menu)
         const BUFFER = 20
         menuRect = inset(menuRect, { dx: -BUFFER, dy: -BUFFER })
-        const [top, right, left, bottom] = corners(menuRect).value
+        const { top, right, left, bottom } = menuRect.corners
         ctx.intentPolygon = [evt.point, top, right, bottom, left]
       },
       clearIntentPolygon(ctx) {
diff --git a/packages/machines/src/menu/menu.types.ts b/packages/machines/menu/src/menu.types.ts
similarity index 89%
rename from packages/machines/src/menu/menu.types.ts
rename to packages/machines/menu/src/menu.types.ts
index b2af0950f1..795a9ce765 100644
--- a/packages/machines/src/menu/menu.types.ts
+++ b/packages/machines/menu/src/menu.types.ts
@@ -1,6 +1,6 @@
 import { Machine, StateMachine as S } from "@ui-machines/core"
-import { PointValue } from "tiny-point"
-import type { Context } from "../utils"
+import { Point } from "@ui-machines/rect-utils"
+import type { Context } from "@ui-machines/types"
 
 export type MenuMachine = Machine
 
@@ -18,7 +18,7 @@ export type MenuMachineContext = Context<{
    * The polygon tells us if the pointer is
    * moving toward the submenu
    */
-  intentPolygon: PointValue[] | null
+  intentPolygon: Point[] | null
   suspendPointer: boolean
   hoverId: string | null
   loop: boolean
diff --git a/packages/machines/number-input/README.md b/packages/machines/number-input/README.md
new file mode 100644
index 0000000000..4236519383
--- /dev/null
+++ b/packages/machines/number-input/README.md
@@ -0,0 +1,19 @@
+# @ui-machines/number-input
+
+Core logic for the number-input widget implemented as a state machine
+
+## Installation
+
+```sh
+yarn add  @ui-machines/number-input
+# or
+npm i  @ui-machines/number-input
+```
+
+## Contribution
+
+Yes please! See the [contributing guidelines](https://github.com/chakra-ui/ui-machines/blob/main/CONTRIBUTING.md) for details.
+
+## Licence
+
+This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ui-machines/blob/main/LICENSE).
diff --git a/packages/machines/number-input/package.json b/packages/machines/number-input/package.json
new file mode 100644
index 0000000000..ef8a6ae631
--- /dev/null
+++ b/packages/machines/number-input/package.json
@@ -0,0 +1,34 @@
+{
+  "name": "@ui-machines/number-input",
+  "version": "0.0.0",
+  "description": "Core logic for the number-input widget implemented as a state machine",
+  "keywords": [
+    "js",
+    "machine",
+    "xstate",
+    "statechart",
+    "component",
+    "chakra-ui",
+    "number-input"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "types": "dist/index.d.ts",
+  "module": "dist/index.mjs",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/number-input",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  },
+  "dependencies": {
+    "@ui-machines/core": "^0.0.0"
+  }
+}
diff --git a/packages/machines/src/number-input/index.ts b/packages/machines/number-input/src/index.ts
similarity index 100%
rename from packages/machines/src/number-input/index.ts
rename to packages/machines/number-input/src/index.ts
diff --git a/packages/machines/src/number-input/number-input.connect.ts b/packages/machines/number-input/src/number-input.connect.ts
similarity index 87%
rename from packages/machines/src/number-input/number-input.connect.ts
rename to packages/machines/number-input/src/number-input.connect.ts
index 257131bbe4..8df2257aec 100644
--- a/packages/machines/src/number-input/number-input.connect.ts
+++ b/packages/machines/number-input/src/number-input.connect.ts
@@ -1,8 +1,7 @@
-import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/prop-types"
-import { fromPointerEvent } from "tiny-point/dom"
-import { dataAttr, EventKeyMap, getEventStep } from "../utils"
-import { cast } from "../utils/fn"
-import { roundPx } from "../utils/number"
+import { dataAttr, EventKeyMap, getEventStep, getNativeEvent } from "@ui-machines/dom-utils"
+import { roundToPx } from "@ui-machines/number-utils"
+import { getEventPoint } from "@ui-machines/rect-utils"
+import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/types"
 import { dom } from "./number-input.dom"
 import { NumberInputSend, NumberInputState } from "./number-input.types"
 import { utils } from "./number-input.utils"
@@ -61,14 +60,13 @@ export function numberInputConnect(
         send("BLUR")
       },
       onChange(event) {
-        const evt = (event.nativeEvent ?? event) as InputEvent
+        const evt = getNativeEvent(event) as InputEvent
         if (evt.isComposing) return
         send({ type: "CHANGE", target: event.currentTarget, hint: "set" })
       },
       onKeyDown(event) {
-        const evt = (event.nativeEvent ?? event) as KeyboardEvent
+        const evt = getNativeEvent(event)
         if (evt.isComposing) return
-
         if (!utils.isValidNumericEvent(ctx, event)) {
           event.preventDefault()
         }
@@ -142,13 +140,12 @@ export function numberInputConnect(
       id: dom.getScrubberId(ctx),
       role: "presentation",
       onMouseDown(event) {
+        const evt = getNativeEvent(event)
         event.preventDefault()
-        const pt = fromPointerEvent(cast(event))
-        const win = cast(event.view ?? window)
-        const dp = win.devicePixelRatio
+        const pt = getEventPoint(evt)
         send({
           type: "PRESS_DOWN_SCRUBBER",
-          point: { x: pt.x - roundPx(7.5, dp), y: pt.y - roundPx(7.5, dp) },
+          point: { x: pt.x - roundToPx(7.5), y: pt.y - roundToPx(7.5) },
         })
       },
       style: {
diff --git a/packages/machines/src/number-input/number-input.dom.ts b/packages/machines/number-input/src/number-input.dom.ts
similarity index 88%
rename from packages/machines/src/number-input/number-input.dom.ts
rename to packages/machines/number-input/src/number-input.dom.ts
index 753404510b..adab18e2b0 100644
--- a/packages/machines/src/number-input/number-input.dom.ts
+++ b/packages/machines/number-input/src/number-input.dom.ts
@@ -1,4 +1,4 @@
-import { roundPx, wrap } from "../utils/number"
+import { roundToPx, wrap } from "@ui-machines/number-utils"
 import { NumberInputMachineContext as Ctx } from "./number-input.types"
 
 type InputEl = HTMLInputElement | null
@@ -22,11 +22,8 @@ export const dom = {
   getCursorEl: (ctx: Ctx) => dom.getDoc(ctx).getElementById(dom.getCursorId(ctx)),
 
   getMousementValue(ctx: Ctx, event: MouseEvent) {
-    const win = dom.getWin(ctx)
-    const dp = win.devicePixelRatio
-
-    const x = roundPx(event.movementX, dp)
-    const y = roundPx(event.movementY, dp)
+    const x = roundToPx(event.movementX)
+    const y = roundToPx(event.movementY)
 
     let hint = x > 0 ? "increment" : x < 0 ? "decrement" : null
 
@@ -38,8 +35,9 @@ export const dom = {
       y: ctx.cursorPoint!.y + y,
     }
 
+    const win = dom.getWin(ctx)
     const width = win.innerWidth
-    const half = roundPx(7.5)
+    const half = roundToPx(7.5)
     point.x = wrap(point.x + half, width) - half
 
     return { hint, point }
diff --git a/packages/machines/src/number-input/number-input.machine.ts b/packages/machines/number-input/src/number-input.machine.ts
similarity index 93%
rename from packages/machines/src/number-input/number-input.machine.ts
rename to packages/machines/number-input/src/number-input.machine.ts
index a3a007cb11..0aa50406ca 100644
--- a/packages/machines/src/number-input/number-input.machine.ts
+++ b/packages/machines/number-input/src/number-input.machine.ts
@@ -1,12 +1,7 @@
 import { choose, createMachine, guards, ref } from "@ui-machines/core"
-import { addDomEvent } from "tiny-dom-event"
-import { nextTick, noop } from "tiny-fn"
-import { supportsPointerEvent } from "tiny-guard"
-import { observeAttributes, uuid } from "../utils"
-import { pipe } from "../utils/fn"
-import { isSafari } from "../utils/guard"
-import { rangy } from "../utils/number"
-import { requestPointerLock } from "../utils/pointerlock"
+import { addDomEvent, nextTick, observeAttributes, requestPointerLock } from "@ui-machines/dom-utils"
+import { rangy } from "@ui-machines/number-utils"
+import { isSafari, pipe, supportsPointerEvent } from "@ui-machines/utils"
 import { dom } from "./number-input.dom"
 import { NumberInputMachineContext, NumberInputMachineState } from "./number-input.types"
 import { utils } from "./number-input.utils"
@@ -18,7 +13,7 @@ export const numberInputMachine = createMachine ctx.dir === "rtl",
-      valueAsNumber: (ctx) => rangy(ctx).getValueAsNumber(),
-      isAtMin: (ctx) => rangy(ctx).isAtMin(),
-      isAtMax: (ctx) => rangy(ctx).isAtMax(),
-      isOutOfRange: (ctx) => !rangy(ctx).isInRange(),
-      canIncrement: (ctx) => !ctx.keepWithinRange || (!ctx.disabled && !rangy(ctx).isAtMax()),
-      canDecrement: (ctx) => !ctx.keepWithinRange || (!ctx.disabled && !rangy(ctx).isAtMin()),
+      valueAsNumber: (ctx) => rangy(ctx).valueAsNumber,
+      isAtMin: (ctx) => rangy(ctx).isAtMin,
+      isAtMax: (ctx) => rangy(ctx).isAtMax,
+      isOutOfRange: (ctx) => !rangy(ctx).isInRange,
+      canIncrement: (ctx) => !ctx.keepWithinRange || (!ctx.disabled && !rangy(ctx).isAtMax),
+      canDecrement: (ctx) => !ctx.keepWithinRange || (!ctx.disabled && !rangy(ctx).isAtMin),
       ariaValueText: (ctx) => ctx.getAriaValueText?.(ctx.value) ?? ctx.value,
       formattedValue: (ctx) => ctx.format?.(ctx.value).toString() ?? ctx.value,
     },
@@ -218,11 +213,11 @@ export const numberInputMachine = createMachine {
             const input = dom.getInputEl(ctx)
-            if (!input) return noop
+            if (!input) return
 
             function onWheel(event: WheelEvent) {
               const isInputFocused = dom.getDoc(ctx).activeElement === input
-              if (!ctx.allowMouseWheel || !isInputFocused) return noop
+              if (!ctx.allowMouseWheel || !isInputFocused) return
               event.preventDefault()
 
               const dir = Math.sign(event.deltaY) * -1
@@ -239,7 +234,7 @@ export const numberInputMachine = createMachine cleanups.forEach((c) => c())
       },
       activatePointerLock(ctx) {
-        if (isSafari() || !supportsPointerEvent()) return noop
+        if (isSafari() || !supportsPointerEvent()) return
         return requestPointerLock(dom.getDoc(ctx))
       },
       trackMousemove(ctx, _evt, { send }) {
diff --git a/packages/machines/src/number-input/number-input.types.ts b/packages/machines/number-input/src/number-input.types.ts
similarity index 97%
rename from packages/machines/src/number-input/number-input.types.ts
rename to packages/machines/number-input/src/number-input.types.ts
index a9642f35c8..11af7c6f1c 100644
--- a/packages/machines/src/number-input/number-input.types.ts
+++ b/packages/machines/number-input/src/number-input.types.ts
@@ -1,6 +1,6 @@
 import { StateMachine as S } from "@ui-machines/core"
-import { PointValue } from "tiny-point"
-import { Context } from "../utils"
+import { Context } from "@ui-machines/types"
+import { Point } from "@ui-machines/rect-utils"
 
 type ValidityState = "rangeUnderflow" | "rangeOverflow"
 
@@ -104,7 +104,7 @@ export type NumberInputMachineContext = Context<{
   /**
    * The scrubber cursor position
    */
-  cursorPoint: PointValue | null
+  cursorPoint: Point | null
   /**
    * Function invoked when the value changes
    */
diff --git a/packages/machines/src/number-input/number-input.utils.ts b/packages/machines/number-input/src/number-input.utils.ts
similarity index 84%
rename from packages/machines/src/number-input/number-input.utils.ts
rename to packages/machines/number-input/src/number-input.utils.ts
index 16d2274c5e..36ca287e8c 100644
--- a/packages/machines/src/number-input/number-input.utils.ts
+++ b/packages/machines/number-input/src/number-input.utils.ts
@@ -1,5 +1,5 @@
+import { rangy } from "@ui-machines/number-utils"
 import type { KeyboardEvent } from "react"
-import { rangy } from "../utils/number"
 import { NumberInputMachineContext as Ctx } from "./number-input.types"
 
 export const utils = {
@@ -18,13 +18,13 @@ export const utils = {
       .join("")
   },
   increment: (ctx: Ctx, step?: number) => {
-    return rangy(ctx).increment(step).clamp().getValue()
+    return rangy(ctx).increment(step).clamp().value
   },
   decrement: (ctx: Ctx, step?: number) => {
-    return rangy(ctx).decrement(step).clamp().getValue()
+    return rangy(ctx).decrement(step).clamp().value
   },
   clamp: (ctx: Ctx) => {
-    return rangy(ctx).clamp().getValue()
+    return rangy(ctx).clamp().value
   },
   parse: (ctx: Ctx, value: string) => {
     return ctx.parse?.(value) ?? value
diff --git a/packages/machines/package.json b/packages/machines/package.json
deleted file mode 100644
index b7d484bea0..0000000000
--- a/packages/machines/package.json
+++ /dev/null
@@ -1,48 +0,0 @@
-{
-  "name": "@ui-machines/web",
-  "version": "0.0.0",
-  "description": "Framework-agnostic State Machines for common UI Patterns",
-  "main": "dist/ui-machines-web.cjs.js",
-  "module": "dist/ui-machines-web.esm.js",
-  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/ui-machines",
-  "author": "Segun Adebayo ",
-  "license": "MIT",
-  "sideEffects": false,
-  "preconstruct": {
-    "entrypoints": [
-      "index.ts"
-    ]
-  },
-  "files": [
-    "dist"
-  ],
-  "publishConfig": {
-    "access": "public"
-  },
-  "bugs": {
-    "url": "https://github.com/chakra-ui/core/issues"
-  },
-  "scripts": {
-    "clean": "rimraf dist"
-  },
-  "dependencies": {
-    "@types/react": "^17.0.20",
-    "@ui-machines/core": "0.0.0",
-    "@ui-machines/prop-types": "0.0.0",
-    "aria-hidden": "^1.1.3",
-    "focus-trap": "^6.7.1",
-    "merge-anything": "^4.0.1",
-    "scroll-into-view-if-needed": "^2.2.28",
-    "tiny-array": "^0.0.1",
-    "tiny-dom-event": "^0.0.2",
-    "tiny-dom-focus": "^0.0.1",
-    "tiny-dom-query": "^0.0.2",
-    "tiny-fn": "^0.0.2",
-    "tiny-guard": "^0.0.3",
-    "tiny-nodelist": "^0.0.1",
-    "tiny-num": "^0.0.3",
-    "tiny-point": "^0.0.1",
-    "tiny-rect": "^0.0.2",
-    "valtio": "^1.2.5"
-  }
-}
diff --git a/packages/machines/pin-input/README.md b/packages/machines/pin-input/README.md
new file mode 100644
index 0000000000..d82665936a
--- /dev/null
+++ b/packages/machines/pin-input/README.md
@@ -0,0 +1,19 @@
+# @ui-machines/pin-input
+
+Core logic for the pin-input widget implemented as a state machine
+
+## Installation
+
+```sh
+yarn add  @ui-machines/pin-input
+# or
+npm i  @ui-machines/pin-input
+```
+
+## Contribution
+
+Yes please! See the [contributing guidelines](https://github.com/chakra-ui/ui-machines/blob/main/CONTRIBUTING.md) for details.
+
+## Licence
+
+This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ui-machines/blob/main/LICENSE).
diff --git a/packages/machines/pin-input/package.json b/packages/machines/pin-input/package.json
new file mode 100644
index 0000000000..3fce5630d7
--- /dev/null
+++ b/packages/machines/pin-input/package.json
@@ -0,0 +1,34 @@
+{
+  "name": "@ui-machines/pin-input",
+  "version": "0.0.0",
+  "description": "Core logic for the pin-input widget implemented as a state machine",
+  "keywords": [
+    "js",
+    "machine",
+    "xstate",
+    "statechart",
+    "component",
+    "chakra-ui",
+    "pin-input"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "types": "dist/index.d.ts",
+  "module": "dist/index.mjs",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/pin-input",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  },
+  "dependencies": {
+    "@ui-machines/core": "^0.0.0"
+  }
+}
diff --git a/packages/machines/src/pin-input/index.ts b/packages/machines/pin-input/src/index.ts
similarity index 100%
rename from packages/machines/src/pin-input/index.ts
rename to packages/machines/pin-input/src/index.ts
diff --git a/packages/machines/src/pin-input/pin-input.connect.ts b/packages/machines/pin-input/src/pin-input.connect.ts
similarity index 96%
rename from packages/machines/src/pin-input/pin-input.connect.ts
rename to packages/machines/pin-input/src/pin-input.connect.ts
index f94ab82294..e77946e187 100644
--- a/packages/machines/src/pin-input/pin-input.connect.ts
+++ b/packages/machines/pin-input/src/pin-input.connect.ts
@@ -1,6 +1,7 @@
 import { StateMachine as S } from "@ui-machines/core"
-import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/prop-types"
-import { ariaAttr, EventKeyMap, getEventKey } from "../utils"
+import { ariaAttr, EventKeyMap, getEventKey } from "@ui-machines/dom-utils"
+import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/types"
+
 import { dom } from "./pin-input.dom"
 import { PinInputMachineContext, PinInputMachineState } from "./pin-input.types"
 
diff --git a/packages/machines/src/pin-input/pin-input.dom.ts b/packages/machines/pin-input/src/pin-input.dom.ts
similarity index 89%
rename from packages/machines/src/pin-input/pin-input.dom.ts
rename to packages/machines/pin-input/src/pin-input.dom.ts
index 8548e8e2de..a352875223 100644
--- a/packages/machines/src/pin-input/pin-input.dom.ts
+++ b/packages/machines/pin-input/src/pin-input.dom.ts
@@ -1,4 +1,4 @@
-import { queryElements } from "tiny-nodelist"
+import { queryElements } from "@ui-machines/dom-utils"
 import { PinInputMachineContext as Ctx } from "./pin-input.types"
 
 export const dom = {
diff --git a/packages/machines/src/pin-input/pin-input.machine.ts b/packages/machines/pin-input/src/pin-input.machine.ts
similarity index 97%
rename from packages/machines/src/pin-input/pin-input.machine.ts
rename to packages/machines/pin-input/src/pin-input.machine.ts
index f3f424b51b..19b9583ab8 100644
--- a/packages/machines/src/pin-input/pin-input.machine.ts
+++ b/packages/machines/pin-input/src/pin-input.machine.ts
@@ -1,6 +1,7 @@
-import { createMachine, ref, guards } from "@ui-machines/core"
-import { fromLength } from "tiny-array"
-import { nextTick } from "tiny-fn"
+import { fromLength } from "@ui-machines/utils"
+import { createMachine, guards, ref } from "@ui-machines/core"
+import { nextTick } from "@ui-machines/dom-utils"
+
 import { dom } from "./pin-input.dom"
 import { PinInputMachineContext, PinInputMachineState } from "./pin-input.types"
 
diff --git a/packages/machines/src/pin-input/pin-input.types.ts b/packages/machines/pin-input/src/pin-input.types.ts
similarity index 96%
rename from packages/machines/src/pin-input/pin-input.types.ts
rename to packages/machines/pin-input/src/pin-input.types.ts
index 49bf922319..e37f4b2598 100644
--- a/packages/machines/src/pin-input/pin-input.types.ts
+++ b/packages/machines/pin-input/src/pin-input.types.ts
@@ -1,4 +1,4 @@
-import type { Context } from "../utils"
+import type { Context } from "@ui-machines/types"
 
 export type PinInputMachineContext = Context<{
   /**
diff --git a/packages/machines/popover/README.md b/packages/machines/popover/README.md
new file mode 100644
index 0000000000..a76f02ecaf
--- /dev/null
+++ b/packages/machines/popover/README.md
@@ -0,0 +1,19 @@
+# @ui-machines/popover
+
+Core logic for the popover widget implemented as a state machine
+
+## Installation
+
+```sh
+yarn add  @ui-machines/popover
+# or
+npm i  @ui-machines/popover
+```
+
+## Contribution
+
+Yes please! See the [contributing guidelines](https://github.com/chakra-ui/ui-machines/blob/main/CONTRIBUTING.md) for details.
+
+## Licence
+
+This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ui-machines/blob/main/LICENSE).
diff --git a/packages/machines/popover/package.json b/packages/machines/popover/package.json
new file mode 100644
index 0000000000..da85aa13d8
--- /dev/null
+++ b/packages/machines/popover/package.json
@@ -0,0 +1,35 @@
+{
+  "name": "@ui-machines/popover",
+  "version": "0.0.0",
+  "description": "Core logic for the popover widget implemented as a state machine",
+  "keywords": [
+    "js",
+    "machine",
+    "xstate",
+    "statechart",
+    "component",
+    "chakra-ui",
+    "popover"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "types": "dist/index.d.ts",
+  "module": "dist/index.mjs",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/popover",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  },
+  "dependencies": {
+    "@ui-machines/core": "^0.0.0",
+    "focus-trap": "^6.7.1"
+  }
+}
diff --git a/packages/machines/src/popover/index.ts b/packages/machines/popover/src/index.ts
similarity index 100%
rename from packages/machines/src/popover/index.ts
rename to packages/machines/popover/src/index.ts
diff --git a/packages/machines/src/popover/popover.connect.ts b/packages/machines/popover/src/popover.connect.ts
similarity index 96%
rename from packages/machines/src/popover/popover.connect.ts
rename to packages/machines/popover/src/popover.connect.ts
index 61cb1e2080..93d21713b9 100644
--- a/packages/machines/src/popover/popover.connect.ts
+++ b/packages/machines/popover/src/popover.connect.ts
@@ -1,6 +1,7 @@
 import { StateMachine as S } from "@ui-machines/core"
-import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/prop-types"
-import { validateBlur } from "../utils"
+import { validateBlur } from "@ui-machines/dom-utils"
+import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/types"
+
 import { dom } from "./popover.dom"
 import { PopoverMachineContext, PopoverMachineState } from "./popover.machine"
 
diff --git a/packages/machines/src/popover/popover.dom.ts b/packages/machines/popover/src/popover.dom.ts
similarity index 87%
rename from packages/machines/src/popover/popover.dom.ts
rename to packages/machines/popover/src/popover.dom.ts
index 932f42da49..251798ddd6 100644
--- a/packages/machines/src/popover/popover.dom.ts
+++ b/packages/machines/popover/src/popover.dom.ts
@@ -1,7 +1,5 @@
-import { last, first } from "tiny-array"
-import { getFocusables } from "tiny-dom-query/focusable"
-import { getTabbables } from "tiny-dom-query/tabbable"
-import { cast, runIfFn } from "tiny-fn"
+import { getFocusables, getTabbables } from "@ui-machines/dom-utils"
+import { cast, first, last, runIfFn } from "@ui-machines/utils"
 import { PopoverMachineContext as Ctx } from "./popover.machine"
 
 export const dom = {
diff --git a/packages/machines/src/popover/popover.machine.ts b/packages/machines/popover/src/popover.machine.ts
similarity index 93%
rename from packages/machines/src/popover/popover.machine.ts
rename to packages/machines/popover/src/popover.machine.ts
index 26bdb7d3a3..564a3adddf 100644
--- a/packages/machines/src/popover/popover.machine.ts
+++ b/packages/machines/popover/src/popover.machine.ts
@@ -1,12 +1,8 @@
 import { choose, createMachine, guards, ref } from "@ui-machines/core"
+import { contains, isTabbable, nextTick, preventBodyScroll, trackPointerDown } from "@ui-machines/dom-utils"
+import type { Context } from "@ui-machines/types"
+import { next } from "@ui-machines/utils"
 import { createFocusTrap, FocusTrap } from "focus-trap"
-import { contains } from "tiny-dom-query"
-import { isTabbable } from "tiny-dom-query/tabbable"
-import { nextTick, noop } from "tiny-fn"
-import { next } from "../utils/array"
-import { preventBodyScroll } from "../utils/body-scroll-lock"
-import { trackPointerDown } from "../utils/pointer-event"
-import { Context } from "../utils/types"
 import { dom } from "./popover.dom"
 
 const { and, or, not } = guards
@@ -105,7 +101,11 @@ export const popoverMachine = createMachine {
+          ctx.pointerdownNode = ref(el)
+        })
+      },
       preventScroll(ctx) {
         return preventBodyScroll({
           allowPinchZoom: true,
@@ -117,7 +117,7 @@ export const popoverMachine = createMachine {
           const el = dom.getContentEl(ctx)
-          if (!ctx.modal || !el) return noop
+          if (!ctx.modal || !el) return
           trap = createFocusTrap(el, {
             escapeDeactivates: false,
             allowOutsideClick: true,
diff --git a/packages/machines/pressable/README.md b/packages/machines/pressable/README.md
new file mode 100644
index 0000000000..e985149122
--- /dev/null
+++ b/packages/machines/pressable/README.md
@@ -0,0 +1,19 @@
+# @ui-machines/pressable
+
+Core logic for the pressable widget implemented as a state machine
+
+## Installation
+
+```sh
+yarn add  @ui-machines/pressable
+# or
+npm i  @ui-machines/pressable
+```
+
+## Contribution
+
+Yes please! See the [contributing guidelines](https://github.com/chakra-ui/ui-machines/blob/main/CONTRIBUTING.md) for details.
+
+## Licence
+
+This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ui-machines/blob/main/LICENSE).
diff --git a/packages/machines/pressable/package.json b/packages/machines/pressable/package.json
new file mode 100644
index 0000000000..a527829039
--- /dev/null
+++ b/packages/machines/pressable/package.json
@@ -0,0 +1,34 @@
+{
+  "name": "@ui-machines/pressable",
+  "version": "0.0.0",
+  "description": "Core logic for the pressable widget implemented as a state machine",
+  "keywords": [
+    "js",
+    "machine",
+    "xstate",
+    "statechart",
+    "component",
+    "chakra-ui",
+    "pressable"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "types": "dist/index.d.ts",
+  "module": "dist/index.mjs",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/pressable",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  },
+  "dependencies": {
+    "@ui-machines/core": "^0.0.0"
+  }
+}
diff --git a/packages/machines/src/pressable/index.ts b/packages/machines/pressable/src/index.ts
similarity index 100%
rename from packages/machines/src/pressable/index.ts
rename to packages/machines/pressable/src/index.ts
diff --git a/packages/machines/src/pressable/pressable.machine.ts b/packages/machines/pressable/src/pressable.machine.ts
similarity index 100%
rename from packages/machines/src/pressable/pressable.machine.ts
rename to packages/machines/pressable/src/pressable.machine.ts
diff --git a/packages/machines/range-slider/README.md b/packages/machines/range-slider/README.md
new file mode 100644
index 0000000000..e30c43f2d4
--- /dev/null
+++ b/packages/machines/range-slider/README.md
@@ -0,0 +1,19 @@
+# @ui-machines/range-slider
+
+Core logic for the range-slider widget implemented as a state machine
+
+## Installation
+
+```sh
+yarn add  @ui-machines/range-slider
+# or
+npm i  @ui-machines/range-slider
+```
+
+## Contribution
+
+Yes please! See the [contributing guidelines](https://github.com/chakra-ui/ui-machines/blob/main/CONTRIBUTING.md) for details.
+
+## Licence
+
+This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ui-machines/blob/main/LICENSE).
diff --git a/packages/machines/range-slider/package.json b/packages/machines/range-slider/package.json
new file mode 100644
index 0000000000..afff601362
--- /dev/null
+++ b/packages/machines/range-slider/package.json
@@ -0,0 +1,35 @@
+{
+  "name": "@ui-machines/range-slider",
+  "version": "0.0.0",
+  "description": "Core logic for the range-slider widget implemented as a state machine",
+  "keywords": [
+    "js",
+    "machine",
+    "xstate",
+    "statechart",
+    "component",
+    "chakra-ui",
+    "range-slider"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "types": "dist/index.d.ts",
+  "module": "dist/index.mjs",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/range-slider",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  },
+  "dependencies": {
+    "@ui-machines/core": "^0.0.0",
+    "@ui-machines/slider": "^0.0.0"
+  }
+}
diff --git a/packages/machines/src/range-slider/index.ts b/packages/machines/range-slider/src/index.ts
similarity index 100%
rename from packages/machines/src/range-slider/index.ts
rename to packages/machines/range-slider/src/index.ts
diff --git a/packages/machines/src/range-slider/range-slider.connect.ts b/packages/machines/range-slider/src/range-slider.connect.ts
similarity index 89%
rename from packages/machines/src/range-slider/range-slider.connect.ts
rename to packages/machines/range-slider/src/range-slider.connect.ts
index a2a1f1a09c..9752d3688a 100644
--- a/packages/machines/src/range-slider/range-slider.connect.ts
+++ b/packages/machines/range-slider/src/range-slider.connect.ts
@@ -1,9 +1,8 @@
-import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/prop-types"
-import { isLeftClick, isModifiedEvent } from "tiny-guard"
-import { toRanges } from "tiny-num"
-import { fromPointerEvent } from "tiny-point/dom"
-import type { EventKeyMap } from "../utils"
-import { dataAttr, getEventKey, getEventStep } from "../utils"
+import { dataAttr, EventKeyMap, getEventKey, getEventStep, getNativeEvent } from "@ui-machines/dom-utils"
+import { multiply, toRanges } from "@ui-machines/number-utils"
+import { getEventPoint } from "@ui-machines/rect-utils"
+import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/types"
+import { isLeftClick, isModifiedEvent } from "@ui-machines/utils"
 import { dom } from "./range-slider.dom"
 import { RangeSliderSend, RangeSliderState } from "./range-slider.types"
 
@@ -52,7 +51,8 @@ export function rangeSliderConnect(
 
     getThumbProps(index: number) {
       const value = values[index]
-      const range = toRanges(ctx)[index]
+      const spacing = multiply(ctx.minStepsBetweenThumbs, ctx.step)
+      const range = toRanges({ ...ctx, spacing })[index]
       const ariaValueText = ctx.getAriaValueText?.(value, index)
       const _ariaLabel = Array.isArray(ariaLabel) ? ariaLabel[index] : ariaLabel
       const _ariaLabelledBy = Array.isArray(ariaLabelledBy) ? ariaLabelledBy[index] : ariaLabelledBy
@@ -144,7 +144,7 @@ export function rangeSliderConnect(
       "data-focused": dataAttr(isFocused),
       style: dom.getRootStyle(ctx),
       onPointerDown(event) {
-        const evt = event.nativeEvent ?? event
+        const evt = getNativeEvent(event)
         if (!isLeftClick(evt) || isModifiedEvent(evt)) return
 
         event.preventDefault()
@@ -152,7 +152,7 @@ export function rangeSliderConnect(
 
         send({
           type: "POINTER_DOWN",
-          point: fromPointerEvent(evt),
+          point: getEventPoint(evt),
         })
       },
     }),
diff --git a/packages/machines/src/range-slider/range-slider.dom.ts b/packages/machines/range-slider/src/range-slider.dom.ts
similarity index 84%
rename from packages/machines/src/range-slider/range-slider.dom.ts
rename to packages/machines/range-slider/src/range-slider.dom.ts
index 362fc1ae12..2567facfc3 100644
--- a/packages/machines/src/range-slider/range-slider.dom.ts
+++ b/packages/machines/range-slider/src/range-slider.dom.ts
@@ -1,14 +1,10 @@
 import { StateMachine } from "@ui-machines/core"
-import { queryElements } from "tiny-nodelist"
-import type { Point } from "tiny-point"
-import { closest } from "tiny-point/distance"
-import { relativeToNode } from "tiny-point/dom"
-import { center } from "tiny-rect"
-import { fromElement } from "tiny-rect/from-element"
-import { dom as sliderDom } from "../../src/slider/slider.dom"
-import { dispatchInputEvent } from "../utils/dispatch-input"
-import { clamp, multiply, percentToValue, snapToStep, toRanges } from "../utils/number"
-import type { Style } from "../utils/types"
+import { dispatchInputEvent, queryElements } from "@ui-machines/dom-utils"
+import { clamp, multiply, percentToValue, snapToStep, toRanges } from "@ui-machines/number-utils"
+import type { Point } from "@ui-machines/rect-utils"
+import { closest, getElementRect, relativeToNode } from "@ui-machines/rect-utils"
+import { slider } from "@ui-machines/slider"
+import type { Style } from "@ui-machines/types"
 import type { RangeSliderMachineContext as Ctx } from "./range-slider.types"
 
 export function getRangeAtIndex(ctx: Ctx, index = ctx.activeIndex) {
@@ -91,11 +87,11 @@ export const dom = {
     dispatchInputEvent(input, value)
   },
 
-  getRootStyle: sliderDom.getRootStyle,
+  getRootStyle: slider.dom.getRootStyle,
   getThumbStyle(ctx: Ctx, index: number) {
     const value = ctx.value[index]
     const thumbSize = ctx.thumbSize?.[index] ?? { width: 0, height: 0 }
-    return sliderDom.getThumbStyle({ ...ctx, value, thumbSize })
+    return slider.dom.getThumbStyle({ ...ctx, value, thumbSize })
   },
   getRangeStyle,
   getTrackStyle: (): Style => ({
@@ -111,7 +107,7 @@ export function getClosestIndex(ctx: Ctx, evt: StateMachine.AnyEventObject) {
     const thumbs = dom.getElements(ctx)
 
     // get the center point of all thumbs
-    const points = thumbs.map((el) => fromElement(el)).map((rect) => center(rect))
+    const points = thumbs.map((el) => getElementRect(el)).map((rect) => rect.center)
 
     // get the closest center point from the event ("pointerdown") point
     const getClosest = closest(...points)
@@ -124,12 +120,12 @@ export function getClosestIndex(ctx: Ctx, evt: StateMachine.AnyEventObject) {
     // when two thumbs are stacked and the user clicks at a point larger than
     // their values, pick the next closest thumb
     const percent = getPointProgress(ctx, evt.point)
-    const pointValue = percentToValue(percent, ctx)
+    const Point = percentToValue(percent, ctx)
 
     const axisPoints = ctx.isHorizontal ? points.map((p) => p.x) : points.map((p) => p.y)
     const isThumbStacked = new Set(axisPoints).size !== points.length
 
-    if (isThumbStacked && pointValue > ctx.value[index]) {
+    if (isThumbStacked && Point > ctx.value[index]) {
       index = clamp(index + 1, { min: 0, max: ctx.value.length - 1 })
     }
   }
diff --git a/packages/machines/src/range-slider/range-slider.machine.ts b/packages/machines/range-slider/src/range-slider.machine.ts
similarity index 94%
rename from packages/machines/src/range-slider/range-slider.machine.ts
rename to packages/machines/range-slider/src/range-slider.machine.ts
index e191d6e1c9..e58d09b08a 100644
--- a/packages/machines/src/range-slider/range-slider.machine.ts
+++ b/packages/machines/range-slider/src/range-slider.machine.ts
@@ -1,8 +1,7 @@
 import { createMachine, ref } from "@ui-machines/core"
-import { nextTick } from "tiny-fn"
-import { fromElement } from "tiny-rect/from-element"
-import { trackPointerMove } from "../utils"
-import { decrement, increment, snapToStep } from "../utils/number"
+import { nextTick, trackPointerMove } from "@ui-machines/dom-utils"
+import { decrement, increment, snapToStep } from "@ui-machines/number-utils"
+import { getElementRect } from "@ui-machines/rect-utils"
 import { dom, getClosestIndex, getRangeAtIndex } from "./range-slider.dom"
 import { RangeSliderMachineContext, RangeSliderMachineState } from "./range-slider.types"
 
@@ -141,7 +140,7 @@ export const rangeSliderMachine = createMachine {
           const thumbs = dom.getElements(ctx)
           ctx.thumbSize = thumbs.map((thumb) => {
-            const { width, height } = fromElement(thumb)
+            const { width, height } = getElementRect(thumb)
             return { width, height }
           })
         })
diff --git a/packages/machines/src/range-slider/range-slider.types.ts b/packages/machines/range-slider/src/range-slider.types.ts
similarity index 98%
rename from packages/machines/src/range-slider/range-slider.types.ts
rename to packages/machines/range-slider/src/range-slider.types.ts
index dd7c10fbfe..b546a12407 100644
--- a/packages/machines/src/range-slider/range-slider.types.ts
+++ b/packages/machines/range-slider/src/range-slider.types.ts
@@ -1,5 +1,5 @@
 import type { StateMachine as S } from "@ui-machines/core"
-import { Context } from "../utils"
+import { Context } from "@ui-machines/types"
 
 export type RangeSliderMachineContext = Context<{
   /**
diff --git a/packages/machines/rating/README.md b/packages/machines/rating/README.md
new file mode 100644
index 0000000000..a3f746f4f1
--- /dev/null
+++ b/packages/machines/rating/README.md
@@ -0,0 +1,19 @@
+# @ui-machines/rating
+
+Core logic for the rating widget implemented as a state machine
+
+## Installation
+
+```sh
+yarn add  @ui-machines/rating
+# or
+npm i  @ui-machines/rating
+```
+
+## Contribution
+
+Yes please! See the [contributing guidelines](https://github.com/chakra-ui/ui-machines/blob/main/CONTRIBUTING.md) for details.
+
+## Licence
+
+This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ui-machines/blob/main/LICENSE).
diff --git a/packages/machines/rating/package.json b/packages/machines/rating/package.json
new file mode 100644
index 0000000000..ba419fbce7
--- /dev/null
+++ b/packages/machines/rating/package.json
@@ -0,0 +1,34 @@
+{
+  "name": "@ui-machines/rating",
+  "version": "0.0.0",
+  "description": "Core logic for the rating widget implemented as a state machine",
+  "keywords": [
+    "js",
+    "machine",
+    "xstate",
+    "statechart",
+    "component",
+    "chakra-ui",
+    "rating"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "types": "dist/index.d.ts",
+  "module": "dist/index.mjs",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/rating",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  },
+  "dependencies": {
+    "@ui-machines/core": "^0.0.0"
+  }
+}
diff --git a/packages/machines/src/rating/index.ts b/packages/machines/rating/src/index.ts
similarity index 100%
rename from packages/machines/src/rating/index.ts
rename to packages/machines/rating/src/index.ts
diff --git a/packages/machines/src/rating/rating.connect.ts b/packages/machines/rating/src/rating.connect.ts
similarity index 92%
rename from packages/machines/src/rating/rating.connect.ts
rename to packages/machines/rating/src/rating.connect.ts
index db32312ce2..a35d3e9839 100644
--- a/packages/machines/src/rating/rating.connect.ts
+++ b/packages/machines/rating/src/rating.connect.ts
@@ -1,10 +1,8 @@
 import { StateMachine as S } from "@ui-machines/core"
-import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/prop-types"
-import { cast } from "tiny-fn"
-import { isLeftClick } from "tiny-guard"
-import { fromPointerEvent, relativeToNode } from "tiny-point/dom"
-import type { EventKeyMap } from "../utils"
-import { dataAttr, getEventKey } from "../utils"
+import { dataAttr, EventKeyMap, getEventKey } from "@ui-machines/dom-utils"
+import { getEventPoint, relativeToNode } from "@ui-machines/rect-utils"
+import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/types"
+import { cast, isLeftClick } from "@ui-machines/utils"
 import { dom } from "./rating.dom"
 import { RatingMachineContext, RatingMachineState } from "./rating.machine"
 
@@ -90,7 +88,7 @@ export function ratingConnect(
         },
         onPointerMove(event) {
           if (!ctx.isInteractive) return
-          const point = fromPointerEvent(cast(event))
+          const point = getEventPoint(cast(event))
           const { progress } = relativeToNode(point, event.currentTarget)
           const isMidway = progress.x < 0.5
           send({ type: "POINTER_OVER", index, isMidway })
diff --git a/packages/machines/src/rating/rating.dom.ts b/packages/machines/rating/src/rating.dom.ts
similarity index 93%
rename from packages/machines/src/rating/rating.dom.ts
rename to packages/machines/rating/src/rating.dom.ts
index 01c1544d6e..2ee6b87d55 100644
--- a/packages/machines/src/rating/rating.dom.ts
+++ b/packages/machines/rating/src/rating.dom.ts
@@ -1,4 +1,4 @@
-import { dispatchInputEvent } from "../utils/dispatch-input"
+import { dispatchInputEvent } from "@ui-machines/dom-utils"
 import { RatingMachineContext as Ctx } from "./rating.machine"
 
 export const dom = {
diff --git a/packages/machines/src/rating/rating.machine.ts b/packages/machines/rating/src/rating.machine.ts
similarity index 97%
rename from packages/machines/src/rating/rating.machine.ts
rename to packages/machines/rating/src/rating.machine.ts
index bc3d489bdd..3f96beed90 100644
--- a/packages/machines/src/rating/rating.machine.ts
+++ b/packages/machines/rating/src/rating.machine.ts
@@ -1,6 +1,6 @@
 import { createMachine, ref } from "@ui-machines/core"
-import { nextTick } from "tiny-fn"
-import { Context } from "../utils/types"
+import { nextTick } from "@ui-machines/dom-utils"
+import { Context } from "@ui-machines/types"
 import { dom } from "./rating.dom"
 
 export type RatingMachineContext = Context<{
diff --git a/packages/machines/slider/README.md b/packages/machines/slider/README.md
new file mode 100644
index 0000000000..0d04c06efd
--- /dev/null
+++ b/packages/machines/slider/README.md
@@ -0,0 +1,19 @@
+# @ui-machines/slider
+
+Core logic for the slider widget implemented as a state machine
+
+## Installation
+
+```sh
+yarn add  @ui-machines/slider
+# or
+npm i  @ui-machines/slider
+```
+
+## Contribution
+
+Yes please! See the [contributing guidelines](https://github.com/chakra-ui/ui-machines/blob/main/CONTRIBUTING.md) for details.
+
+## Licence
+
+This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ui-machines/blob/main/LICENSE).
diff --git a/packages/machines/slider/package.json b/packages/machines/slider/package.json
new file mode 100644
index 0000000000..24151b399a
--- /dev/null
+++ b/packages/machines/slider/package.json
@@ -0,0 +1,34 @@
+{
+  "name": "@ui-machines/slider",
+  "version": "0.0.0",
+  "description": "Core logic for the slider widget implemented as a state machine",
+  "keywords": [
+    "js",
+    "machine",
+    "xstate",
+    "statechart",
+    "component",
+    "chakra-ui",
+    "slider"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "types": "dist/index.d.ts",
+  "module": "dist/index.mjs",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/slider",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  },
+  "dependencies": {
+    "@ui-machines/core": "^0.0.0"
+  }
+}
diff --git a/packages/machines/src/slider/index.ts b/packages/machines/slider/src/index.ts
similarity index 85%
rename from packages/machines/src/slider/index.ts
rename to packages/machines/slider/src/index.ts
index 835137e306..54dc828f4b 100644
--- a/packages/machines/src/slider/index.ts
+++ b/packages/machines/slider/src/index.ts
@@ -1,9 +1,11 @@
 import { sliderConnect } from "./slider.connect"
 import { sliderMachine } from "./slider.machine"
+import { dom } from "./slider.dom"
 
 export const slider = {
   machine: sliderMachine,
   connect: sliderConnect,
+  dom,
 }
 
 export type { SliderMachineContext, SliderMachineState } from "./slider.types"
diff --git a/packages/machines/src/slider/slider.connect.ts b/packages/machines/slider/src/slider.connect.ts
similarity index 93%
rename from packages/machines/src/slider/slider.connect.ts
rename to packages/machines/slider/src/slider.connect.ts
index fba8a05057..a435fd4a6f 100644
--- a/packages/machines/src/slider/slider.connect.ts
+++ b/packages/machines/slider/src/slider.connect.ts
@@ -1,10 +1,9 @@
 import type { StateMachine as S } from "@ui-machines/core"
-import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/prop-types"
-import { isLeftClick, isModifiedEvent } from "tiny-guard"
-import { valueToPercent } from "tiny-num"
-import { fromPointerEvent } from "tiny-point/dom"
-import type { EventKeyMap } from "../utils"
-import { dataAttr, getEventKey, getEventStep } from "../utils"
+import { dataAttr, EventKeyMap, getEventKey, getEventStep, getNativeEvent } from "@ui-machines/dom-utils"
+import { valueToPercent } from "@ui-machines/number-utils"
+import { getEventPoint } from "@ui-machines/rect-utils"
+import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/types"
+import { isLeftClick, isModifiedEvent } from "@ui-machines/utils"
 import { dom } from "./slider.dom"
 import type { SliderMachineContext, SliderMachineState } from "./slider.types"
 
@@ -151,14 +150,14 @@ export function sliderConnect(
       "data-focused": dataAttr(isFocused),
       "aria-disabled": ctx.disabled || undefined,
       onPointerDown(event) {
-        const evt = event.nativeEvent ?? event
+        const evt = getNativeEvent(event)
         // allow only primary pointer clicks
         if (!isLeftClick(evt) || isModifiedEvent(evt)) return
         event.preventDefault()
         event.stopPropagation()
         send({
           type: "POINTER_DOWN",
-          point: fromPointerEvent(evt),
+          point: getEventPoint(evt),
         })
       },
       style: dom.getRootStyle(ctx),
diff --git a/packages/machines/src/slider/slider.dom.ts b/packages/machines/slider/src/slider.dom.ts
similarity index 94%
rename from packages/machines/src/slider/slider.dom.ts
rename to packages/machines/slider/src/slider.dom.ts
index bf47343858..2a4dcf3b2c 100644
--- a/packages/machines/src/slider/slider.dom.ts
+++ b/packages/machines/slider/src/slider.dom.ts
@@ -1,8 +1,8 @@
-import { clamp, percentToValue, snapToStep, transform, valueToPercent } from "tiny-num"
-import type { Point } from "tiny-point"
-import { relativeToNode } from "tiny-point/dom"
-import type { Style } from "../utils"
-import { dispatchInputEvent } from "../utils"
+import { dispatchInputEvent } from "@ui-machines/dom-utils"
+import { clamp, percentToValue, snapToStep, transform, valueToPercent } from "@ui-machines/number-utils"
+import type { Point } from "@ui-machines/rect-utils"
+import { relativeToNode } from "@ui-machines/rect-utils"
+import type { Style } from "@ui-machines/types"
 import type { SliderMachineContext as Ctx } from "./slider.types"
 
 type SharedContext = {
diff --git a/packages/machines/src/slider/slider.machine.ts b/packages/machines/slider/src/slider.machine.ts
similarity index 94%
rename from packages/machines/src/slider/slider.machine.ts
rename to packages/machines/slider/src/slider.machine.ts
index af8c550d0e..1baa4cc110 100644
--- a/packages/machines/src/slider/slider.machine.ts
+++ b/packages/machines/slider/src/slider.machine.ts
@@ -1,8 +1,7 @@
 import { createMachine, ref } from "@ui-machines/core"
-import { nextTick } from "tiny-fn"
-import { fromElement } from "tiny-rect/from-element"
-import { trackPointerMove } from "../utils"
-import { clamp, decrement, increment, snapToStep } from "../utils/number"
+import { nextTick, trackPointerMove } from "@ui-machines/dom-utils"
+import { clamp, decrement, increment, snapToStep } from "@ui-machines/number-utils"
+import { getElementRect } from "@ui-machines/rect-utils"
 import { dom } from "./slider.dom"
 import { SliderMachineContext, SliderMachineState } from "./slider.types"
 
@@ -142,7 +141,7 @@ export const sliderMachine = createMachine {
           const thumb = dom.getThumbEl(ctx)
           if (!thumb) return
-          const { width, height } = fromElement(thumb)
+          const { width, height } = getElementRect(thumb)
           ctx.thumbSize.width = width
           ctx.thumbSize.height = height
         })
diff --git a/packages/machines/src/slider/slider.types.ts b/packages/machines/slider/src/slider.types.ts
similarity index 97%
rename from packages/machines/src/slider/slider.types.ts
rename to packages/machines/slider/src/slider.types.ts
index a591c94a2d..585c01c63f 100644
--- a/packages/machines/src/slider/slider.types.ts
+++ b/packages/machines/slider/src/slider.types.ts
@@ -1,4 +1,4 @@
-import { Context } from "../utils"
+import { Context } from "@ui-machines/types"
 
 export type SliderMachineContext = Context<{
   /**
diff --git a/packages/machines/split-view/README.md b/packages/machines/split-view/README.md
new file mode 100644
index 0000000000..a6c2683408
--- /dev/null
+++ b/packages/machines/split-view/README.md
@@ -0,0 +1,19 @@
+# @ui-machines/split-view
+
+Core logic for the split-view widget implemented as a state machine
+
+## Installation
+
+```sh
+yarn add  @ui-machines/split-view
+# or
+npm i  @ui-machines/split-view
+```
+
+## Contribution
+
+Yes please! See the [contributing guidelines](https://github.com/chakra-ui/ui-machines/blob/main/CONTRIBUTING.md) for details.
+
+## Licence
+
+This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ui-machines/blob/main/LICENSE).
diff --git a/packages/machines/split-view/package.json b/packages/machines/split-view/package.json
new file mode 100644
index 0000000000..9b761ccd6a
--- /dev/null
+++ b/packages/machines/split-view/package.json
@@ -0,0 +1,34 @@
+{
+  "name": "@ui-machines/split-view",
+  "version": "0.0.0",
+  "description": "Core logic for the split-view widget implemented as a state machine",
+  "keywords": [
+    "js",
+    "machine",
+    "xstate",
+    "statechart",
+    "component",
+    "chakra-ui",
+    "split-view"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "types": "dist/index.d.ts",
+  "module": "dist/index.mjs",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/split-view",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  },
+  "dependencies": {
+    "@ui-machines/core": "^0.0.0"
+  }
+}
diff --git a/packages/machines/src/split-view/index.ts b/packages/machines/split-view/src/index.ts
similarity index 100%
rename from packages/machines/src/split-view/index.ts
rename to packages/machines/split-view/src/index.ts
diff --git a/packages/machines/src/split-view/split-view.connect.ts b/packages/machines/split-view/src/split-view.connect.ts
similarity index 99%
rename from packages/machines/src/split-view/split-view.connect.ts
rename to packages/machines/split-view/src/split-view.connect.ts
index a92fff6463..274b976389 100644
--- a/packages/machines/src/split-view/split-view.connect.ts
+++ b/packages/machines/split-view/src/split-view.connect.ts
@@ -1,6 +1,6 @@
 import { StateMachine as S } from "@ui-machines/core"
-import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/prop-types"
-import { dataAttr, EventKeyMap, getEventKey, getEventStep } from "../utils"
+import { dataAttr, EventKeyMap, getEventKey, getEventStep } from "@ui-machines/dom-utils"
+import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/types"
 import { dom } from "./split-view.dom"
 import { SplitViewMachineContext, SplitViewMachineState } from "./split-view.machine"
 
diff --git a/packages/machines/src/split-view/split-view.dom.ts b/packages/machines/split-view/src/split-view.dom.ts
similarity index 100%
rename from packages/machines/src/split-view/split-view.dom.ts
rename to packages/machines/split-view/src/split-view.dom.ts
diff --git a/packages/machines/src/split-view/split-view.machine.ts b/packages/machines/split-view/src/split-view.machine.ts
similarity index 95%
rename from packages/machines/src/split-view/split-view.machine.ts
rename to packages/machines/split-view/src/split-view.machine.ts
index 0ebcf76c59..dbc1d8ab88 100644
--- a/packages/machines/src/split-view/split-view.machine.ts
+++ b/packages/machines/split-view/src/split-view.machine.ts
@@ -1,8 +1,8 @@
 import { createMachine, ref } from "@ui-machines/core"
-import { nextTick } from "tiny-fn"
-import { clamp, decrement, increment, snapToStep } from "tiny-num"
-import { relativeToNode } from "tiny-point/dom"
-import { Context, trackPointerMove } from "../utils"
+import { nextTick, trackPointerMove } from "@ui-machines/dom-utils"
+import { clamp, decrement, increment, snapToStep } from "@ui-machines/number-utils"
+import { relativeToNode } from "@ui-machines/rect-utils"
+import { Context } from "@ui-machines/types"
 import { dom } from "./split-view.dom"
 
 export type SplitViewMachineContext = Context<{
diff --git a/packages/machines/src/index.ts b/packages/machines/src/index.ts
deleted file mode 100644
index 9654319612..0000000000
--- a/packages/machines/src/index.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-/* PLOP_INJECT_EXPORT */
-export * from "./accordion"
-export * from "./combobox"
-export * from "./dialog"
-export * from "./editable"
-export * from "./menu"
-export * from "./number-input"
-export * from "./pin-input"
-export * from "./popover"
-export * from "./range-slider"
-export * from "./rating"
-export * from "./slider"
-export * from "./split-view"
-export * from "./tabs"
-export * from "./tags-input"
-export * from "./toast"
-export * from "./tooltip"
-export { mergeProps } from "./utils/merge-props"
diff --git a/packages/machines/src/utils/contains.ts b/packages/machines/src/utils/contains.ts
deleted file mode 100644
index eb82710616..0000000000
--- a/packages/machines/src/utils/contains.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { isElement } from "./guard"
-
-type Node = HTMLElement | EventTarget | null
-
-export const contains = (parent: Node | undefined, child: Node) => {
-  if (!parent) return false
-  return parent === child || (isElement(parent) && isElement(child) && parent.contains(child))
-}
diff --git a/packages/machines/src/utils/dom-attr.ts b/packages/machines/src/utils/dom-attr.ts
deleted file mode 100644
index 79cfeaee4e..0000000000
--- a/packages/machines/src/utils/dom-attr.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-type Booleanish = boolean | "true" | "false"
-
-export const dataAttr = (guard: boolean | undefined) => {
-  return (guard ? "" : undefined) as Booleanish
-}
-
-export const ariaAttr = (guard: boolean | undefined) => {
-  return guard ? true : undefined
-}
diff --git a/packages/machines/src/utils/dom-env.ts b/packages/machines/src/utils/dom-env.ts
deleted file mode 100644
index 1b5c9b30e8..0000000000
--- a/packages/machines/src/utils/dom-env.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-export function getOwner(el: HTMLElement) {
-  return {
-    doc: el?.ownerDocument ?? document,
-    win: el?.ownerDocument.defaultView ?? window,
-    root: el?.getRootNode(),
-  }
-}
-
-export function getParent(el: HTMLElement): HTMLElement {
-  const { doc } = getOwner(el)
-  if (el.localName === "html") return el
-  return el.assignedSlot || el.parentElement || doc.documentElement
-}
diff --git a/packages/machines/src/utils/fn.ts b/packages/machines/src/utils/fn.ts
deleted file mode 100644
index 994775f02b..0000000000
--- a/packages/machines/src/utils/fn.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-export const runIfFn = (
-  v: T,
-  ...a: T extends (...a: any[]) => void ? Parameters : never
-): T extends (...a: any[]) => void ? ReturnType : T => {
-  return typeof v === "function" ? v(...a) : v
-}
-
-export const noop = () => {}
-
-export const pipe =
-  (...fns: Array<(a: T) => T>) =>
-  (v: T) =>
-    fns.reduce((a, b) => b(a), v)
-
-export const cast = (v: unknown) => v as T
-
-export const nextTick = (fn: VoidFunction) => {
-  const set = new Set()
-  function raf(fn: VoidFunction) {
-    const id = requestAnimationFrame(fn)
-    set.add(() => cancelAnimationFrame(id))
-  }
-  raf(() => raf(fn))
-  return function cleanup() {
-    set.forEach(function (fn) {
-      fn()
-    })
-  }
-}
-
-export const callAll =
-   void>(...fns: (T | undefined)[]) =>
-  (...a: Parameters) => {
-    fns.forEach(function (fn) {
-      fn?.(...a)
-    })
-  }
-
-export function warn(m: string): void
-export function warn(c: boolean, m: string): void
-export function warn(...a: any[]): void {
-  const m = a.length === 1 ? a[0] : a[1]
-  const c = a.length === 2 ? a[0] : true
-  if (c && process.env.NODE_ENV !== "production") {
-    console.warn(m)
-  }
-}
-
-export function invariant(m: string): void
-export function invariant(c: boolean, m: string): void
-export function invariant(...a: any[]): void {
-  const m = a.length === 1 ? a[0] : a[1]
-  const c = a.length === 2 ? a[0] : true
-  if (c && process.env.NODE_ENV !== "production") {
-    throw new Error(m)
-  }
-}
diff --git a/packages/machines/src/utils/index.ts b/packages/machines/src/utils/index.ts
deleted file mode 100644
index 13392f7f9f..0000000000
--- a/packages/machines/src/utils/index.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-export * from "./dispatch-input"
-export * from "./dom-attr"
-export * from "./keyboard-event"
-export * from "./live-region"
-export * from "./mutation-observer"
-export * from "./pointer-event"
-export * from "./validate-blur"
-export * from "./uuid"
-export * from "./types"
diff --git a/packages/machines/src/utils/number.ts b/packages/machines/src/utils/number.ts
deleted file mode 100644
index 5052681da1..0000000000
--- a/packages/machines/src/utils/number.ts
+++ /dev/null
@@ -1,154 +0,0 @@
-type Num = Record
-
-export function wrap(num: number, max: number) {
-  return ((num % max) + max) % max
-}
-
-export function roundPx(num: number, dp?: number) {
-  if (dp != null) {
-    const dp = window.devicePixelRatio
-    return Math.floor(num * dp + 0.5) / dp
-  }
-  return Math.round(num)
-}
-
-const decimalFormat = new Intl.NumberFormat("en-US", { style: "decimal" })
-
-function formatter(n: number) {
-  return parseFloat(decimalFormat.format(n))
-}
-
-export function countDecimals(v: number | undefined) {
-  return decimalFormat.formatToParts(v).find((p) => p.type === "fraction")?.value.length ?? 0
-}
-
-export const valueToPercent = (v: number, r: Num<"step" | "min" | "max">) => ((v - r.min) * 100) / (r.max - r.min)
-
-export const percentToValue = (v: number, r: Num<"min" | "max">) => r.min + (r.max - r.min) * v
-
-export const transform = (a: [number, number], b: [number, number]) => {
-  const i = { min: a[0], max: a[1] }
-  const o = { min: b[0], max: b[1] }
-  return (v: number) => {
-    if (i.min === i.max || o.min === o.max) return o.min
-    const ratio = (o.max - o.min) / (i.max - i.min)
-    return o.min + ratio * (v - i.min)
-  }
-}
-
-export const clamp = (v: number, o: Num<"min" | "max">) => Math.min(Math.max(v, o.min), o.max)
-export const increment = (v: number, s: number) => formatter(v + s)
-export const decrement = (v: number, s: number) => formatter(v - s)
-export const multiply = (v: number, s: number) => formatter(v * s)
-
-export function round(v: number, t?: number) {
-  const p = 10 ** (t ?? 10)
-  v = Math.round(v * p) / p
-  return t ? v.toFixed(t) : v.toString()
-}
-
-export function snapToStep(value: number, step: number) {
-  const p = countDecimals(step)
-  const v = Math.round(value / step) * step
-  return round(v, p)
-}
-
-export function toRanges(o: Num<"min" | "max"> & { value: number[]; spacing: number }) {
-  const spacing = o.spacing ?? 0
-  return o.value.map((v, i) => {
-    const min = i === 0 ? o.min : o.value[i - 1] + spacing
-    const max = i === o.value.length - 1 ? o.max : o.value[i + 1] - spacing
-    return { min, max, value: v }
-  })
-}
-
-export function valueOf(v: string | number) {
-  const num = parseFloat(v.toString().replace(/[^\w.-]+/g, ""))
-  return !isNaN(num) ? num : 0
-}
-
-export function getMaxPrecision(o: { value: string | number; precision?: number; step: number }) {
-  const stepPrecision = countDecimals(o.step)
-  const val = valueOf(o.value)
-  const valuePrecision = isNaN(val) ? stepPrecision : Math.max(countDecimals(val), stepPrecision)
-  return Math.max(valuePrecision, o.precision ?? 0)
-}
-
-export const isAtMax = (v: number, o: Num<"max">) => v >= o.max
-export const isAtMin = (v: number, o: Num<"min">) => v <= o.min
-export const isWithinRange = (v: number, o: Num<"min" | "max">) => v >= o.min && v <= o.max
-
-export function toRangeArray(o: Num<"min" | "max" | "step">): number[] {
-  let i = o.min
-  const range: number[] = []
-  while (i <= o.max) {
-    range.push(i)
-    i = increment(i, o.step)
-  }
-  return range
-}
-
-export type RangeOptions = Num<"min" | "max"> & {
-  step: number
-  precision?: number
-  value: T
-}
-
-export function rangy(options: RangeOptions) {
-  const { min, max, step, precision, value } = options
-
-  const utils = {
-    isInRange() {
-      return isWithinRange(utils.getValueAsNumber(), { min, max })
-    },
-    isAtMax() {
-      return isAtMax(utils.getValueAsNumber(), { max })
-    },
-    isAtMin() {
-      return isAtMin(utils.getValueAsNumber(), { min })
-    },
-    snapToStep() {
-      const value = snapToStep(utils.getValueAsNumber(), step)
-      return rangy({ ...options, value })
-    },
-    increment(stepOverride?: number) {
-      const value = increment(utils.getValueAsNumber(), stepOverride ?? step)
-      return rangy({ ...options, value })
-    },
-    decrement(stepOverride?: number) {
-      const value = decrement(utils.getValueAsNumber(), stepOverride ?? step)
-      return rangy({ ...options, value })
-    },
-    toPrecision() {
-      return rangy({ ...options, value: utils.getValue() })
-    },
-    toMax() {
-      return rangy({ ...options, value: max })
-    },
-    toMin() {
-      return rangy({ ...options, value: min })
-    },
-    fromPercent(percent: number) {
-      const value = percentToValue(percent, { min, max })
-      return rangy({ ...options, value })
-    },
-    clamp() {
-      const value = clamp(utils.getValueAsNumber(), { min, max })
-      return rangy({ ...options, value })
-    },
-    getPercent() {
-      return valueToPercent(utils.getValueAsNumber(), { min, max, step })
-    },
-    getValueAsNumber() {
-      return valueOf(value)
-    },
-    getValue() {
-      return round(utils.getValueAsNumber(), utils.getPrecision())
-    },
-    getPrecision() {
-      return getMaxPrecision({ value, precision, step })
-    },
-  }
-
-  return utils
-}
diff --git a/packages/machines/src/utils/uuid.ts b/packages/machines/src/utils/uuid.ts
deleted file mode 100644
index 0fd8a87eda..0000000000
--- a/packages/machines/src/utils/uuid.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export const uuid = (() => {
-  let id = 0
-  return () => {
-    id++
-    return id.toString(36)
-  }
-})()
diff --git a/packages/machines/tabs/README.md b/packages/machines/tabs/README.md
new file mode 100644
index 0000000000..4910b76d1d
--- /dev/null
+++ b/packages/machines/tabs/README.md
@@ -0,0 +1,19 @@
+# @ui-machines/tabs
+
+Core logic for the tabs widget implemented as a state machine
+
+## Installation
+
+```sh
+yarn add  @ui-machines/tabs
+# or
+npm i  @ui-machines/tabs
+```
+
+## Contribution
+
+Yes please! See the [contributing guidelines](https://github.com/chakra-ui/ui-machines/blob/main/CONTRIBUTING.md) for details.
+
+## Licence
+
+This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ui-machines/blob/main/LICENSE).
diff --git a/packages/machines/tabs/package.json b/packages/machines/tabs/package.json
new file mode 100644
index 0000000000..2b4d9ed677
--- /dev/null
+++ b/packages/machines/tabs/package.json
@@ -0,0 +1,34 @@
+{
+  "name": "@ui-machines/tabs",
+  "version": "0.0.0",
+  "description": "Core logic for the tabs widget implemented as a state machine",
+  "keywords": [
+    "js",
+    "machine",
+    "xstate",
+    "statechart",
+    "component",
+    "chakra-ui",
+    "tabs"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "types": "dist/index.d.ts",
+  "module": "dist/index.mjs",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/tabs",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  },
+  "dependencies": {
+    "@ui-machines/core": "^0.0.0"
+  }
+}
diff --git a/packages/machines/src/tabs/index.ts b/packages/machines/tabs/src/index.ts
similarity index 100%
rename from packages/machines/src/tabs/index.ts
rename to packages/machines/tabs/src/index.ts
diff --git a/packages/machines/src/tabs/tabs.connect.ts b/packages/machines/tabs/src/tabs.connect.ts
similarity index 93%
rename from packages/machines/src/tabs/tabs.connect.ts
rename to packages/machines/tabs/src/tabs.connect.ts
index cf4c3cc791..bafad9b493 100644
--- a/packages/machines/src/tabs/tabs.connect.ts
+++ b/packages/machines/tabs/src/tabs.connect.ts
@@ -1,9 +1,8 @@
 import { StateMachine as S } from "@ui-machines/core"
-import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/prop-types"
-import { cast } from "tiny-fn"
-import { isSafari } from "tiny-guard"
-import type { EventKeyMap } from "../utils"
-import { getEventKey } from "../utils"
+import { getEventKey, EventKeyMap } from "@ui-machines/dom-utils"
+import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/types"
+import { isSafari } from "@ui-machines/utils"
+
 import { dom } from "./tabs.dom"
 import { TabsMachineContext, TabsMachineState } from "./tabs.machine"
 
@@ -107,7 +106,7 @@ export function tabsConnect(
         willChange: "left, right, top, bottom, width, height",
         transitionProperty: "left, right, top, bottom, width, height",
         transitionDuration: ctx.measuredRect ? "200ms" : "0ms",
-        ...cast(ctx.indicatorRect),
+        ...(ctx.indicatorRect as any),
       },
     }),
   }
diff --git a/packages/machines/src/tabs/tabs.dom.ts b/packages/machines/tabs/src/tabs.dom.ts
similarity index 90%
rename from packages/machines/src/tabs/tabs.dom.ts
rename to packages/machines/tabs/src/tabs.dom.ts
index eb356b82dd..1c00091aa3 100644
--- a/packages/machines/src/tabs/tabs.dom.ts
+++ b/packages/machines/tabs/src/tabs.dom.ts
@@ -1,5 +1,5 @@
-import { first, last } from "tiny-array"
-import { itemById, nextById, prevById, queryElements } from "tiny-nodelist"
+import { first, last } from "@ui-machines/utils"
+import { itemById, nextById, prevById, queryElements } from "@ui-machines/dom-utils"
 import { TabsMachineContext as Ctx } from "./tabs.machine"
 
 export const dom = {
diff --git a/packages/machines/src/tabs/tabs.machine.ts b/packages/machines/tabs/src/tabs.machine.ts
similarity index 98%
rename from packages/machines/src/tabs/tabs.machine.ts
rename to packages/machines/tabs/src/tabs.machine.ts
index 2c9669b864..3d88c4c843 100644
--- a/packages/machines/src/tabs/tabs.machine.ts
+++ b/packages/machines/tabs/src/tabs.machine.ts
@@ -1,6 +1,7 @@
 import { createMachine, guards, ref } from "@ui-machines/core"
-import { nextTick } from "tiny-fn"
-import { Context } from "../utils/types"
+import { nextTick } from "@ui-machines/dom-utils"
+import { Context } from "@ui-machines/types"
+
 import { dom } from "./tabs.dom"
 
 const { not } = guards
diff --git a/packages/machines/tags-input/README.md b/packages/machines/tags-input/README.md
new file mode 100644
index 0000000000..aea9c0164d
--- /dev/null
+++ b/packages/machines/tags-input/README.md
@@ -0,0 +1,19 @@
+# @ui-machines/tags-input
+
+Core logic for the tags-input widget implemented as a state machine
+
+## Installation
+
+```sh
+yarn add  @ui-machines/tags-input
+# or
+npm i  @ui-machines/tags-input
+```
+
+## Contribution
+
+Yes please! See the [contributing guidelines](https://github.com/chakra-ui/ui-machines/blob/main/CONTRIBUTING.md) for details.
+
+## Licence
+
+This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ui-machines/blob/main/LICENSE).
diff --git a/packages/machines/tags-input/package.json b/packages/machines/tags-input/package.json
new file mode 100644
index 0000000000..28c30ee9bb
--- /dev/null
+++ b/packages/machines/tags-input/package.json
@@ -0,0 +1,34 @@
+{
+  "name": "@ui-machines/tags-input",
+  "version": "0.0.0",
+  "description": "Core logic for the tags-input widget implemented as a state machine",
+  "keywords": [
+    "js",
+    "machine",
+    "xstate",
+    "statechart",
+    "component",
+    "chakra-ui",
+    "tags-input"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "types": "dist/index.d.ts",
+  "module": "dist/index.mjs",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/tags-input",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  },
+  "dependencies": {
+    "@ui-machines/core": "^0.0.0"
+  }
+}
diff --git a/packages/machines/src/tags-input/index.ts b/packages/machines/tags-input/src/index.ts
similarity index 100%
rename from packages/machines/src/tags-input/index.ts
rename to packages/machines/tags-input/src/index.ts
diff --git a/packages/machines/src/tags-input/tags-input.connect.ts b/packages/machines/tags-input/src/tags-input.connect.ts
similarity index 94%
rename from packages/machines/src/tags-input/tags-input.connect.ts
rename to packages/machines/tags-input/src/tags-input.connect.ts
index 664439049c..db8b179907 100644
--- a/packages/machines/src/tags-input/tags-input.connect.ts
+++ b/packages/machines/tags-input/src/tags-input.connect.ts
@@ -1,9 +1,6 @@
 import { StateMachine as S } from "@ui-machines/core"
-import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/prop-types"
-import { dataAttr } from "../utils/dom-attr"
-import { getEventKey } from "../utils/keyboard-event"
-import { EventKeyMap } from "../utils/types"
-import { validateBlur } from "../utils/validate-blur"
+import { dataAttr, EventKeyMap, getEventKey, getNativeEvent, validateBlur } from "@ui-machines/dom-utils"
+import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/types"
 import { dom } from "./tags-input.dom"
 import { TagsInputMachineContext, TagsInputMachineState } from "./tags-input.machine"
 
@@ -62,7 +59,7 @@ export function tagsInputConnect(
         send({ type: "PASTE", value })
       },
       onKeyDown(event) {
-        const evt = event.nativeEvent || event
+        const evt = getNativeEvent(event)
         if (evt.isComposing) return
         const keyMap: EventKeyMap = {
           ArrowDown() {
diff --git a/packages/machines/src/tags-input/tags-input.dom.ts b/packages/machines/tags-input/src/tags-input.dom.ts
similarity index 95%
rename from packages/machines/src/tags-input/tags-input.dom.ts
rename to packages/machines/tags-input/src/tags-input.dom.ts
index da92430bc6..5e3f737922 100644
--- a/packages/machines/src/tags-input/tags-input.dom.ts
+++ b/packages/machines/tags-input/src/tags-input.dom.ts
@@ -1,4 +1,4 @@
-import { nextById, prevById, queryElements, indexOfId } from "tiny-nodelist"
+import { indexOfId, nextById, prevById, queryElements } from "@ui-machines/dom-utils"
 import { TagsInputMachineContext as Ctx } from "./tags-input.machine"
 
 export const dom = {
diff --git a/packages/machines/src/tags-input/tags-input.machine.ts b/packages/machines/tags-input/src/tags-input.machine.ts
similarity index 99%
rename from packages/machines/src/tags-input/tags-input.machine.ts
rename to packages/machines/tags-input/src/tags-input.machine.ts
index 3227168593..f6b2ef527d 100644
--- a/packages/machines/src/tags-input/tags-input.machine.ts
+++ b/packages/machines/tags-input/src/tags-input.machine.ts
@@ -1,6 +1,7 @@
 import { createMachine, guards, ref } from "@ui-machines/core"
-import { nextTick } from "tiny-fn"
-import type { Context } from "../utils"
+import { nextTick } from "@ui-machines/dom-utils"
+import type { Context } from "@ui-machines/types"
+
 import { dom } from "./tags-input.dom"
 
 const { and, not, or } = guards
diff --git a/packages/machines/toast/README.md b/packages/machines/toast/README.md
new file mode 100644
index 0000000000..f412e59139
--- /dev/null
+++ b/packages/machines/toast/README.md
@@ -0,0 +1,19 @@
+# @ui-machines/toast
+
+Core logic for the toast widget implemented as a state machine
+
+## Installation
+
+```sh
+yarn add  @ui-machines/toast
+# or
+npm i  @ui-machines/toast
+```
+
+## Contribution
+
+Yes please! See the [contributing guidelines](https://github.com/chakra-ui/ui-machines/blob/main/CONTRIBUTING.md) for details.
+
+## Licence
+
+This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ui-machines/blob/main/LICENSE).
diff --git a/packages/machines/toast/package.json b/packages/machines/toast/package.json
new file mode 100644
index 0000000000..3fe2ac8dfc
--- /dev/null
+++ b/packages/machines/toast/package.json
@@ -0,0 +1,34 @@
+{
+  "name": "@ui-machines/toast",
+  "version": "0.0.0",
+  "description": "Core logic for the toast widget implemented as a state machine",
+  "keywords": [
+    "js",
+    "machine",
+    "xstate",
+    "statechart",
+    "component",
+    "chakra-ui",
+    "toast"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "types": "dist/index.d.ts",
+  "module": "dist/index.mjs",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/toast",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  },
+  "dependencies": {
+    "@ui-machines/core": "^0.0.0"
+  }
+}
diff --git a/packages/machines/src/toast/index.ts b/packages/machines/toast/src/index.ts
similarity index 100%
rename from packages/machines/src/toast/index.ts
rename to packages/machines/toast/src/index.ts
diff --git a/packages/machines/src/toast/toast-group.connect.ts b/packages/machines/toast/src/toast-group.connect.ts
similarity index 98%
rename from packages/machines/src/toast/toast-group.connect.ts
rename to packages/machines/toast/src/toast-group.connect.ts
index c619c36a51..a78ea8f8ed 100644
--- a/packages/machines/src/toast/toast-group.connect.ts
+++ b/packages/machines/toast/src/toast-group.connect.ts
@@ -1,6 +1,6 @@
 import { StateMachine as S } from "@ui-machines/core"
-import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/prop-types"
-import { runIfFn } from "tiny-fn"
+import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/types"
+import { runIfFn } from "@ui-machines/utils"
 import { dom } from "./toast.dom"
 import {
   ToastGroupContainerProps,
diff --git a/packages/machines/src/toast/toast-group.machine.ts b/packages/machines/toast/src/toast-group.machine.ts
similarity index 94%
rename from packages/machines/src/toast/toast-group.machine.ts
rename to packages/machines/toast/src/toast-group.machine.ts
index c48caa875e..d99c63c3e4 100644
--- a/packages/machines/src/toast/toast-group.machine.ts
+++ b/packages/machines/toast/src/toast-group.machine.ts
@@ -1,5 +1,4 @@
 import { createMachine, ref } from "@ui-machines/core"
-import { isNumber } from "../utils/guard"
 import { createToastMachine } from "./toast.machine"
 import { ToastGroupMachineContext } from "./toast.types"
 
@@ -18,7 +17,9 @@ export const toastGroupMachine = createMachine({
     offsets: { left: 0, right: 0, top: 0, bottom: 0 },
   },
   computed: {
-    spacingValue: (ctx) => (isNumber(ctx.spacing) ? `${ctx.spacing}px` : ctx.spacing),
+    spacingValue: (ctx) => {
+      return typeof ctx.spacing === "number" ? `${ctx.spacing}px` : ctx.spacing
+    },
   },
   on: {
     SETUP: {
diff --git a/packages/machines/src/toast/toast.connect.ts b/packages/machines/toast/src/toast.connect.ts
similarity index 96%
rename from packages/machines/src/toast/toast.connect.ts
rename to packages/machines/toast/src/toast.connect.ts
index 60c56ee314..850c4347ab 100644
--- a/packages/machines/src/toast/toast.connect.ts
+++ b/packages/machines/toast/src/toast.connect.ts
@@ -1,6 +1,6 @@
 import { StateMachine as S } from "@ui-machines/core"
-import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/prop-types"
-import { dataAttr } from "../utils"
+import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/types"
+import { dataAttr } from "@ui-machines/dom-utils"
 import { dom } from "./toast.dom"
 import { ToastMachineContext, ToastMachineState } from "./toast.types"
 
diff --git a/packages/machines/src/toast/toast.dom.ts b/packages/machines/toast/src/toast.dom.ts
similarity index 92%
rename from packages/machines/src/toast/toast.dom.ts
rename to packages/machines/toast/src/toast.dom.ts
index bf83fcda99..19662438c5 100644
--- a/packages/machines/src/toast/toast.dom.ts
+++ b/packages/machines/toast/src/toast.dom.ts
@@ -1,5 +1,4 @@
-import { ToastPlacement } from "."
-import { ToastGroupMachineContext as GroupCtx, ToastMachineContext as Ctx } from "./toast.types"
+import { ToastGroupMachineContext as GroupCtx, ToastMachineContext as Ctx, ToastPlacement } from "./toast.types"
 
 export const dom = {
   getDoc: (ctx: Ctx | GroupCtx) => ctx.doc ?? document,
diff --git a/packages/machines/src/toast/toast.machine.ts b/packages/machines/toast/src/toast.machine.ts
similarity index 97%
rename from packages/machines/src/toast/toast.machine.ts
rename to packages/machines/toast/src/toast.machine.ts
index bc0777ba67..489038871f 100644
--- a/packages/machines/src/toast/toast.machine.ts
+++ b/packages/machines/toast/src/toast.machine.ts
@@ -1,6 +1,6 @@
 import { createMachine, guards } from "@ui-machines/core"
-import { addDomEvent } from "../utils/dom-event"
-import { noop } from "../utils/fn"
+import { addDomEvent } from "@ui-machines/dom-utils"
+
 import { dom } from "./toast.dom"
 import { ToastMachineContext, ToastMachineState, ToastOptions } from "./toast.types"
 import { getToastDuration } from "./toast.utils"
@@ -102,7 +102,7 @@ export function createToastMachine(options: ToastOptions = {}) {
     {
       activities: {
         trackDocumentVisibility(ctx, _evt, { send }) {
-          if (!ctx.pauseOnPageIdle) return noop
+          if (!ctx.pauseOnPageIdle) return
           const doc = dom.getDoc(ctx) as Document & { msHidden?: boolean; webkitHidden?: string }
           return addDomEvent(doc, "visibilitychange", () => {
             const isPageHidden = doc.hidden || doc.msHidden || doc.webkitHidden
diff --git a/packages/machines/src/toast/toast.types.ts b/packages/machines/toast/src/toast.types.ts
similarity index 98%
rename from packages/machines/src/toast/toast.types.ts
rename to packages/machines/toast/src/toast.types.ts
index 8510c5d194..c9be7739f8 100644
--- a/packages/machines/src/toast/toast.types.ts
+++ b/packages/machines/toast/src/toast.types.ts
@@ -1,5 +1,5 @@
 import { Machine } from "@ui-machines/core"
-import { Context, Direction } from "../utils"
+import { Context, Direction } from "@ui-machines/types"
 
 export type ToastType = "success" | "error" | "loading" | "info" | "custom"
 
diff --git a/packages/machines/src/toast/toast.utils.ts b/packages/machines/toast/src/toast.utils.ts
similarity index 91%
rename from packages/machines/src/toast/toast.utils.ts
rename to packages/machines/toast/src/toast.utils.ts
index 259ee7ee27..43326114e8 100644
--- a/packages/machines/src/toast/toast.utils.ts
+++ b/packages/machines/toast/src/toast.utils.ts
@@ -1,6 +1,5 @@
-import { ToastGroupMachineContext } from "."
-import { Style } from "../utils/types"
-import { ToastMachine, ToastMachineContext, ToastPlacement, ToastType } from "./toast.types"
+import { Style } from "@ui-machines/types"
+import { ToastGroupMachineContext, ToastMachine, ToastMachineContext, ToastPlacement, ToastType } from "./toast.types"
 
 export function getToastsByPlacement(toasts: ToastMachine[]) {
   const result: Partial> = {}
diff --git a/packages/machines/tooltip/README.md b/packages/machines/tooltip/README.md
new file mode 100644
index 0000000000..aded6e93d3
--- /dev/null
+++ b/packages/machines/tooltip/README.md
@@ -0,0 +1,19 @@
+# @ui-machines/tooltip
+
+Core logic for the tooltip widget implemented as a state machine
+
+## Installation
+
+```sh
+yarn add  @ui-machines/tooltip
+# or
+npm i  @ui-machines/tooltip
+```
+
+## Contribution
+
+Yes please! See the [contributing guidelines](https://github.com/chakra-ui/ui-machines/blob/main/CONTRIBUTING.md) for details.
+
+## Licence
+
+This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ui-machines/blob/main/LICENSE).
diff --git a/packages/machines/tooltip/package.json b/packages/machines/tooltip/package.json
new file mode 100644
index 0000000000..da657a1e9a
--- /dev/null
+++ b/packages/machines/tooltip/package.json
@@ -0,0 +1,34 @@
+{
+  "name": "@ui-machines/tooltip",
+  "version": "0.0.0",
+  "description": "Core logic for the tooltip widget implemented as a state machine",
+  "keywords": [
+    "js",
+    "machine",
+    "xstate",
+    "statechart",
+    "component",
+    "chakra-ui",
+    "tooltip"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "types": "dist/index.d.ts",
+  "module": "dist/index.mjs",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/tooltip",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  },
+  "dependencies": {
+    "@ui-machines/core": "^0.0.0"
+  }
+}
diff --git a/packages/machines/src/tooltip/index.ts b/packages/machines/tooltip/src/index.ts
similarity index 100%
rename from packages/machines/src/tooltip/index.ts
rename to packages/machines/tooltip/src/index.ts
diff --git a/packages/machines/src/tooltip/tooltip.connect.ts b/packages/machines/tooltip/src/tooltip.connect.ts
similarity index 95%
rename from packages/machines/src/tooltip/tooltip.connect.ts
rename to packages/machines/tooltip/src/tooltip.connect.ts
index 15bada3a6c..fad6a33856 100644
--- a/packages/machines/src/tooltip/tooltip.connect.ts
+++ b/packages/machines/tooltip/src/tooltip.connect.ts
@@ -1,7 +1,7 @@
 import { StateMachine as S } from "@ui-machines/core"
-import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/prop-types"
-import { dataAttr, getEventKey } from "../utils"
-import type { EventKeyMap } from "../utils/types"
+import { normalizeProp, PropTypes, ReactPropTypes } from "@ui-machines/types"
+import { dataAttr, getEventKey, EventKeyMap } from "@ui-machines/dom-utils"
+
 import { dom } from "./tooltip.dom"
 import { tooltipStore } from "./tooltip.store"
 import { TooltipMachineContext, TooltipMachineState } from "./tooltip.types"
diff --git a/packages/machines/src/tooltip/tooltip.dom.ts b/packages/machines/tooltip/src/tooltip.dom.ts
similarity index 93%
rename from packages/machines/src/tooltip/tooltip.dom.ts
rename to packages/machines/tooltip/src/tooltip.dom.ts
index 79df01dce9..5bf357ab43 100644
--- a/packages/machines/src/tooltip/tooltip.dom.ts
+++ b/packages/machines/tooltip/src/tooltip.dom.ts
@@ -1,4 +1,4 @@
-import { getScrollParent } from "tiny-dom-query/scrollable"
+import { getScrollParent } from "@ui-machines/dom-utils"
 import { TooltipMachineContext as Ctx } from "./tooltip.types"
 
 export const dom = {
diff --git a/packages/machines/src/tooltip/tooltip.machine.ts b/packages/machines/tooltip/src/tooltip.machine.ts
similarity index 91%
rename from packages/machines/src/tooltip/tooltip.machine.ts
rename to packages/machines/tooltip/src/tooltip.machine.ts
index 3a76d8e973..ca328521ae 100644
--- a/packages/machines/src/tooltip/tooltip.machine.ts
+++ b/packages/machines/tooltip/src/tooltip.machine.ts
@@ -1,10 +1,6 @@
-import { createMachine, ref } from "@ui-machines/core"
-import { addDomEvent, addPointerEvent } from "tiny-dom-event"
-import { noop } from "tiny-fn"
-import { isElement, isSafari } from "tiny-guard"
-import { subscribe } from "valtio"
-import { uuid } from "../utils"
-import { addPointerlockChangeListener } from "../utils/pointerlock"
+import { createMachine, ref, subscribe } from "@ui-machines/core"
+import { addDomEvent, addPointerEvent, addPointerlockChangeListener, isHTMLElement } from "@ui-machines/dom-utils"
+import { isSafari, noop, uuid } from "@ui-machines/utils"
 import { dom } from "./tooltip.dom"
 import { tooltipStore } from "./tooltip.store"
 import { TooltipMachineContext, TooltipMachineState } from "./tooltip.types"
@@ -133,7 +129,7 @@ export const tooltipMachine = createMachine {
           const selector = "[data-controls=tooltip][data-expanded]"
-          if (isElement(event.target) && event.target.closest(selector)) return
+          if (isHTMLElement(event.target) && event.target.closest(selector)) return
           send("POINTER_LEAVE")
         })
       },
diff --git a/packages/machines/src/tooltip/tooltip.store.ts b/packages/machines/tooltip/src/tooltip.store.ts
similarity index 84%
rename from packages/machines/src/tooltip/tooltip.store.ts
rename to packages/machines/tooltip/src/tooltip.store.ts
index d8a9413353..72f543fab4 100644
--- a/packages/machines/src/tooltip/tooltip.store.ts
+++ b/packages/machines/tooltip/src/tooltip.store.ts
@@ -1,4 +1,4 @@
-import { proxy } from "valtio"
+import { proxy } from "@ui-machines/core"
 
 type Id = string | null
 
diff --git a/packages/machines/src/tooltip/tooltip.types.ts b/packages/machines/tooltip/src/tooltip.types.ts
similarity index 100%
rename from packages/machines/src/tooltip/tooltip.types.ts
rename to packages/machines/tooltip/src/tooltip.types.ts
diff --git a/packages/types/package.json b/packages/types/package.json
new file mode 100644
index 0000000000..8328c9eec0
--- /dev/null
+++ b/packages/types/package.json
@@ -0,0 +1,26 @@
+{
+  "name": "@ui-machines/types",
+  "version": "0.0.0",
+  "keywords": [
+    "js",
+    "utils",
+    "utils"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "module": "dist/index.mjs",
+  "types": "dist/index.d.ts",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/utilities/types",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  }
+}
diff --git a/packages/machines/src/utils/types.ts b/packages/types/src/index.ts
similarity index 57%
rename from packages/machines/src/utils/types.ts
rename to packages/types/src/index.ts
index 98badad5cd..84cc239be9 100644
--- a/packages/machines/src/utils/types.ts
+++ b/packages/types/src/index.ts
@@ -1,30 +1,9 @@
-import type * as R from "react"
-
-export type Dict = Record
+import type * as React from "react"
 
 export type Direction = "ltr" | "rtl"
 
 export type Orientation = "horizontal" | "vertical"
 
-type Key =
-  | "ArrowDown"
-  | "ArrowUp"
-  | "ArrowLeft"
-  | "ArrowRight"
-  | "Space"
-  | "Enter"
-  | "Comma"
-  | "Escape"
-  | "Backspace"
-  | "Delete"
-  | "Home"
-  | "End"
-  | "Tab"
-  | "PageUp"
-  | "PageDown"
-
-export type EventKeyMap = Partial void>>
-
 export type Context = T & {
   /**
    * The unique identifier of the accordion.
@@ -45,6 +24,8 @@ export type Context = T & {
   dir?: Direction
 }
 
-export type Style = R.CSSProperties & {
+export type Style = React.CSSProperties & {
   [prop: string]: string | number | undefined
 }
+
+export * from "./prop-types"
diff --git a/packages/prop-types/src/index.ts b/packages/types/src/prop-types.ts
similarity index 98%
rename from packages/prop-types/src/index.ts
rename to packages/types/src/prop-types.ts
index 8461291514..4afb49f4d0 100644
--- a/packages/prop-types/src/index.ts
+++ b/packages/types/src/prop-types.ts
@@ -1,8 +1,8 @@
 import type * as React from "react"
 
-type Booleanish = boolean | "true" | "false"
+type Dict = Record
 
-type Dict = Record
+type Booleanish = boolean | "true" | "false"
 
 type Omit = { [P in Exclude]?: T[P] }
 
diff --git a/packages/utilities/core/package.json b/packages/utilities/core/package.json
new file mode 100644
index 0000000000..dceca7f932
--- /dev/null
+++ b/packages/utilities/core/package.json
@@ -0,0 +1,27 @@
+{
+  "name": "@ui-machines/utils",
+  "version": "0.0.0",
+  "description": "",
+  "keywords": [
+    "js",
+    "utils",
+    "core"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "module": "dist/index.mjs",
+  "types": "dist/index.d.ts",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/utilities/core",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  }
+}
diff --git a/packages/machines/src/utils/array.ts b/packages/utilities/core/src/array.ts
similarity index 53%
rename from packages/machines/src/utils/array.ts
rename to packages/utilities/core/src/array.ts
index 4557397406..53e3893a1d 100644
--- a/packages/machines/src/utils/array.ts
+++ b/packages/utilities/core/src/array.ts
@@ -6,69 +6,27 @@ export function toArray(v: T | T[] | undefined | null): T[] {
 export const fromLength = (length: number) => Array.from(Array(length).keys())
 
 export const first = (v: T[]): T | undefined => v[0]
+
 export const last = (v: T[]): T | undefined => v[v.length - 1]
 
 export const isEmpty = (v: T[]): boolean => v.length === 0
-export const has = (v: T[], t: any): boolean => v.indexOf(t) !== -1
 
-export const chunk = (v: T[], size: number): T[][] => {
-  const res: T[][] = []
-  return v.reduce((rows, value, index) => {
-    if (index % size === 0) rows.push([value])
-    else last(rows)?.push(value)
-    return rows
-  }, res)
-}
+export const has = (v: T[], t: any): boolean => v.indexOf(t) !== -1
 
 export const add = (v: T[], ...items: T[]): T[] => v.concat(items)
-export const addAt = (v: T[], idx: number, ...items: T[]): T[] => {
-  v.splice(idx, 0, ...items)
-  return v
-}
+
+export const remove = (v: T[], item: T): T[] => removeAt(v, v.indexOf(item))
 
 export const removeAt = (v: T[], i: number): T[] => {
   if (i > -1) v.splice(i, 1)
   return v
 }
 
-export const remove = (v: T[], item: T): T[] => removeAt(v, v.indexOf(item))
-export const each = (v: T[], fn: (value: T, index: number, arr: T[]) => K): void => {
-  const len = v.length
-  for (let i = 0; i < len; i++) fn(v[i], i, v)
-}
-
-export const find = (v: T[], fn: (value: T, key: number, arr: T[]) => boolean): T | undefined => {
-  const len = v.length
-  for (let i = 0; i < len; i++) if (fn(v[i], i, v)) return v[i]
-}
-
-export function filter(v: T[], fn: (value: T, key: number, arr: T[]) => boolean): T[] {
-  const arr: T[] = []
-  each(v, (...a) => fn(...a) && arr.push(a[0]))
-  return arr
-}
-
 export function clear(v: T[]): T[] {
   while (v.length > 0) v.pop()
   return v
 }
 
-export function replace(v: T[], idx: number, ...items: T[]): T[] {
-  if (idx > -1) v.splice(idx, 1, ...items)
-  return v
-}
-
-export function move(v: T[], from: number, to: number): T[] {
-  const len = v.length
-  from = from < 0 ? len + from : from
-  to = to < 0 ? len + to : to
-  if (from >= 0 && from < len) {
-    const x = v.splice(from, 1)
-    v.splice(to, 0, x[0])
-  }
-  return v
-}
-
 export type IndexOptions = {
   step?: number
   loop?: boolean
@@ -98,18 +56,11 @@ export function prev(v: T[], index: number, opts: IndexOptions = {}): T | und
   return v[prevIndex(v, index, opts)]
 }
 
-export type SearchOptions = {
-  toString: (item: T) => string
-  current: T | undefined
-}
-
-export function search(v: T[], query: string | null | undefined, opts: SearchOptions): T | undefined {
-  const { toString, current } = opts
-  if (query == null) return current
-  const match = (item: T) => toString(item).toLowerCase().startsWith(query.toLowerCase())
-  const filtered = filter(v, match)
-  if (!current) return first(filtered)
-  if (isEmpty(filtered)) return current
-  if (filtered.length === 1) return first(filtered)
-  return next(filtered, filtered.indexOf(current))
+export const chunk = (v: T[], size: number): T[][] => {
+  const res: T[][] = []
+  return v.reduce((rows, value, index) => {
+    if (index % size === 0) rows.push([value])
+    else last(rows)?.push(value)
+    return rows
+  }, res)
 }
diff --git a/packages/utilities/core/src/functions.ts b/packages/utilities/core/src/functions.ts
new file mode 100644
index 0000000000..0d7cc1009c
--- /dev/null
+++ b/packages/utilities/core/src/functions.ts
@@ -0,0 +1,31 @@
+export const runIfFn = (
+  v: T,
+  ...a: T extends (...a: any[]) => void ? Parameters : never
+): T extends (...a: any[]) => void ? ReturnType : T => {
+  return typeof v === "function" ? v(...a) : v
+}
+
+export const cast = (v: unknown): T => v as T
+
+export const noop = () => {}
+
+export const pipe =
+  (...fns: Array<(a: T) => T>) =>
+  (v: T) =>
+    fns.reduce((a, b) => b(a), v)
+
+export const callAll =
+   void>(...fns: (T | undefined)[]) =>
+  (...a: Parameters) => {
+    fns.forEach(function (fn) {
+      fn?.(...a)
+    })
+  }
+
+export const uuid = (() => {
+  let id = 0
+  return () => {
+    id++
+    return id.toString(36)
+  }
+})()
diff --git a/packages/machines/src/utils/guard.ts b/packages/utilities/core/src/guard.ts
similarity index 93%
rename from packages/machines/src/utils/guard.ts
rename to packages/utilities/core/src/guard.ts
index 3aa908143d..1649896696 100644
--- a/packages/machines/src/utils/guard.ts
+++ b/packages/utilities/core/src/guard.ts
@@ -18,8 +18,6 @@ export const isObject = (v: any): v is Record => !(v == null || typ
 export const isNumber = (v: any): v is number => typeof v === "number" && !Number.isNaN(v)
 export const isString = (v: any): v is string => typeof v === "string"
 export const isFunction = (v: any): v is Function => typeof v === "function"
-export const isElement = (v: any): v is HTMLElement =>
-  isObject(v) && v.nodeType === Node.ELEMENT_NODE && isString(v.nodeName)
 
 export const supportsPointerEvent = () => isDom() && window.onpointerdown === null
 export const supportsTouchEvent = () => isDom() && window.ontouchstart === null
diff --git a/packages/utilities/core/src/index.ts b/packages/utilities/core/src/index.ts
new file mode 100644
index 0000000000..937e3b25f1
--- /dev/null
+++ b/packages/utilities/core/src/index.ts
@@ -0,0 +1,4 @@
+export * from "./array"
+export * from "./functions"
+export * from "./guard"
+export * from "./warning"
diff --git a/packages/utilities/core/src/warning.ts b/packages/utilities/core/src/warning.ts
new file mode 100644
index 0000000000..2ab80cf547
--- /dev/null
+++ b/packages/utilities/core/src/warning.ts
@@ -0,0 +1,19 @@
+export function warn(m: string): void
+export function warn(c: boolean, m: string): void
+export function warn(...a: any[]): void {
+  const m = a.length === 1 ? a[0] : a[1]
+  const c = a.length === 2 ? a[0] : true
+  if (c && process.env.NODE_ENV !== "production") {
+    console.warn(m)
+  }
+}
+
+export function invariant(m: string): void
+export function invariant(c: boolean, m: string): void
+export function invariant(...a: any[]): void {
+  const m = a.length === 1 ? a[0] : a[1]
+  const c = a.length === 2 ? a[0] : true
+  if (c && process.env.NODE_ENV !== "production") {
+    throw new Error(m)
+  }
+}
diff --git a/packages/utilities/dom/package.json b/packages/utilities/dom/package.json
new file mode 100644
index 0000000000..b3593b2854
--- /dev/null
+++ b/packages/utilities/dom/package.json
@@ -0,0 +1,27 @@
+{
+  "name": "@ui-machines/dom-utils",
+  "version": "0.0.0",
+  "description": "",
+  "keywords": [
+    "js",
+    "utils",
+    "dom"
+  ],
+  "author": "Segun Adebayo ",
+  "homepage": "https://github.com/chakra-ui/ui-machines#readme",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "module": "dist/index.mjs",
+  "types": "dist/index.d.ts",
+  "repository": "https://github.com/chakra-ui/ui-machines/tree/main/packages/utilities/dom",
+  "sideEffects": false,
+  "files": [
+    "dist"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "bugs": {
+    "url": "https://github.com/chakra-ui/ui-machines/issues"
+  }
+}
diff --git a/packages/machines/src/utils/body-pointer-event.ts b/packages/utilities/dom/src/body-pointer-event.ts
similarity index 75%
rename from packages/machines/src/utils/body-pointer-event.ts
rename to packages/utilities/dom/src/body-pointer-event.ts
index 51c3d3d59b..f17753c4ff 100644
--- a/packages/machines/src/utils/body-pointer-event.ts
+++ b/packages/utilities/dom/src/body-pointer-event.ts
@@ -1,4 +1,5 @@
-import { isLeftClick } from "tiny-guard"
+import { isLeftClick } from "@ui-machines/utils"
+import { nextTick } from "./next-tick"
 
 let changeCount = 0
 let originalBodyPointerEvents: string
@@ -36,7 +37,7 @@ export function preventBodyPointerEvents(opts: Partial = {}
     }
   }
 
-  function flush() {
+  function reset() {
     changeCount--
     if (changeCount === 0) {
       doc.body.style.pointerEvents = originalBodyPointerEvents
@@ -55,14 +56,22 @@ export function preventBodyPointerEvents(opts: Partial = {}
 
     return function () {
       if (isTouchOrPenPressed) {
-        doc.addEventListener("click", flush, { once: true })
+        doc.addEventListener("click", reset, { once: true })
       } else if (isLeftClickPressed) {
-        doc.addEventListener("pointerup", flush, { once: true })
+        doc.addEventListener("pointerup", reset, { once: true })
       } else {
-        flush()
+        reset()
       }
     }
   }
 
-  return { apply, listen }
+  const cleanups: Array = []
+  cleanups.push(apply())
+  nextTick(() => {
+    cleanups.push(listen())
+  })
+
+  return function () {
+    cleanups.forEach((cleanup) => cleanup?.())
+  }
 }
diff --git a/packages/machines/src/utils/body-scroll-lock.ts b/packages/utilities/dom/src/body-scroll-lock.ts
similarity index 91%
rename from packages/machines/src/utils/body-scroll-lock.ts
rename to packages/utilities/dom/src/body-scroll-lock.ts
index b6326dc196..143cdace6a 100644
--- a/packages/machines/src/utils/body-scroll-lock.ts
+++ b/packages/utilities/dom/src/body-scroll-lock.ts
@@ -1,8 +1,7 @@
+import { isDom, isIos, noop, pipe } from "@ui-machines/utils"
 import scrollIntoView from "scroll-into-view-if-needed"
-import { addDomEvent } from "../utils/dom-event"
-import { getScrollParent } from "tiny-dom-query/scrollable"
-import { cast, noop, pipe } from "tiny-fn"
-import { isDom, isIos } from "tiny-guard"
+import { addDomEvent } from "./listener"
+import { getScrollParent } from "./scrollable"
 
 interface PreventScrollOptions {
   disabled?: boolean
@@ -16,8 +15,8 @@ const nonTextInputTypes = new Set(["checkbox", "radio", "range", "color", "file"
 export function preventBodyScroll(opts?: PreventScrollOptions) {
   const { document: docProp, disabled = false, allowPinchZoom } = opts ?? {}
 
-  const doc = cast(docProp ?? document)
-  const win = cast(doc?.defaultView ?? window)
+  const doc = docProp ?? document
+  const win = doc?.defaultView ?? window
 
   const viewport = isDom() ? win.visualViewport : null
   const docEl = doc.documentElement
@@ -103,8 +102,8 @@ export function preventBodyScroll(opts?: PreventScrollOptions) {
       win.scrollTo(0, 0)
     }
 
-    let scrollX = win.pageXOffset
-    let scrollY = win.pageYOffset
+    let scrollX = win.scrollX
+    let scrollY = win.scrollY
     let restoreStyles = pipe(
       setStyle(docEl, "paddingRight", `${win.innerWidth - docEl.clientWidth}px`),
       setStyle(docEl, "overflow", "hidden"),
diff --git a/packages/machines/src/utils/computed-style.ts b/packages/utilities/dom/src/computed-style.ts
similarity index 90%
rename from packages/machines/src/utils/computed-style.ts
rename to packages/utilities/dom/src/computed-style.ts
index 818e29acea..5fc1f3b64d 100644
--- a/packages/machines/src/utils/computed-style.ts
+++ b/packages/utilities/dom/src/computed-style.ts
@@ -4,7 +4,7 @@ type El = HTMLElement | null | undefined
 
 const styleCache: WeakMap = new WeakMap()
 
-export function getElementStyle(el: El): Styles {
+export function getComputedStyle(el: El): Styles {
   if (!el) return {} as Styles
   let style: Styles | undefined = styleCache.get(el)
   if (!style) {
@@ -22,7 +22,7 @@ export function setElementStyle(el: El, styles: Styles) {
 
 export function checkElementStyle(el: El, k: Key, v: string | string[]) {
   if (!el) return false
-  const style = getElementStyle(el)
+  const style = getComputedStyle(el)
   const val = Array.isArray(v) ? v : [v]
   const vv = style?.getPropertyValue(k)
   return vv !== null ? val.includes(vv) : false
diff --git a/packages/machines/src/utils/dispatch-input.ts b/packages/utilities/dom/src/dispatch-event.ts
similarity index 100%
rename from packages/machines/src/utils/dispatch-input.ts
rename to packages/utilities/dom/src/dispatch-event.ts
diff --git a/packages/machines/src/utils/validate-blur.ts b/packages/utilities/dom/src/focus-event.ts
similarity index 65%
rename from packages/machines/src/utils/validate-blur.ts
rename to packages/utilities/dom/src/focus-event.ts
index b145b3828e..2d303e2fe2 100644
--- a/packages/machines/src/utils/validate-blur.ts
+++ b/packages/utilities/dom/src/focus-event.ts
@@ -1,12 +1,9 @@
-import { toArray } from "tiny-array"
-import { cast } from "tiny-fn"
-
 /**
  * Determine if the blur event within an element is valid
  */
 export function validateBlur(event: Event, opts: Options) {
-  const exclude = toArray(opts.exclude)
-  const relatedTarget = cast(event.relatedTarget ?? opts.fallback)
+  const exclude = Array.isArray(opts.exclude) ? opts.exclude : [opts.exclude]
+  const relatedTarget = (event.relatedTarget ?? opts.fallback) as HTMLElement
   return exclude.every((el) => !el?.contains(relatedTarget))
 }
 
diff --git a/packages/machines/src/utils/focusable.ts b/packages/utilities/dom/src/focusable.ts
similarity index 52%
rename from packages/machines/src/utils/focusable.ts
rename to packages/utilities/dom/src/focusable.ts
index 4b1c8c882d..003a96e853 100644
--- a/packages/machines/src/utils/focusable.ts
+++ b/packages/utilities/dom/src/focusable.ts
@@ -1,27 +1,44 @@
-import { checkElementStyle } from "./computed-style"
-import { isElement } from "./guard"
+import { getComputedStyle } from "./computed-style"
+import { isDisabled, isHTMLElement } from "./query"
+
+export const focusableSelector = [
+  "input:not([disabled]):not([type=hidden])",
+  "select:not([disabled])",
+  "textarea:not([disabled])",
+  "button:not([disabled])",
+  "embed",
+  "iframe",
+  "object",
+  "a[href]",
+  "area[href]",
+  "[tabindex]",
+  "audio[controls]",
+  "video[controls]",
+  "*[tabindex]:not([aria-disabled])",
+  "[contenteditable]:not([contenteditable=false])",
+  "details > summary:first-of-type",
+].join(",")
 
 export function isHidden(el: HTMLElement | null, until?: HTMLElement) {
-  if (!el || checkElementStyle(el, "visibility", "hidden")) return true
+  const style = getComputedStyle(el)
+  if (!el || style.getPropertyValue("visibility") === "hidden") return true
   while (el) {
     if (until != null && el === until) return false
-    if (checkElementStyle(el, "display", "none")) return true
+    if (style.getPropertyValue("display") === "none") return true
     el = el.parentElement
   }
   return false
 }
 
-export const isDisabled = (el: HTMLElement | null): boolean => {
-  return el?.getAttribute("disabled") != null || !!el?.getAttribute("aria-disabled") === true
-}
-
 /**
  * Returns the focusable elements within the element
  */
-export const getFocusables = (el: HTMLElement | null, includeContainer = false) => {
+export const getFocusables = (el: HTMLElement | Document | null, includeContainer = false) => {
   if (!el) return []
   let els = Array.from(el.querySelectorAll(focusableSelector))
-  if (includeContainer) els.unshift(el)
+  if (includeContainer && isHTMLElement(el)) {
+    els.unshift(el)
+  }
   return els.filter((el) => isFocusable(el) && !isHidden(el))
 }
 
@@ -29,24 +46,20 @@ export const getFocusables = (el: HTMLElement | null, includeContainer = false)
  * Whether this element is focusable
  */
 export const isFocusable = (el: HTMLElement | null) => {
-  if (!isElement(el) || isHidden(el) || isDisabled(el)) return false
+  if (!isHTMLElement(el) || isHidden(el) || isDisabled(el)) return false
   return el?.matches(focusableSelector)
 }
 
-export const focusableSelector = [
-  "input:not([disabled]):not([type=hidden])",
-  "select:not([disabled])",
-  "textarea:not([disabled])",
-  "button:not([disabled])",
-  "embed",
-  "iframe",
-  "object",
-  "a[href]",
-  "area[href]",
-  "[tabindex]",
-  "audio[controls]",
-  "video[controls]",
-  "*[tabindex]:not([aria-disabled])",
-  "[contenteditable]:not([contenteditable=false])",
-  "details > summary:first-of-type",
-].join(",")
+/**
+ * Returns the tabbable elements within the element
+ */
+export const getTabbables = (el: HTMLElement | Document, includeContainer = false) => {
+  return getFocusables(el, includeContainer).filter(isTabbable)
+}
+
+/**
+ * Whether this element is tabbable
+ */
+export const isTabbable = (el: HTMLElement | null) => {
+  return isFocusable(el) && !isDisabled(el) && !isHidden(el)
+}
diff --git a/packages/utilities/dom/src/index.ts b/packages/utilities/dom/src/index.ts
new file mode 100644
index 0000000000..ef73c6de06
--- /dev/null
+++ b/packages/utilities/dom/src/index.ts
@@ -0,0 +1,29 @@
+type Booleanish = boolean | "true" | "false"
+
+export const dataAttr = (guard: boolean | undefined) => {
+  return (guard ? "" : undefined) as Booleanish
+}
+
+export const ariaAttr = (guard: boolean | undefined) => {
+  return guard ? true : undefined
+}
+
+export * from "./keyboard-event"
+export * from "./next-tick"
+export * from "./query"
+export * from "./sr-only"
+export * from "./body-pointer-event"
+export * from "./body-scroll-lock"
+export * from "./computed-style"
+export * from "./focus-event"
+export * from "./focusable"
+export * from "./listener"
+export * from "./live-region"
+export * from "@ui-machines/core/src/merge-props"
+export * from "./mutation-observer"
+export * from "./pointer-event"
+export * from "./pointerlock"
+export * from "./text-selection"
+export * from "./nodelist"
+export * from "./dispatch-event"
+export * from "./scrollable"
diff --git a/packages/machines/src/utils/keyboard-event.ts b/packages/utilities/dom/src/keyboard-event.ts
similarity index 77%
rename from packages/machines/src/utils/keyboard-event.ts
rename to packages/utilities/dom/src/keyboard-event.ts
index 1fb60dc8a5..0cfaea625e 100644
--- a/packages/machines/src/utils/keyboard-event.ts
+++ b/packages/utilities/dom/src/keyboard-event.ts
@@ -1,8 +1,24 @@
 import type { KeyboardEvent } from "react"
 
-/* -----------------------------------------------------------------------------
- * RTL Keymap
- * -----------------------------------------------------------------------------*/
+type EventKey =
+  | "ArrowDown"
+  | "ArrowUp"
+  | "ArrowLeft"
+  | "ArrowRight"
+  | "Space"
+  | "Enter"
+  | "Comma"
+  | "Escape"
+  | "Backspace"
+  | "Delete"
+  | "Home"
+  | "End"
+  | "Tab"
+  | "PageUp"
+  | "PageDown"
+  | (string & {})
+
+export type EventKeyMap = Partial void>>
 
 const rtlKeyMap = {
   ArrowLeft: "ArrowRight",
@@ -11,10 +27,6 @@ const rtlKeyMap = {
   End: "Home",
 }
 
-/* -----------------------------------------------------------------------------
- * Same keymap but with shortcuts
- * -----------------------------------------------------------------------------*/
-
 const sameKeyMap = {
   Up: "ArrowUp",
   Down: "ArrowDown",
diff --git a/packages/machines/src/utils/dom-event.ts b/packages/utilities/dom/src/listener.ts
similarity index 94%
rename from packages/machines/src/utils/dom-event.ts
rename to packages/utilities/dom/src/listener.ts
index 849af16564..2486cc0d9d 100644
--- a/packages/machines/src/utils/dom-event.ts
+++ b/packages/utilities/dom/src/listener.ts
@@ -1,5 +1,3 @@
-import { cast } from "./fn"
-
 export const t = (v: any) => Object.prototype.toString.call(v).slice(8, -1)
 
 export const isRef = (v: any): v is RefTarget => {
@@ -10,7 +8,7 @@ export const runIfFn = (fn: any): HTMLElement | null => {
   return t(fn) === "Function" ? fn() : fn
 }
 
-export const isTouchEvent = (v: Event): v is TouchEvent => {
+const isTouchEvent = (v: Event): v is TouchEvent => {
   return t(v) === "Object" && !!(v as TouchEvent).touches
 }
 
@@ -33,8 +31,8 @@ export function addDomEvent(
   options?: boolean | AddEventListenerOptions,
 ) {
   const node = isRef(target) ? target.current : runIfFn(target)
-  node?.addEventListener(event, cast(listener), options)
-  return () => node?.removeEventListener(event, cast(listener), options)
+  node?.addEventListener(event, listener as any, options)
+  return () => node?.removeEventListener(event, listener as any, options)
 }
 
 export function addPointerEvent(
diff --git a/packages/machines/src/utils/live-region.ts b/packages/utilities/dom/src/live-region.ts
similarity index 70%
rename from packages/machines/src/utils/live-region.ts
rename to packages/utilities/dom/src/live-region.ts
index f8454da3e9..6ac55e9648 100644
--- a/packages/machines/src/utils/live-region.ts
+++ b/packages/utilities/dom/src/live-region.ts
@@ -1,9 +1,4 @@
-import { isDom } from "tiny-guard"
-import { Style } from "./types"
-
-/* -----------------------------------------------------------------------------
- * Live Region for screen reader technology
- * -----------------------------------------------------------------------------*/
+import { srOnlyStyle } from "./sr-only"
 
 type LiveRegionOptions = {
   ariaLive: "polite" | "assertive"
@@ -13,25 +8,13 @@ type LiveRegionOptions = {
   doc?: Document
 }
 
-export const srOnlyStyle: Style = {
-  border: "0",
-  clip: "rect(0 0 0 0)",
-  height: "1px",
-  margin: "-1px",
-  overflow: "hidden",
-  padding: "0",
-  position: "absolute",
-  width: "1px",
-  whiteSpace: "nowrap",
-}
-
 export class LiveRegion {
   region: HTMLElement | null = null
   doc: Document | null
 
   constructor(opts: Partial = {}) {
     const { ariaLive = "polite", role = "log", ariaRelevant = "additions", doc: _doc } = opts
-    this.doc = _doc ?? isDom() ? document : null
+    this.doc = _doc || document
     const exists = this.doc?.getElementById("__machine-region")
 
     if (!this.doc || exists) return
diff --git a/packages/machines/src/utils/mutation-observer.ts b/packages/utilities/dom/src/mutation-observer.ts
similarity index 77%
rename from packages/machines/src/utils/mutation-observer.ts
rename to packages/utilities/dom/src/mutation-observer.ts
index ab62f56d6a..2d19e215ff 100644
--- a/packages/machines/src/utils/mutation-observer.ts
+++ b/packages/utilities/dom/src/mutation-observer.ts
@@ -1,4 +1,4 @@
-import { noop } from "tiny-fn"
+import { noop } from "@ui-machines/utils"
 
 export function observeAttributes(
   node: HTMLElement | null,
@@ -7,7 +7,8 @@ export function observeAttributes(
 ) {
   if (!node) return noop
   const attrs = Array.isArray(attributes) ? attributes : [attributes]
-  const obs = new MutationObserver((changes) => {
+  const win = node.ownerDocument.defaultView || window
+  const obs = new win.MutationObserver((changes) => {
     for (const change of changes) {
       if (change.type === "attributes" && change.attributeName && attrs.includes(change.attributeName)) {
         fn(change)
diff --git a/packages/utilities/dom/src/next-tick.ts b/packages/utilities/dom/src/next-tick.ts
new file mode 100644
index 0000000000..e128bebd61
--- /dev/null
+++ b/packages/utilities/dom/src/next-tick.ts
@@ -0,0 +1,13 @@
+export const nextTick = (fn: VoidFunction) => {
+  const set = new Set()
+  function raf(fn: VoidFunction) {
+    const id = globalThis.requestAnimationFrame(fn)
+    set.add(() => globalThis.cancelAnimationFrame(id))
+  }
+  raf(() => raf(fn))
+  return function cleanup() {
+    set.forEach(function (fn) {
+      fn()
+    })
+  }
+}
diff --git a/packages/machines/src/utils/nodelist.ts b/packages/utilities/dom/src/nodelist.ts
similarity index 100%
rename from packages/machines/src/utils/nodelist.ts
rename to packages/utilities/dom/src/nodelist.ts
diff --git a/packages/machines/src/utils/pointer-event.ts b/packages/utilities/dom/src/pointer-event.ts
similarity index 66%
rename from packages/machines/src/utils/pointer-event.ts
rename to packages/utilities/dom/src/pointer-event.ts
index 7b4cd5e13e..898cdb24ba 100644
--- a/packages/machines/src/utils/pointer-event.ts
+++ b/packages/utilities/dom/src/pointer-event.ts
@@ -1,25 +1,11 @@
-import { pipe } from "tiny-fn"
-import { isLeftClick, isMouseEvent } from "tiny-guard"
-import { distance } from "tiny-point/distance"
-import { ref } from "valtio"
-import {
-  addPointerEvent,
-  AnyPointerEvent,
-  EventListenerWithPointInfo as Listener,
-  PointerEventInfo,
-} from "../utils/dom-event"
+import { pipe, isLeftClick, isMouseEvent } from "@ui-machines/utils"
+import { addPointerEvent, AnyPointerEvent, EventListenerWithPointInfo as Listener, PointerEventInfo } from "./listener"
 
-type TrackPointerDownOptions = {
-  doc?: Document
-  pointerdownNode?: HTMLElement | null
-}
-
-export function trackPointerDown(ctx: TrackPointerDownOptions) {
-  const doc = ctx.doc ?? document
+export function trackPointerDown(doc: Document, onPointerDown: (el: HTMLElement) => void) {
   const win = doc.defaultView ?? window
   const fn = (event: PointerEvent) => {
     if (event.target instanceof win.HTMLElement) {
-      ctx.pointerdownNode = ref(event.target)
+      onPointerDown(event.target)
     }
   }
   doc.addEventListener("pointerdown", fn)
@@ -39,7 +25,9 @@ export function trackPointerMove(opts: TrackPointerMoveOptions) {
   const { doc = document, threshold = 5 } = ctx
 
   const handlePointerMove: Listener = (event, info) => {
-    if (distance(info.point) < threshold) return
+    const { point: p } = info
+    const distance = Math.sqrt(p.x ** 2 + p.y ** 2)
+    if (distance < threshold) return
 
     // Because Safari doesn't trigger mouseup events when it's above a `