3 |
4 | [](https://npmjs.com/package/vue-draggable-resizable)
5 | [](LICENSE.md)
6 | [](https://www.npmjs.com/package/vue-draggable-resizable)
7 |
8 | > Vue Component for draggable and resizable elements.
9 |
10 | If you are looking for the version 1 of the component, it is available on the [v1 branch](https://github.com/mauricius/vue-draggable-resizable/tree/v1).
11 |
12 | ## Table of Contents
13 |
14 | * [Features](#features)
15 | * [Live Playground](#live-playground)
16 | * [Install and basic usage](#install-and-basic-usage)
17 | * [Props](#props)
18 | * [Events](#events)
19 | * [Styling](#styling)
20 | * [Contributing](#contributing)
21 | * [License](#license)
22 |
23 | ### Features
24 |
25 | * No dependencies
26 | * Use draggable, resizable or both
27 | * Define handles for resizing
28 | * Restrict size and movement to parent element
29 | * Snap element to custom grid
30 | * Restrict drag to vertical or horizontal axis
31 | * Maintain aspect ratio
32 | * Touch enabled
33 | * Use your own classes
34 | * Provide your own markup for handles
35 |
36 | ### Live Playground
37 |
38 | For examples of the component go to the [live playground](https://mauricius.github.io/vue-draggable-resizable/)
39 |
40 | Alternatively you can run the playground on your own computer:
41 |
42 | * Clone this repository
43 | * `npm install`
44 | * `npm run story:dev`
45 | * Visit [http://localhost:6006/](http://localhost:6006/)
46 |
47 | ---
48 |
49 | ## Install and basic usage
50 |
51 | ```bash
52 | $ npm install --save vue-draggable-resizable
53 | ```
54 |
55 |
56 | Register the component globally
57 |
58 | ```js
59 | // main.js
60 | import { createApp } from 'vue'
61 | import VueDraggableResizable from 'vue-draggable-resizable'
62 | import App from './App.vue'
63 |
64 | createApp(App)
65 | .component("vue-draggable-resizable", VueDraggableResizable)
66 | .mount('#app')
67 | ```
68 |
69 | You may now use the component in your markup
70 |
71 | ```vue
72 | // App.vue
73 |
74 |
75 |
76 |
Hello! I'm a flexible component. You can drag me around and you can resize me.
77 |
78 |
79 |
80 | ```
81 |
82 | The component itself does not include any CSS. You'll need to include it separately in your `App.vue`:
83 |
84 | ```vue
85 |
88 | ```
89 |
90 | ### Props
91 |
92 | #### className
93 | Type: `String`
94 | Required: `false`
95 | Default: `vdr`
96 |
97 | Used to set the custom `class` of a draggable-resizable component.
98 |
99 | ```html
100 |
101 | ```
102 |
103 | #### classNameDraggable
104 | Type: `String`
105 | Required: `false`
106 | Default: `draggable`
107 |
108 | Used to set the custom `class` of a draggable-resizable component when `draggable` is enable.
109 |
110 | ```html
111 |
112 | ```
113 |
114 | #### classNameResizable
115 | Type: `String`
116 | Required: `false`
117 | Default: `resizable`
118 |
119 | Used to set the custom `class` of a draggable-resizable component when `resizable` is enable.
120 |
121 | ```html
122 |
123 | ```
124 |
125 | #### classNameDragging
126 | Type: `String`
127 | Required: `false`
128 | Default: `dragging`
129 |
130 | Used to set the custom `class` of a draggable-resizable component when is dragging.
131 |
132 | ```html
133 |
134 | ```
135 |
136 | #### classNameResizing
137 | Type: `String`
138 | Required: `false`
139 | Default: `resizing`
140 |
141 | Used to set the custom `class` of a draggable-resizable component when is resizing.
142 |
143 | ```html
144 |
145 | ```
146 |
147 | #### classNameActive
148 | Type: `String`
149 | Required: `false`
150 | Default: `active`
151 |
152 | Used to set the custom `class` of a draggable-resizable component when is active.
153 |
154 | ```html
155 |
156 | ```
157 |
158 | #### classNameHandle
159 | Type: `String`
160 | Required: `false`
161 | Default: `handle`
162 |
163 | Used to set the custom common `class` of each handle element. This way you can style each handle individually using the selector `-`, where `handle code` identifies one of the handles provided by the `handle` prop.
164 |
165 | So for example, this component:
166 |
167 | ```html
168 |
169 | ```
170 |
171 | renders the following:
172 |
173 | ```html
174 |
175 |
176 |
177 |
178 | [...]
179 |
180 | ```
181 |
182 | #### scale
183 | Type: `Number|Array`
184 | Required: `false`
185 | Default: `1`
186 |
187 | The `scale` prop controls the scale property when the CSS 3 [scale transformation](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scale) is applied to one of the parent elements. If not provided the default value is 1.
188 |
189 | ```html
190 |
191 |
192 |
193 | ```
194 |
195 | #### disableUserSelect
196 | Type: `Boolean`
197 | Required: `false`
198 | Default: `true`
199 |
200 | By default, the component adds the style declaration `'user-select:none'` to itself to prevent text selection during drag. You can disable this behaviour by setting this prop to `false`.
201 |
202 | ```html
203 |
204 | ```
205 |
206 | #### enableNativeDrag
207 | Type: `Boolean`
208 | Required: `false`
209 | Default: `false`
210 |
211 | By default, the browser's native drag and drop funcionality (usually used for images and some other elements) is disabled, as it may conflict with the one provided by the component. If you need, for whatever reason, to have this functionality back you can set this prop to `true`.
212 |
213 | ```html
214 |
215 | ```
216 |
217 | #### active
218 | Type: `Boolean`
219 | Required: `false`
220 | Default: `false`
221 |
222 | Determines if the component should be active or not. The prop reacts to changes and also can be used with the `sync`[modifier](https://vuejs.org/v2/guide/components.html#sync-Modifier) to keep the state in sync with the parent. You can use along with the `preventDeactivation` prop in order to fully control the active behavior from outside the component.
223 |
224 | ```html
225 |
226 | ```
227 |
228 | #### preventDeactivation
229 | Type: `Boolean`
230 | Required: `false`
231 | Default: `false`
232 |
233 | Determines if the component should be deactivated when the user clicks/taps outside it.
234 |
235 | ```html
236 |
237 | ```
238 |
239 | #### draggable
240 | Type: `Boolean`
241 | Required: `false`
242 | Default: `true`
243 |
244 | Defines it the component should be draggable or not.
245 |
246 | ```html
247 |
248 | ```
249 |
250 | #### resizable
251 | Type: `Boolean`
252 | Required: `false`
253 | Default: `true`
254 |
255 | Defines it the component should be resizable or not.
256 |
257 | ```html
258 |
259 | ```
260 |
261 | #### w
262 | Type: `Number|String`
263 | Required: `false`
264 | Default: `200`
265 |
266 | Define the initial width of the element. It also supports `auto`, but when you start resizing the value will fallback to a number.
267 |
268 | ```html
269 |
270 | ```
271 |
272 | #### h
273 | Type: `Number|String`
274 | Required: `false`
275 | Default: `200`
276 |
277 | Define the initial height of the element. It also supports `auto`, but when you start resizing the value will fallback to a number.
278 |
279 | ```html
280 |
281 | ```
282 |
283 | #### minWidth
284 | Type: `Number`
285 | Required: `false`
286 | Default: `50`
287 |
288 | Define the minimal width of the element.
289 |
290 | ```html
291 |
292 | ```
293 |
294 | #### minHeight
295 | Type: `Number`
296 | Required: `false`
297 | Default: `50`
298 |
299 | Define the minimal height of the element.
300 |
301 | ```html
302 |
303 | ```
304 |
305 | #### maxWidth
306 | Type: `Number`
307 | Required: `false`
308 | Default: `null`
309 |
310 | Define the maximum width of the element.
311 |
312 | ```html
313 |
314 | ```
315 |
316 | #### maxHeight
317 | Type: `Number`
318 | Required: `false`
319 | Default: `null`
320 |
321 | Define the maximum height of the element.
322 |
323 | ```html
324 |
325 | ```
326 |
327 | #### x
328 | Type: `Number`
329 | Required: `false`
330 | Default: `0`
331 |
332 | Define the initial x position of the element.
333 |
334 | ```html
335 |
336 | ```
337 |
338 | #### y
339 | Type: `Number`
340 | Required: `false`
341 | Default: `0`
342 |
343 | Define the initial y position of the element.
344 |
345 | ```html
346 |
347 | ```
348 |
349 | #### z
350 | Type: `Number|String`
351 | Required: `false`
352 | Default: `auto`
353 |
354 | Define the z-index of the element.
355 |
356 | ```html
357 |
358 | ```
359 |
360 | #### handles
361 | Type: `Array`
362 | Required: `false`
363 | Default: `['tl', 'tm', 'tr', 'mr', 'br', 'bm', 'bl', 'ml']`
364 |
365 | Define the array of handles to restrict the element resizing:
366 | * `tl` - Top left
367 | * `tm` - Top middle
368 | * `tr` - Top right
369 | * `mr` - Middle right
370 | * `br` - Bottom right
371 | * `bm` - Bottom middle
372 | * `bl` - Bottom left
373 | * `ml` - Middle left
374 |
375 | ```html
376 |
377 | ```
378 |
379 | #### axis
380 | Type: `String`
381 | Required: `false`
382 | Default: `both`
383 |
384 | Define the axis on which the element is draggable. Available values are `x`, `y` or `both`.
385 |
386 | ```html
387 |
388 | ```
389 |
390 | #### grid
391 | Type: `Array`
392 | Required: `false`
393 | Default: `[1,1]`
394 |
395 | Define the grid on which the element is snapped.
396 |
397 | ```html
398 |
399 | ```
400 |
401 | #### parent
402 | Type: `Boolean`
403 | Required: `false`
404 | Default: `false`
405 |
406 | Restricts the movement and the dimensions of the component to the parent.
407 |
408 | ```html
409 |
410 | ```
411 |
412 | #### dragHandle
413 | Type: `String`
414 | Required: `false`
415 |
416 | Defines the selector that should be used to drag the component.
417 |
418 | ```html
419 |
420 | ```
421 |
422 | #### dragCancel
423 | Type: `String`
424 | Required: `false`
425 |
426 | Defines a selector that should be used to prevent drag initialization.
427 |
428 | ```html
429 |
430 | ```
431 |
432 | #### lockAspectRatio
433 | Type: `Boolean`
434 | Required: `false`
435 | Default: `false`
436 |
437 | The `lockAspectRatio` property is used to lock aspect ratio. This property doesn't play well with `grid`, so make sure to use only one at a time.
438 |
439 | ```html
440 |
441 | ```
442 |
443 | #### onDragStart
444 | Type: `Function`
445 | Required: `false`
446 | Default: `null`
447 |
448 | Called when dragging starts (element is clicked or touched). If `false` is returned by any handler, the action will cancel. You can use this function to prevent bubbling of events.
449 |
450 | ```html
451 |
452 | ```
453 |
454 | ```js
455 | function onDragStartCallback(ev){
456 | ...
457 | // return false; — for cancel
458 | }
459 | ```
460 |
461 | #### onDrag
462 | Type: `Function`
463 | Required: `false`
464 | Default: `null`
465 |
466 | Called before the element is dragged. The function receives the next values of `x` and `y`. If `false` is returned by any handler, the action will cancel.
467 |
468 | ```html
469 |
470 | ```
471 |
472 | ```js
473 | function onDragStartCallback(x, y){
474 | ...
475 | // return false; — for cancel
476 | }
477 | ```
478 |
479 |
480 | #### onResizeStart
481 | Type: `Function`
482 | Required: `false`
483 | Default: `null`
484 |
485 | Called when resizing starts (handle is clicked or touched). If `false` is returned by any handler, the action will cancel.
486 |
487 | ```html
488 |
489 | ```
490 |
491 | ```js
492 |
493 | function onResizeStartCallback(handle, ev){
494 | ...
495 | // return false; — for cancel
496 | }
497 | ```
498 |
499 | #### onResize
500 | Type: `Function`
501 | Required: `false`
502 | Default: `null`
503 |
504 | Called before the element is resized. The function receives the handle and the next values of `x`, `y`, `width` and `height`. If `false` is returned by any handler, the action will cancel.
505 |
506 | ```html
507 |
508 | ```
509 |
510 | ```js
511 |
512 | function onResizeStartCallback(handle, x, y, width, height){
513 | ...
514 | // return false; — for cancel
515 | }
516 | ```
517 | ---
518 |
519 | ### Events
520 |
521 | #### activated
522 |
523 | Parameters: `-`
524 |
525 | Called whenever the component gets clicked, in order to show handles.
526 |
527 | ```html
528 |
529 | ```
530 |
531 | #### deactivated
532 |
533 | Parameters: `-`
534 |
535 | Called whenever the user clicks anywhere outside the component, in order to deactivate it.
536 |
537 | ```html
538 |
539 | ```
540 |
541 | #### resizing
542 |
543 | Parameters:
544 | * `left` the X position of the element
545 | * `top` the Y position of the element
546 | * `width` the width of the element
547 | * `height` the height of the element
548 |
549 | Called whenever the component gets resized.
550 |
551 | ```html
552 |
553 | ```
554 |
555 | #### resizestop
556 |
557 | Parameters:
558 | * `left` the X position of the element
559 | * `top` the Y position of the element
560 | * `width` the width of the element
561 | * `height` the height of the element
562 |
563 | Called whenever the component stops getting resized.
564 |
565 | ```html
566 |
567 | ```
568 |
569 | #### dragging
570 |
571 | Parameters:
572 | * `left` the X position of the element
573 | * `top` the Y position of the element
574 |
575 | Called whenever the component gets dragged.
576 |
577 | ```html
578 |
579 | ```
580 |
581 | #### dragstop
582 |
583 | Parameters:
584 | * `left` the X position of the element
585 | * `top` the Y position of the element
586 |
587 | Called whenever the component stops getting dragged.
588 |
589 | ```html
590 |
591 | ```
592 |
593 | ---
594 |
595 | ### Styling
596 |
597 | You can style the component using appropriate class names passed as props to the component. Moreover you can replace the default styles for the handles, provided in the source file `vue-draggable-resizable.css`, but you should take care to define position and size for them. The default classes for handles are `handle` and `handle-tl`, `handle-br` and so on.
598 |
599 | The component also provides [named slots](https://vuejs.org/guide/components/slots.html#named-slots) for each handle, so you can use your markup inside each one.
600 |
601 | ## Thanks
602 |
603 | Thanks to @kirillmurashov for his work on [vue-drag-resize](https://github.com/kirillmurashov/vue-drag-resize) component.
604 |
605 | ## Security
606 |
607 | If you discover any security related issues, please email maurizio.bonani@gmail.com instead of using the issue tracker.
608 |
609 | ## Contributing
610 |
611 | Any contribution to the code or any part of the documentation and any idea and/or suggestion are very welcome.
612 |
613 | ``` bash
614 | # serve with hot reload at localhost:8080
615 | npm run dev
616 |
617 | # distribution build
618 | npm run build
619 |
620 | # build the histoire docs
621 | npm run story:build
622 |
623 | # run tests
624 | npm run test
625 |
626 | # run histoire at localhost:6006
627 | npm run story:dev
628 | ```
629 |
630 | ## License
631 |
632 | The MIT License (MIT). Please see [License File](LICENSE) for more information.
633 |
--------------------------------------------------------------------------------
/cypress.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'cypress';
2 |
3 | export default defineConfig({
4 | component: {
5 | devServer: {
6 | framework: "vue",
7 | bundler: "vite",
8 | },
9 | },
10 | });
11 |
--------------------------------------------------------------------------------
/cypress/support/commands.js:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 |
11 | import '@4tw/cypress-drag-drop'
12 |
--------------------------------------------------------------------------------
/cypress/support/component-index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Components App
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/cypress/support/component.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/component.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands'
18 | import '../../src/components/vue-draggable-resizable.css'
19 |
20 | // Alternatively you can use CommonJS syntax:
21 | // require('./commands')
22 |
23 | import { mount } from 'cypress/vue'
24 |
25 | Cypress.Commands.add('mount', (...args) => {
26 | return mount(...args).then(({ wrapper }) => {
27 | return cy.wrap(wrapper).as('vue')
28 | })
29 | })
30 |
31 | // Example use:
32 | // cy.mount(MyComponent)
33 |
--------------------------------------------------------------------------------
/histoire.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'histoire'
2 | import { HstVue } from '@histoire/plugin-vue'
3 |
4 | export default defineConfig({
5 | vite: {
6 | base: "",
7 | },
8 | routerMode: 'hash',
9 | plugins: [
10 | HstVue(),
11 | ],
12 | setupFile: './stories/histoire.setup.js',
13 | tree: {
14 | groups: [
15 | {
16 | id: 'top',
17 | title: '',
18 | },
19 | {
20 | title: 'Basic Stories',
21 | include: file => file.path.startsWith('stories/basic'),
22 | },
23 | {
24 | title: 'Grid Stories',
25 | include: file => file.path.startsWith('stories/grid'),
26 | },
27 | {
28 | title: 'Parent Stories',
29 | include: file => file.path.startsWith('stories/parent'),
30 | },
31 | {
32 | title: 'Aspect Ratio Stories',
33 | include: file => file.path.startsWith('stories/aspect-ratio'),
34 | },
35 | {
36 | title: 'Styling Stories',
37 | include: file => file.path.startsWith('stories/styling'),
38 | },
39 | {
40 | title: 'Events Stories',
41 | include: file => file.path.startsWith('stories/events'),
42 | },
43 | {
44 | title: 'Callback Stories',
45 | include: file => file.path.startsWith('stories/callback'),
46 | },
47 | {
48 | title: 'Advanced Stories',
49 | include: file => file.path.startsWith('stories/advanced'),
50 | },
51 | {
52 | title: 'How To',
53 | include: file => file.path.startsWith('stories/how-to'),
54 | },
55 | ],
56 | },
57 | })
58 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | vue-draggable-resizable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-draggable-resizable",
3 | "version": "3.0.0-beta.2",
4 | "author": "Maurizio Bonani ",
5 | "private": false,
6 | "description": "Vue3 Component for resizable and draggable elements",
7 | "type": "module",
8 | "files": [
9 | "dist"
10 | ],
11 | "main": "dist/vue-draggable-resizable.umd.cjs",
12 | "module": "dist/vue-draggable-resizable.js",
13 | "unpkg": "dist/vue-draggable-resizable.umd.cjs",
14 | "browser": {
15 | "./sfc": "src/vue-draggable-resizable.vue"
16 | },
17 | "exports": {
18 | ".": {
19 | "import": "./dist/vue-draggable-resizable.js",
20 | "require": "./dist/vue-draggable-resizable.umd.cjs"
21 | },
22 | "./style.css": {
23 | "import": "./dist/style.css",
24 | "require": "./dist/style.css"
25 | }
26 | },
27 | "scripts": {
28 | "dev": "vite",
29 | "build": "vite build",
30 | "test": "vitest run",
31 | "test:ui": "vitest --ui",
32 | "test:coverage": "vitest run --coverage",
33 | "test:watch": "vitest",
34 | "cypress": "npx cypress open",
35 | "story:dev": "histoire dev",
36 | "story:build": "histoire build",
37 | "story:preview": "histoire preview"
38 | },
39 | "devDependencies": {
40 | "@4tw/cypress-drag-drop": "^2.2.5",
41 | "@babel/core": "^7.18.6",
42 | "@histoire/plugin-vue": "^0.17.6",
43 | "@vitejs/plugin-vue": "^4.3.4",
44 | "@vitest/ui": "^0.15.1",
45 | "@vue/test-utils": "^2.2.7",
46 | "babel-loader": "^8.2.5",
47 | "cypress": "^13.6.2",
48 | "histoire": "^0.17.6",
49 | "jsdom": "^19.0.0",
50 | "vite": "^4.4.9",
51 | "vitest": "^0.28.4",
52 | "vue": "^3.2.25",
53 | "vue-loader": "^16.8.3"
54 | },
55 | "peerDependencies": {
56 | "vue": "^3.2.25"
57 | },
58 | "repository": {
59 | "type": "git",
60 | "url": "https://github.com/mauricius/vue-draggable-resizable.git"
61 | },
62 | "license": "MIT",
63 | "bugs": {
64 | "url": "https://github.com/mauricius/vue-draggable-resizable/issues"
65 | },
66 | "homepage": "https://github.com/mauricius/vue-draggable-resizable",
67 | "keywords": [
68 | "vue",
69 | "component",
70 | "dragabble",
71 | "resizable"
72 | ]
73 | }
74 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mauricius/vue-draggable-resizable/72cda0844f765c85df7ae423de12bb54790bcc75/public/favicon.ico
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | ## Component with Aspect Ratio
33 |
34 | A component, with `:lock-aspect-ratio` prop to keep the aspect ratio of the component during resize.
35 |
36 |
--------------------------------------------------------------------------------
/stories/aspect-ratio/MaxWidthMaxHeight.story.vue:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
24 |
Keep aspect ratio and set maxWidth to {{ maxWidth }} and maxHeight to {{ maxHeight }}.
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | ## Component with Aspect Ratio and maxWidth, maxHeight
37 |
38 | A component, with `:lock-aspect-ratio` prop and `:max-width` set to `300` and `:max-height` set to `250`. Notice that locking the aspect ratio also forces the max width to be 250.
39 |
40 |
--------------------------------------------------------------------------------
/stories/aspect-ratio/MinWidthMinHeight.story.vue:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
24 |
Keep aspect ratio and set minWidth to {{ minWidth }} and minHeight to {{ minHeight }}.
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | ## Component with Aspect Ratio and minHeight, minWidth
37 |
38 | A component, with `:lock-aspect-ratio` prop and `:min-height` set to `100` and `:min-width` set to `50`. Notice that locking the aspect ratio also forces the Min Width to be 100 (Factor: 1 / 1).
39 |
40 |
--------------------------------------------------------------------------------
/stories/aspect-ratio/WithGrid.story.vue:
--------------------------------------------------------------------------------
1 |
37 |
38 |
39 |
40 |
41 |
42 |
Keep aspect ratio in component costrained on grid {{ grid }}.
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | ## Component with Aspect Ratio costrained on 20x20 Grid
54 |
55 | Having a component costrained on a Grid doesn't play so well when using the `:lock-aspect-ratio` prop. You can notice that you have different results by dragging, for example, the right handle or the bottom handle.
56 |
57 |
--------------------------------------------------------------------------------
/stories/basic/Active.story.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
22 |
Controlling the active state from outside the component by providing the active prop.
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | ## Basic component with active control
33 |
34 | A basic component, with `active` prop to control the active state from outside the component.
35 |
36 |
--------------------------------------------------------------------------------
/stories/basic/Axis.story.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
22 |
Draggable on {{ axis }} axis.
23 |
24 |
25 |
26 |
40 |
41 |
42 |
43 |
44 |
45 | ## Basic component with axis prop
46 |
47 | A basic component, with `:axis` prop to control on which axis the component is draggable. Suitable values are `x`, `y` or `both`.
48 |
49 |
--------------------------------------------------------------------------------
/stories/basic/Basic.story.vue:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
You can drag me around and resize me as you wish.
11 |
12 |
13 |
14 |
15 |
16 |
17 | ## Basic component
18 |
19 | The most basic component, without any props, free to move even outside the parent element.
20 |
21 |
--------------------------------------------------------------------------------
/stories/basic/CancelHandle.story.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
Cannot Drag Here
11 |
12 |
13 |
14 |
15 |
16 | ## Basic component with Drag Cancel
17 |
18 | A basic component, that cannot be dragged through a handle, specified by the prop `:drag-cancel` and a valid CSS selector.
19 |
20 |
--------------------------------------------------------------------------------
/stories/basic/ControlledComponent.story.vue:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 |
24 |
25 |
Basic controlled component.
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | ## Basic controlled component
39 |
40 | A basic controlled component, with `x`, `y`, `w` and `h` props to control the position and the size of the component. You should also provide callbacks to sync the state with the parent.
41 |
42 |
--------------------------------------------------------------------------------
/stories/basic/DragHandle.story.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
Drag Only Here
11 |
12 |
13 |
14 |
15 |
16 | ## Basic component with Drag Handle
17 |
18 | A basic component, that cannot be dragged through a handle, specified by the prop `:drag-handle` and a valid CSS selector.
19 |
20 |
--------------------------------------------------------------------------------
/stories/basic/Form.story.vue:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
27 |
28 |
29 |
Basic component with form inside.
30 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | ## Basic component with form
41 |
42 | A basic component, with a form inside. The input should be focusable and the button should be clickable.
43 |
44 |
--------------------------------------------------------------------------------
/stories/basic/Handles.story.vue:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 |
24 |
25 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | ## Basic component with handles prop
39 |
40 | You can choose what handles to provide to the component using the `handles` prop, which accepts an array of handles. For example, if you want to costrain resizing only on horizontal axis you can provide only left and right handles `:handles="['ml','mr']"`.
41 |
42 |
--------------------------------------------------------------------------------
/stories/basic/MaxWidthMaxHeight.story.vue:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
22 |
23 |
Basic component with programmable maxWidth and maxHeight props.
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | ## Basic component with Max Height and Max Width
35 |
36 | A basic component, with Max Height and Max Width provided respectively by `:max-height` and `:max-width` props
37 |
38 |
--------------------------------------------------------------------------------
/stories/basic/MinWidthMinHeight.story.vue:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
22 |
23 |
Basic component with programmable minWidth and minHeight props.
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | ## Basic component with Min Height and Min Width
34 |
35 | A basic component, with minimum height and minimum width provided respectively by `:min-width` and `:min-height` props.
36 |
37 |
--------------------------------------------------------------------------------
/stories/basic/NativeDragEnabled.story.vue:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
Native drag disabled. Try to drag the component from the ball.
10 |
11 |
12 |
13 |
Native drag enabled. Try to drag the component from the ball.
14 |
15 |
16 |
17 |
18 |
19 |
20 | ## Component with native drag enabled
21 |
22 | A basic component, with `:enable-native-drag` prop set to `true`, in order to allow native browser's drag behavior. You can see the difference by dragging each component using the ball. Default value is `false`.
23 |
24 |
--------------------------------------------------------------------------------
/stories/basic/NotDraggable.story.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
22 |
Basic component that is {{ draggable ? 'also' : 'not' }} draggable.
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | ## Component not draggable
33 |
34 | A basic component, with `:draggable` prop set to `false`, so it's not draggable.
35 |
36 |
--------------------------------------------------------------------------------
/stories/basic/NotResizable.story.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
22 |
Basic component that is {{ resizable ? 'also' : 'not' }} resizable.
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | ## Component not resizable
33 |
34 | A basic component, with `:resizable` prop set to `false`, so it's not resizable.
35 |
36 |
--------------------------------------------------------------------------------
/stories/basic/PreventDeactivation.story.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
22 |
Prevents the deactivation of the component by providing the prevent-deactivation prop.
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | ## Prevent deactivation
33 |
34 | A basic component, with `:prevent-deactivation` prop to avoid untoggling active state when clicking outside.
35 |
36 |
--------------------------------------------------------------------------------
/stories/basic/Scale.story.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
22 |
Change the "scale" property to support CSS scale transform. Current value is {{ scale }}
23 |
24 |
25 |
Component with default scale prop set to 1
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | ## Basic component with scale prop
36 |
37 | A basic component, with `:scale` prop to control the scale property when the CSS 3 scale transformation is applied to one of the parent elements. If not provided the default value is `1`.
38 |
39 |
--------------------------------------------------------------------------------
/stories/basic/SizeAuto.story.vue:
--------------------------------------------------------------------------------
1 |
25 |
26 |
27 |
28 |
29 |
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cupiditate aperiam explicabo animi expedita unde perspiciatis quae, consequatur consequuntur libero assumenda, accusantium repellat illo asperiores molestiae ea quasi distinctio, aspernatur saepe!
30 |
31 |
32 | Size: {{ width }} x {{ height }}
33 |
34 |
35 |
36 |
37 |
38 | ## Basic component with "auto" width and height
39 |
40 | A basic component with initial values for `w` and `h` props set to `auto`. As soon as the component is resized their values fall back to numbers.
41 |
42 |
--------------------------------------------------------------------------------
/stories/basic/ZIndex.story.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
22 |
Controlling the z-index from outside the component by providing the :z prop.
23 |
24 |
25 | 1
26 |
27 |
28 | 9
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | ## Basic component with "auto" width and height
39 |
40 | A basic component with initial values for `w` and `h` props set to `auto`. As soon as the component is resized their values fall back to numbers.
41 |
42 |
--------------------------------------------------------------------------------
/stories/callback/OnDrag.story.vue:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
24 |
25 | Can't touch me
26 |
27 |
28 |
29 |
30 |
31 | ## onDrag callback
32 |
33 | A component with `:onDrag` prop that accepts a function that gets called on dragging. If the function returns `false`, the drag action is cancelled.
34 |
35 |
--------------------------------------------------------------------------------
/stories/callback/OnDragStart.story.vue:
--------------------------------------------------------------------------------
1 |
32 |
33 |
34 |
35 |
36 |
Start dragging!
37 |
The component is locked!
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | ## onDragStart callback
48 |
49 | A component, with `:onDragStart` prop that accepts a function that gets called when dragging starts (element is clicked or touched). If the function returns `false`, the action is cancelled. You can use this function to prevent bubbling of events.
50 |
51 | ```js
52 | function onDragStartCallback(ev){
53 | ...
54 | // return false; — for cancel
55 | }
56 | ```
57 |
58 |
--------------------------------------------------------------------------------
/stories/callback/OnResize.story.vue:
--------------------------------------------------------------------------------
1 |
25 |
26 |
27 |
28 |
29 |
30 | Can't touch me
31 |
32 |
33 |
34 |
35 |
36 | ## onResize callback
37 |
38 | A component with `:onResize` prop that accepts a function that gets called on resizing. If the function returns `false`, the action is cancelled.
39 |
40 |
--------------------------------------------------------------------------------
/stories/callback/OnResizeStart.story.vue:
--------------------------------------------------------------------------------
1 |
32 |
33 |
34 |
35 |
36 |
Start resizing!
37 |
The component is locked!
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | ## onResizeStart callback
48 |
49 | A component, with `:onResizeStart` prop that accepts a function that gets called when dragging starts (element is clicked or touched). If the function returns `false`, the resizing action is cancelled. You can use this function to prevent bubbling of events.
50 |
51 | ```js
52 | function onResizeStartCallback(handle, ev){
53 | ...
54 | // return false; — for cancel
55 | }
56 | ```
57 |
58 |
--------------------------------------------------------------------------------
/stories/events/Activated.story.vue:
--------------------------------------------------------------------------------
1 |
31 |
32 |
33 |
34 |
35 |
The component has been activated.
36 |
37 |
38 |
39 |
40 |
41 | ## Activated and deactivated events
42 |
43 | The `activated` event is emitted when the component gets activated. The `deactivated` event is emitted when the component gets deactivated.
44 |
45 |
--------------------------------------------------------------------------------
/stories/events/Dragging.story.vue:
--------------------------------------------------------------------------------
1 |
35 |
36 |
37 |
38 |
39 |
{{ dragging ? 'You are dragging me' : 'Standing still' }} X: {{ x }} / Y: {{ y }}
40 |
41 |
42 |
43 |
44 |
45 | ## Dragging and dragstop events
46 |
47 | The `dragging(x, y)` event is emitted when the component is dragged. The `dragstop(x, y)` event is emmitted when the dragging stops.
48 |
49 |
--------------------------------------------------------------------------------
/stories/events/Resizing.story.vue:
--------------------------------------------------------------------------------
1 |
39 |
40 |
41 |
42 |
43 |
{{ resizing ? 'You are resizing me' : 'This is my favourite shape' }}
44 | X: {{ x }} / Y: {{ y }} - Width: {{ width }} / Height: {{ height }}
45 |
46 |
47 |
48 |
49 |
50 | ## Resizing and resizestop events
51 |
52 | The `resizing(x, y, width, height)` event is emitted when the component is resized. The `resizestop(x, y, width, height)` event is emmitted when the resizing stops.
53 |
54 |
--------------------------------------------------------------------------------
/stories/grid/Grid.story.vue:
--------------------------------------------------------------------------------
1 |
34 |
35 |
36 |
37 |
38 |
39 |
Grid {{ grid[0] }}x {{ grid[1] }} starting from the top-left corner
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | ## Basic component with Grid
52 |
53 | A basic component, with `:grid=[20,20]` prop to set the dimensions of grid cells (height and width in pixels).
54 |
55 |
--------------------------------------------------------------------------------
/stories/grid/GridWithMaxWidthMaxHeight.story.vue:
--------------------------------------------------------------------------------
1 |
38 |
39 |
40 |
41 |
42 |
43 |
Grid {{ grid[0] }}x{{ grid[1] }} starting with a {{ x }}x{{ y }} offset and max width equal to {{ maxWidth }} and max height equal to {{ maxHeight }}.
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | ## Grid 20x40 pixels with 10x10 offset and maxHeight, maxWidth values
52 |
53 | If you provide `:max-height` and `:max-width` values that are higer than the respective grid values, you can notice that resizing stops to the lower suitable value. For example on the x axis the lowest valid value that respects max width and grid[x] constraint is `80`. The same applies for the y axis.
54 |
55 |
--------------------------------------------------------------------------------
/stories/grid/GridWithMinWidthMinHeight.story.vue:
--------------------------------------------------------------------------------
1 |
38 |
39 |
40 |
41 |
42 |
43 |
Grid {{ grid[0] }}x{{ grid[1] }} starting with a {{ x }}x{{ y }} offset and min width equal to {{ minWidth }} and min height equal to {{ minHeight }}.
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | ## Grid 20x40 pixels with 10x10 offset and minHeight, minWidth values
52 |
53 | If you provide `:min-height` and `:min-width` values that are lower than the respective grid values, you can notice that resizing stops to the lowest suitable value. For example on the x axis the lowest valid value that respects the min width and grid[x] constraint is `40`. The same applies for the y axis.
54 |
55 |
--------------------------------------------------------------------------------
/stories/histoire.setup.js:
--------------------------------------------------------------------------------
1 | import './styles.css'
2 |
--------------------------------------------------------------------------------
/stories/how-to/DragMultiple.story.vue:
--------------------------------------------------------------------------------
1 |
94 |
95 |
96 |
97 | dragging(element.id, left, top)"
107 | @dragstop="(left, top) => dragstop(element.id, left, top)"
108 | >
109 |
{{ element.text }}
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | ## Drag Multiple Elements
120 |
121 | This is not a feature provided by the component by default, but it's an example of how you can build complex scenarios using existing features.
122 |
123 | Make sure to click anywhere inside the container before starting to drag elements, due to how the ctrl event handler is registered.
124 |
125 |
--------------------------------------------------------------------------------
/stories/how-to/FrameSelection.story.vue:
--------------------------------------------------------------------------------
1 |
159 |
160 |
161 |
162 |
188 | Number of selected elements: {{selectedItemNum}}
189 |
190 |
191 |
192 |
193 |
194 |
213 |
214 |
215 | ## Select and drag Multiple Elements
216 |
217 | This is not a feature provided by the component by default, but it's an example of how you can build complex scenarios using existing features.
218 |
219 | Make a selection with the mouse to include one or more elements so you can drag them together.
220 |
221 |
--------------------------------------------------------------------------------
/stories/how-to/HowTo.stories.js:
--------------------------------------------------------------------------------
1 | import VueDraggableResizable from '../../src/components/vue-draggable-resizable.vue';
2 |
3 | export default {
4 | title: 'How To',
5 | component: VueDraggableResizable
6 | };
7 |
8 | export const FrameSelection = () => ({
9 | components: { VueDraggableResizable },
10 | template: `
11 |
You cannot move me or resize me outside my parent element.
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | ## Component costraind in parent
35 |
36 | Component that cannot be dragged or resized outside its parent element, defined with the prop `:parent="true"`.
37 |
38 |
--------------------------------------------------------------------------------
/stories/parent/ControlledComponent.story.vue:
--------------------------------------------------------------------------------
1 |
40 |
41 |
42 |
43 |
44 |
45 |
You cannot move me or resize me outside my parent.
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | ## Parent controlled Component with Grid
60 |
61 | A basic parent controlled component, with `:x`, `:y`, `:w` and `:h` props to control the position and the size of the component. Notice that using also the `:grid` prop, the component will react only with a valid multiple of grid values.
62 |
63 |
--------------------------------------------------------------------------------
/stories/parent/DisableUserSelect.story.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
22 |
23 |
You can {{ disableUserSelect ? 'not' : '' }} select text inside the component by putting :disableUserSelect prop equal to {{ disableUserSelect }}.
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | ## Component with text selection disabled
35 |
36 | Component that disables text selection of an element using the prop `:disable-user-select="true"` prop.
37 |
38 |
--------------------------------------------------------------------------------
/stories/parent/Grid.story.vue:
--------------------------------------------------------------------------------
1 |
31 |
32 |
33 |
34 |
35 |
36 |
You cannot move me or resize me outside my parent.
37 |
38 |
39 |
40 |
41 |
42 |
43 | ## Component with grid costraind in parent
44 |
45 | Component attached to a grid, that cannot be dragged or resized outside its parent element, defined with the prop `:parent="true"`. In this case the size of the parent matches perfectly the grid.
46 |
47 |
--------------------------------------------------------------------------------
/stories/parent/ParentGridEvenOffset.story.vue:
--------------------------------------------------------------------------------
1 |
33 |
34 |
35 |
36 |
37 |
38 |
You cannot move me or resize me outside my parent.
39 |
40 |
41 |
42 |
43 |
44 |
45 | ## Component costraind in parent and on a grid with an even 17x17 offset
46 |
47 | Component attached to a grid with an even offset.
48 |
49 |
--------------------------------------------------------------------------------
/stories/parent/ParentGridMaxWidthMaxHeight.story.vue:
--------------------------------------------------------------------------------
1 |
37 |
38 |
39 |
40 |
41 |
42 |
Component costrained in parent with maxWidth equal to {{ maxWidth }} and maxHeight equal to {{ maxHeight }}.
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | ## Component with grid costraind in parent with maxWidth and maxHeight
55 |
56 | Component attached to a grid, that cannot be dragged or resized outside its parent element, with `:max-width` and `:max-height` props to limit its size. Notice that using `20` as grid prop for the y axis, the maximum height of the element is `280` instead of `290`.
57 |
58 |
--------------------------------------------------------------------------------
/stories/parent/ParentGridOffset.story.vue:
--------------------------------------------------------------------------------
1 |
33 |
34 |
35 |
36 |
37 |
38 |
You cannot move me or resize me outside my parent. And my edges cannot touch the parent element.
39 |
40 |
41 |
42 |
43 |
44 |
45 | ## Component costraind in parent and on a grid with 10x10 offset
46 |
47 | Component attached to a grid with a small offset. Its starting position is not perfectly aligned with the top-left corner of the parent.
48 |
49 |
--------------------------------------------------------------------------------
/stories/parent/ParentMaxWidthMaxHeight.story.vue:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
22 |
23 |
24 |
Component costrained in parent with maxWidth equal to {{ maxWidth }} and maxHeight equal to {{ maxHeight }}.