├── .prettierrc.json
├── .github
├── FUNDING.yml
└── workflows
│ ├── release.yml
│ └── bundle-check.yml
├── .vscode
└── extensions.json
├── readme
└── demo.gif
├── public
└── favicon.ico
├── lib
└── main.ts
├── src
├── assets
│ └── logo.png
├── main.ts
├── env.d.ts
├── components
│ ├── HelloWorld.vue
│ └── Sortable.vue
├── App.vue
└── examples
│ └── WithStore.vue
├── renovate.json
├── tsconfig.node.json
├── vite.site.config.ts
├── .prettierignore
├── .gitignore
├── .npmignore
├── .eslintrc.js
├── index.html
├── tsconfig.dist.json
├── tsconfig.site.json
├── vite.config.ts
├── LICENSE
├── package.json
├── README.md
└── pnpm-lock.yaml
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: MaxLeiter
2 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["Vue.volar"]
3 | }
4 |
--------------------------------------------------------------------------------
/readme/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MaxLeiter/sortablejs-vue3/HEAD/readme/demo.gif
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MaxLeiter/sortablejs-vue3/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/lib/main.ts:
--------------------------------------------------------------------------------
1 | import Sortable from "../src/components/Sortable.vue";
2 |
3 | export { Sortable };
4 |
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MaxLeiter/sortablejs-vue3/HEAD/src/assets/logo.png
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from "vue";
2 | import App from "./App.vue";
3 |
4 | const app = createApp(App);
5 |
6 | app.mount("#app");
7 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": ["group:allNonMajor", "config:base"]
4 | }
5 |
--------------------------------------------------------------------------------
/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "esnext",
5 | "moduleResolution": "node"
6 | },
7 | "include": ["vite.config.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/vite.site.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import vue from "@vitejs/plugin-vue";
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [vue()],
7 | });
8 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | dist-ssr
4 | *.local
5 |
6 | # Editor directories and files
7 | .vscode/*
8 | !.vscode/extensions.json
9 | .idea
10 | .DS_Store
11 | *.suo
12 | *.ntvs*
13 | *.njsproj
14 | *.sln
15 | *.sw?
16 |
17 | .vercel
18 |
19 | # Custom
20 | sortablejs-*.tgz
21 |
--------------------------------------------------------------------------------
/src/env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | declare module "*.vue" {
4 | import type { DefineComponent } from "vue";
5 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
6 | const component: DefineComponent<{}, {}, any>;
7 | export default component;
8 | }
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
26 | .vercel
27 |
28 | # Custom
29 | sortablejs-*.tgz
30 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | # .gitignore, because npm ignores it if this file is present.
2 | # Logs
3 | logs
4 | *.log
5 | npm-debug.log*
6 | yarn-debug.log*
7 | yarn-error.log*
8 | pnpm-debug.log*
9 | lerna-debug.log*
10 |
11 | node_modules
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
26 | .vercel
27 |
28 | # Custom
29 | sortablejs-*.tgz
30 |
31 | # Specific to ignoring when packaging
32 | .github
33 |
34 | readme
35 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | require("@rushstack/eslint-patch/modern-module-resolution");
2 |
3 | module.exports = {
4 | env: {
5 | node: true,
6 | },
7 | extends: [
8 | "eslint:recommended",
9 | "plugin:vue/vue3-recommended",
10 | "@vue/eslint-config-typescript",
11 | "prettier",
12 | ],
13 | parser: "vue-eslint-parser",
14 | parserOptions: {
15 | parser: "@typescript-eslint/parser",
16 | sourceType: "module",
17 | },
18 | rules: {
19 | // override/add rules settings here, such as:
20 | // 'vue/no-unused-vars': 'error'
21 | },
22 | };
23 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | sortablejs-vue3
8 |
9 |
10 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - v*
7 | workflow_dispatch:
8 |
9 | jobs:
10 | release:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v3
14 | - uses: actions/setup-node@v3
15 | with:
16 | node-version: "18"
17 | registry-url: "https://registry.npmjs.org"
18 | - uses: pnpm/action-setup@v2
19 | name: Install pnpm
20 | with:
21 | version: 8
22 | run_install: false
23 | - run: pnpm i
24 | - run: pnpm build
25 | - run: pnpm publish
26 | env:
27 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
28 |
--------------------------------------------------------------------------------
/tsconfig.dist.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "useDefineForClassFields": true,
5 | "module": "esnext",
6 | "moduleResolution": "node",
7 | "strict": true,
8 | "jsx": "preserve",
9 | "sourceMap": true,
10 | "resolveJsonModule": true,
11 | "isolatedModules": true,
12 | "esModuleInterop": true,
13 | "lib": ["esnext", "dom"],
14 | "skipLibCheck": true,
15 | "baseUrl": "./",
16 | "rootDir": "./",
17 | "declaration": true,
18 | "outDir": "dist",
19 | "allowSyntheticDefaultImports": true
20 | },
21 | "files": ["lib/main.ts", "src/components/Sortable.vue"],
22 | "references": [{ "path": "./tsconfig.node.json" }]
23 | }
24 |
--------------------------------------------------------------------------------
/tsconfig.site.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "useDefineForClassFields": true,
5 | "module": "esnext",
6 | "moduleResolution": "node",
7 | "strict": true,
8 | "jsx": "preserve",
9 | "sourceMap": true,
10 | "resolveJsonModule": true,
11 | "isolatedModules": true,
12 | "esModuleInterop": true,
13 | "lib": ["esnext", "dom"],
14 | "skipLibCheck": true,
15 | "baseUrl": "./",
16 | "rootDir": "./",
17 | "declaration": true,
18 | "outDir": "dist",
19 | "allowSyntheticDefaultImports": true
20 | },
21 | "include": ["src/**/*.ts", "src/**/*.vue", "lib/**/*.ts"],
22 | "references": [{ "path": "./tsconfig.node.json" }]
23 | }
24 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import vue from "@vitejs/plugin-vue";
3 | import * as path from "path";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [vue()],
8 | resolve: {
9 | dedupe: ["vue"],
10 | preserveSymlinks: false,
11 | },
12 | logLevel: "info",
13 | build: {
14 | target: "esnext",
15 | minify: "terser",
16 | lib: {
17 | entry: path.resolve(__dirname, "lib/main.ts"),
18 | name: "SortableJS-Vue3",
19 | fileName: (format) => `sortablejs-vue3.${format}.js`,
20 | },
21 | rollupOptions: {
22 | // make sure to externalize deps that shouldn't be bundled
23 | // into your library
24 | external: ["vue", "sortablejs"],
25 | output: {
26 | // Provide global variables to use in the UMD build
27 | // for externalized deps
28 | globals: {
29 | vue: "Vue",
30 | sortablejs: "Sortable",
31 | },
32 | },
33 | },
34 | },
35 | });
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Max Leiter
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.github/workflows/bundle-check.yml:
--------------------------------------------------------------------------------
1 | name: Bundle Size Check
2 |
3 | on:
4 | workflow_dispatch:
5 | pull_request:
6 | branches:
7 | - main
8 |
9 | jobs:
10 | bundle-size:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Checkout
14 | uses: actions/checkout@v3
15 |
16 | - name: Set up Node.js
17 | uses: actions/setup-node@v3
18 | with:
19 | node-version: 16
20 |
21 | - name: Install pnpm
22 | run: npm install -g pnpm
23 |
24 | - name: Install dependencies
25 | run: pnpm install
26 |
27 | - name: Build project
28 | run: pnpm run build
29 |
30 | - name: Calculate bundle size
31 | id: bundle-size
32 | run: |
33 | SIZE=$(du -s dist | awk '{print $1}')
34 | echo "Bundle size: $SIZE bytes"
35 | echo "::set-output name=size::$SIZE"
36 |
37 | - name: Store bundle size as artifact
38 | uses: actions/upload-artifact@v3
39 | with:
40 | name: bundle-size
41 | path: |
42 | dist/
43 | !dist/**/*.map
44 |
45 | - name: Add bundle size comment
46 | uses: peter-evans/create-or-update-comment@v2.1.1
47 | with:
48 | token: ${{ secrets.GITHUB_TOKEN }}
49 | issue-number: ${{ github.event.pull_request.number }}
50 | body: |
51 | 📦 **Bundle size:** The bundle size increased by ${{ steps.bundle-size.outputs.size }} bytes.
52 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sortablejs-vue3",
3 | "version": "1.3.0",
4 | "author": {
5 | "email": "maxwell.leiter@gmail.com",
6 | "name": "Max Leiter",
7 | "url": "https://maxleiter.com"
8 | },
9 | "funding": {
10 | "type": "individual",
11 | "url": "https://github.com/sponsors/MaxLeiter/"
12 | },
13 | "license": "MIT",
14 | "repository": {
15 | "type": "git",
16 | "url": "https://github.com/maxleiter/sortablejs-vue3"
17 | },
18 | "scripts": {
19 | "dev": "vite",
20 | "build": "vite build && vue-tsc --emitDeclarationOnly --project tsconfig.dist.json && mv dist/lib dist/types && rm -rf dist/favicon.ico",
21 | "build:site": "vue-tsc --noEmit --project tsconfig.site.json && vite --config vite.site.config.ts build",
22 | "preview": "vite preview",
23 | "lint": "pnpm prettier --write '**/*.{ts,vue,json}'"
24 | },
25 | "types": "./dist/types/main.d.ts",
26 | "files": [
27 | "dist"
28 | ],
29 | "main": "./dist/sortablejs-vue3.umd.js",
30 | "module": "./dist/sortablejs-vue3.es.js",
31 | "exports": {
32 | ".": {
33 | "types": "./dist/types/main.d.ts",
34 | "import": "./dist/sortablejs-vue3.es.js",
35 | "require": "./dist/sortablejs-vue3.umd.js"
36 | }
37 | },
38 | "dependencies": {
39 | "sortablejs": "^1.15.0",
40 | "vue": "^3.3.7"
41 | },
42 | "peerDependencies": {
43 | "sortablejs": "^1.15.0",
44 | "vue": "^3.2.25"
45 | },
46 | "devDependencies": {
47 | "@types/node": "18.14.2",
48 | "@types/sortablejs": "1.15.4",
49 | "@vitejs/plugin-vue": "4.4.0",
50 | "eslint-config-prettier": "^9.0.0",
51 | "prettier": "3.0.3",
52 | "terser": "5.22.0",
53 | "typescript": "5.2.2",
54 | "vite": "4.5.0",
55 | "vue-component-type-helpers": "^2.1.6",
56 | "vue-tsc": "1.8.22"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
139 |
140 |
186 |
187 |
188 |
189 |
190 |
193 |
194 |
195 | {{ element.text }}
196 |
200 |
201 |
202 | {{ element.text }}
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 | SortableJS-vue3 demo
9 |
10 | Source on GitHub
11 |
12 |
13 |
14 | First run
15 | yarn add sortablejs-vue3
16 | sortablejs
22 |
23 |
24 | Then add
25 | import { Sortable } from "sortablejs-vue3"
26 | in your <script setup>
27 |
28 |
29 | Finally use the component:
30 |
31 | {{ ` console.log(event)"
36 | @end="(event) => console.log(event)">
37 |
38 |
39 | {{ element.name }}
40 |
41 |
42 | ` }}
43 |
44 |
45 |
46 |
47 | Props
48 |
49 |
50 | options : An object supporting all SortedJS options. See Sortable on GitHub
51 | for a full list .
52 |
53 |
54 | list : An array-like object of elements to be made draggable.
55 |
56 |
57 | itemKey : A key to index the elements of the list.
58 |
59 |
60 | tag : The element type to render as. Defaults to div.
61 |
62 |
63 |
64 |
65 | Open your console to view the events being logged while you interact with
66 | the list below.
67 |
68 |
69 |
70 |
79 |
80 |
81 |
190 |
--------------------------------------------------------------------------------
/src/components/Sortable.vue:
--------------------------------------------------------------------------------
1 |
156 |
157 |
158 |
159 |
160 |
167 |
168 |
169 |
170 |
--------------------------------------------------------------------------------
/src/examples/WithStore.vue:
--------------------------------------------------------------------------------
1 |
99 |
100 |
101 |
102 |
103 |
107 |
108 |
109 | {{ element.text }}
110 |
111 |
112 |
113 |
117 |
118 |
119 | {{ element.text }}
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
173 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SortableJS-vue3
2 |
3 | [Demo](https://sortablejs-vue3.maxleiter.com) | [npm](https://www.npmjs.com/package/sortablejs-vue3)
4 |
5 | 
6 |
7 | This is a thin wrapper around the great [SortableJS](https://github.com/SortableJS/Sortable) library. I had many issues migrating from Vue.Draggable to vue.draggable.next, and after briefly investigating I decided that it was too complicated and a smaller solution was the answer. This wrapper attempts to keep you as close to Sortable as possible.
8 |
9 | ### Why not use \?
10 |
11 | - `Vue.Draggable` only supports Vue 2
12 | - `vue.draggable.next` uses the Options API, has multiple open (and afaict useful) pull requests, and had weird bugs/side-effects when I tried and used it
13 | - `shopify/draggable` and [`vue-shopify-dragable`](https://github.com/zjffun/vue-shopify-draggable) seemed promising but they don't supported nested components
14 |
15 | ## Usage
16 |
17 | You can see a demo with more complete code at [https://sortablejs-vue3.maxleiter.com](https://sortablejs-vue3.maxleiter.com).
18 |
19 | 1. Install the package:
20 |
21 | ```bash
22 | pnpm add sortablejs-vue3 sortablejs
23 | ```
24 |
25 | or
26 |
27 | ```bash
28 | npm install sortablejs-vue3 sortablejs
29 | ```
30 |
31 | 2. Import the component in your `