parent
							
								
									8acc3567be
								
							
						
					
					
						commit
						ef3264756c
					
				| @ -0,0 +1,23 @@ | ||||
| .DS_Store | ||||
| node_modules | ||||
| /dist | ||||
| 
 | ||||
| 
 | ||||
| # local env files | ||||
| .env.local | ||||
| .env.*.local | ||||
| 
 | ||||
| # Log files | ||||
| npm-debug.log* | ||||
| yarn-debug.log* | ||||
| yarn-error.log* | ||||
| pnpm-debug.log* | ||||
| 
 | ||||
| # Editor directories and files | ||||
| .idea | ||||
| .vscode | ||||
| *.suo | ||||
| *.ntvs* | ||||
| *.njsproj | ||||
| *.sln | ||||
| *.sw? | ||||
| @ -0,0 +1,24 @@ | ||||
| # moz-todo-vue | ||||
| 
 | ||||
| ## Project setup | ||||
| ``` | ||||
| npm install | ||||
| ``` | ||||
| 
 | ||||
| ### Compiles and hot-reloads for development | ||||
| ``` | ||||
| npm run serve | ||||
| ``` | ||||
| 
 | ||||
| ### Compiles and minifies for production | ||||
| ``` | ||||
| npm run build | ||||
| ``` | ||||
| 
 | ||||
| ### Lints and fixes files | ||||
| ``` | ||||
| npm run lint | ||||
| ``` | ||||
| 
 | ||||
