├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── babel.config.js ├── config └── webpack.config.js ├── demo.gif ├── docs-src ├── App.vue ├── assets │ ├── descriptions-advanced.json │ ├── descriptions-basic.json │ ├── descriptions-custom.json │ ├── descriptions-dynamic.json │ ├── descriptions-wrappers.json │ ├── logo-github.svg │ └── logo-vue.png ├── components │ ├── Home.vue │ └── UsernameGenerator.vue └── main.js ├── docs ├── css │ ├── app.65cd258f.css │ └── chunk-vendors.90b90f44.css ├── img │ └── logo-vue.82b9c7a5.png ├── index.html ├── js │ ├── app.b20c9a4b.js │ ├── app.b20c9a4b.js.map │ ├── chunk-vendors.b3d4376b.js │ └── chunk-vendors.b3d4376b.js.map └── logo.png ├── getting_started.png ├── package-lock.json ├── package.json ├── src ├── DdForm.vue ├── DdFormView.vue ├── assets │ ├── file.vue │ ├── icon-check.vue │ ├── icon-expand.vue │ └── icon-upload.vue ├── config.js ├── index.js ├── main.js └── views │ ├── ButtonAdd.vue │ ├── ButtonDrag.vue │ ├── ButtonRemove.vue │ ├── ButtonSubmit.vue │ ├── Headline.vue │ ├── ViewArea.vue │ ├── ViewCheckbox.vue │ ├── ViewCounter.vue │ ├── ViewDatetime.vue │ ├── ViewRadio.vue │ ├── ViewSelect.vue │ ├── ViewText.vue │ ├── ViewTick.vue │ └── ViewUpload.vue └── vue.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | docs/ 2 | docs-src/ 3 | build/ 4 | tests/ 5 | coverage/ 6 | .babelrc -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Marek Mensa 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 📋 Vue Described-Data Form 2 | 3 | A fresh way to create simple or complex forms – **without programming!** 4 | 5 | ![](https://raw.githubusercontent.com/marekmensa/vue-dd-form/master/demo.gif) 6 | 7 | 8 | # 🕹 Demo 9 | 10 | Try it yourself in a [Live Demo](https://marekmensa.github.io/vue-dd-form/)! 11 | 12 | 13 | # 📖 About 14 | 15 | vue-dd-form aims to reduce the of time creating forms, while keeping the flexibility and data-model persistence. This project is a first implementation of the **Described-Data approach**. 16 | 17 | 18 | ## What is Descibed-Data? 19 | 20 | Described-Data is a concept inspired by the [JSON Schema](https://json-schema.org/). Basically, each node in the data set is assigned a **view** (input), which it then represents on the UI. In practise, vue-dd-form only needs your **data** and **descriptions** to render itself! 21 | 22 | **"I use a JSON Schema, what is the difference?"** 23 | - **clarity**: data is described by a dotted-notation, which makes the whole set much more readable 24 | - **view-oriented**: each node as assigned a specific view (eg. image-upload), not a general type (eg. string) 25 | 26 | 27 | # 🛠️ Getting started 28 | 29 | 30 | 1. Install the package 31 | ``` 32 | npm install --save vue-dd-form 33 | ``` 34 | 35 | 2. Import the component 36 | 37 | ```javascript 38 | import ddForm from 'vue-dd-form'; 39 | ``` 40 | 41 | ```javascript 42 | components: { 43 | ddForm, 44 | } 45 | ``` 46 | 47 | 3. And use it! 48 | 49 | ```html 50 | 54 | 55 | ``` 56 | 57 | ...inside your `data()` tag 58 | ```javascript 59 | exampleDataSet: {}, 60 | exampleDescriptions: { 61 | "name": { view: 'text', label: 'Full name'} 62 | } 63 | ``` 64 | Output of this simple example looks like this: 65 | 66 | ![](https://github.com/marekmensa/vue-dd-form/blob/master/getting_started.png?raw=true) 67 | 68 | ⬇️ **More about all params & events below.** 69 | 70 | --- 71 | 72 | 73 | # 🔍 Usage 74 | 75 | 76 | ## Descriptions 77 | 78 | Your JS Data is described by another JS Object targeting all nodes which should be rendered on the screen. Imagine a data model of a IMDB movie: 79 | 80 | ```javascript 81 | { 82 | author: { 83 | name: "J. Cameron", 84 | birth: "2020-09-08T12:11:03.332Z", 85 | active: true 86 | } 87 | title: "Titanic", 88 | description: "Lorem ipsum ...", 89 | language: "English", 90 | genres: ["Action", "Drama"] 91 | } 92 | ``` 93 | 94 | ...the descriptions could look something like this: 95 | 96 | ```javascript 97 | { 98 | author: { view: "group", label: "Author" }, 99 | author.name: { view: "text", label: "Name of author" }, 100 | author.birth: { view: "datetime", label: "Date of birth" }, 101 | author.active: { view: "tick", label: "Is the author still active?" }, 102 | title: { view: "text", label: "Movie title" }, 103 | description: { view: "area", "label": "Description" }, 104 | genres: { view: "checkbox", "label: "Genres", options: ["Action", "Comedy", "Drama"] }, 105 | language: { view: "select", label: "Original language", "options: ["English", "Spanish", "Korean"] } 106 | } 107 | ``` 108 | 109 | **Description paths** 110 | 111 | So as you can see nodes are targeted by a dotted notation. Each description object has a required value of `view`, which specifies, to which UI element should the node be rendered. Currently there is 11 basic view types, though you can specify your own (see _Custom views_). 112 | 113 | 114 | ### Wildcard paths 115 | If you want to describe every array's child, you can use the **wildcard path**. Look closely at this data set: 116 | 117 | ```javascript 118 | { 119 | programme: [ 120 | // Day 1 121 | { 122 | header: 'Friday', 123 | subheader: '25th September 2020', 124 | items: [ 125 | // Item 1 126 | { 127 | title: 'Arrival', 128 | subtitle: 'please be on time', 129 | time: '9AM' 130 | }, 131 | // Item 2 132 | { 133 | title: 'Workshop 1', 134 | subtitle: 'hosted by John Doe', 135 | time: '11AM' 136 | } 137 | // Item 3 ... 138 | }, 139 | // Day 2 ... 140 | ], 141 | } 142 | ``` 143 | 144 | The wildcard paths can be leveraged like this: 145 | 146 | ```javascript 147 | programme: { view: 'collection' }, 148 | programme[*]: { view: 'group', label: 'Day no. {_index}' }, // more about the {_index} at Dynamic values 149 | programme[*].header: { type: 'text', label: 'Title' }, 150 | programme[*].subheader: { type: 'text', label: 'Short description' }, 151 | programme[*].items: { type: 'collection', label: 'Sessions' }, 152 | programme[*].items[*]: { type: 'group' }, 153 | programme[*].items[*].title: { type: 'text', label: 'Session name' }, 154 | programme[*].items[*].subtitle: { type: 'area', label: 'About' }, 155 | programme[*].items[*].time: { type: 'text', label: 'Time of start' }, 156 | ``` 157 | 158 | 159 | ### Dynamic values 160 | 161 | Any view type can have a String in description value. If the string is found in provided `functions` set, given function gets executed. The function also receives the child's path and value as a parameter. 162 | 163 | ```jsx 164 | { 165 | view: 'group' 166 | hidden: '_groupHidden' 167 | } 168 | 169 | ``` 170 | 171 | ...while in JS code 172 | 173 | ```jsx 174 | 178 | 179 | 180 | data() { 181 | return { 182 | myFunctions: { 183 | '_groupHidden': this.groupHidden, 184 | '_groupIndex': this.groupIndex, 185 | }, 186 | }; 187 | }, 188 | 189 | methods: { 190 | groupHidden({path, value}) { 191 | return value.item < 0; 192 | }, 193 | groupIndex({path}) { 194 | return this.getIndex(path); 195 | } 196 | }, 197 | 198 | ``` 199 | 200 | Methods can be also put inline to the string. For these cases, the dynamic value needs to be wrapped inside the brackets. 201 | 202 | ```jsx 203 | { 204 | view: 'group' 205 | label: 'Day no. {_groupIndex}' 206 | } 207 | 208 | ``` 209 | 210 | Check the [demo's source code](https://github.com/marekmensa/vue-dd-form/blob/master/docs-src/components/Home.vue) to see it in use. 211 | 212 | 213 | ### Side note to Descriptions 214 | The order of descriptions defines the order of the views on the UI. It is also needed to describe first the Object and then it's sub-nodes. 215 | 216 | --- 217 | 218 | 219 | ## View types 220 | 221 | There is 11 basic view types included in this package: 222 | 223 | - group 224 | - collection 225 | - text 226 | - area 227 | - select 228 | - checkbox 229 | - counter 230 | - datetime 231 | - upload 232 | - radio 233 | - tick 234 | 235 | 236 | ## collection 237 | 238 | Serves as Array container and expects to have multiple inner children. Collection shows just an add-child button by default. It is only an abstraction and has no visual representation. 239 | 240 | **Usage** 241 | 242 | ```jsx 243 | { 244 | view: 'collection', 245 | } 246 | ``` 247 | 248 | **Possible value types** 249 | 250 | _(Array)_: Consumes only `array` 251 | 252 | **Arguments** 253 | 254 | - `label` _(String)_: Shows title on the top of the view 255 | - `class` _(String or Array)_: View's assigned class 256 | - `wrapper` _(String)_: Name of the view's wrapper 257 | - `hidden` _(Boolean)_: Hides or shows the view 258 | - `draggable` _(Boolean)_: Allows or disallows children dragging 259 | - `deletable` _(Boolean)_: Allows or disallows children delete 260 | - `addable` _(Boolean)_: Allows or disallows to add children 261 | - `defaultValue` _(*)_: Override of view's default value 262 | 263 | 264 | ## group 265 | 266 | Serves as Object container and expects to have nested children. It is only an abstraction and has no visual representation. 267 | 268 | **Usage** 269 | 270 | ```jsx 271 | { 272 | view: 'group', 273 | } 274 | ``` 275 | 276 | **Possible value types** 277 | 278 | `(Object) or null`: Consumes only `object` 279 | 280 | **Arguments** 281 | 282 | - `label` _(String)_: Shows title on the top of the view 283 | - `class` _(String or Array)_: View's assigned class 284 | - `wrapper` _(String)_: Name of the view's wrapper 285 | - `hidden` _(Boolean)_: Shows or hides the view 286 | - `append` _(Object)_: Specifies the UI invisible appendant data to be merged with the object (triggered while adding new item to array) 287 | - `defaultValue` _(*)_: Override of view's default value 288 | 289 | 290 | ## text 291 | 292 | Acts as a basic single-line text field. 293 | 294 | **Usage** 295 | 296 | ```jsx 297 | { 298 | view: 'text', 299 | } 300 | ``` 301 | 302 | **Possible value types** 303 | 304 | `String`: Consumes only String 305 | 306 | **Arguments** 307 | 308 | - `label` _(String)_: Shows title on the top of the view 309 | - `class` _(String or Array)_: View's assigned class 310 | - `hidden` _(Boolean)_: Hides or shows the view 311 | - `wrapper` _(String)_: Name of the view's wrapper 312 | - `defaultValue` _(*)_: Override of view's default value 313 | 314 | 315 | 316 | ## select 317 | 318 | Acts as a drow-down box. 319 | 320 | **Usage** 321 | 322 | ```jsx 323 | { 324 | view: 'select', 325 | } 326 | ``` 327 | 328 | **Possible value types** 329 | 330 | `String or null`: Consumes String or null 331 | 332 | **Arguments** 333 | 334 | - `label` _(String)_: Shows title on the top of the view 335 | - `class` _(String or Array)_: View's assigned class 336 | - `hidden` _(Boolean)_: Hides or shows the view 337 | - `wrapper` _(String)_: Name of the view's wrapper 338 | - `options` _(Array)_: Field option values 339 | - `defaultValue` _(*)_: Override of view's default value 340 | 341 | - **Plain mode** 342 | 343 | ```jsx 344 | ["Dog", "Cat"] 345 | ``` 346 | 347 | - **Value-text mode** 348 | 349 | ```jsx 350 | [ 351 | { text: "Dog", value: "doggo" }, 352 | { text: "Cat", value: "caterpillar" } 353 | ] 354 | ``` 355 | 356 | 357 | ## checkbox 358 | 359 | Acts as a checkbox set. 360 | 361 | **Usage** 362 | 363 | ```jsx 364 | { 365 | view: 'checkbox', 366 | } 367 | ``` 368 | 369 | **Possible value types** 370 | 371 | `Array`: Consumes Array of strings 372 | 373 | **Arguments** 374 | 375 | - `label` _(String)_: Shows title on the top of the view 376 | - `class` _(String or Array)_: View's assigned class 377 | - `hidden` _(Boolean)_: Hides or shows the view 378 | - `wrapper` _(String)_: Name of the view's wrapper 379 | - `options` _(Array)_: Field option values 380 | - `defaultValue` _(*)_: Override of view's default value 381 | 382 | - **Plain mode** 383 | 384 | ```jsx 385 | ["Dog", "Cat"] 386 | ``` 387 | 388 | - **Value-text mode** 389 | 390 | ```jsx 391 | [ 392 | { text: "Dog", value: "doggo" }, 393 | { text: "Cat", value: "caterpillar" } 394 | ] 395 | ``` 396 | 397 | ## counter 398 | 399 | Acts as a counter box. 400 | 401 | **Usage** 402 | 403 | ```jsx 404 | { 405 | view: 'counter', 406 | } 407 | ``` 408 | 409 | **Possible value types** 410 | 411 | `Number`: Consumes a Number 412 | 413 | **Arguments** 414 | 415 | - `label` _(String)_: Shows title on the top of the view 416 | - `class` _(String or Array)_: View's assigned class 417 | - `hidden` _(Boolean)_: Hides or shows the view 418 | - `wrapper` _(String)_: Name of the view's wrapper 419 | - `min` _(Number)_: Minimum value to select 420 | - `max` _(Number)_: Maximum value to select 421 | - `defaultValue` _(*)_: Override of view's default value 422 | 423 | 424 | ## datetime 425 | 426 | Acts as a date-time selection field. 427 | 428 | **Usage** 429 | 430 | ```jsx 431 | { 432 | view: 'datetime', 433 | } 434 | ``` 435 | 436 | **Possible value types** 437 | 438 | `Date or String`: Consumes a Date, String or Timestamp (Firebase) but always returns Date 439 | 440 | **Arguments** 441 | 442 | - `label` _(String)_: Shows title on the top of the view 443 | - `class` _(String or Array)_: View's assigned class 444 | - `hidden` _(Boolean)_: Hides or shows the view 445 | - `wrapper` _(String)_: Name of the view's wrapper 446 | - `min` _(String_)*: Minimum date value 447 | - `max` _(String_)*: Maximum date value 448 | - `defaultValue` _(*)_: Override of view's default value 449 | 450 | _* String in a Date format_ 451 | 452 | 453 | ## upload 454 | 455 | Acts as a box for file uploads and renders into preview box, if consumable by web (image, video, ...). 456 | 457 | **Usage** 458 | 459 | ```jsx 460 | { 461 | view: 'upload', 462 | } 463 | ``` 464 | 465 | **Possible value types** 466 | 467 | `String`: Consumes a String 468 | 469 | **Arguments** 470 | 471 | - `label` _(String)_: Shows title on the top of the view 472 | - `class` _(String or Array)_: View's assigned class 473 | - `endpoint` _(String)_: API endpoint URL* 474 | - `payload` _(Object or String)_: API payload data* 475 | - `hidden` _(Boolean)_: Hides or shows the view 476 | - `wrapper` _(String)_: Name of the view's wrapper 477 | - `defaultValue` _(*)_: Override of view's default value 478 | 479 | _* Endpoint URL receives a POST call with FormData (`image` and `payload`)_ 480 | 481 | **⚠️ Note from author** 482 | File upload functionality is heavily domain-oriented, thus I'd advise you to clone the [ViewUpload.vue]([https://github.com/marekmensa/vue-dd-form/blob/master/src/views/ViewUpload.vue](https://github.com/marekmensa/vue-dd-form/blob/master/src/views/ViewUpload.vue)), modify it by your needs and use it as a **Custom view**. 483 | 484 | 485 | ## area 486 | 487 | Acts as a multi-line text field with optional WYSIWYG editor. 488 | 489 | **Usage** 490 | 491 | ```jsx 492 | { 493 | view: 'area', 494 | } 495 | ``` 496 | 497 | **Possible value types** 498 | 499 | `String`: Consumes only String 500 | 501 | **Arguments** 502 | 503 | - `label` _(String)_: Shows title on the top of the view 504 | - `class` _(String or Array)_: View's assigned class 505 | - `hidden` _(Boolean)_: Hides or shows the view 506 | - `wrapper` _(String)_: Name of the view's wrapper 507 | - `html` (Boolean): Whether or not to allow WYSIWYG features 508 | - `defaultValue` _(*)_: Override of view's default value 509 | 510 | 511 | ## radio 512 | 513 | Acts as a radio button set. 514 | 515 | **Usage** 516 | 517 | ```jsx 518 | { 519 | view: 'radio', 520 | } 521 | 522 | ``` 523 | 524 | **Possible value types** 525 | 526 | `String`: Consumes a String or null 527 | 528 | **Arguments** 529 | 530 | - `label` _(String)_: Shows title on the top of the view 531 | - `class` _(String or Array)_: View's assigned class 532 | - `hidden` _(Boolean)_: Hides or shows the view 533 | - `wrapper` _(String)_: Name of the view's wrapper 534 | - `options` _(Array)_: Field option values 535 | - `defaultValue` _(*)_: Override of view's default value 536 | 537 | - **Plain mode** 538 | 539 | ```jsx 540 | ["Dog", "Cat"] 541 | ``` 542 | 543 | - **Value-text mode** 544 | 545 | ```jsx 546 | [ 547 | { text: "Dog", value: "doggo" }, 548 | { text: "Cat", value: "caterpillar" } 549 | ] 550 | ``` 551 | 552 | ## tick 553 | 554 | Acts as a single checkbox. 555 | 556 | **Usage** 557 | 558 | ```jsx 559 | { 560 | view: 'tick', 561 | } 562 | 563 | ``` 564 | 565 | **Possible value types** 566 | 567 | `Boolean`: Consumes a Boolean 568 | 569 | **Arguments** 570 | 571 | - `label` _(String)_: Shows title on the top of the view 572 | - `class` _(String or Array)_: View's assigned class 573 | - `hidden` _(Boolean)_: Hides or shows the view 574 | - `wrapper` _(String)_: Name of the view's wrapper 575 | - `defaultValue` _(*)_: Override of view's default value 576 | 577 | 578 | ## Custom views 579 | 580 | Any custom view can be inserted via `:views` property. Custom views are superior to the default ones, so `text` can be overwritten by a custom one. 581 | 582 | Usage: 583 | - pass a Object of components to `:views` property in dd-form 584 | - component will receive `path, value and description` properties 585 | - the component must emit a @change event with `value and path` properties 586 | 587 | ```jsx 588 | customViews: { 589 | 'text': customTextView, 590 | 'generator': generatorView, 591 | } 592 | 593 | ``` 594 | 595 | ```jsx 596 | import customTextView from 'path/to/custom-view'; 597 | 598 | ``` 599 | 600 | ...and bind the data in dd-form 601 | 602 | ```jsx 603 | 607 | ``` 608 | 609 | **Check the [demo's source code](https://github.com/marekmensa/vue-dd-form/blob/master/docs-src/components/Home.vue) to see it in use.** 610 | 611 | 612 | ### Advanced: Sub-elements 613 | Some sub-elements can be replaced too: `button-add`, `button-remove`, `button-submit`, `headline`. 614 | 615 | ```jsx 616 | customViews: { 617 | 'collection.button-add': customButtonAdd, 618 | 'collection.headline': customHeadline, 619 | 'collection.button-remove': customButtonRemove, 620 | 'group.headline': customHeadline, 621 | 'group.button-submit': customButtonSubmit, 622 | } 623 | ``` 624 | 625 | --- 626 | 627 | ## Other features 628 | 629 | 630 | 631 | ### Language customization 632 | 633 | vue-dd-form provides a `:lang` property, which can rewrite the default language wording. 634 | 635 | ```jsx 636 | 640 | ``` 641 | 642 | ...and the lang object 643 | ```jsx 644 | customLang: { 645 | add: 'Add item', 646 | remove: 'Remove item', 647 | save: 'Save data' 648 | } 649 | ``` 650 | 651 | 652 | ### Wrappers (beta) 653 | 654 | Views can be wrapped inside separate boxes (DIVs) so we can position them in any way. Look at example data: 655 | 656 | ```jsx 657 | { 658 | programme: [ 659 | { 660 | header: 'Friday', 661 | subheader: '25th September 2020', 662 | items: [ 663 | ... 664 | ], 665 | } 666 | ``` 667 | 668 | If we wanted, for instance, to have header and sub-header on the left side of the screen and items on the right, the descriptions would look as follows: 669 | 670 | ```jsx 671 | programme[*].header: { type: 'text' }, 672 | programme[*].subheader: { type: 'text', wrapper: 'left' }, 673 | programme[*].items: { type: 'collection', wrapper: 'left' }, 674 | ``` 675 | 676 | In result HTML, the views would look like this 677 | 678 | ```html 679 |
680 | 681 |
...
682 | 683 |
...
684 |
685 |
686 | 687 |
...
688 |
689 | ``` 690 | 691 | Afterwards, only thing to be defined are the CSS classes. Check the [demo's source code](https://github.com/marekmensa/vue-dd-form/blob/master/docs-src/components/Home.vue) to see it in use. 692 | 693 | 694 | --- 695 | 696 | 697 | ## Events 698 | 699 | `@change` fired after any value change, emits path, value changed & current data set 700 | 701 | ```html 702 | change({ path, value, data }) { 703 | // eslint-disable-next-line no-console 704 | console.log(path, value); // ex. => 'programme[*].header', 'Friday' 705 | console.log(data); // ex. => { ... } 706 | }, 707 | 708 | ``` 709 | 710 | `@submit` fired after form submit, emits data value 711 | 712 | ```jsx 713 | submit({ data }) { 714 | // eslint-disable-next-line no-console 715 | console.log(data); // ex. => { ... } 716 | }, 717 | 718 | ``` 719 | 720 | `@add` fired after a item is added to a collection, emits path, value added & current data set 721 | 722 | ```html 723 | add({ path, value, data }) { 724 | // eslint-disable-next-line no-console 725 | console.log(path, value); // ex. => 'programme[*].options', { header: 'Friday', ... } 726 | console.log(data); // ex. => { ... } 727 | }, 728 | 729 | ``` 730 | 731 | `@remove` fired after a item is added to a collection, emits path, value removed, index & current data set 732 | 733 | ```html 734 | remove({ path, value, data, index }) { 735 | // eslint-disable-next-line no-console 736 | console.log(path, value); // ex. => 'programme[*].options', { header: 'Friday', ... } 737 | console.log(data); // ex. => { ... } 738 | console.log(index); // ex. => 1 739 | }, 740 | 741 | ``` 742 | 743 | --- 744 | 745 | 746 | ## Styling 747 | 748 | Form can be styled in verious ways depending on the depth of the adjustment: 749 | - Any view can be assigned a class parameter. Class can be your custom one or one of the helper classes below. 750 | - Any view in a group view can be assigned a wrapper parameter (see Wrappers). 751 | - If none of above does not fulfill your needs, you can override or define your own views (see Custom views) 752 | 753 | 754 | ### Helper classes 755 | 756 | - `col--1-3` (sets width to 1/3 of the available space) 757 | - `col--2-3` (sets width to 2/3 of the available space) 758 | - `col--1-2` (sets width to one half of the available space) 759 | - `col--1-1` (sets full-width) 760 | - `row` (makes the div's direction inline) 761 | - `row--boxed` (makes the div's direction inline & puts it in a shadowed box) 762 | - `row--responsive` (makes the div's direction inline, but wraps on mobile) 763 | 764 | 765 | ### Other classes appearing in UI 766 | 767 | - `view` 768 | - `view—root` 769 | - `view—branch` 770 | - `view—leaf` 771 | - `view__container` 772 | - `view__container—removable` 773 | - `view__wrapper—removable` 774 | - `button` 775 | - `button—add` 776 | - `button—remove` 777 | - `button—submit` 778 | - `headline` 779 | 780 | 781 | 782 | # 🏁 Conclusion 783 | 784 | There are many useful things which are still not yet implemented (validation, CDN availability etc.). I'd be very thankful for any contributions! Described-Data would work the best if it was multi-platform so if you feel like cooperating (React etc.), hit me up! 785 | 786 | # License 787 | 788 | [The MIT License](http://opensource.org/licenses/MIT) 789 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /config/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const VueLoaderPlugin = require('vue-loader/lib/plugin') 3 | 4 | module.exports = { 5 | entry: path.resolve(__dirname + './../src/index.js'), 6 | output: { 7 | path: path.resolve(__dirname + './../dist'), 8 | filename: 'vue-dd-form.js' 9 | }, 10 | module: { 11 | rules: [{ 12 | test: /\.js$/, 13 | use: 'babel-loader' 14 | }, 15 | { 16 | test: /\.vue$/, 17 | use: 'vue-loader' 18 | }, 19 | { 20 | test: /\.css$/, 21 | use: [ 22 | 'css-loader' 23 | ] 24 | }, 25 | { 26 | test: /\.s[ac]ss$/i, 27 | use: [ 28 | 'css-loader', 29 | 'sass-loader', 30 | ] 31 | }, 32 | { 33 | test: /\.svg$/, 34 | use: [ 35 | 'babel-loader', 36 | 'vue-svg-loader', 37 | ], 38 | }, 39 | ] 40 | }, 41 | plugins: [ 42 | new VueLoaderPlugin() 43 | ] 44 | } -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marekmensa/vue-dd-form/6ea1993194c2125ae2064b30a3117c1db47016da/demo.gif -------------------------------------------------------------------------------- /docs-src/App.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 30 | 31 | 105 | -------------------------------------------------------------------------------- /docs-src/assets/descriptions-advanced.json: -------------------------------------------------------------------------------- 1 | { 2 | "public": { "view": "tick", "label": "Make your profile public" }, 3 | "name": { "view": "text", "label": "Full name" }, 4 | "bio": { "view": "area", "html": true, "label": "Short bio" }, 5 | "avatar": { 6 | "view": "upload", 7 | "label": "Profile photo (not uploading in demo)" 8 | }, 9 | "milestones": { "view": "collection", "label": "Milestones" }, 10 | "milestones[*]": { "view": "group" }, 11 | "milestones[*].title": { "view": "text", "label": "Milestone title" }, 12 | "milestones[*].date": { "view": "datetime", "label": "Date" }, 13 | "milestones[*].importance": { 14 | "view": "counter", 15 | "label": "Importance (0 – 10)", 16 | "min": 1, 17 | "max": 10 18 | }, 19 | "education": { "view": "group", "label": "Education" }, 20 | "education.status": { 21 | "view": "radio", 22 | "label": "Current status", 23 | "options": [ 24 | { "text": "I'm studying", "value": "student" }, 25 | { "text": "I'm employed", "value": "empolyed" }, 26 | { "text": "I'm a freelancer", "value": "freelance" } 27 | ] 28 | }, 29 | "education.reached": { 30 | "view": "select", 31 | "label": "Highest level of education reached", 32 | "options": [ 33 | "Early childhood education (‘less than primary’ for educational attainment)", 34 | "Primary education", 35 | "Lower secondary education", 36 | "Upper secondary education", 37 | "Post-secondary non-tertiary education", 38 | "Short-cycle tertiary education", 39 | "Bachelor’s or equivalent level", 40 | "Master’s or equivalent level", 41 | "Doctoral or equivalent level" 42 | ] 43 | }, 44 | "education.certificates": { 45 | "view": "checkbox", 46 | "label": "Certificates", 47 | "options": [ 48 | "Certified Information Security Manager (CISM)", 49 | "Certified Ethical Hacker (CEH)", 50 | "Certified Information Systems Security Professional (CISSP)", 51 | "Certified in Risk and Information Systems Control (CRISC)", 52 | "Certified Information Systems Auditor (CISA)", 53 | "Google Certified Professional Cloud Architect" 54 | ] 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /docs-src/assets/descriptions-basic.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": {"view": "text", "label": "Movie title"}, 3 | "description": {"view": "area", "label": "Description"}, 4 | "genres": {"view": "checkbox", "label": "Genres", "options": ["Action", "Comedy", "Drama", "Fantasy", "Horror", "Mystery", "Romance", "Thriller"]}, 5 | "language": {"view": "select", "label": "Original language", "options": ["English", "Spanish", "Korean", "Chinese", "French", "Hindi", "German"]} 6 | } -------------------------------------------------------------------------------- /docs-src/assets/descriptions-custom.json: -------------------------------------------------------------------------------- 1 | { 2 | "fullname": { "view": "text", "label": "Full name"}, 3 | "username": { "view": "generator", "header": "Generate random username"}, 4 | "consent": { "view": "tick", "label": "I aggree with terms & conditions"} 5 | } -------------------------------------------------------------------------------- /docs-src/assets/descriptions-dynamic.json: -------------------------------------------------------------------------------- 1 | { 2 | "limitLogins": { "view": "tick", "label": "Limit login attempts" }, 3 | "limitCount": { "view": "counter", "label": "Number of attempts", "hidden": "_limitNotSelected" }, 4 | "users": { "view": "collection", "label": "Users", "addable": "_addable" }, 5 | "users[*]": { "view": "group", "label": "User no. {_userIndex}" }, 6 | "users[*].name": { "view": "text", "label": "Username" }, 7 | "users[*].email": { "view": "text", "label": "Email"}, 8 | "users[*].type": { "view": "radio", "label": "User type", "options": "_userTypes"} 9 | } -------------------------------------------------------------------------------- /docs-src/assets/descriptions-wrappers.json: -------------------------------------------------------------------------------- 1 | { 2 | "general": { "view": "group","label": "General information", "class": ["row", "general"], "wrapper": ["row--boxed", "col--1-3" ]}, 3 | "general.public": { "view": "tick", "label": "Make your profile public" }, 4 | "general.name": { "view": "text", "label": "Full name" }, 5 | "general.bio": { "view": "area", "html": true, "label": "Short bio" }, 6 | "general.avatar": { "view": "upload", "label": "Profile photo (not uploading in demo)" }, 7 | "education": { "view": "group", "label": "Education", "wrapper": ["row--boxed", "col--2-3" ] }, 8 | "education.status": { 9 | "view": "radio", 10 | "label": "Current status", 11 | "options": [ 12 | { "text": "I'm studying", "value": "student" }, 13 | { "text": "I'm employed", "value": "empolyed" }, 14 | { "text": "I'm a freelancer", "value": "freelance" } 15 | ] 16 | }, 17 | "education.reached": { 18 | "view": "select", 19 | "label": "Highest level of education reached", 20 | "options": [ 21 | "Early childhood education (‘less than primary’ for educational attainment)", 22 | "Primary education", 23 | "Lower secondary education", 24 | "Upper secondary education", 25 | "Post-secondary non-tertiary education", 26 | "Short-cycle tertiary education", 27 | "Bachelor’s or equivalent level", 28 | "Master’s or equivalent level", 29 | "Doctoral or equivalent level" 30 | ] 31 | }, 32 | "education.certificates": { 33 | "view": "checkbox", 34 | "label": "Certificates", 35 | "options": [ 36 | "Certified Information Security Manager (CISM)", 37 | "Certified Ethical Hacker (CEH)", 38 | "Certified Information Systems Security Professional (CISSP)", 39 | "Certified in Risk and Information Systems Control (CRISC)", 40 | "Certified Information Systems Auditor (CISA)", 41 | "Google Certified Professional Cloud Architect" 42 | ] 43 | }, 44 | "milestones": { "view": "collection", "label": "Milestones", "wrapper": ["col--2-3", "row--boxed", "milestones"] }, 45 | "milestones[*]": { "view": "group" }, 46 | "milestones[*].title": { "view": "text", "label": "Milestone title" }, 47 | "milestones[*].date": { "view": "datetime", "label": "Date" }, 48 | "milestones[*].importance": { 49 | "view": "counter", 50 | "label": "Importance (0 – 10)", 51 | "min": 1, 52 | "max": 10 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /docs-src/assets/logo-github.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /docs-src/assets/logo-vue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marekmensa/vue-dd-form/6ea1993194c2125ae2064b30a3117c1db47016da/docs-src/assets/logo-vue.png -------------------------------------------------------------------------------- /docs-src/components/Home.vue: -------------------------------------------------------------------------------- 1 | 91 | 92 | 213 | 214 | 215 | 291 | -------------------------------------------------------------------------------- /docs-src/components/UsernameGenerator.vue: -------------------------------------------------------------------------------- 1 | 9 | 39 | -------------------------------------------------------------------------------- /docs-src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App.vue'; 3 | import ddForm from '../src'; 4 | Vue.use(ddForm); 5 | 6 | Vue.config.productionTip = false; 7 | 8 | new Vue({ 9 | render: (h) => h(App), 10 | }).$mount('#app'); 11 | -------------------------------------------------------------------------------- /docs/css/app.65cd258f.css: -------------------------------------------------------------------------------- 1 | .input-text[data-v-480999da]{outline:none;border:1px solid #d8d8d8;background-color:#fff;height:40px;max-height:40px;display:flex;flex-grow:1;padding:0 10px;font-family:inherit;border-radius:0;transition:.3s;font-size:16px;font-weight:300;color:#000;letter-spacing:1px}.input-text[data-v-480999da]:focus{border:1px solid #797979}.input-text__wrapper[data-v-480999da]{display:flex;flex-direction:column;flex-grow:1;position:relative;background:#43b984;background-image:url(https://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/Van_Gogh_-_Starry_Night_-_Google_Art_Project.jpg/1280px-Van_Gogh_-_Starry_Night_-_Google_Art_Project.jpg);background-position-y:-105px;background-position-x:-355px;padding:10px 15px 20px}.input-text__description[data-v-480999da]{margin-bottom:10px}.input-text__label[data-v-480999da]{color:#fff;font-size:16px;height:auto;font-weight:300;letter-spacing:.15px;position:relative}h3{margin:40px 0 0}ul{list-style-type:none;padding:0}li{display:inline-block;margin:0 10px}a{color:#42b983}.copyright{text-align:left;padding-left:20px;color:#959595;font-weight:500}.highlight{color:#42b983}.switcher__item{cursor:pointer;color:#2c3e50;transition:all .3s ease;font-size:18px;padding:0 20px}.switcher__item--active,.switcher__item:hover{color:#42b983;text-decoration:underline}.preview-form{width:100%;background:#fff;padding:40px 0;margin-top:40px}.preview-form__interface{text-align:left;max-width:700px;margin:0 auto}.preview-form__interface--wrappers{max-width:100%!important}.preview-form__interface--wrappers .view--root>.view--branch{flex-direction:row!important;flex-wrap:wrap!important;justify-content:left}.preview-form__interface--wrappers .row--boxed{margin-right:60px}.preview-form__interface--wrappers .row--boxed .view__container,.preview-form__interface--wrappers .row--boxed .view__wrapper{width:100%}.preview-code,.preview-form__interface--wrappers .milestones{margin-top:60px}.preview-code{display:flex;flex-direction:row;justify-content:space-around}.preview-code__box{width:42.5%}#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#2c3e50;margin-top:20px}body{margin:0;background:#eee}pre{display:block!important;max-height:350px;margin-top:20px!important}.header{padding:0 20px;display:flex;flex-direction:row;justify-content:start;align-items:center}.header__logo{width:40px;height:40px}.header__title{padding:0 20px;font-weight:200;white-space:nowrap}.header__title strong{font-weight:600}.header__spacer{width:100%}.header__button{display:flex;flex-direction:row;align-items:center;justify-content:center;border:1px solid transparent;border-radius:4px;box-shadow:none;font-size:1rem;height:2.5em;line-height:1.5;cursor:pointer;padding-bottom:calc(.5em - 1px);padding-left:1em;padding-right:1em;padding-top:calc(.5em - 1px);text-align:center;white-space:nowrap;background-color:#0a0a0a;color:#fff}.header__button-icon{width:30px;margin-left:5px}.header__button-wrapper{text-decoration:none}.headline__title[data-v-25a45002]{color:#000;font-weight:300;font-size:28px;letter-spacing:-1.09px}@media(min-width:1400px){.headline__title[data-v-25a45002]{font-size:38px}}.button-add[data-v-e2123bd8]{color:#363636;font-size:16px;font-weight:300;letter-spacing:1px;display:flex;flex-direction:row;align-items:center;height:50px;padding:0 10px;border:1px dashed #e2e2e2;transition:.3s;cursor:pointer}.button-add[data-v-e2123bd8]:hover{border:1px dashed #4cce52}.button-remove[data-v-d9cfa768]{cursor:pointer!important;font-weight:300;min-width:24px;border:1px solid #f0f0f0;transition:color .3s ease;color:#9b9b9b;display:flex;justify-content:center;align-items:center}.button-remove[data-v-d9cfa768]:hover{color:#4cce52}.button-remove--is-sliding-enter-active[data-v-d9cfa768]{-webkit-animation:slide-in-data-v-d9cfa768 .3s;animation:slide-in-data-v-d9cfa768 .3s}.button-remove--is-sliding-leave-active[data-v-d9cfa768]{-webkit-animation:slide-out-data-v-d9cfa768 .3s;animation:slide-out-data-v-d9cfa768 .3s}@-webkit-keyframes slide-in-data-v-d9cfa768{0%{transform:translate(-10%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes slide-in-data-v-d9cfa768{0%{transform:translate(-10%);opacity:0}to{transform:translate(0);opacity:1}}@-webkit-keyframes slide-out-data-v-d9cfa768{0%{transform:translate(0);opacity:1}to{transform:translate(-10%);opacity:0}}@keyframes slide-out-data-v-d9cfa768{0%{transform:translate(0);opacity:1}to{transform:translate(-10%);opacity:0}}.button-drag[data-v-32be9bad]{cursor:move!important;font-weight:300;min-width:24px;border:1px solid #f0f0f0;transition:color .3s ease;color:#9b9b9b;display:flex;justify-content:center;align-items:center}.button-drag[data-v-32be9bad]:hover{color:#4cce52}.button-drag--is-sliding-enter-active[data-v-32be9bad]{-webkit-animation:slide-in-data-v-32be9bad .3s;animation:slide-in-data-v-32be9bad .3s}.button-drag--is-sliding-leave-active[data-v-32be9bad]{-webkit-animation:slide-out-data-v-32be9bad .3s;animation:slide-out-data-v-32be9bad .3s}@-webkit-keyframes slide-in-data-v-32be9bad{0%{transform:translate(-10%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes slide-in-data-v-32be9bad{0%{transform:translate(-10%);opacity:0}to{transform:translate(0);opacity:1}}@-webkit-keyframes slide-out-data-v-32be9bad{0%{transform:translate(0);opacity:1}to{transform:translate(-10%);opacity:0}}@keyframes slide-out-data-v-32be9bad{0%{transform:translate(0);opacity:1}to{transform:translate(-10%);opacity:0}}.input-text[data-v-8143fb32]{outline:none;border:1px solid #d8d8d8;background-color:#fff;height:40px;max-height:40px;display:flex;flex-grow:1;padding:0 10px;font-family:inherit;border-radius:0;transition:.3s;font-size:16px;font-weight:300;color:#000;letter-spacing:1px}.input-text[data-v-8143fb32]:focus{border:1px solid #797979}.input-text__wrapper[data-v-8143fb32]{display:flex;flex-direction:column;flex-grow:1;position:relative}.input-text__description[data-v-8143fb32]{margin-bottom:10px}.input-text__label[data-v-8143fb32]{color:#797979;font-size:16px;height:auto;font-weight:300;letter-spacing:.15px;position:relative}.input-upload[data-v-05fd5cf4]{cursor:pointer}.input-upload__area[data-v-05fd5cf4]{width:100%;height:0;padding-bottom:50px;border:1px dashed #d8d8d8;position:relative}.input-upload__icon[data-v-05fd5cf4]{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:30px}.input-upload__label[data-v-05fd5cf4]{text-align:left;margin-bottom:10px;color:#797979;font-size:16px;font-weight:300}.input-upload__image-wrapper[data-v-05fd5cf4]{position:absolute;left:0;top:0;right:0;bottom:0;display:flex;flex-direction:column;align-items:center;justify-content:center}.input-upload__image[data-v-05fd5cf4]{max-width:100%;max-height:100%}.input-upload__input[data-v-05fd5cf4]{display:none}.input-area[data-v-05206c3c]{outline:none;border:1px solid #d8d8d8!important;box-shadow:none!important;border-radius:0!important;background-color:#fff;height:150px;flex-grow:1;padding:10px!important;font-family:inherit;transition:.3s;font-size:16px;font-weight:300;height:200px;color:#000;letter-spacing:1px;overflow:hidden;overflow-y:scroll;resize:none}.input-area strong[data-v-05206c3c]{font-weight:500}.input-area p[data-v-05206c3c]{margin:0}.input-area__wrapper[data-v-05206c3c]{display:flex;flex-direction:column;flex-grow:1;position:relative;cursor:default}.input-area__description[data-v-05206c3c]{margin-bottom:10px}.input-area__label[data-v-05206c3c]{color:#797979;font-size:16px;height:auto;font-weight:300;letter-spacing:.15px;position:relative}.input-area__label[data-v-05206c3c]:after{color:#ffd012;line-height:1;position:absolute;right:0;top:0;transform:translate(130%,-10%)}.ql-container .ql-snow[data-v-05206c3c]{border-color:#d8d8d8!important}.ql-editor[data-v-05206c3c]{font-family:Open Sans,sans-serif;font-weight:200}.input-select[data-v-6b92807e]{border:1px solid #d8d8d8;position:relative;display:flex;color:#000;font-size:16px;font-weight:300;background-color:#fff}.input-select--contrasted[data-v-6b92807e]{border:1px solid #4cce52}.input-select__wrapper[data-v-6b92807e]{display:flex;flex-direction:column;flex-grow:1;position:relative}.input-select__description[data-v-6b92807e]{margin-bottom:10px}.input-select__label[data-v-6b92807e]{color:#797979;font-size:16px;font-weight:300;letter-spacing:.15px;position:relative}.input-select__label[data-v-6b92807e]:after{color:#ffd012;line-height:1;position:absolute;right:0;top:0;transform:translate(130%,-10%)}.input-select__label--required[data-v-6b92807e]:after{content:"*"}.input-select__options-wrapper[data-v-6b92807e]{position:absolute;width:calc(100% + 2px);left:-1px;top:100%;overflow:auto;max-height:200px;background-color:#fff;z-index:1;border:1px solid #d8d8d8}.input-select__options-wrapper--contrasted[data-v-6b92807e]{border:1px solid #4cce52}.input-select__options-wrapper--is-fading-enter-active[data-v-6b92807e]{-webkit-animation:fade-in-data-v-6b92807e .3s;animation:fade-in-data-v-6b92807e .3s}.input-select__options-wrapper--is-fading-leave-active[data-v-6b92807e]{-webkit-animation:fade-out-data-v-6b92807e .3s;animation:fade-out-data-v-6b92807e .3s}.input-select__options[data-v-6b92807e]{list-style:none;margin:0;padding:0;display:block}.input-select__option[data-v-6b92807e]{width:100%;height:40px;display:flex;align-items:center;justify-content:flex-start;padding:0 10px;transition:.3s;margin:0;cursor:pointer}.input-select__option--current[data-v-6b92807e]{justify-content:space-between}.input-select__option--contrasted[data-v-6b92807e]:hover:not(.input-select__option--contrasted:hover--current){background-color:#4cce52}.input-select__option[data-v-6b92807e]:not(.input-select__option--current):hover{background-color:#d8d8d8;color:#fff}.input-select__icon[data-v-6b92807e]{flex-shrink:0;margin-left:10px;transition:.3s;transform:translateY(-25%) rotate(0deg)}.input-select__icon--expanded[data-v-6b92807e]{transform:translateY(-25%) rotate(180deg)}@-webkit-keyframes fade-in-data-v-6b92807e{0%{opacity:0}to{opacity:1}}@keyframes fade-in-data-v-6b92807e{0%{opacity:0}to{opacity:1}}@-webkit-keyframes fade-out-data-v-6b92807e{0%{opacity:1}to{opacity:0}}@keyframes fade-out-data-v-6b92807e{0%{opacity:1}to{opacity:0}}.input-tick[data-v-4e972b3c]{display:none}.input-tick__wrapper[data-v-4e972b3c]{flex-direction:row;display:flex}.input-tick__icon-wrapper[data-v-4e972b3c]{width:25px;height:25px;border:1px solid #e2e2e2;background-color:#fff;flex-shrink:0;display:flex;align-items:center;justify-content:center;cursor:pointer}.input-tick__icon-wrapper--checked[data-v-4e972b3c]{border:1px solid #4cce52}.input-tick__icon[data-v-4e972b3c]{width:15px;height:auto;fill:#e2e2e2}.input-tick__icon--checked[data-v-4e972b3c]{fill:#4cce52}.input-tick__label[data-v-4e972b3c]{margin-left:15px;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.input-tick__headline[data-v-4e972b3c]{color:#000;font-size:16px;font-weight:300;letter-spacing:1px;margin:0}.input-tick__link a[data-v-4e972b3c]:link,.input-tick__link a[data-v-4e972b3c]:visited{color:#4cce52;font-weight:500}.input-tick__paragraph[data-v-4e972b3c]{color:#797979;font-size:13px;font-weight:300;letter-spacing:1px;margin:0 1px}.input-checkbox[data-v-021a2e6b]{display:flex;flex-direction:column;flex-grow:1}.input-checkbox__description[data-v-021a2e6b]{margin-bottom:10px}.input-checkbox__label[data-v-021a2e6b]{color:#797979;height:auto;font-size:16px;font-weight:300;letter-spacing:.15px;position:relative}.input-checkbox__label[data-v-021a2e6b]:after{color:#ffd012;line-height:1;position:absolute;right:0;top:0;transform:translate(130%,-10%)}.input-checkbox__options[data-v-021a2e6b]{margin-top:10px}.input-checkbox__option[data-v-021a2e6b]{margin-bottom:10px}.input-checkbox__option[data-v-021a2e6b]:last-of-type{margin-bottom:0}.input-counter[data-v-68d18439]{outline:none;border:0;border:1px solid #d8d8d8;height:40px;display:flex;flex-grow:1;padding:0 10px;padding-right:30px;font-family:inherit;border-radius:0;transition:.3s;font-size:16px;font-weight:300;color:#000;letter-spacing:1px;background-color:#fff;cursor:default;max-width:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.input-counter[data-v-68d18439]:focus{border:1px solid #797979}.input-counter__container[data-v-68d18439]{display:flex;flex-direction:column}.input-counter__description[data-v-68d18439]{margin-bottom:10px}.input-counter__label[data-v-68d18439]{color:#797979;font-size:16px;font-weight:300;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;letter-spacing:.15px}.input-counter__wrapper[data-v-68d18439]{position:relative;display:flex}.input-counter__handles[data-v-68d18439]{position:absolute;right:0;width:24px;height:40px;border:1px solid #e2e2e2;background-color:#f9f9f9;transition:.3s;display:flex;flex-direction:column}.input-counter:focus+.input-counter__handles[data-v-68d18439]{border:1px solid #797979}.input-counter__handle[data-v-68d18439]{height:50%;display:flex;flex-direction:row;align-items:center;justify-content:center;color:#4cce52;transition:.3s;cursor:pointer}.input-counter__handle[data-v-68d18439]:first-of-type{border-bottom:1px solid #e1e1e1}.input-counter__handle[data-v-68d18439]:hover{background-color:#d8d8d8}.input-counter__icon[data-v-68d18439]{width:8px;fill:#4cce52;height:20px;display:flex;align-items:center;font-weight:500;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.vdatetime-month-picker__item--selected,.vdatetime-popup__title,.vdatetime-time-picker__item--selected,.vdatetime-year-picker__item--selected{color:#4cce52!important}.vdatetime-calendar__month__day--selected:hover>span>span,.vdatetime-calendar__month__day--selected>span>span{background:#4cce52!important}.vdatetime-calendar__navigation,.vdatetime-popup__actions,.vdatetime-time-picker__item{font-weight:300}.vdatetime-calendar__month__weekday{font-weight:400}.vdatetime-popup__actions{margin-top:15px}.vdatetime-popup__actions__button{color:#000}.vdatetime-popup__actions__button:hover{color:#4cce52}.vdatetime-overlay{background:transparent}.vdatetime-popup{font-family:Open Sans,sans-serif;position:absolute;top:77.5px;left:auto;transform:none}.vdatetime-popup__header{background:#4cce52!important}.vdatetime{width:calc(50% - 15px)}.input-datetime{display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:space-between}.input-datetime input{outline:none;box-sizing:border-box;border:1px solid #d8d8d8;background-color:#fff;height:40px;width:100%;max-height:40px;display:flex;flex-grow:1;padding:0 10px;font-family:inherit;border-radius:0;transition:.3s;font-size:16px;font-weight:300;color:#000;letter-spacing:1px}.input-datetime__wrapper{display:flex;flex-direction:column;position:relative}.input-datetime__description{margin-bottom:10px}.input-datetime__label{color:#797979;font-size:16px;height:auto;font-weight:300;letter-spacing:.15px;position:relative}.input-radio[data-v-8de7aae4]{display:flex;flex-direction:column;flex-grow:1}.input-radio__description[data-v-8de7aae4]{margin-bottom:10px}.input-radio__label[data-v-8de7aae4]{color:#797979;height:auto;font-size:16px;font-weight:300;letter-spacing:.15px;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.input-radio__label[data-v-8de7aae4]:after{color:#ffd012;line-height:1;position:absolute;right:0;top:0;transform:translate(130%,-10%)}.input-radio__options[data-v-8de7aae4]{display:flex;flex-direction:column;flex-wrap:wrap}.input-radio__option[data-v-8de7aae4]{margin-bottom:10px}.input-radio__option[data-v-8de7aae4]:last-of-type{margin-bottom:0}.input-radio__radio[data-v-8de7aae4]{width:24px;height:24px;border-radius:24px;border:1px solid #e2e2e2;position:relative;margin-right:15px;cursor:pointer;flex-shrink:0}.input-radio__radio[data-v-8de7aae4]:before{content:"";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:13px;height:13px;background-color:#4cce52;transition:.3s;opacity:0;border-radius:7px}.input-radio__radio--checked[data-v-8de7aae4]:before{opacity:1}.input-radio__option-label[data-v-8de7aae4]{color:#000;font-size:16px;font-weight:300;letter-spacing:1px;display:flex;flex-direction:row;align-items:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer}.input-radio__input[data-v-8de7aae4]{display:none}.button[data-v-7e331ab4]{display:flex;flex-direction:row;align-items:center;justify-content:center;border:0;box-shadow:0 2px 17px rgba(0,0,0,.11);background-color:#58d365;color:#fff;font-size:16px;font-weight:300;transition:.3s;font-family:inherit;outline:none;cursor:pointer;border-radius:0;position:relative;flex-shrink:0;margin:25px 0;width:270px;height:60px;padding:0 40px}@media(min-width:768px){.button[data-v-7e331ab4]{font-size:14px}}@media(min-width:1400px){.button[data-v-7e331ab4]{font-size:16px}}.button[data-v-7e331ab4]:hover{box-shadow:0 0 0 transparent;background-color:#4db352}.view{display:flex;flex-direction:column;width:100%;transition:width .3s ease}.view--root{margin:0 70px}.view--branch,.view--leaf{margin:15px 0}.view__container--removable,.view__wrapper--draggable{position:relative}.view__wrapper--draggable .view,.view__wrapper--draggable .view__container{cursor:auto}.view__wrapper--draggable .view__wrapper:hover{cursor:move}.view__container{display:flex;flex-direction:row;justify-content:start;align-items:center;transition:.2s}.button--drag{left:-70px;margin-left:20px}.button--drag,.button--remove{position:absolute;transition:visibility .2s linear,opacity .2s linear}.button--remove{right:-70px;margin-right:20px}.button--add{margin-top:10px}.button--submit{margin-left:70px!important}.headline{margin-bottom:10px;width:100%}.ghost{background:#f9f9f9}.ghost div{opacity:0}h2{margin:0;margin-top:25px}.col--1-3{width:calc(33.33333% - 100px)}.col--2-3{width:calc(66.66667% - 400px)}.col--1-2{width:50%}.col--1-1{width:100%}.row,.row--boxed{display:flex;flex-direction:row;flex-wrap:wrap}.row--boxed{box-shadow:0 0 17px rgba(0,0,0,.1);padding:10px 20px}.row-responsive{display:flex;flex-direction:row}@media(max-width:1023px){.row-responsive{flex-direction:column}} -------------------------------------------------------------------------------- /docs/css/chunk-vendors.90b90f44.css: -------------------------------------------------------------------------------- 1 | code[class*=language-],pre[class*=language-]{color:#ccc;background:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#999}.token.punctuation{color:#ccc}.token.attr-name,.token.deleted,.token.namespace,.token.tag{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#7ec699}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green}div pre[class*=language-]{display:inline-block;padding-right:10em;padding-top:3rem;border-radius:6px;background-image:url('data:image/svg+xml;utf8, ');background-repeat:no-repeat;background-position:16px 16px;-webkit-box-shadow:5px 5px 15px 0 rgba(50,50,50,.75);box-shadow:5px 5px 15px 0 rgba(50,50,50,.75)}.vdatetime-fade-enter-active,.vdatetime-fade-leave-active{transition:opacity .4s}.vdatetime-fade-enter,.vdatetime-fade-leave-to{opacity:0}.vdatetime-overlay{z-index:999;position:fixed;top:0;right:0;bottom:0;left:0;background:rgba(0,0,0,.5);transition:opacity .5s}.vdatetime-popup{z-index:1000;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:340px;max-width:calc(100% - 30px);box-shadow:0 1px 3px 0 rgba(0,0,0,.3);color:#444;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;line-height:1.18;background:#fff;-webkit-tap-highlight-color:rgba(0,0,0,0)}.vdatetime-popup,.vdatetime-popup *{box-sizing:border-box}.vdatetime-popup__header{padding:18px 30px;background:#3f51b5;color:#fff;font-size:32px}.vdatetime-popup__title{margin-bottom:8px;font-size:21px;font-weight:300}.vdatetime-popup__year{font-weight:300;font-size:14px;opacity:.7;cursor:pointer;transition:opacity .3s}.vdatetime-popup__year:hover{opacity:1}.vdatetime-popup__date{line-height:1;cursor:pointer}.vdatetime-popup__actions{padding:0 20px 10px 30px;text-align:right}.vdatetime-popup__actions__button{display:inline-block;border:none;padding:10px 20px;background:transparent;font-size:16px;color:#3f51b5;cursor:pointer;transition:color .3s}.vdatetime-popup__actions__button:hover{color:#444}.vdatetime-calendar__navigation--next:hover svg path,.vdatetime-calendar__navigation--previous:hover svg path{stroke:#888}.vdatetime-calendar__navigation,.vdatetime-calendar__navigation *{box-sizing:border-box}.vdatetime-calendar__navigation{position:relative;margin:15px 0;padding:0 30px;width:100%}.vdatetime-calendar__navigation--next,.vdatetime-calendar__navigation--previous{position:absolute;top:0;padding:0 5px;width:18px;cursor:pointer}.vdatetime-calendar__navigation--next svg,.vdatetime-calendar__navigation--previous svg{width:8px;height:13px}.vdatetime-calendar__navigation--next svg path,.vdatetime-calendar__navigation--previous svg path{transition:stroke .3s}.vdatetime-calendar__navigation--previous{left:25px}.vdatetime-calendar__navigation--next{right:25px;transform:scaleX(-1)}.vdatetime-calendar__current--month{text-align:center;text-transform:capitalize}.vdatetime-calendar__month{padding:0 20px;transition:height .2s}.vdatetime-calendar__month__day,.vdatetime-calendar__month__weekday{display:inline-block;width:14.28571%;line-height:36px;text-align:center;font-size:15px;font-weight:300;cursor:pointer}.vdatetime-calendar__month__day>span,.vdatetime-calendar__month__weekday>span{display:block;width:100%;position:relative;height:0;padding:0 0 100%;overflow:hidden}.vdatetime-calendar__month__day>span>span,.vdatetime-calendar__month__weekday>span>span{display:flex;justify-content:center;align-items:center;position:absolute;top:0;right:0;bottom:0;left:0;border:0;border-radius:50%;transition:background-color .3s,color .3s}.vdatetime-calendar__month__weekday{font-weight:700}.vdatetime-calendar__month__day:hover>span>span{background:#eee}.vdatetime-calendar__month__day--selected:hover>span>span,.vdatetime-calendar__month__day--selected>span>span{color:#fff;background:#3f51b5}.vdatetime-calendar__month__day--disabled{opacity:.4;cursor:default}.vdatetime-calendar__month__day--disabled:hover>span>span{color:inherit;background:transparent}.vdatetime-time-picker__list::-webkit-scrollbar-thumb{background:#ccc}.vdatetime-time-picker__list::-webkit-scrollbar-track{background:#efefef}.vdatetime-time-picker,.vdatetime-time-picker *{box-sizing:border-box}.vdatetime-time-picker:after{content:"";display:table;clear:both}.vdatetime-time-picker__list{float:left;width:50%;height:305px;overflow-y:scroll;-webkit-overflow-scrolling:touch}.vdatetime-time-picker__list::-webkit-scrollbar{width:3px}.vdatetime-time-picker__with-suffix .vdatetime-time-picker__list{width:33.3%}.vdatetime-time-picker__item{padding:10px 0;font-size:20px;text-align:center;cursor:pointer;transition:font-size .3s}.vdatetime-time-picker__item:hover{font-size:32px}.vdatetime-time-picker__item--selected{color:#3f51b5;font-size:32px}.vdatetime-time-picker__item--disabled{opacity:.4;cursor:default;font-size:20px!important}.vdatetime-year-picker__list::-webkit-scrollbar-thumb{background:#ccc}.vdatetime-year-picker__list::-webkit-scrollbar-track{background:#efefef}.vdatetime-year-picker,.vdatetime-year-picker *{box-sizing:border-box}.vdatetime-year-picker:after{content:"";display:table;clear:both}.vdatetime-year-picker__list{float:left;width:100%;height:305px;overflow-y:scroll;-webkit-overflow-scrolling:touch}.vdatetime-year-picker__list::-webkit-scrollbar{width:3px}.vdatetime-year-picker__item{padding:10px 0;font-size:20px;text-align:center;cursor:pointer;transition:font-size .3s}.vdatetime-year-picker__item:hover{font-size:32px}.vdatetime-year-picker__item--selected{color:#3f51b5;font-size:32px}.vdatetime-year-picker__item--disabled{opacity:.4;cursor:default}.vdatetime-year-picker__item--disabled:hover{color:inherit;background:transparent}.vdatetime-month-picker__list::-webkit-scrollbar-thumb{background:#ccc}.vdatetime-month-picker__list::-webkit-scrollbar-track{background:#efefef}.vdatetime-month-picker,.vdatetime-month-picker *{box-sizing:border-box}.vdatetime-month-picker:after{content:"";display:table;clear:both}.vdatetime-month-picker__list{float:left;width:100%;height:305px;overflow-y:scroll;-webkit-overflow-scrolling:touch}.vdatetime-month-picker__list::-webkit-scrollbar{width:3px}.vdatetime-month-picker__item{padding:10px 0;font-size:20px;text-align:center;cursor:pointer;transition:font-size .3s}.vdatetime-month-picker__item:hover{font-size:32px}.vdatetime-month-picker__item--selected{color:#3f51b5;font-size:32px}.vdatetime-month-picker__item--disabled{opacity:.4;cursor:default}.vdatetime-month-picker__item--disabled:hover{color:inherit;background:transparent} -------------------------------------------------------------------------------- /docs/img/logo-vue.82b9c7a5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marekmensa/vue-dd-form/6ea1993194c2125ae2064b30a3117c1db47016da/docs/img/logo-vue.82b9c7a5.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | vue-dd-form demo
-------------------------------------------------------------------------------- /docs/js/app.b20c9a4b.js: -------------------------------------------------------------------------------- 1 | (function(t){function e(e){for(var s,r,o=e[0],c=e[1],l=e[2],d=0,p=[];d{if("success"===t.status){const e=t.data[0].path;this.$emit("change",{path:this.path,value:e}),this.$store.dispatch("notifications/push",{key:"uploaded",type:"success"})}else this.$store.dispatch("notifications/push",{key:t.message,type:"failure"})}).catch(()=>{this.$store.dispatch("notifications/push",{key:"errorTryAgain",type:"failure"})}))}},components:{iconUpload:vt.a,iconFile:bt.a}},_t=gt,wt=(a("d16b"),Object(z["a"])(_t,ut,dt,!1,null,"05fd5cf4",null)),Ct=wt.exports,yt=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"input-area__wrapper",on:{mouseenter:function(e){t.hover=!0},mouseleave:function(e){t.hover=!1}}},[t.label?a("div",{staticClass:"input-area__description"},[a("label",{staticClass:"input-area__label",domProps:{textContent:t._s(t.label)}})]):t._e(),t.html?a("vue-editor",{attrs:{"editor-toolbar":t.customToolbar},on:{input:t.updateHtml},model:{value:t.content,callback:function(e){t.content=e},expression:"content"}}):a("textarea",{staticClass:"input-area",domProps:{value:t.value},on:{input:t.update}})],1)},xt=[],jt=a("5873"),kt=a("2f62"),At=a("3e09"),Pt=a.n(At);class Vt{constructor(t,e){this.loader=t,this.profile=e}upload(){return this.loader.file.then(t=>new Promise((e,a)=>{const s=new FormData;s.append("image",t),s.append("id",this.profile.email),s.append("uid",this.profile.uid),ht.a.post("/api/images",s).then(({data:t})=>{"success"===t.status?e({default:t.data[0].path}):a(t.message)}).catch(()=>{a()})}))}abort(){}}var St={props:["path","value","description"],computed:{...Object(kt["a"])("user",["profile"])},data(){return{hover:!1,content:"",label:this.description.label,html:this.description.html,customToolbar:[["bold","italic","underline"],[{list:"ordered"},{list:"bullet"}]]}},created(){this.content=this.value},components:{VueEditor:jt["a"]},methods:{dompurify:Pt.a,clean(t){return Pt.a.sanitize(t)},update(t){this.$emit("change",{path:this.path,value:t.target.value})},updateHtml(){this.$emit("change",{path:this.path,value:this.clean(this.content)})},CustomUploadAdapterPlugin(t){t.plugins.get("FileRepository").createUploadAdapter=t=>new Vt(t,this.profile)}}},Ot=St,Et=(a("c205"),Object(z["a"])(Ot,yt,xt,!1,null,"05206c3c",null)),Dt=Et.exports,It=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"input-select__wrapper"},[t.label?a("div",{staticClass:"input-select__description"},[a("div",{staticClass:"input-select__label",domProps:{textContent:t._s(t.label)}})]):t._e(),a("div",{staticClass:"input-select",class:{"input-select--contrasted":t.current}},[a("div",{staticClass:"input-select__option input-select__option--current",class:{"input-select__option--contrasted":t.current},on:{click:function(e){t.expanded=!t.expanded}}},[t.current?a("span",[t._v(" "+t._s(t.mask(t.current))+" ")]):a("span",[t._v(" "+t._s("Select an option")+" ")]),a("icon-expand",{staticClass:"input-select__icon",class:{"input-select__icon--expanded":t.expanded}})],1),a("transition",{attrs:{name:"input-select__options-wrapper--is-fading"}},[t.expanded?a("div",{staticClass:"input-select__options-wrapper",class:{"input-select__options-wrapper--contrasted":t.current}},[a("ul",{staticClass:"input-select__options"},[a("li",{staticClass:"input-select__option",class:{"input-select__option--contrasted":t.current},domProps:{textContent:t._s("Select an option")},on:{click:function(e){return t.choose("")}}}),t._l(t.options,(function(e,s){return a("li",{key:s,staticClass:"input-select__option",class:{"input-select__option--contrasted":t.current},on:{click:function(a){t.choose(t.getValue(e))}}},[t._v(" "+t._s(t.getText(e))+" ")])}))],2)]):t._e()])],1)])},Mt=[],Tt=a("b967"),$t=a.n(Tt),zt={data(){return{expanded:!1,label:this.description.label,options:this.description.options}},props:{path:{},value:{},description:{}},computed:{current:{get(){return this.value||null},cache:!1}},methods:{get:r.a,mask(t){const e=this.options.find(e=>e.value===t||e===t);return this.getText(e)},getValue(t){return t.value||t},getText(t){return t.text||t},choose(t){this.expanded=!this.expanded,this.$emit("change",{path:this.path,value:t})}},components:{iconExpand:$t.a}},Nt=zt,Ft=(a("b4b6"),Object(z["a"])(Nt,It,Mt,!1,null,"6b92807e",null)),Rt=Ft.exports,Ht=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("label",{staticClass:"input-tick__wrapper"},[a("input",{staticClass:"input-tick",attrs:{type:"checkbox"},domProps:{checked:t.checked},on:{change:t.update}}),a("div",{staticClass:"input-tick__icon-wrapper",class:{"input-tick__icon-wrapper--checked":t.checked}},[a("icon-check",{staticClass:"input-tick__icon",class:{"input-tick__icon--checked":t.checked}})],1),this.labelValue?a("div",{staticClass:"input-tick__label"},[a("h2",{staticClass:"input-tick__headline"},[a("span",{domProps:{textContent:t._s(this.labelValue)}})])]):t._e()])},Ut=[],Bt=a("b934"),Lt=a.n(Bt),Kt={props:["path","value","description","label"],methods:{update(){this.checked=!this.checked,this.$emit("change",{path:this.path,value:this.checked})}},data(){return{checked:this.value,labelValue:this.label||this.description.label}},components:{iconCheck:Lt.a}},Gt=Kt,Jt=(a("551a"),Object(z["a"])(Gt,Ht,Ut,!1,null,"4e972b3c",null)),Wt=Jt.exports,Yt=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"input-checkbox"},[t.label?a("div",{staticClass:"input-checkbox__description"},[a("label",{staticClass:"input-checkbox__label",domProps:{textContent:t._s(t.label)}})]):t._e(),a("div",{staticClass:"input-checkbox__options"},t._l(t.options,(function(e,s){return a("view-tick",{key:t.getValue(e),staticClass:"input-checkbox__option",attrs:{value:t.status[s],path:s,label:t.getText(e)},on:{change:function(e){return t.update(s)}}})})),1)])},qt=[],Qt={data(){return{label:this.description.label,options:this.description.options}},props:{value:{},path:{},description:{}},computed:{current(){return this.value||[]},status(){return this.options.map(t=>m()(this.current,this.getValue(t)))}},methods:{set:c.a,includes:m.a,compact:p.a,getValue(t){return t.value||t},getText(t){return t.text||t},update(t){const e=[...this.status];e[t]=!e[t],this.$emit("change",{path:this.path,value:p()(e.map((t,e)=>t?this.getValue(this.options[e]):null))})}},components:{viewTick:Wt}},Xt=Qt,Zt=(a("69c2"),Object(z["a"])(Xt,Yt,qt,!1,null,"021a2e6b",null)),te=Zt.exports,ee=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"input-counter__container"},[t.label?a("div",{staticClass:"input-counter__description"},[a("label",{staticClass:"input-counter__label",domProps:{textContent:t._s(t.label)}})]):t._e(),a("div",{staticClass:"input-counter__wrapper"},[a("input",{staticClass:"input-counter",attrs:{type:"text",disabled:"disabled"},domProps:{value:t.count}}),a("div",{staticClass:"input-counter__handles"},[a("div",{staticClass:"input-counter__handle",on:{click:t.add}},[a("div",{staticClass:"input-counter__icon"},[t._v("+")])]),a("div",{staticClass:"input-counter__handle",on:{click:t.subtract}},[a("div",{staticClass:"input-counter__icon"},[t._v("–")])])])])])},ae=[],se={props:["path","value","description"],data(){return{count:0,label:this.description.label,min:this.description.min,max:this.description.max}},created(){this.count=this.value,this.countthis.min},smallerThanMax(){return!this.max||this.count0&&this.biggerThanMin&&(this.count-=1,this.update())},update(){this.$emit("change",{path:this.path,value:this.count})}}},ie=se,ne=(a("db34"),Object(z["a"])(ie,ee,ae,!1,null,"68d18439",null)),re=ne.exports,oe=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"input-datetime__wrapper"},[t.label?a("div",{staticClass:"input-datetime__description"},[a("label",{staticClass:"input-datetime__label",domProps:{textContent:t._s(t.label)}})]):t._e(),a("div",{staticClass:"input-datetime"},[a("datetime",{attrs:{"min-datetime":t.min,"max-datetime":t.max,type:"date",phrases:t.phrases},on:{input:t.update},model:{value:t.current,callback:function(e){t.current=e},expression:"current"}}),a("datetime",{attrs:{"min-datetime":t.min,"max-datetime":t.max,type:"time",phrases:t.phrases,"minute-step":5},on:{input:t.update},model:{value:t.current,callback:function(e){t.current=e},expression:"current"}})],1)])},ce=[],le=a("c1df"),ue=a.n(le),de=a("859b"),pe=(a("d355"),{data(){return{current:"",phrases:{ok:"Confirm",cancel:"Cancel"},label:this.description.label,min:this.description.min,max:this.description.max}},created(){this.current=this.stringify(u()(this.dateFormat))},props:["path","value","description"],computed:{dateFormat(){if("datetime"!==this.description.view)return null;let t=u()(this.value);return"string"===typeof this.value&&(t=Date(t)),this.value.seconds&&(t=t.toDate()),t}},methods:{get:r.a,stringify(t){return t.toISOString()},update(t){t&&this.$emit("change",{path:this.path,value:ue()(t).toDate()})}},components:{Datetime:de["Datetime"]}}),he=pe,me=(a("b563"),Object(z["a"])(he,oe,ce,!1,null,null,null)),ve=me.exports,fe=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"input-radio"},[t.label?a("div",{staticClass:"input-radio__description"},[a("label",{staticClass:"input-radio__label",domProps:{textContent:t._s(t.label)}})]):t._e(),a("div",{staticClass:"input-radio__options"},t._l(t.options,(function(e,s){return a("div",{key:s,staticClass:"input-radio__option"},[a("label",{staticClass:"input-radio__option-label"},[a("div",{staticClass:"input-radio__radio",class:{"input-radio__radio--checked":t.getValue(e)===t.current}}),a("input",{staticClass:"input-radio__input",attrs:{type:"radio"},domProps:{value:t.getValue(e),checked:t.getValue(e)===t.current},on:{change:t.update}}),t._v(" "+t._s(t.getText(e))+" ")])])})),0)])},be=[],ge={data(){return{current:this.value,label:this.description.label,options:this.description.options}},props:{value:{},path:{},description:{}},mounted(){this.current=this.value},watch:{value:{handler(){this.current=this.value},deep:!0}},methods:{get:r.a,getValue(t){return t.value||t},getText(t){return t.text||t},update(t){this.current=t.target.value,this.$emit("change",{path:this.path,value:this.current})}}},_e=ge,we=(a("2855"),Object(z["a"])(_e,fe,be,!1,null,"8de7aae4",null)),Ce=we.exports,ye={name:"ddFormView",props:["descriptions","data","path","functions","views","lang"],data(){return{hover:!1,hoverTimeout:null,hoverProcessing:!1,types:{..._},dataValue:this.data,allViews:{text:lt,upload:Ct,area:Dt,select:Rt,tick:Wt,checkbox:te,counter:re,datetime:ve,radio:Ce,"group.headline":F,"collection.button-add":K,"collection.headline":F,"collection.button-remove":Q,"collection.button-drag":st,...this.views},viewKeys:[],draggableOptions:{draggable:".view__container",filter:"input",preventOnFilter:!1,animation:0},elementStyles:{hidden:{visibility:"hidden",opacity:"0"},none:{}}}},created(){f()(this.data)&&this.update({path:this.path,value:w[this.description.view]}),this.isLeaf||this.generateKeys(this.isGroup?this.groupNodes:this.dataValue),this.isGroup&&this.mergeAppend(),this.isDatetime&&this.purifyDatetime()},computed:{isRoot(){return!this.path},descriptionPath(){let t=null;return this.findFirstValidDescriptionPath(e=>{t=e}),t},description(){const t=this.descriptionPath?u()(this.descriptions[this.descriptionPath]):{view:"group"};return V()(t,(e,a)=>{t[a]=this.getValue(e)}),t},isGroup(){return this.description&&this.description.view===_.GROUP},isDatetime(){return this.description&&this.description.view===_.DATETIME},isCollection(){return this.description&&this.description.view===_.COLLECTION},isLeaf(){return this.description&&this.description.view!==_.GROUP&&this.description.view!==_.COLLECTION},isRemovable(){return!!this.$slots["remove-button"]},isHidden(){return this.description.hidden},isDraggable(){return!!this.description.draggable||f()(this.description.draggable)},isDeletable(){return!!this.description.deletable||f()(this.description.deletable)},isAddable(){return!!this.description.addable||f()(this.description.addable)},isNextChildDescribed(){return!!this.descriptionForNextChild(this.path,this.dataValue.length)},pathNodes(){return this.splitPath(this.path||"")},descriptionNodesMap(){const t={};return Object.keys(this.descriptions).forEach(e=>{t[e]=this.splitPath(e)}),t},groupNodes(){const t=[];return Object.keys(this.descriptions).forEach(e=>{if(this.isRoot){const a=this.splitPath(e)[0];t.push(a)}else{const a=p()(e.split(this.descriptionPath+"."))[0],s=this.splitPath(a)[0];e!==this.descriptionPath&&e.startsWith(this.descriptionPath)&&t.push(s)}}),A()(t)},groupWrappers(){const t=this.groupNodes.map(t=>this.findFirstDescriptionForNode(t)),e=t.map(t=>t?t.wrapper:"").filter(t=>t);return[...A()(e),null]}},methods:{get:r.a,set:c.a,unset:j.a,clone:u.a,compact:p.a,isUndefined:f.a,forEach:V.a,uuid:O.a,splitPath(t){return p()(t.split(/[.[\]]/))},validate(t,e){if(t.length!==e.length)return!1;let a=!0;return t.forEach((t,s)=>{const i=e[s];i!==t&&"*"!==i&&(a=!1)}),a},purifyDatetime(){let t=u()(this.dataValue);"string"===typeof this.dataValue&&(t=Date(t)),this.dataValue.seconds&&(t=t.toDate()),this.dataValue=t},mergeAppend(){this.description.append&&this.update({path:this.path,value:{...this.description.append,...this.dataValue}})},isViewInWrapper(t,e){const a=this.findFirstDescriptionForNode(t),s=a?a.wrapper:null;return s===e||!e&&!s},findFirstValidDescriptionPath(t,e){Object.keys(this.descriptionNodesMap).forEach(a=>{const s=this.descriptionNodesMap[a];this.validate(e?this.splitPath(e):this.pathNodes,s)&&t(a)})},findFirstDescriptionForNode(t){const e=this.isRoot?"":this.path+".",a=`${e}${t}`;let s=null;return this.findFirstValidDescriptionPath(t=>{s=t},a),this.descriptions[s]},groupNodePath(t){return this.isRoot?t:`${this.path}.${t}`},collectionNodePath(t){return`${this.path}[${t}]`},descriptionForNextChild(t,e){let a=null;const s=`${t}[${e}]`;return this.findFirstValidDescriptionPath(t=>{t&&(a={...this.descriptions[t],path:t})},s),a},remove(t,e){const a=this.dataValue.filter((t,a)=>a!==e);this.update({path:t,value:a}),this.removeKey(e)},add(t,e){const a=u()(this.dataValue);e&&(a.push(this.chunkForPath(t,e)),this.addKey()),this.update({path:t,value:a})},addKey(){this.viewKeys.push(O.a.generate())},removeKey(t){this.viewKeys=this.viewKeys.filter((e,a)=>a!==t)},chunkForPath(t,e){const a=e.view;let s=u()(w[e.view]);return a===_.GROUP&&(s=u()({}),Object.keys(this.descriptions).forEach(t=>{const a=p()(t.split(e.path+"."))[0],i=this.descriptions[t];if(t.startsWith(e.path)&&!m()(a,"[")){const t=u()(w[i.view]);c()(s,a,f()(t)?null:t)}})),s},getValue(t){let e=t;if("string"===typeof t&&this.functions){const a=this.getStringVariables(t);this.functions[t]?e=this.functions[t]({path:this.path,value:this.dataValue}):a&&a.forEach(t=>{if(this.functions[t]){const a=this.functions[t]({path:this.path,value:this.dataValue});e=this.replaceAll(e,`{${t}}`,a)}})}return e},getStringVariables(t){const e=[],a=/{([^}]+)}/g;let s;while(s=a.exec(t))e.push(s[1]);return e},replaceAll(t,e,a){return t.replace(new RegExp(e,"g"),a)},generateKeys(t){const e=[];t.forEach((t,a)=>{e[a]=O.a.generate()}),this.viewKeys=[...e]},updateCollection(){this.update({path:this.path,value:this.dataValue}),this.generateKeys(this.dataValue)},update({path:t,value:e}){this.setLocalData({path:t,value:e}),this.$emit("change",{path:t,value:e})},setLocalData({path:t,value:e}){if(t===this.path)this.dataValue=u()(e);else{const a=p()(t.split(this.path))[0];c()(this.dataValue,a,e),j()(this.dataValue,"")}},easeHover(t){this.hoverTimeout&&clearTimeout(this.hoverTimeout),t?(this.hover=!0,this.hoverProcessing=!1):(this.hoverProcessing=!0,this.hoverTimeout=setTimeout(()=>{this.hover=!1,this.hoverProcessing=!1},2e3))}},components:{draggable:D.a,headline:F,buttonAdd:K,buttonRemove:Q,buttonDrag:st,viewText:lt,viewUpload:Ct,viewArea:Dt,viewSelect:Rt,viewTick:Wt,viewCheckbox:te,viewCounter:re,viewDatetime:ve,viewRadio:Ce}},xe=ye,je=Object(z["a"])(xe,C,y,!1,null,null,null),ke=je.exports,Ae=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("button",{staticClass:"button"},[t._v(" "+t._s(t.text)+" ")])},Pe=[],Ve={props:["text"]},Se=Ve,Oe=(a("1d8f"),Object(z["a"])(Se,Ae,Pe,!1,null,"7e331ab4",null)),Ee=Oe.exports,De={props:["descriptions","data","functions","views","lang"],data(){return{values:null,langValue:{add:"+ Add",remove:"–",drag:"≡",save:"Save",...this.lang}}},created(){this.values=u()(this.data)||w[this.viewTypes.GROUP]},computed:{submitButtonComponent(){return this.views&&this.views["group.button-submit"]||"button-submit"}},methods:{get:r.a,set:c.a,compact:p.a,clone:u.a,includes:m.a,isUndefined:f.a,merge:g.a,update({path:t,value:e}){c()(this.data,t,e),this.$emit("change",{path:t,value:e,data:this.data})},submit(){this.$emit("submit",{data:this.data})}},components:{ddFormView:ke,buttonSubmit:Ee}},Ie=De,Me=(a("cb20"),Object(z["a"])(Ie,s,i,!1,null,null,null));e["a"]=Me.exports},4678:function(t,e,a){var s={"./af":"2bfb","./af.js":"2bfb","./ar":"8e73","./ar-dz":"a356","./ar-dz.js":"a356","./ar-kw":"423e","./ar-kw.js":"423e","./ar-ly":"1cfd","./ar-ly.js":"1cfd","./ar-ma":"0a84","./ar-ma.js":"0a84","./ar-sa":"8230","./ar-sa.js":"8230","./ar-tn":"6d83","./ar-tn.js":"6d83","./ar.js":"8e73","./az":"485c","./az.js":"485c","./be":"1fc1","./be.js":"1fc1","./bg":"84aa","./bg.js":"84aa","./bm":"a7fa","./bm.js":"a7fa","./bn":"9043","./bn.js":"9043","./bo":"d26a","./bo.js":"d26a","./br":"6887","./br.js":"6887","./bs":"2554","./bs.js":"2554","./ca":"d716","./ca.js":"d716","./cs":"3c0d","./cs.js":"3c0d","./cv":"03ec","./cv.js":"03ec","./cy":"9797","./cy.js":"9797","./da":"0f14","./da.js":"0f14","./de":"b469","./de-at":"b3eb","./de-at.js":"b3eb","./de-ch":"bb71","./de-ch.js":"bb71","./de.js":"b469","./dv":"598a","./dv.js":"598a","./el":"8d47","./el.js":"8d47","./en-au":"0e6b","./en-au.js":"0e6b","./en-ca":"3886","./en-ca.js":"3886","./en-gb":"39a6","./en-gb.js":"39a6","./en-ie":"e1d3","./en-ie.js":"e1d3","./en-il":"7333","./en-il.js":"7333","./en-in":"ec2e","./en-in.js":"ec2e","./en-nz":"6f50","./en-nz.js":"6f50","./en-sg":"b7e9","./en-sg.js":"b7e9","./eo":"65db","./eo.js":"65db","./es":"898b","./es-do":"0a3c","./es-do.js":"0a3c","./es-us":"55c9","./es-us.js":"55c9","./es.js":"898b","./et":"ec18","./et.js":"ec18","./eu":"0ff2","./eu.js":"0ff2","./fa":"8df4","./fa.js":"8df4","./fi":"81e9","./fi.js":"81e9","./fil":"d69a","./fil.js":"d69a","./fo":"0721","./fo.js":"0721","./fr":"9f26","./fr-ca":"d9f8","./fr-ca.js":"d9f8","./fr-ch":"0e49","./fr-ch.js":"0e49","./fr.js":"9f26","./fy":"7118","./fy.js":"7118","./ga":"5120","./ga.js":"5120","./gd":"f6b4","./gd.js":"f6b4","./gl":"8840","./gl.js":"8840","./gom-deva":"aaf2","./gom-deva.js":"aaf2","./gom-latn":"0caa","./gom-latn.js":"0caa","./gu":"e0c5","./gu.js":"e0c5","./he":"c7aa","./he.js":"c7aa","./hi":"dc4d","./hi.js":"dc4d","./hr":"4ba9","./hr.js":"4ba9","./hu":"5b14","./hu.js":"5b14","./hy-am":"d6b6","./hy-am.js":"d6b6","./id":"5038","./id.js":"5038","./is":"0558","./is.js":"0558","./it":"6e98","./it-ch":"6f12","./it-ch.js":"6f12","./it.js":"6e98","./ja":"079e","./ja.js":"079e","./jv":"b540","./jv.js":"b540","./ka":"201b","./ka.js":"201b","./kk":"6d79","./kk.js":"6d79","./km":"e81d","./km.js":"e81d","./kn":"3e92","./kn.js":"3e92","./ko":"22f8","./ko.js":"22f8","./ku":"2421","./ku.js":"2421","./ky":"9609","./ky.js":"9609","./lb":"440c","./lb.js":"440c","./lo":"b29d","./lo.js":"b29d","./lt":"26f9","./lt.js":"26f9","./lv":"b97c","./lv.js":"b97c","./me":"293c","./me.js":"293c","./mi":"688b","./mi.js":"688b","./mk":"6909","./mk.js":"6909","./ml":"02fb","./ml.js":"02fb","./mn":"958b","./mn.js":"958b","./mr":"39bd","./mr.js":"39bd","./ms":"ebe4","./ms-my":"6403","./ms-my.js":"6403","./ms.js":"ebe4","./mt":"1b45","./mt.js":"1b45","./my":"8689","./my.js":"8689","./nb":"6ce3","./nb.js":"6ce3","./ne":"3a39","./ne.js":"3a39","./nl":"facd","./nl-be":"db29","./nl-be.js":"db29","./nl.js":"facd","./nn":"b84c","./nn.js":"b84c","./oc-lnc":"167b","./oc-lnc.js":"167b","./pa-in":"f3ff","./pa-in.js":"f3ff","./pl":"8d57","./pl.js":"8d57","./pt":"f260","./pt-br":"d2d4","./pt-br.js":"d2d4","./pt.js":"f260","./ro":"972c","./ro.js":"972c","./ru":"957c","./ru.js":"957c","./sd":"6784","./sd.js":"6784","./se":"ffff","./se.js":"ffff","./si":"eda5","./si.js":"eda5","./sk":"7be6","./sk.js":"7be6","./sl":"8155","./sl.js":"8155","./sq":"c8f3","./sq.js":"c8f3","./sr":"cf1e","./sr-cyrl":"13e9","./sr-cyrl.js":"13e9","./sr.js":"cf1e","./ss":"52bd","./ss.js":"52bd","./sv":"5fbd","./sv.js":"5fbd","./sw":"74dc","./sw.js":"74dc","./ta":"3de5","./ta.js":"3de5","./te":"5cbb","./te.js":"5cbb","./tet":"576c","./tet.js":"576c","./tg":"3b1b","./tg.js":"3b1b","./th":"10e8","./th.js":"10e8","./tk":"5aff","./tk.js":"5aff","./tl-ph":"0f38","./tl-ph.js":"0f38","./tlh":"cf75","./tlh.js":"cf75","./tr":"0e81","./tr.js":"0e81","./tzl":"cf51","./tzl.js":"cf51","./tzm":"c109","./tzm-latn":"b53d","./tzm-latn.js":"b53d","./tzm.js":"c109","./ug-cn":"6117","./ug-cn.js":"6117","./uk":"ada2","./uk.js":"ada2","./ur":"5294","./ur.js":"5294","./uz":"2e8c","./uz-latn":"010e","./uz-latn.js":"010e","./uz.js":"2e8c","./vi":"2921","./vi.js":"2921","./x-pseudo":"fd7e","./x-pseudo.js":"fd7e","./yo":"7f33","./yo.js":"7f33","./zh-cn":"5c3a","./zh-cn.js":"5c3a","./zh-hk":"49ab","./zh-hk.js":"49ab","./zh-mo":"3a6c","./zh-mo.js":"3a6c","./zh-tw":"90ea","./zh-tw.js":"90ea"};function i(t){var e=n(t);return a(e)}function n(t){if(!a.o(s,t)){var e=new Error("Cannot find module '"+t+"'");throw e.code="MODULE_NOT_FOUND",e}return s[t]}i.keys=function(){return Object.keys(s)},i.resolve=n,t.exports=i,i.id="4678"},"536a":function(t,e,a){},"53d3":function(t,e,a){},"551a":function(t,e,a){"use strict";var s=a("ea3c"),i=a.n(s);i.a},"5d17":function(t,e,a){"use strict";var s=a("0cc8"),i=a.n(s);i.a},"69c2":function(t,e,a){"use strict";var s=a("e8bb"),i=a.n(s);i.a},"6faa":function(t){t.exports=JSON.parse('{"public":{"view":"tick","label":"Make your profile public"},"name":{"view":"text","label":"Full name"},"bio":{"view":"area","html":true,"label":"Short bio"},"avatar":{"view":"upload","label":"Profile photo (not uploading in demo)"},"milestones":{"view":"collection","label":"Milestones"},"milestones[*]":{"view":"group"},"milestones[*].title":{"view":"text","label":"Milestone title"},"milestones[*].date":{"view":"datetime","label":"Date"},"milestones[*].importance":{"view":"counter","label":"Importance (0 – 10)","min":1,"max":10},"education":{"view":"group","label":"Education"},"education.status":{"view":"radio","label":"Current status","options":[{"text":"I\'m studying","value":"student"},{"text":"I\'m employed","value":"empolyed"},{"text":"I\'m a freelancer","value":"freelance"}]},"education.reached":{"view":"select","label":"Highest level of education reached","options":["Early childhood education (‘less than primary’ for educational attainment)","Primary education","Lower secondary education","Upper secondary education","Post-secondary non-tertiary education","Short-cycle tertiary education","Bachelor’s or equivalent level","Master’s or equivalent level","Doctoral or equivalent level"]},"education.certificates":{"view":"checkbox","label":"Certificates","options":["Certified Information Security Manager (CISM)","Certified Ethical Hacker (CEH)","Certified Information Systems Security Professional (CISSP)","Certified in Risk and Information Systems Control (CRISC)","Certified Information Systems Auditor (CISA)","Google Certified Professional Cloud Architect"]}}')},8774:function(t,e,a){},"8c17":function(t,e,a){"use strict";var s=a("a1e6"),i=a.n(s);i.a},"8fa5":function(t,e,a){"use strict";var s=a("0c33"),i=a.n(s);i.a},"91fa":function(t){t.exports=JSON.parse('{"fullname":{"view":"text","label":"Full name"},"username":{"view":"generator","header":"Generate random username"},"consent":{"view":"tick","label":"I aggree with terms & conditions"}}')},9409:function(t){t.exports=JSON.parse('{"general":{"view":"group","label":"General information","class":["row","general"],"wrapper":["row--boxed","col--1-3"]},"general.public":{"view":"tick","label":"Make your profile public"},"general.name":{"view":"text","label":"Full name"},"general.bio":{"view":"area","html":true,"label":"Short bio"},"general.avatar":{"view":"upload","label":"Profile photo (not uploading in demo)"},"education":{"view":"group","label":"Education","wrapper":["row--boxed","col--2-3"]},"education.status":{"view":"radio","label":"Current status","options":[{"text":"I\'m studying","value":"student"},{"text":"I\'m employed","value":"empolyed"},{"text":"I\'m a freelancer","value":"freelance"}]},"education.reached":{"view":"select","label":"Highest level of education reached","options":["Early childhood education (‘less than primary’ for educational attainment)","Primary education","Lower secondary education","Upper secondary education","Post-secondary non-tertiary education","Short-cycle tertiary education","Bachelor’s or equivalent level","Master’s or equivalent level","Doctoral or equivalent level"]},"education.certificates":{"view":"checkbox","label":"Certificates","options":["Certified Information Security Manager (CISM)","Certified Ethical Hacker (CEH)","Certified Information Systems Security Professional (CISSP)","Certified in Risk and Information Systems Control (CRISC)","Certified Information Systems Auditor (CISA)","Google Certified Professional Cloud Architect"]},"milestones":{"view":"collection","label":"Milestones","wrapper":["col--2-3","row--boxed","milestones"]},"milestones[*]":{"view":"group"},"milestones[*].title":{"view":"text","label":"Milestone title"},"milestones[*].date":{"view":"datetime","label":"Date"},"milestones[*].importance":{"view":"counter","label":"Importance (0 – 10)","min":1,"max":10}}')},"946f":function(t,e,a){},a1e6:function(t,e,a){},a2a1:function(t,e,a){},a470:function(t,e,a){},a825:function(t,e){t.exports={functional:!0,render(t,e){const{_c:a,_v:s,data:i,children:n=[]}=e,{class:r,staticClass:o,style:c,staticStyle:l,attrs:u={},...d}=i;return a("svg",{class:[r,o],style:[c,l],attrs:Object.assign({version:"1.2",baseProfile:"tiny",xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 19 17"},u),...d},n.concat([a("g",{attrs:{transform:"translate(-409 -386)"}},[a("path",{attrs:{fill:"#57D364",d:"M422.4 398.9c-.1-.4.1-.8.5-.9 1.9-.6 2.8-2.1 2.8-4.5.6-2.7-1.2-5.4-3.9-5.9-2.7-.6-5.4 1.2-5.9 3.9-.1.4-.1.8-.1 1.1l-.1.8-.8-.2c-1.4-.4-2.9.4-3.3 1.8-.1.2-.1.5-.1.8 0 1.5 1.2 2.7 2.7 2.7h.1c.4 0 .7.3.8.7s-.3.7-.7.8h-.2c-2.3 0-4.2-1.9-4.2-4.2 0-2.3 1.9-4.2 4.2-4.2h.4c1.1-3.4 4.7-5.3 8.1-4.2 2.6.9 4.5 3.3 4.5 6.1 0 3.1-1.3 5.1-3.8 5.9-.5.1-.9-.1-1-.5zm-4.3-4.8c.3-.3.7-.3 1 0l2 2c.3.3.3.7 0 1-.1.1-.3.2-.5.2s-.4-.1-.5-.2l-.8-.8v4.6c0 .4-.2.8-.6.8-.4 0-.8-.2-.8-.6v-4.8l-.8.8c-.3.3-.7.3-1 0-.3-.3-.3-.7 0-1l2-2z"}}),a("image",{attrs:{width:"19",height:"15","xlink:href":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAPCAYAAAAGRPQsAAAACXBIWXMAAAsSAAALEgHS3X78AAAA GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABVJREFUeNpiYBgFo2AUjIIBAwAB BgAEgwABenzI8QAAAABJRU5ErkJggg==",transform:"translate(409 387)"}}),a("path",{attrs:{fill:"#FFF",d:"M418.6 402c-.5 0-.9-.4-1-.9v-4.2l-.3.3c-.2.2-.4.3-.7.3-.2 0-.5-.1-.7-.3-.4-.4-.4-1 0-1.4l1.9-1.9v-.5l.3.3c.4-.2.9-.2 1.2.2l2 2c.2.2.3.4.3.7 0 .3-.1.5-.3.7-.2.2-.4.3-.7.3-.3 0-.5-.1-.7-.3l-.3-.3v4c.1.5-.3 1-.9 1.1 0-.1 0-.1-.1-.1zm-.5-6.2v5.3c0 .3.3.4.5.4.3 0 .5-.3.4-.5v-5.2l1.2 1.2c.1.1.2.1.3.1.1 0 .3-.1.3-.1.2-.2.2-.5 0-.7l-2-2c-.2-.2-.5-.2-.7 0l-2 2c-.2.2-.2.5 0 .7.1.1.2.1.3.1.1 0 .2-.1.3-.1l1.4-1.2zm-3.9 4.3c-2.4 0-4.4-2-4.4-4.4 0-1.2.5-2.3 1.3-3.1s1.9-1.3 3.1-1.3h.2c.6-1.6 1.7-2.9 3.3-3.7 1.6-.8 3.4-1 5.1-.4 2.8.9 4.6 3.4 4.6 6.3 0 3.2-1.4 5.3-4 6.1-.5.2-1.1-.1-1.2-.6-.2-.5.1-1.1.6-1.2 1.8-.6 2.6-2 2.6-4.3.3-1.3 0-2.6-.7-3.6s-1.8-1.8-3-2.1c-2.6-.5-5.1 1.1-5.6 3.7-.1.4-.1.7-.1 1.1l-.2 1.1-1-.3c-.6-.2-1.3-.1-1.9.2-.6.3-1 .8-1.2 1.5-.1.2-.1.5-.1.7 0 1.4 1.1 2.5 2.4 2.5h.1c.3 0 .5.1.7.2s.3.4.3.7c0 .5-.4 1-.9 1v-.1zm-.1-8.3c-1.1 0-2 .4-2.8 1.1-.7.7-1.1 1.7-1.1 2.8 0 2.2 1.8 3.9 3.9 3.9h.2c.3 0 .5-.2.4-.5 0-.1-.1-.2-.2-.3-.1-.1-.2-.1-.3-.1h-.1c-1.6 0-3-1.3-3-2.9 0-.3 0-.6.1-.8.2-.8.7-1.4 1.4-1.8.7-.4 1.5-.5 2.2-.3l.5.1.1-.5c0-.4 0-.8.1-1.1.3-1.6 1.4-2.9 2.7-3.6-.2.1-.3.1-.5.2-1.5.8-2.6 2-3.1 3.6l-.1.2h-.2-.2zm8.5 7c.1.3.3.4.6.3 2.4-.8 3.7-2.7 3.7-5.7 0-2.1-1.1-4.1-2.8-5.2.4.4.8.8 1.2 1.3.8 1.2 1 2.6.7 4 0 2.5-1 4.1-3 4.7-.3.1-.5.4-.4.6z"}})])]))}}},ae37:function(t,e,a){},af8f:function(t,e,a){"use strict";var s=a("e847"),i=a.n(s);i.a},b4b6:function(t,e,a){"use strict";var s=a("c39c"),i=a.n(s);i.a},b563:function(t,e,a){"use strict";var s=a("a2a1"),i=a.n(s);i.a},b635:function(t,e,a){"use strict";(function(t){var s=a("3f4d");function i(t){i.installed||(i.installed=!0,t.component("dd-form",s["a"]))}const n={install:i};let r=null;"undefined"!==typeof window?r=window.Vue:"undefined"!==typeof t&&(r=t.vue),r&&r.use(n),s["a"].install=i,e["a"]=s["a"]}).call(this,a("c8ba"))},b934:function(t,e){t.exports={functional:!0,render(t,e){const{_c:a,_v:s,data:i,children:n=[]}=e,{class:r,staticClass:o,style:c,staticStyle:l,attrs:u={},...d}=i;return a("svg",{class:[r,o],style:[c,l],attrs:Object.assign({version:"1.2",baseProfile:"tiny",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 45.4 32.2"},u),...d},n.concat([a("path",{attrs:{d:"M14.7 32.2L0 17.5 1.4 16l13.3 13.3L44 0l1.4 1.5z"}})]))}}},b967:function(t,e){t.exports={functional:!0,render(t,e){const{_c:a,_v:s,data:i,children:n=[]}=e,{class:r,staticClass:o,style:c,staticStyle:l,attrs:u={},...d}=i;return a("svg",{class:[r,o],style:[c,l],attrs:Object.assign({xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",width:"10",height:"5"},u),...d},n.concat([a("image",{attrs:{width:"10",height:"5","xlink:href":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAFCAYAAAB8ZH1oAAAAPElEQVQYV2O0sLBo+PfvXz0DHsDExNTICJLHpxik6MSJEw1ghbgUwxSB5OEK0RUjK8JQCFMMokHWITsbAK//IS7o+E4nAAAAAElFTkSuQmCC"}})]))}}},bea3:function(t,e,a){t.exports=a.p+"img/logo-vue.82b9c7a5.png"},c205:function(t,e,a){"use strict";var s=a("d088"),i=a.n(s);i.a},c39c:function(t,e,a){},cb20:function(t,e,a){"use strict";var s=a("946f"),i=a.n(s);i.a},ce7a:function(t,e,a){},d088:function(t,e,a){},d16b:function(t,e,a){"use strict";var s=a("ce7a"),i=a.n(s);i.a},d90a:function(t,e,a){},db34:function(t,e,a){"use strict";var s=a("f8c7"),i=a.n(s);i.a},e58e:function(t,e,a){"use strict";a.r(e);a("e260"),a("e6cf"),a("cca6"),a("a79d");var s=a("2b0e"),i=function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",{attrs:{id:"app"}},[s("div",{staticClass:"header"},[s("img",{staticClass:"header__logo",attrs:{alt:"Vue logo",src:a("bea3")}}),t._m(0),s("div",{staticClass:"header__spacer"}),s("a",{staticClass:"header__button-wrapper",attrs:{href:"https://github.com/marekmensa/vue-dd-form",target:"_blank"}},[s("button",{staticClass:"header__button"},[t._v("View code "),s("GithubIcon",{staticClass:"header__button-icon"})],1)])]),s("Home")],1)},n=[function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("h1",{staticClass:"header__title"},[a("strong",[t._v("vue-dd-form")]),t._v(" demo")])}],r=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"home"},[a("ul",{staticClass:"switcher"},[a("li",[a("a",{staticClass:"switcher__item",class:{"switcher__item--active":t.active===t.types.BASIC},on:{click:function(e){return t.select(t.types.BASIC)}}},[t._v("Basic")])]),a("li",[a("a",{staticClass:"switcher__item",class:{"switcher__item--active":t.active===t.types.ADVANCED},on:{click:function(e){return t.select(t.types.ADVANCED)}}},[t._v("Advanced")])]),a("li",[a("a",{staticClass:"switcher__item",class:{"switcher__item--active":t.active===t.types.DYNAMIC},on:{click:function(e){return t.select(t.types.DYNAMIC)}}},[t._v("Dynamic values")])]),a("li",[a("a",{staticClass:"switcher__item",class:{"switcher__item--active":t.active===t.types.CUSTOM},on:{click:function(e){return t.select(t.types.CUSTOM)}}},[t._v("Custom views")])]),a("li",[a("a",{staticClass:"switcher__item",class:{"switcher__item--active":t.active===t.types.WRAPPERS},on:{click:function(e){return t.select(t.types.WRAPPERS)}}},[t._v("Wrappers (beta)")])])]),a("div",{staticClass:"preview-code"},[a("div",{staticClass:"preview-code__box"},[t._m(0),t.renderCode?a("vue-code-highlight",{attrs:{language:"js"}},[a("pre",[t._v(t._s(JSON.stringify(t.descriptions[t.active],null,4)))])]):t._e()],1),a("div",{staticClass:"preview-code__box"},[t._m(1),t.renderCode?a("vue-code-highlight",{attrs:{language:"js"}},[a("pre",[t._v(t._s(JSON.stringify(t.output[t.active],null,4)))])]):t._e()],1)]),a("div",{staticClass:"preview-form"},[t._m(2),t.renderForm&&t.active===t.types.BASIC?a("dd-form",{staticClass:"preview-form__interface preview-form__interface--basic",attrs:{descriptions:t.descriptions.basic,data:t.output.basic},on:{submit:t.submit,change:t.change}}):t.renderForm&&t.active===t.types.ADVANCED?a("dd-form",{staticClass:"preview-form__interface preview-form__interface--advanced",attrs:{descriptions:t.descriptions.advanced,data:t.output.advanced,lang:t.customLang},on:{submit:t.submit,change:t.change}}):t.renderForm&&t.active===t.types.DYNAMIC?a("dd-form",{staticClass:"preview-form__interface preview-form__interface--dynamic",attrs:{descriptions:t.descriptions.dynamic,data:t.output.dynamic,functions:t.functions},on:{submit:t.submit,change:t.change}}):t.renderForm&&t.active===t.types.CUSTOM?a("dd-form",{staticClass:"preview-form__interface preview-form__interface--custom",attrs:{descriptions:t.descriptions.custom,data:t.output.custom,views:t.customViews},on:{submit:t.submit,change:t.change}}):t.renderForm&&t.active===t.types.WRAPPERS?a("dd-form",{staticClass:"preview-form__interface preview-form__interface--wrappers",attrs:{descriptions:t.descriptions[t.active],data:t.output[t.active]},on:{submit:t.submit,change:t.change}}):t._e()],1),a("p",{staticClass:"copyright"},[t._v("© Designed & developed by Marek Mensa ")])])},o=[function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("h3",[a("span",{staticClass:"highlight"},[t._v("1.")]),t._v(" descriptions")])},function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("h3",[a("span",{staticClass:"highlight"},[t._v("2.")]),t._v(" data (changes in real-time)")])},function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("h3",[a("span",{staticClass:"highlight"},[t._v("3.")]),t._v(" form ")])}],c=(a("fb6a"),a("a9e3"),a("ac1f"),a("1276"),a("d36c")),l=a("c228"),u=a.n(l),d=(a("4357"),a("0439"),a("3ba4")),p=a("6faa"),h=a("33c0"),m=a("91fa"),v=a("9409"),f=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"input-text__wrapper"},[t.header?a("div",{staticClass:"input-text__description"},[a("label",{staticClass:"input-text__label",domProps:{textContent:t._s(t.header)}})]):t._e(),a("input",{staticClass:"input-text",attrs:{disabled:t.disabled},domProps:{value:t.value},on:{focus:t.generate,input:t.update}})])},b=[],g=(a("a4d3"),a("e01a"),a("4795"),{props:["path","value","description"],computed:{},data:function(){return{disabled:!1,header:this.description.header}},components:{},methods:{generate:function(){var t=this;this.disabled=!0,this.update({target:{value:null}},"Please wait..."),setTimeout((function(){var e=["Apple","Banana","The","Orange","House","Boat","Lake","Car","Andy"],a=Math.floor(Math.random()*e.length);t.update({target:{value:null}},e[a])}),500)},update:function(t,e){this.$emit("change",{path:this.path,value:t.target.value||e})}}}),_=g,w=(a("1504"),a("2877")),C=Object(w["a"])(_,f,b,!1,null,"480999da",null),y=C.exports,x={name:"Home",props:{},methods:{select:function(t){this.active=t,this.forceCodeRerender(),this.forceFormRerender()},submit:function(t){var e=t.data;this.output[this.active]=e,this.forceCodeRerender()},change:function(t){var e=t.path,a=t.data;this.output[this.active]=a,this.forceCodeRerender(),"limitLogins"==e&&this.forceFormRerender()},firstUpper:function(t){return t.charAt(0).toUpperCase()+t.slice(1)},forceCodeRerender:function(){var t=this;this.renderCode=!1,this.$nextTick((function(){t.renderCode=!0}))},forceFormRerender:function(){var t=this;this.renderForm=!1,this.$nextTick((function(){t.renderForm=!0}))},splitPath:function(t){return u()(t.split(/[.[\]]/))},userIndex:function(t){var e=t.path,a=Number(this.splitPath(e)[1]);return a+1},addable:function(){return!this.output.dynamic.users||this.output.dynamic.users.length<5},limitNotSelected:function(){return!1===this.output.dynamic.limitLogins},userTypes:function(){return["basic","anonymous","admin"]}},data:function(){return{types:{BASIC:"basic",ADVANCED:"advanced",DYNAMIC:"dynamic",CUSTOM:"custom",WRAPPERS:"wrappers"},active:"",customViews:{generator:y},output:{basic:{title:"Parasite (2019)",description:"Greed and class discrimination threaten the newly formed symbiotic relationship between the wealthy Park family and the destitute Kim clan.",genres:[],language:"Korean"},advanced:{},dynamic:{},custom:{},wrappers:{}},descriptions:{basic:d,advanced:p,dynamic:h,custom:m,wrappers:v},functions:{_addable:this.addable,_limitNotSelected:this.limitNotSelected,_userTypes:this.userTypes,_userIndex:this.userIndex},renderCode:!0,renderForm:!0,customLang:{save:"Continue",add:"+ Add a milestone"}}},components:{VueCodeHighlight:c["a"]},computed:{},created:function(){this.active=this.types.BASIC}},j=x,k=(a("09fc"),Object(w["a"])(j,r,o,!1,null,null,null)),A=k.exports,P=a("3c36"),V=a.n(P),S={name:"App",components:{Home:A,GithubIcon:V.a}},O=S,E=(a("af8f"),Object(w["a"])(O,i,n,!1,null,null,null)),D=E.exports,I=a("b635");s["a"].use(I["a"]),s["a"].config.productionTip=!1,new s["a"]({render:function(t){return t(D)}}).$mount("#app")},e847:function(t,e,a){},e8bb:function(t,e,a){},ea3c:function(t,e,a){},f8c7:function(t,e,a){},fdd7:function(t,e,a){"use strict";var s=a("ae37"),i=a.n(s);i.a}}); 2 | //# sourceMappingURL=app.b20c9a4b.js.map -------------------------------------------------------------------------------- /docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marekmensa/vue-dd-form/6ea1993194c2125ae2064b30a3117c1db47016da/docs/logo.png -------------------------------------------------------------------------------- /getting_started.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marekmensa/vue-dd-form/6ea1993194c2125ae2064b30a3117c1db47016da/getting_started.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-dd-form", 3 | "version": "1.0.21", 4 | "description": "", 5 | "main": "src/index.js", 6 | "author": "Marek Mensa", 7 | "repository": "https://github.com/marekmensa/vue-dd-form/", 8 | "bugs": "", 9 | "keywords": [ 10 | "vue-dd-form", 11 | "dd-form", 12 | "described-data", 13 | "json", 14 | "data", 15 | "form", 16 | "forms", 17 | "generator", 18 | "vue" 19 | ], 20 | "license": "MIT License", 21 | "scripts": { 22 | "serve": "vue-cli-service serve", 23 | "build": "webpack --config config/webpack.config.js", 24 | "build:docs": "vue-cli-service build", 25 | "lint": "vue-cli-service lint" 26 | }, 27 | "dependencies": { 28 | "axios": "^0.24.0", 29 | "core-js": "^3.6.5", 30 | "dompurify": "^2.3.3", 31 | "lodash": "^4.17.20", 32 | "luxon": "^2.1.1", 33 | "moment": "^2.27.0", 34 | "path": "^0.12.7", 35 | "shortid": "^2.2.15", 36 | "vue": "^2.6.11", 37 | "vue-code-highlight": "^0.7.5", 38 | "vue-datetime": "^1.0.0-beta.14", 39 | "vue2-editor": "^2.10.2", 40 | "vuedraggable": "^2.24.3", 41 | "vuex": "^3.5.1" 42 | }, 43 | "devDependencies": { 44 | "@vue/cli-plugin-babel": "^4.5.0", 45 | "@vue/cli-plugin-eslint": "^4.5.0", 46 | "@vue/cli-service": "^4.5.0", 47 | "@vue/eslint-config-airbnb": "^5.0.2", 48 | "babel-core": "^6.26.3", 49 | "babel-eslint": "^10.1.0", 50 | "babel-loader": "^8.1.0", 51 | "babel-preset-env": "^1.7.0", 52 | "cross-env": "^7.0.2", 53 | "css-loader": "^4.2.2", 54 | "eslint": "^6.7.2", 55 | "eslint-plugin-import": "^2.20.2", 56 | "eslint-plugin-vue": "^6.2.2", 57 | "file-loader": "^6.1.0", 58 | "node-sass": "^4.14.1", 59 | "sass-loader": "^8.0.2", 60 | "vue-loader": "^15.9.3", 61 | "vue-svg-loader": "^0.16.0", 62 | "vue-template-compiler": "^2.6.12", 63 | "webpack": "^4.44.1", 64 | "webpack-cli": "^3.3.12", 65 | "webpack-dev-server": "^3.11.0" 66 | }, 67 | "eslintConfig": { 68 | "root": true, 69 | "env": { 70 | "node": true 71 | }, 72 | "extends": [ 73 | "plugin:vue/essential", 74 | "eslint:recommended" 75 | ], 76 | "parserOptions": { 77 | "parser": "babel-eslint" 78 | }, 79 | "rules": {} 80 | }, 81 | "browserslist": [ 82 | "> 1%", 83 | "last 2 versions", 84 | "not ie <= 8" 85 | ] 86 | } 87 | -------------------------------------------------------------------------------- /src/DdForm.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 98 | 99 | 213 | -------------------------------------------------------------------------------- /src/DdFormView.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 133 | 134 | 555 | -------------------------------------------------------------------------------- /src/assets/file.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/icon-check.vue: -------------------------------------------------------------------------------- 1 | 19 | -------------------------------------------------------------------------------- /src/assets/icon-expand.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/icon-upload.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | const viewTypes = { 2 | COLLECTION: 'collection', 3 | GROUP: 'group', 4 | TEXT: 'text', 5 | SELECT: 'select', 6 | CHECKBOX: 'checkbox', 7 | COUNTER: 'counter', 8 | DATETIME: 'datetime', 9 | UPLOAD: 'upload', 10 | AREA: 'area', 11 | RADIO: 'radio', 12 | TICK: 'tick', 13 | }; 14 | 15 | const defaultViewValues = { 16 | collection: [], 17 | group: {}, 18 | text: '', 19 | select: '', 20 | checkbox: [], 21 | counter: 0, 22 | datetime: new Date(), 23 | upload: '', 24 | area: '', 25 | radio: '', 26 | tick: false, 27 | }; 28 | 29 | export { 30 | viewTypes, 31 | defaultViewValues, 32 | }; 33 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import ddForm from "./DdForm.vue"; 2 | 3 | function install(Vue) { 4 | if (install.installed) return; 5 | install.installed = true; 6 | Vue.component("dd-form", ddForm); 7 | } 8 | 9 | const plugin = { 10 | install 11 | }; 12 | 13 | let GlobalVue = null; 14 | if (typeof window !== "undefined") { 15 | GlobalVue = window.Vue; 16 | } else if (typeof global !== "undefined") { 17 | GlobalVue = global.vue; 18 | } 19 | if (GlobalVue) { 20 | GlobalVue.use(plugin); 21 | } 22 | 23 | ddForm.install = install; 24 | 25 | export default ddForm; -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | 4 | Vue.config.productionTip = false 5 | 6 | new Vue({ 7 | render: h => h(App), 8 | }).$mount('#app') 9 | -------------------------------------------------------------------------------- /src/views/ButtonAdd.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 19 | 20 | 40 | -------------------------------------------------------------------------------- /src/views/ButtonDrag.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | 15 | 61 | -------------------------------------------------------------------------------- /src/views/ButtonRemove.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | 18 | 64 | -------------------------------------------------------------------------------- /src/views/ButtonSubmit.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 52 | -------------------------------------------------------------------------------- /src/views/Headline.vue: -------------------------------------------------------------------------------- 1 | 8 | 22 | 26 | -------------------------------------------------------------------------------- /src/views/ViewArea.vue: -------------------------------------------------------------------------------- 1 | 20 | 106 | -------------------------------------------------------------------------------- /src/views/ViewCheckbox.vue: -------------------------------------------------------------------------------- 1 | 19 | 69 | 110 | -------------------------------------------------------------------------------- /src/views/ViewCounter.vue: -------------------------------------------------------------------------------- 1 | 19 | 72 | -------------------------------------------------------------------------------- /src/views/ViewDatetime.vue: -------------------------------------------------------------------------------- 1 | 12 | 66 | -------------------------------------------------------------------------------- /src/views/ViewRadio.vue: -------------------------------------------------------------------------------- 1 | 17 | 62 | 153 | -------------------------------------------------------------------------------- /src/views/ViewSelect.vue: -------------------------------------------------------------------------------- 1 | 32 | 83 | 218 | -------------------------------------------------------------------------------- /src/views/ViewText.vue: -------------------------------------------------------------------------------- 1 | 9 | 36 | -------------------------------------------------------------------------------- /src/views/ViewTick.vue: -------------------------------------------------------------------------------- 1 | 14 | 44 | -------------------------------------------------------------------------------- /src/views/ViewUpload.vue: -------------------------------------------------------------------------------- 1 | 14 | 83 | 133 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | lintOnSave: false, 5 | 6 | outputDir: './docs', 7 | publicPath: './', 8 | 9 | configureWebpack: { 10 | entry: { 11 | app: path.resolve(__dirname, './docs-src/main.js'), 12 | }, 13 | resolve: { 14 | alias: { 15 | '@': path.resolve(__dirname, './docs-src'), 16 | }, 17 | }, 18 | }, 19 | chainWebpack: config => { 20 | config.module 21 | .rule('js') 22 | .include 23 | .add(path.resolve(__dirname, './docs-src')) 24 | 25 | const svgRule = config.module.rule('svg') 26 | 27 | // clear all existing loaders. 28 | // if you don't do this, the loader below will be appended to 29 | // existing loaders of the rule. 30 | svgRule.uses.clear() 31 | 32 | // add replacement loader(s) 33 | svgRule 34 | .use('vue-svg-loader') 35 | .loader('vue-svg-loader') 36 | } 37 | } --------------------------------------------------------------------------------