vue-editable-table
Version:
An editable table component for Vue with Tailwind CSS
2 lines (1 loc) • 6.15 kB
JavaScript
(function(e,m){typeof exports=="object"&&typeof module<"u"?module.exports=m(require("vue")):typeof define=="function"&&define.amd?define(["vue"],m):(e=typeof globalThis<"u"?globalThis:e||self,e.EditableTable=m(e.Vue))})(this,function(e){"use strict";const m={class:"p-0"},E={class:"py-1"},h={class:"relative overflow-x-auto"},V={class:"table-fixed border-collapse border border-gray-200 min-w-max"},B=["value","onInput","readonly"],C=["onClick"],S={key:0,class:"relative w-10 text-center"},J=["value","onInput","onFocus","readonly"],O={key:0,class:""},v=["onClick"];return{__name:"EditableTable",props:{modelValue:{type:Array,required:!0},columnNames:{type:Array,required:!0},canaddcolumn:{type:Boolean,required:!0},canaddrow:{type:Boolean,required:!0},canremovecolumn:{type:Boolean,required:!0},removerows:{type:Array},canremoverow:{type:Boolean,required:!0},removecolumns:{type:Array},disablecolumns:{type:Array},disablerows:{type:Array},colstyle:{type:Array}},emits:["update:modelValue","update:columnNames"],setup(s,{emit:A}){const N=e.ref({top:0,left:0}),r=s,p=e.ref(!1),c=A,n=e.ref(JSON.parse(JSON.stringify(r.modelValue))),a=e.ref(JSON.parse(JSON.stringify(r.columnNames))),y=e.computed(()=>a.value.length),u=e.reactive({row:null,col:null});e.watch(()=>r.modelValue,t=>{JSON.stringify(t)!==JSON.stringify(n.value)&&(n.value=JSON.parse(JSON.stringify(t)))},{deep:!0}),e.watch(()=>r.columnNames,t=>{JSON.stringify(t)!==JSON.stringify(a.value)&&(a.value=JSON.parse(JSON.stringify(t)))},{deep:!0});const R=(t,o)=>u.row===t&&u.col===o,q=(t,o)=>{u.row=t,u.col=o},z=()=>{u.row=null,u.col=null},L=(t,o,d)=>{const l=d.target.value;n.value[t][o]!==l&&(n.value[t][o]=l,c("update:modelValue",JSON.parse(JSON.stringify(n.value))))},T=(t,o)=>{const d=o.target.value;a.value[t]!==d&&(a.value[t]=d,c("update:columnNames",[...a.value]))},k=e.ref(null),F=async()=>{p.value=!p.value;debugger;await e.nextTick(),f()},P=()=>{a.value.push(`Column ${y.value+1}`),n.value.forEach(t=>{t.push("")}),b(),p.value=!1},$=t=>{y.value<=1||(a.value.splice(t,1),n.value.forEach(o=>{o.splice(t,1)}),b())},_=()=>{debugger;const t=Array(y.value).fill("");n.value.push(t),c("update:modelValue",JSON.parse(JSON.stringify(n.value))),c("addRow",JSON.parse(JSON.stringify(t))),p.value=!1},j=t=>{n.value.splice(t,1),c("update:modelValue",JSON.parse(JSON.stringify(n.value))),c("removeRow",t)},b=()=>{c("update:modelValue",JSON.parse(JSON.stringify(n.value))),c("update:columnNames",[...a.value])},f=()=>{if(k.value!=null){const t=k.value.getBoundingClientRect();N.value={top:t.top+window.scrollY+t.height,left:t.left+window.scrollX-140}}};return e.onMounted(()=>{window.addEventListener("scroll",f),window.addEventListener("resize",f)}),e.onUnmounted(()=>{window.removeEventListener("scroll",f),window.removeEventListener("resize",f)}),(t,o)=>(e.openBlock(),e.createElementBlock("div",m,[e.createElementVNode("div",null,[e.renderSlot(t.$slots,"header")]),p.value?(e.openBlock(),e.createElementBlock("div",{key:0,class:"fixed z-[9999] w-36 rounded-md bg-white shadow-lg ring-1 ring-black/5",style:e.normalizeStyle({top:N.value.top+"px",left:N.value.left+"px"}),role:"menu","aria-orientation":"vertical","aria-labelledby":"user-menu-button",tabindex:"-1"},[e.createElementVNode("div",E,[r.canaddrow?(e.openBlock(),e.createElementBlock("div",{key:0,class:"flex items-center cursor-pointer px-4 py-2 text-sm text-gray-700 hover:bg-gray-100",onClick:_},o[0]||(o[0]=[e.createElementVNode("i",{class:"icon-rows-plus-bottom mr-2"},null,-1),e.createTextVNode(" Add Row ")]))):e.createCommentVNode("",!0),r.canaddcolumn?(e.openBlock(),e.createElementBlock("div",{key:1,class:"flex items-center px-4 py-2 cursor-pointer text-sm text-gray-700 hover:bg-gray-100",onClick:P},o[1]||(o[1]=[e.createElementVNode("i",{class:"icon-columns-plus-right mr-2"},null,-1),e.createTextVNode(" Add Column ")]))):e.createCommentVNode("",!0)])],4)):e.createCommentVNode("",!0),e.createElementVNode("div",h,[o[3]||(o[3]=e.createElementVNode("div",null,null,-1)),e.createElementVNode("table",V,[e.createElementVNode("thead",null,[e.createElementVNode("tr",null,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(y.value,(d,l)=>(e.openBlock(),e.createElementBlock("th",{key:l,class:e.normalizeClass([s.colstyle[l]?s.colstyle[l]:"","relative border border-gray-300 bg-gray-100 text-left"])},[e.createElementVNode("input",{value:a.value[l],onInput:g=>T(l,g),readonly:s.disablecolumns.includes(l),placeholder:"Column name",class:"w-full pl-1 mt-1 mb-1 border-none bg-transparent focus:bg-white outline-none"},null,40,B),r.canremovecolumn==!0&&!s.removecolumns.includes(l)?(e.openBlock(),e.createElementBlock("button",{key:0,onClick:g=>$(l),class:"absolute icon-column-delete right-1 top-1/2 -translate-y-1/2 h-4 flex items-center justify-center"},null,8,C)):e.createCommentVNode("",!0)],2))),128)),r.canaddcolumn||r.canaddrow||r.canremovecolumn||r.canremoverow?(e.openBlock(),e.createElementBlock("th",S,[e.createElementVNode("button",{ref_key:"buttonRef",ref:k,onClick:F,class:"icon-filter-list p-0 m-0 text-gray-600 hover:text-gray-800"},null,512),o[2]||(o[2]=e.createElementVNode("div",{class:"relative inline-block text-left"},null,-1))])):e.createCommentVNode("",!0)])]),e.createElementVNode("tbody",null,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(n.value,(d,l)=>(e.openBlock(),e.createElementBlock("tr",{key:l},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(y.value,(g,i)=>(e.openBlock(),e.createElementBlock("td",{key:i,class:e.normalizeClass(["border border-gray-200 bg-white relative",s.colstyle[i]?s.colstyle[i]:""])},[e.createElementVNode("input",{value:n.value[l][i],onInput:w=>L(l,i,w),onFocus:w=>q(l,i),readonly:s.disablerows.includes(l),onBlur:z,class:e.normalizeClass({"w-full pl-2 pt-0 m-0 bg-white border-none outline-none":!0,"bg-white":R(l,i)})},null,42,J)],2))),128)),r.canremoverow==!0&&!s.removerows.includes(l)?(e.openBlock(),e.createElementBlock("td",O,[e.createElementVNode("button",{onClick:g=>j(l),class:"icon-rows-delete flex p-0 m-0 items-center justify-center"},null,8,v)])):e.createCommentVNode("",!0)]))),128))])])])]))}}});