| ### Customize configuration | ||||
| See [Configuration Reference](https://cli.vuejs.org/config/). | ||||
| @ -0,0 +1,5 @@ | ||||
| module.exports = { | ||||
|   presets: [ | ||||
|     '@vue/cli-plugin-babel/preset' | ||||
|   ] | ||||
| } | ||||
| @ -0,0 +1,19 @@ | ||||
| { | ||||
|   "compilerOptions": { | ||||
|     "target": "es5", | ||||
|     "module": "esnext", | ||||
|     "baseUrl": "./", | ||||
|     "moduleResolution": "node", | ||||
|     "paths": { | ||||
|       "@/*": [ | ||||
|         "src/*" | ||||
|       ] | ||||
|     }, | ||||
|     "lib": [ | ||||
|       "esnext", | ||||
|       "dom", | ||||
|       "dom.iterable", | ||||
|       "scripthost" | ||||
|     ] | ||||
|   } | ||||
| } | ||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								| @ -0,0 +1,44 @@ | ||||
| { | ||||
|   "name": "moz-todo-vue", | ||||
|   "version": "0.1.0", | ||||
|   "private": true, | ||||
|   "scripts": { | ||||
|     "serve": "vue-cli-service serve", | ||||
|     "build": "vue-cli-service build", | ||||
|     "lint": "vue-cli-service lint" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "core-js": "^3.8.3", | ||||
|     "lodash.uniqueid": "^4.0.1", | ||||
|     "vue": "^3.2.13" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@babel/core": "^7.12.16", | ||||
|     "@babel/eslint-parser": "^7.12.16", | ||||
|     "@vue/cli-plugin-babel": "~5.0.0", | ||||
|     "@vue/cli-plugin-eslint": "~5.0.0", | ||||
|     "@vue/cli-service": "~5.0.0", | ||||
|     "eslint": "^7.32.0", | ||||
|     "eslint-plugin-vue": "^8.0.3" | ||||
|   }, | ||||
|   "eslintConfig": { | ||||
|     "root": true, | ||||
|     "env": { | ||||
|       "node": true | ||||
|     }, | ||||
|     "extends": [ | ||||
|       "plugin:vue/vue3-essential", | ||||
|       "eslint:recommended" | ||||
|     ], | ||||
|     "parserOptions": { | ||||
|       "parser": "@babel/eslint-parser" | ||||
|     }, | ||||
|     "rules": {} | ||||
|   }, | ||||
|   "browserslist": [ | ||||
|     "> 1%", | ||||
|     "last 2 versions", | ||||
|     "not dead", | ||||
|     "not ie 11" | ||||
|   ] | ||||
| } | ||||
| After Width: | Height: | Size: 4.2 KiB | 
| @ -0,0 +1,17 @@ | ||||
| <!DOCTYPE html> | ||||
| <html lang=""> | ||||
|   <head> | ||||
|     <meta charset="utf-8"> | ||||
|     <meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||||
|     <meta name="viewport" content="width=device-width,initial-scale=1.0"> | ||||
|     <link rel="icon" href="<%= BASE_URL %>favicon.ico"> | ||||
|     <title><%= htmlWebpackPlugin.options.title %></title> | ||||
|   </head> | ||||
|   <body> | ||||
|     <noscript> | ||||
|       <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> | ||||
|     </noscript> | ||||
|     <div id="app"></div> | ||||
|     <!-- built files will be auto injected --> | ||||
|   </body> | ||||
| </html> | ||||
| @ -0,0 +1,193 @@ | ||||
| <template> | ||||
|   <div id = "app"> | ||||
|   <h1>To-Do List</h1> | ||||
|   <to-do-form @todo-added="addToDo"></to-do-form> | ||||
|   <h2 id="list-summary" ref="listSummary" tabindex="-1">{{ listSummary }}</h2> | ||||
|   <ul aria-labelledby="list-summary" class="stack-large"> | ||||
|     <li v-for="item in ToDoItems" :key="item.id"> | ||||
|       <to-do-item  | ||||
|         :label="item.label"  | ||||
|         :done="item.done" | ||||
|         :id="item.id" | ||||
|         @checkbox-changed = "updateDoneStatus(item.id)" | ||||
|         @item-deleted="deleteToDo(item.id)" | ||||
|         @item-edited="editToDo(item.id,$event)"></to-do-item> | ||||
|     </li> | ||||
|   </ul> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| import ToDoItem from "./components/ToDoItem.vue"; | ||||
| import uniqueId from "lodash.uniqueid"; | ||||
| import ToDoForm from "./components/ToDoForm.vue"; | ||||
| 
 | ||||
| export default { | ||||
|   name: 'App', | ||||
|   components:{ | ||||
|     ToDoItem, ToDoForm | ||||
|   }, | ||||
| 
 | ||||
|   data(){ | ||||
|     return{ | ||||
|       ToDoItems:[ | ||||
|         {id:uniqueId("todo-"),label:"Learn Vue",done:false}, | ||||
|         { | ||||
|           id:uniqueId("todo-"), | ||||
|           label:"Create a Vue project with the CLI", | ||||
|           done:true, | ||||
|         }, | ||||
|         {id:uniqueId("todo-"),label:"Have fun",done:true}, | ||||
|         {id:uniqueId("todo-"),label:"Create a to-do list",done:false}, | ||||
|       ], | ||||
|     }; | ||||
|   }, | ||||
| 
 | ||||
|   methods:{ | ||||
|     addToDo(toDoLabel) | ||||
|     { | ||||
|       this.ToDoItems.push({id:uniqueId('todo-'),label: toDoLabel,done:false}); | ||||
|     }, | ||||
| 
 | ||||
|     updateDoneStatus(toDoId) | ||||
|     { | ||||
|       const toDoToUpdate = this.ToDoItems.find((item)=>item.id === toDoId) | ||||
|       toDoToUpdate.done = !toDoToUpdate.done; | ||||
|     }, | ||||
| 
 | ||||
|     deleteToDo(toDoId) | ||||
|     { | ||||
|       const itemIndex = this.ToDoItems.findIndex((item)=>item.id === toDoId); | ||||
|       this.ToDoItems.splice(itemIndex,1); | ||||
|       this.$refs.listSummary.focus(); | ||||
|     }, | ||||
|     editToDo(toDoId,newLabel) | ||||
|     { | ||||
|       const toDoToEdit = this.ToDoItems.find((item)=>item.id === toDoId); | ||||
|       toDoToEdit.label = newLabel; | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   computed:{ | ||||
|     listSummary() | ||||
|     { | ||||
|       const numberFinishedItems = this.ToDoItems.filter((item)=>item.done).length | ||||
|       return `${numberFinishedItems} out of ${this.ToDoItems.length} items | ||||
|       completed`  | ||||
|     } | ||||
|   } | ||||
| }; | ||||
| </script> | ||||
| 
 | ||||
| <style> | ||||
|   /* 全局样式 */ | ||||
|   .btn { | ||||
|     padding: 0.8rem 1rem 0.7rem; | ||||
|     border: 0.2rem solid #4d4d4d; | ||||
|     cursor: pointer; | ||||
|     text-transform: capitalize; | ||||
|   } | ||||
|   .btn__danger { | ||||
|     color: #fff; | ||||
|     background-color: #ca3c3c; | ||||
|     border-color: #bd2130; | ||||
|   } | ||||
|   .btn__filter { | ||||
|     border-color: lightgrey; | ||||
|   } | ||||
|   .btn__danger:focus { | ||||
|     outline-color: #c82333; | ||||
|   } | ||||
|   .btn__primary { | ||||
|     color: #fff; | ||||
|     background-color: #000; | ||||
|   } | ||||
|   .btn-group { | ||||
|     display: flex; | ||||
|     justify-content: space-between; | ||||
|   } | ||||
|   .btn-group > * { | ||||
|     flex: 1 1 auto; | ||||
|   } | ||||
|   .btn-group > * + * { | ||||
|     margin-left: 0.8rem; | ||||
|   } | ||||
|   .label-wrapper { | ||||
|     margin: 0; | ||||
|     flex: 0 0 100%; | ||||
|     text-align: center; | ||||
|   } | ||||
|   [class*="__lg"] { | ||||
|     display: inline-block; | ||||
|     width: 100%; | ||||
|     font-size: 1.9rem; | ||||
|   } | ||||
|   [class*="__lg"]:not(:last-child) { | ||||
|     margin-bottom: 1rem; | ||||
|   } | ||||
|   @media screen and (min-width: 620px) { | ||||
|     [class*="__lg"] { | ||||
|       font-size: 2.4rem; | ||||
|     } | ||||
|   } | ||||
|   .visually-hidden { | ||||
|     position: absolute; | ||||
|     height: 1px; | ||||
|     width: 1px; | ||||
|     overflow: hidden; | ||||
|     clip: rect(1px 1px 1px 1px); | ||||
|     clip: rect(1px, 1px, 1px, 1px); | ||||
|     clip-path: rect(1px, 1px, 1px, 1px); | ||||
|     white-space: nowrap; | ||||
|   } | ||||
|   [class*="stack"] > * { | ||||
|     margin-top: 0; | ||||
|     margin-bottom: 0; | ||||
|   } | ||||
|   .stack-small > * + * { | ||||
|     margin-top: 1.25rem; | ||||
|   } | ||||
|   .stack-large > * + * { | ||||
|     margin-top: 2.5rem; | ||||
|   } | ||||
|   @media screen and (min-width: 550px) { | ||||
|     .stack-small > * + * { | ||||
|       margin-top: 1.4rem; | ||||
|     } | ||||
|     .stack-large > * + * { | ||||
|       margin-top: 2.8rem; | ||||
|     } | ||||
|   } | ||||
|   /* 全局样式结束 */ | ||||
|   #app { | ||||
|     background: #fff; | ||||
|     margin: 2rem 0 4rem 0; | ||||
|     padding: 1rem; | ||||
|     padding-top: 0; | ||||
|     position: relative; | ||||
|     box-shadow: | ||||
|       0 2px 4px 0 rgba(0, 0, 0, 0.2), | ||||
|       0 2.5rem 5rem 0 rgba(0, 0, 0, 0.1); | ||||
|   } | ||||
|   @media screen and (min-width: 550px) { | ||||
|     #app { | ||||
|       padding: 4rem; | ||||
|     } | ||||
|   } | ||||
|   #app > * { | ||||
|     max-width: 50rem; | ||||
|     margin-left: auto; | ||||
|     margin-right: auto; | ||||
|   } | ||||
|   #app > form { | ||||
|     max-width: 100%; | ||||
|   } | ||||
|   #app h1 { | ||||
|     display: block; | ||||
|     min-width: 100%; | ||||
|     width: 100%; | ||||
|     text-align: center; | ||||
|     margin: 0; | ||||
|     margin-bottom: 1rem; | ||||
|   } | ||||
| </style> | ||||
| After Width: | Height: | Size: 6.7 KiB | 
| @ -0,0 +1,73 @@ | ||||
| *, | ||||
| *::before, | ||||
| *::after{ | ||||
|     box-sizing:border-box; | ||||
| } | ||||
| *:focus{ | ||||
|     outline:3px dashed #228bec; | ||||
| } | ||||
| html{ | ||||
|     font:62.5%/1.15 sans-serif; | ||||
| } | ||||
| h1, | ||||
| h2{ | ||||
|     margin-bottom:0; | ||||
| } | ||||
| ul{ | ||||
|     list-style:none; | ||||
|     padding:0; | ||||
| } | ||||
| button{ | ||||
|     border:none; | ||||
|     margin:0; | ||||
|     padding:0; | ||||
|     width:auto; | ||||
|     overflow:visible; | ||||
|     background:transparent; | ||||
|     color:inherit; | ||||
|     font:inherit; | ||||
|     line-height:normal; | ||||
|     -webkit-font-smoothing:inherit; | ||||
|     -moz-osx-font-smoothing:inherit; | ||||
|     appearance:none; | ||||
| } | ||||
| button::-moz-focus-inner{ | ||||
|     border:0; | ||||
| } | ||||
| button, | ||||
| input, | ||||
| optgroup, | ||||
| select, | ||||
| textarea{ | ||||
|     font-family:inherit; | ||||
|     font-size:100%; | ||||
|     line-height:1.15; | ||||
|     margin:0; | ||||
| } | ||||
| button, | ||||
| input{ | ||||
|     overflow:visible; | ||||
| } | ||||
| input[type="text"]{ | ||||
|     border-radius:0; | ||||
| } | ||||
| body{ | ||||
|     width:100%; | ||||
|     max-width:68rem; | ||||
|     margin:0 auto; | ||||
|     font: | ||||
|     1.6rem/1.25 "Helvetica Neue", | ||||
|     Helvetica, | ||||
|     Arial, | ||||
|     sans-serif; | ||||
|   background-color: #f5f5f5; | ||||
|   color: #4d4d4d; | ||||
|   -moz-osx-font-smoothing: grayscale; | ||||
|   -webkit-font-smoothing: antialiased; | ||||
| } | ||||
| @media screen and (min-width: 620px) { | ||||
|   body { | ||||
|     font-size: 1.9rem; | ||||
|     line-height: 1.31579; | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,58 @@ | ||||
| <template> | ||||
|   <div class="hello"> | ||||
|     <h1>{{ msg }}</h1> | ||||
|     <p> | ||||
|       For a guide and recipes on how to configure / customize this project,<br> | ||||
|       check out the | ||||
|       <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>. | ||||
|     </p> | ||||
|     <h3>Installed CLI Plugins</h3> | ||||
|     <ul> | ||||
|       <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li> | ||||
|       <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li> | ||||
|     </ul> | ||||
|     <h3>Essential Links</h3> | ||||
|     <ul> | ||||
|       <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li> | ||||
|       <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li> | ||||
|       <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li> | ||||
|       <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li> | ||||
|       <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li> | ||||
|     </ul> | ||||
|     <h3>Ecosystem</h3> | ||||
|     <ul> | ||||
|       <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li> | ||||
|       <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li> | ||||
|       <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li> | ||||
|       <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li> | ||||
|       <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li> | ||||
|     </ul> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| export default { | ||||
|   name: 'HelloWorld', | ||||
|   props: { | ||||
|     msg: String | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| 
 | ||||
| <!-- Add "scoped" attribute to limit CSS to this component only --> | ||||
| <style scoped> | ||||
| h3 { | ||||
|   margin: 40px 0 0; | ||||
| } | ||||
| ul { | ||||
|   list-style-type: none; | ||||
|   padding: 0; | ||||
| } | ||||
| li { | ||||
|   display: inline-block; | ||||
|   margin: 0 10px; | ||||
| } | ||||
| a { | ||||
|   color: #42b983; | ||||
| } | ||||
| </style> | ||||
| @ -0,0 +1,41 @@ | ||||
| <template> | ||||
|     <form @submit.prevent = "onSubmit"> | ||||
|         <h2 class="label-wrapper"> | ||||
|         <label for="new-todo-input" class="label__lg"> | ||||
|             What needs to be done? | ||||
|         </label> | ||||
|         </h2> | ||||
|         <input | ||||
|             type = "text" | ||||
|             id="new-todo-input" | ||||
|             name="new-todo" | ||||
|             autocomplete="off" | ||||
|             v-model = "label"  | ||||
|             class  = "input__lg" | ||||
|         /> | ||||
|         <button type="submit" class="btn btn__primary btn__lg">Add</button> | ||||
|     </form> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
|     export default{ | ||||
|         methods:{ | ||||
|             onSubmit() | ||||
|             { | ||||
|                 if(this.label === "") | ||||
|             { | ||||
|                 return | ||||
|             } | ||||
|                 this.$emit("todo-added",this.label); | ||||
|                 this.label=""; | ||||
|             } | ||||
|         }, | ||||
|          | ||||
|         data() | ||||
|         { | ||||
|             return{ | ||||
|                 label:"", | ||||
|             }; | ||||
|         }, | ||||
|     }; | ||||
| </script> | ||||
| @ -0,0 +1,205 @@ | ||||
| <template> | ||||
| <div class="stack-small" v-if="!isEditing"> | ||||
|     <div class="custom-checkbox"> | ||||
|         <input  | ||||
|         type="checkbox"  | ||||
|         :id="id"  | ||||
|         :checked="isDone"  | ||||
|         class="checkbox" | ||||
|         @change="$emit('checkbox-changed')" | ||||
|         > | ||||
|         <label :for="id" class="checkbox-label">{{ label }}</label> | ||||
|     </div> | ||||
|     <div class="btn-group"> | ||||
|         <button  | ||||
|             type="button"  | ||||
|             class="btn" | ||||
|             ref="editButton"  | ||||
|             @click="toggleToItemEditForm"> | ||||
|             Edit<span class="visually-hidden">{{ label }}</span> | ||||
|         </button> | ||||
|         <button type="button" class="btn btn__danger" @click="deleteToDo"> | ||||
|             Delete<span class="visually-hidden">{{ label }}</span> | ||||
|         </button> | ||||
|     </div> | ||||
| </div> | ||||
| <to-do-item-edit-form v-else  | ||||
|     :id="id"  | ||||
|     :label="label" | ||||
|     @item-edited="itemEdited" | ||||
|     @edit-cancelled="editCancelled"> | ||||
| </to-do-item-edit-form> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
|     import ToDoItemEditForm from './ToDoItemEditForm.vue'; | ||||
|     export default{ | ||||
|         components:{ | ||||
|                 ToDoItemEditForm | ||||
|         }, | ||||
| 
 | ||||
|         props:{ | ||||
|             label:{required:true,type:String}, | ||||
|             done:{default:false,type:Boolean}, | ||||
|             id:{required: true, type: String} | ||||
|         }, | ||||
| 
 | ||||
|         data() | ||||
|         { | ||||
|             return{ | ||||
|                 isEditing: false | ||||
|             }; | ||||
|         }, | ||||
|         computed:{ | ||||
|             isDone(){ | ||||
|                 return this.done; | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         methods:{ | ||||
|             deleteToDo() | ||||
|             { | ||||
|                 this.$emit('item-deleted'); | ||||
|             }, | ||||
|             toggleToItemEditForm() | ||||
|             { | ||||
|                 console.log(this.$refs.editButton); | ||||
|                 this.isEditing = true; | ||||
|             }, | ||||
| 
 | ||||
|             itemEdited(newLabel) | ||||
|             { | ||||
|                 this.$emit('item-edited',newLabel); | ||||
|                 this.isEditing = false; | ||||
|                 this.focusOnEditButton(); | ||||
|             }, | ||||
|             editCancelled() | ||||
|             { | ||||
|                 this.isEditing = false; | ||||
|                 this.focusOnEditButton(); | ||||
|             }, | ||||
|             focusOnEditButton() | ||||
|             { | ||||
|                 this.$nextTick(()=>{ | ||||
|                 const editButtonRef = this.$refs.editButton; | ||||
|                 editButtonRef.focus(); | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| </script> | ||||
| 
 | ||||
| <style scoped> | ||||
|     .custom-checkbox > .checkbox-label { | ||||
|   font-family: Arial, sans-serif; | ||||
|   -webkit-font-smoothing: antialiased; | ||||
|   -moz-osx-font-smoothing: grayscale; | ||||
|   font-weight: 400; | ||||
|   font-size: 16px; | ||||
|   font-size: 1rem; | ||||
|   line-height: 1.25; | ||||
|   color: #0b0c0c; | ||||
|   display: block; | ||||
|   margin-bottom: 5px; | ||||
| } | ||||
| .custom-checkbox > .checkbox { | ||||
|   font-family: Arial, sans-serif; | ||||
|   -webkit-font-smoothing: antialiased; | ||||
|   -moz-osx-font-smoothing: grayscale; | ||||
|   font-weight: 400; | ||||
|   font-size: 16px; | ||||
|   font-size: 1rem; | ||||
|   line-height: 1.25; | ||||
|   box-sizing: border-box; | ||||
|   width: 100%; | ||||
|   height: 40px; | ||||
|   height: 2.5rem; | ||||
|   margin-top: 0; | ||||
|   padding: 5px; | ||||
|   border: 2px solid #0b0c0c; | ||||
|   border-radius: 0; | ||||
|   appearance: none; | ||||
| } | ||||
| .custom-checkbox > input:focus { | ||||
|   outline: 3px dashed #fd0; | ||||
|   outline-offset: 0; | ||||
|   box-shadow: inset 0 0 0 2px; | ||||
| } | ||||
| .custom-checkbox { | ||||
|   font-family: Arial, sans-serif; | ||||
|   -webkit-font-smoothing: antialiased; | ||||
|   font-weight: 400; | ||||
|   font-size: 1.6rem; | ||||
|   line-height: 1.25; | ||||
|   display: block; | ||||
|   position: relative; | ||||
|   min-height: 40px; | ||||
|   margin-bottom: 10px; | ||||
|   padding-left: 40px; | ||||
|   clear: left; | ||||
| } | ||||
| .custom-checkbox > input[type="checkbox"] { | ||||
|   -webkit-font-smoothing: antialiased; | ||||
|   cursor: pointer; | ||||
|   position: absolute; | ||||
|   z-index: 1; | ||||
|   top: -2px; | ||||
|   left: -2px; | ||||
|   width: 44px; | ||||
|   height: 44px; | ||||
|   margin: 0; | ||||
|   opacity: 0; | ||||
| } | ||||
| .custom-checkbox > .checkbox-label { | ||||
|   font-size: inherit; | ||||
|   font-family: inherit; | ||||
|   line-height: inherit; | ||||
|   display: inline-block; | ||||
|   margin-bottom: 0; | ||||
|   padding: 8px 15px 5px; | ||||
|   cursor: pointer; | ||||
|   touch-action: manipulation; | ||||
| } | ||||
| .custom-checkbox > label::before { | ||||
|   content: ""; | ||||
|   box-sizing: border-box; | ||||
|   position: absolute; | ||||
|   top: 0; | ||||
|   left: 0; | ||||
|   width: 40px; | ||||
|   height: 40px; | ||||
|   border: 2px solid currentcolor; | ||||
|   background: transparent; | ||||
| } | ||||
| .custom-checkbox > input[type="checkbox"]:focus + label::before { | ||||
|   border-width: 4px; | ||||
|   outline: 3px dashed #228bec; | ||||
| } | ||||
| .custom-checkbox > label::after { | ||||
|   box-sizing: content-box; | ||||
|   content: ""; | ||||
|   position: absolute; | ||||
|   top: 11px; | ||||
|   left: 9px; | ||||
|   width: 18px; | ||||
|   height: 7px; | ||||
|   transform: rotate(-45deg); | ||||
|   border: solid; | ||||
|   border-width: 0 0 5px 5px; | ||||
|   border-top-color: transparent; | ||||
|   opacity: 0; | ||||
|   background: transparent; | ||||
| } | ||||
| .custom-checkbox > input[type="checkbox"]:checked + label::after { | ||||
|   opacity: 1; | ||||
| } | ||||
| @media only screen and (min-width: 40rem) { | ||||
|   label, | ||||
|   input, | ||||
|   .custom-checkbox { | ||||
|     font-size: 19px; | ||||
|     font-size: 1.9rem; | ||||
|     line-height: 1.31579; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @ -0,0 +1,89 @@ | ||||
| <template> | ||||
|     <form class="stack-small" @submit.prevent = "onSubmit"> | ||||
|         <div> | ||||
|             <label class="edit-label">Edit Name for "{{ label }}"</label> | ||||
|             <input | ||||
|                 :id = "id" | ||||
|                 ref="labelInput" | ||||
|                 type="text" | ||||
|                 autocomplete="off" | ||||
|                 v-model.lazy.trim="newLabel"/> | ||||
|         </div> | ||||
|         <div class="btn-group"> | ||||
|             <button type="button" class="btn" @click="onCancel"> | ||||
|                 Cancel | ||||
|                 <span class="visually-hidden">editing{{ label }}</span> | ||||
|             </button> | ||||
|             <button type="submit" class="btn btn__primary"> | ||||
|                 Save | ||||
|                 <span class="visually-hidden">edit for{{ label }}</span> | ||||
|             </button> | ||||
|         </div> | ||||
|     </form> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
|     export default{ | ||||
|         props:{ | ||||
|             label:{ | ||||
|                 type:String, | ||||
|                 required: true, | ||||
|             }, | ||||
|             id:{ | ||||
|                 type:String, | ||||
|                 required: true, | ||||
|             }, | ||||
|         }, | ||||
| 
 | ||||
|         data() | ||||
|         { | ||||
|             return{ | ||||
|                 newLabel: this.label, | ||||
|             }; | ||||
|         }, | ||||
| 
 | ||||
|         methods:{ | ||||
|             onSubmit(){ | ||||
|                 if(this.newLabel && this.newLabel !== this.label){ | ||||
|                 this.$emit("item-edited",this.newLabel); | ||||
|             } | ||||
|             }, | ||||
|             onCancel(){ | ||||
|                 this.$emit("edit-cancelled"); | ||||
|             }, | ||||
|         }, | ||||
| 
 | ||||
|         mounted() | ||||
|         { | ||||
|             const labelInputRef = this.$refs.labelInput; | ||||
|             labelInputRef.focus(); | ||||
|         } | ||||
|     } | ||||
| </script> | ||||
| 
 | ||||
| <style scoped> | ||||
|   .edit-label { | ||||
|     font-family: Arial, sans-serif; | ||||
|     -webkit-font-smoothing: antialiased; | ||||
|     -moz-osx-font-smoothing: grayscale; | ||||
|     color: #0b0c0c; | ||||
|     display: block; | ||||
|     margin-bottom: 5px; | ||||
|   } | ||||
|   input { | ||||
|     display: inline-block; | ||||
|     margin-top: 0.4rem; | ||||
|     width: 100%; | ||||
|     min-height: 4.4rem; | ||||
|     padding: 0.4rem 0.8rem; | ||||
|     border: 2px solid #565656; | ||||
|   } | ||||
|   form { | ||||
|     display: flex; | ||||
|     flex-direction: row; | ||||
|     flex-wrap: wrap; | ||||
|   } | ||||
|   form > * { | ||||
|     flex: 0 0 100%; | ||||
|   } | ||||
| </style> | ||||
| @ -0,0 +1,5 @@ | ||||
| import { createApp } from 'vue' | ||||
| import App from './App.vue' | ||||
| import "./assets/reset.css" | ||||
| 
 | ||||
| createApp(App).mount('#app') | ||||
| @ -0,0 +1,4 @@ | ||||
| const { defineConfig } = require('@vue/cli-service') | ||||
| module.exports = defineConfig({ | ||||
|   transpileDependencies: true | ||||
| }) | ||||
					Loading…
					
					
				
		Reference in new issue