├── .github └── workflows │ └── release.yml ├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── src └── index.ts └── tsconfig.json /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | branches: 5 | - main 6 | jobs: 7 | release: 8 | name: Release 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v2 13 | 14 | - name: Setup Node.js 15 | uses: actions/setup-node@v2 16 | with: 17 | node-version: '12.x' 18 | 19 | - name: Install dependencies 20 | run: npm ci 21 | 22 | - name: Build 23 | run: npm run build 24 | 25 | - name: Release 26 | env: 27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 28 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 29 | run: npx semantic-release 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | test 4 | *.tgz -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](https://badgen.net/bundlephobia/minzip/svelte-useactions) 2 | 3 | ## About 4 | 5 | This library is based on the [svelte-material-ui](https://github.com/hperrin/svelte-material-ui) 6 | useActions implementation. 7 | 8 | It enables you to use [actions](https://svelte.dev/docs#use_action) on custom components. Additionally you get type safety. 9 | 10 | ## Installation 11 | 12 | ```bash 13 | npm i svelte-useactions 14 | 15 | #or 16 | 17 | yarn add svelte-useactions 18 | ``` 19 | 20 | ## Basic Example 21 | 22 | First create your component that accepts an array of actions. 23 | 24 | ```svelte 25 | 26 | 27 | 33 | 34 | 35 | ``` 36 | 37 | Next define your action function 38 | 39 | ```ts 40 | // autofocus.ts 41 | 42 | export const autofocus: Action = (node) => { 43 | node.focus(); 44 | }; 45 | ``` 46 | 47 | Now you can define actions for components. 48 | 49 | ```svelte 50 | 51 | 52 | 56 | 57 | 58 | ``` 59 | 60 | You can also define parameters 61 | 62 | ```ts 63 | // autofocus.ts 64 | 65 | export const autofocus: Action = (node, text) => { 66 | node.focus(); 67 | console.log(text); 68 | }; 69 | ``` 70 | 71 | ```svelte 72 | 73 | 74 | 75 | ``` 76 | 77 | ## Note 78 | 79 | `createActionList` is merely used for type-safety. If you don't care 80 | about it you can just input a normal action list. 81 | 82 | Example: 83 | 84 | ```svelte 85 | 86 | 87 | 88 | ``` 89 | 90 | ## API 91 | 92 | ### `useActions` 93 | 94 | Used in tandem with the `use` directive. Accepts an [action list](#actionlist) as a parameter. 95 | 96 | ```svelte 97 | 103 | 104 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | ``` 123 | 124 | ### `ActionList` 125 | 126 | An array of tuples where the first item is the action and optionally the 127 | parameters of the action as the second item. 128 | 129 | ```ts 130 | let actions: ActionList = []; 131 | const duration = 500; 132 | 133 | // With one action 134 | actions = [[autofocus]]; 135 | 136 | // One action with parameters 137 | actions = [[longpress, duration]]; 138 | 139 | // Multiple actions 140 | actions = [[longpress, duration], [autofocus]]; 141 | ``` 142 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-useactions", 3 | "version": "0.0.0-development", 4 | "description": "", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "keywords": [], 8 | "files": [ 9 | "dist" 10 | ], 11 | "author": "", 12 | "license": "ISC", 13 | "scripts": { 14 | "build": "tsc -p .", 15 | "watch": "tsc --watch -p .", 16 | "semantic-release": "semantic-release" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/paolotiu/svelte-useactions.git" 21 | }, 22 | "devDependencies": { 23 | "semantic-release": "^17.4.4" 24 | }, 25 | "release": { 26 | "branches": [ 27 | "main" 28 | ] 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The return type of an action. 3 | */ 4 | export type ActionReturn = { 5 | destroy?: () => void; 6 | update?: (params: Params) => void; 7 | } | void; 8 | 9 | /** 10 | * Action type shim 11 | */ 12 | export type ActionLike = (node: Node, params: any) => any; 13 | 14 | /** 15 | * A primitive Action 16 | */ 17 | export type Action = ( 18 | node: Node, 19 | params?: Params 20 | ) => ActionReturn; 21 | 22 | /** 23 | * A list of actions 24 | */ 25 | export type ActionList< 26 | Node extends HTMLElement, 27 | Arr extends Array> = Array> 28 | > = [ 29 | ...{ 30 | [I in keyof Arr]: Arr[I] extends ActionLike 31 | ? Parameters[1] extends undefined 32 | ? [Arr[I]] 33 | : [Arr[I], Parameters[1]] 34 | : never; 35 | } 36 | ]; 37 | 38 | /** 39 | * A wrapper function that provides intellisense 40 | */ 41 | export const createActionList = >>( 42 | actions: ActionList 43 | ): ActionList => { 44 | return actions; 45 | }; 46 | 47 | /** 48 | * Takes in actions as a parameter and executes them all. 49 | * Also manages the update and destroy functions if present. 50 | */ 51 | export const useActions = >>( 52 | node: Node, 53 | actions: ActionList 54 | ) => { 55 | const actionReturns: ActionReturn>[] = []; 56 | 57 | if (actions) { 58 | actions.forEach((currentTuple) => { 59 | const action = currentTuple[0]; 60 | const params = currentTuple[1]; 61 | 62 | actionReturns.push(action(node, params)); 63 | }); 64 | } 65 | 66 | return { 67 | update(actions: ActionList) { 68 | actions.forEach((currentTuple, i) => { 69 | const currentReturn = actionReturns[i]; 70 | const params = currentTuple[1]; 71 | 72 | if (!currentReturn) return; 73 | 74 | if (typeof params !== 'undefined') { 75 | currentReturn.update?.(params); 76 | } 77 | }); 78 | }, 79 | destroy() { 80 | actionReturns.forEach((currentReturn) => { 81 | if (currentReturn) currentReturn.destroy?.(); 82 | }); 83 | }, 84 | }; 85 | }; 86 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "lib": ["ES2020", "DOM"], 6 | "declaration": true, 7 | "outDir": "./dist", 8 | "strict": true, 9 | "noUnusedLocals": true, 10 | "noUnusedParameters": true, 11 | "esModuleInterop": true, 12 | "skipLibCheck": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "preserveSymlinks": true 15 | }, 16 | "exclude": ["examples", "dist", "tests"], 17 | "include": ["src"] 18 | } 19 | --------------------------------------------------------------------------------