vue3-tailwind-components 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
package/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # vue3-tailwind-components
2
+ This is a simple set of Vue 3, Tailwind based components. At the moment these consist of:
3
+ * [Button](./src/components/button/README.md)
4
+ * [Table](./src/components/table/README.md)
5
+ * [Paginator](./src/components/paginator/README.md)
6
+ * [Switch](./src/components/switch/README.md)
7
+
8
+
9
+
10
+ I will be extending them as I need more Vue 3 Tailwind components. To use them you can
11
+
12
+ ```shell
13
+ npm install richardhulbert/vue3-tailwind-components --save
14
+ ```
15
+ You can then just import the ones you want to use.
16
+
17
+ ### Colors
18
+ I expect that if you use this library you will already understand how to use Tailwind generally. It comes with a generous
19
+ color pallet of gradated colors. In the background Tailwind strips out the classes it does not see directly in your code to keep your css small
20
+ but this creates a problem for us. It cannot see computed (concatenated strings). In order to use our components you will need to edit your.
21
+ `tailwind.config.js` file in the root of your project.
22
+
23
+ ```javascript
24
+ ...
25
+ safelist: [
26
+ {
27
+ pattern: /bg-(\w+)-(\d00)/,
28
+ variants: ['hover', 'focus'],
29
+ },
30
+ {
31
+ pattern: /border-(\w+)-(\d00)/,
32
+ },
33
+ {
34
+ pattern: /text-(\w+)-(\d00)/,
35
+ },
36
+ ],
37
+ ...
38
+ ```
39
+ This tells Tailwind - Do not remove these classes from the CSS
40
+
41
+ You can be more specific and therefore reduce the size of the resultant css by doing something like this
42
+
43
+ ```javascript
44
+ {
45
+ pattern: /border-(slate|amber|primary)-(200|500|700)/
46
+ }
47
+ ```
48
+ Another suggestion would be to create color aliases in `tailwind.config.js` like this:
49
+
50
+ ```javascript
51
+ theme: {
52
+ extend: {
53
+ colors:{
54
+ primary:colors.cyan,
55
+ secondary:colors.lime
56
+ }
57
+ },
58
+ }
59
+
60
+ ```
61
+
62
+ You can then do something like this:
63
+ ```vue
64
+ <tw-button @click="clearProducts" color="primary" ouutline class="ml-3 ">Clear</tw-button>`
65
+ ```
66
+ This is useful in the situation where you want to change the colour of a lot of buttons in one go.
67
+
68
+
69
+ ## Running this project locally
70
+
71
+ See [Vite Configuration Reference](https://vitejs.dev/config/).
72
+
73
+ ## Project Setup
74
+
75
+ ```sh
76
+ npm install
77
+ ```
78
+
79
+ ### Compile and Hot-Reload for Development
80
+
81
+ ```sh
82
+ npm run dev
83
+ ```
84
+
85
+ ### Compile and Minify for Production
86
+
87
+ ```sh
88
+ npm run build
89
+ ```
Binary file
@@ -0,0 +1,302 @@
1
+ import { openBlock as o, createElementBlock as l, createElementVNode as n, normalizeClass as i, Fragment as p, renderList as b, toDisplayString as y, renderSlot as h, createTextVNode as g, resolveComponent as k, createVNode as C, withCtx as _, createBlock as v } from "vue";
2
+ const f = (e, s) => {
3
+ const t = e.__vccOpts || e;
4
+ for (const [u, c] of s)
5
+ t[u] = c;
6
+ return t;
7
+ }, w = {
8
+ props: {
9
+ items: {
10
+ type: Array,
11
+ default: []
12
+ },
13
+ headings: {
14
+ type: Array
15
+ },
16
+ border: {
17
+ type: Boolean,
18
+ default: !0
19
+ },
20
+ striped: {
21
+ type: Boolean,
22
+ default: !1
23
+ },
24
+ hover: {
25
+ type: Boolean,
26
+ default: !1
27
+ },
28
+ headingColor: {
29
+ type: String,
30
+ default: "slate"
31
+ },
32
+ borderColor: {
33
+ type: String,
34
+ default: "slate"
35
+ },
36
+ stripeColor: {
37
+ type: String,
38
+ default: "slate"
39
+ },
40
+ hoverColor: {
41
+ type: String,
42
+ default: "slate"
43
+ }
44
+ },
45
+ computed: {
46
+ headingClass() {
47
+ return "bg-" + this.headingColor + "-200";
48
+ },
49
+ boarderClass() {
50
+ return this.border ? "border border-" + this.borderColor + "-200" : "";
51
+ }
52
+ },
53
+ methods: {
54
+ rowStripe(e) {
55
+ let s = this.hover ? " hover:bg-" + this.hoverColor + "-100" : "";
56
+ return this.striped ? e % 2 !== 0 ? "bg-" + this.stripeColor + "-100 " + s : "" + s : s;
57
+ }
58
+ }
59
+ }, P = { class: "border-collapse table-auto w-full text-sm" }, x = { class: "p-2 font-normal" }, $ = { class: "text-gray-600" };
60
+ function B(e, s, t, u, c, r) {
61
+ return o(), l("table", P, [
62
+ n("thead", {
63
+ class: i([r.headingClass, "text-gray-800"])
64
+ }, [
65
+ n("tr", null, [
66
+ (o(!0), l(p, null, b(t.headings, (a) => (o(), l("th", x, y(a.label), 1))), 256))
67
+ ])
68
+ ], 2),
69
+ n("tbody", $, [
70
+ (o(!0), l(p, null, b(t.items, (a, d) => (o(), l("tr", {
71
+ key: d,
72
+ class: i(r.rowStripe(d))
73
+ }, [
74
+ (o(!0), l(p, null, b(t.headings, (m) => (o(), l("td", {
75
+ class: i([r.boarderClass, "p-2"])
76
+ }, [
77
+ h(e.$slots, m.field, { item: a }, () => [
78
+ g(y(a[m.field]), 1)
79
+ ])
80
+ ], 2))), 256))
81
+ ], 2))), 128))
82
+ ])
83
+ ]);
84
+ }
85
+ const G = /* @__PURE__ */ f(w, [["render", B]]), S = {
86
+ props: {
87
+ color: {
88
+ type: String,
89
+ default: "slate"
90
+ },
91
+ outline: {
92
+ type: Boolean,
93
+ default: !1
94
+ },
95
+ corners: {
96
+ type: Boolean,
97
+ default: !1
98
+ }
99
+ },
100
+ computed: {
101
+ bgcolor() {
102
+ let e = "bg-" + this.color + "-500 hover:bg-" + this.color + "-700 text-white border-" + this.color + "-500";
103
+ return this.outline && (e = "border-" + this.color + "-500 hover:bg-" + this.color + "-500 text-" + this.color + "-500 hover:text-white border"), this.corners || (e += " rounded "), e;
104
+ }
105
+ }
106
+ };
107
+ function T(e, s, t, u, c, r) {
108
+ return o(), l("button", {
109
+ class: i([r.bgcolor, "transition-colors ease-in font-bold py-2 px-6 font-light border text-sm"])
110
+ }, [
111
+ h(e.$slots, "default")
112
+ ], 2);
113
+ }
114
+ const H = /* @__PURE__ */ f(S, [["render", T]]), N = {
115
+ props: {
116
+ buttonPosition: {
117
+ type: String,
118
+ default: "middle"
119
+ },
120
+ color: {
121
+ type: String,
122
+ default: "slate"
123
+ },
124
+ selected: {
125
+ type: Boolean,
126
+ default: !1
127
+ },
128
+ disabled: {
129
+ type: Boolean,
130
+ default: !1
131
+ }
132
+ },
133
+ computed: {
134
+ positionClass() {
135
+ switch (this.buttonPosition) {
136
+ case "first":
137
+ return " rounded-l ";
138
+ case "last":
139
+ return " rounded-r ";
140
+ default:
141
+ return "";
142
+ }
143
+ },
144
+ finalClass() {
145
+ return this.disabled ? " border-" + this.color + "-200 text-" + this.color + "-200 " + this.positionClass : this.selected ? " bg-" + this.color + "-200 " + this.positionClass : " hover:bg-" + this.color + "-300 border-" + this.color + "-300 text-" + this.color + "-500 " + this.positionClass;
146
+ }
147
+ }
148
+ };
149
+ function V(e, s, t, u, c, r) {
150
+ return o(), l("li", null, [
151
+ n("button", {
152
+ class: i([r.finalClass, "px-3 py-2 ml-0 leading-tight transition-colors border"])
153
+ }, [
154
+ h(e.$slots, "default")
155
+ ], 2)
156
+ ]);
157
+ }
158
+ const O = /* @__PURE__ */ f(N, [["render", V]]), I = {
159
+ components: { TwPaginatorButton: O },
160
+ props: {
161
+ numOfPages: {
162
+ type: Number,
163
+ default: 0
164
+ },
165
+ currentPage: {
166
+ type: Number,
167
+ default: 0
168
+ },
169
+ color: {
170
+ type: String,
171
+ default: "slate"
172
+ }
173
+ },
174
+ methods: {
175
+ paginate(e) {
176
+ this.$emit("paginate", e);
177
+ },
178
+ increment() {
179
+ this.currentPage < this.numOfPages && this.$emit("paginate", this.currentPage + 1);
180
+ },
181
+ decrement() {
182
+ this.currentPage > 1 && this.$emit("paginate", this.currentPage - 1);
183
+ }
184
+ }
185
+ }, A = { "aria-label": "Pagination" }, E = { class: "inline-flex -space-x-px" };
186
+ function z(e, s, t, u, c, r) {
187
+ const a = k("tw-paginator-button");
188
+ return o(), l("nav", A, [
189
+ n("ul", E, [
190
+ C(a, {
191
+ color: t.color,
192
+ onClick: r.decrement,
193
+ disabled: t.currentPage <= 1,
194
+ "button-position": "first"
195
+ }, {
196
+ default: _(() => [
197
+ h(e.$slots, "first", {}, () => [
198
+ g("Previous")
199
+ ])
200
+ ]),
201
+ _: 3
202
+ }, 8, ["color", "onClick", "disabled"]),
203
+ (o(!0), l(p, null, b(t.numOfPages, (d) => (o(), v(a, {
204
+ color: t.color,
205
+ key: d,
206
+ onClick: (m) => r.paginate(d),
207
+ selected: d === t.currentPage
208
+ }, {
209
+ default: _(() => [
210
+ g(y(d), 1)
211
+ ]),
212
+ _: 2
213
+ }, 1032, ["color", "onClick", "selected"]))), 128)),
214
+ C(a, {
215
+ color: t.color,
216
+ onClick: r.increment,
217
+ disabled: t.currentPage >= t.numOfPages,
218
+ "button-position": "last"
219
+ }, {
220
+ default: _(() => [
221
+ h(e.$slots, "last", {}, () => [
222
+ g("Next")
223
+ ])
224
+ ]),
225
+ _: 3
226
+ }, 8, ["color", "onClick", "disabled"])
227
+ ])
228
+ ]);
229
+ }
230
+ const J = /* @__PURE__ */ f(I, [["render", z]]), D = {
231
+ props: {
232
+ color: {
233
+ type: String,
234
+ default: "slate"
235
+ },
236
+ modelValue: {
237
+ type: Boolean,
238
+ default: !1
239
+ }
240
+ },
241
+ data() {
242
+ return {
243
+ checked: !1
244
+ };
245
+ },
246
+ methods: {
247
+ handleInput(e) {
248
+ this.checked = !this.checked, this.$emit("update:modelValue", this.checked);
249
+ }
250
+ },
251
+ watch: {
252
+ modelValue: {
253
+ handler(e) {
254
+ this.checked = e;
255
+ },
256
+ immediate: !0
257
+ }
258
+ },
259
+ computed: {
260
+ backClass() {
261
+ return this.checked ? "bg-" + this.color + "-500" : "bg-" + this.color + "-200";
262
+ },
263
+ knobClass() {
264
+ return this.checked ? "right-0" : "left-0";
265
+ },
266
+ labelClass() {
267
+ return "text-" + this.color + "-500";
268
+ }
269
+ }
270
+ }, F = { class: "relative" }, L = ["value"];
271
+ function j(e, s, t, u, c, r) {
272
+ return o(), l("div", {
273
+ class: "flex cursor-pointer select-none items-center",
274
+ onClick: s[0] || (s[0] = (...a) => r.handleInput && r.handleInput(...a))
275
+ }, [
276
+ n("div", F, [
277
+ n("input", {
278
+ type: "checkbox",
279
+ class: "sr-only",
280
+ value: c.checked
281
+ }, null, 8, L),
282
+ n("div", {
283
+ class: i([r.backClass, "h-5 w-10 rounded-full shadow-inner"])
284
+ }, null, 2),
285
+ n("div", {
286
+ class: i([r.knobClass, "dot border border-slate-200 shadow-switch-1 absolute -top-0 h-5 w-5 rounded-full bg-white transition-transform transition-duration: 300ms"])
287
+ }, null, 2)
288
+ ]),
289
+ n("div", {
290
+ class: i([r.labelClass, "mx-2"])
291
+ }, [
292
+ h(e.$slots, "default")
293
+ ], 2)
294
+ ]);
295
+ }
296
+ const K = /* @__PURE__ */ f(D, [["render", j]]);
297
+ export {
298
+ H as TwButton,
299
+ J as TwPaginator,
300
+ K as TwSwitch,
301
+ G as TwTable
302
+ };
@@ -0,0 +1 @@
1
+ (function(n,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(n=typeof globalThis<"u"?globalThis:n||self,e(n.MyLib={},n.Vue))})(this,function(n,e){"use strict";const d=(t,l)=>{const o=t.__vccOpts||t;for(const[c,a]of l)o[c]=a;return o},f={props:{items:{type:Array,default:[]},headings:{type:Array},border:{type:Boolean,default:!0},striped:{type:Boolean,default:!1},hover:{type:Boolean,default:!1},headingColor:{type:String,default:"slate"},borderColor:{type:String,default:"slate"},stripeColor:{type:String,default:"slate"},hoverColor:{type:String,default:"slate"}},computed:{headingClass(){return"bg-"+this.headingColor+"-200"},boarderClass(){return this.border?"border border-"+this.borderColor+"-200":""}},methods:{rowStripe(t){let l=this.hover?" hover:bg-"+this.hoverColor+"-100":"";return this.striped?t%2!==0?"bg-"+this.stripeColor+"-100 "+l:""+l:l}}},m={class:"border-collapse table-auto w-full text-sm"},p={class:"p-2 font-normal"},u={class:"text-gray-600"};function g(t,l,o,c,a,r){return e.openBlock(),e.createElementBlock("table",m,[e.createElementVNode("thead",{class:e.normalizeClass([r.headingClass,"text-gray-800"])},[e.createElementVNode("tr",null,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(o.headings,s=>(e.openBlock(),e.createElementBlock("th",p,e.toDisplayString(s.label),1))),256))])],2),e.createElementVNode("tbody",u,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(o.items,(s,i)=>(e.openBlock(),e.createElementBlock("tr",{key:i,class:e.normalizeClass(r.rowStripe(i))},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(o.headings,h=>(e.openBlock(),e.createElementBlock("td",{class:e.normalizeClass([r.boarderClass,"p-2"])},[e.renderSlot(t.$slots,h.field,{item:s},()=>[e.createTextVNode(e.toDisplayString(s[h.field]),1)])],2))),256))],2))),128))])])}const b=d(f,[["render",g]]),k={props:{color:{type:String,default:"slate"},outline:{type:Boolean,default:!1},corners:{type:Boolean,default:!1}},computed:{bgcolor(){let t="bg-"+this.color+"-500 hover:bg-"+this.color+"-700 text-white border-"+this.color+"-500";return this.outline&&(t="border-"+this.color+"-500 hover:bg-"+this.color+"-500 text-"+this.color+"-500 hover:text-white border"),this.corners||(t+=" rounded "),t}}};function _(t,l,o,c,a,r){return e.openBlock(),e.createElementBlock("button",{class:e.normalizeClass([r.bgcolor,"transition-colors ease-in font-bold py-2 px-6 font-light border text-sm"])},[e.renderSlot(t.$slots,"default")],2)}const C=d(k,[["render",_]]),y={props:{buttonPosition:{type:String,default:"middle"},color:{type:String,default:"slate"},selected:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1}},computed:{positionClass(){switch(this.buttonPosition){case"first":return" rounded-l ";case"last":return" rounded-r ";default:return""}},finalClass(){return this.disabled?" border-"+this.color+"-200 text-"+this.color+"-200 "+this.positionClass:this.selected?" bg-"+this.color+"-200 "+this.positionClass:" hover:bg-"+this.color+"-300 border-"+this.color+"-300 text-"+this.color+"-500 "+this.positionClass}}};function B(t,l,o,c,a,r){return e.openBlock(),e.createElementBlock("li",null,[e.createElementVNode("button",{class:e.normalizeClass([r.finalClass,"px-3 py-2 ml-0 leading-tight transition-colors border"])},[e.renderSlot(t.$slots,"default")],2)])}const w={components:{TwPaginatorButton:d(y,[["render",B]])},props:{numOfPages:{type:Number,default:0},currentPage:{type:Number,default:0},color:{type:String,default:"slate"}},methods:{paginate(t){this.$emit("paginate",t)},increment(){this.currentPage<this.numOfPages&&this.$emit("paginate",this.currentPage+1)},decrement(){this.currentPage>1&&this.$emit("paginate",this.currentPage-1)}}},S={"aria-label":"Pagination"},E={class:"inline-flex -space-x-px"};function P(t,l,o,c,a,r){const s=e.resolveComponent("tw-paginator-button");return e.openBlock(),e.createElementBlock("nav",S,[e.createElementVNode("ul",E,[e.createVNode(s,{color:o.color,onClick:r.decrement,disabled:o.currentPage<=1,"button-position":"first"},{default:e.withCtx(()=>[e.renderSlot(t.$slots,"first",{},()=>[e.createTextVNode("Previous")])]),_:3},8,["color","onClick","disabled"]),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(o.numOfPages,i=>(e.openBlock(),e.createBlock(s,{color:o.color,key:i,onClick:h=>r.paginate(i),selected:i===o.currentPage},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(i),1)]),_:2},1032,["color","onClick","selected"]))),128)),e.createVNode(s,{color:o.color,onClick:r.increment,disabled:o.currentPage>=o.numOfPages,"button-position":"last"},{default:e.withCtx(()=>[e.renderSlot(t.$slots,"last",{},()=>[e.createTextVNode("Next")])]),_:3},8,["color","onClick","disabled"])])])}const x=d(w,[["render",P]]),T={props:{color:{type:String,default:"slate"},modelValue:{type:Boolean,default:!1}},data(){return{checked:!1}},methods:{handleInput(t){this.checked=!this.checked,this.$emit("update:modelValue",this.checked)}},watch:{modelValue:{handler(t){this.checked=t},immediate:!0}},computed:{backClass(){return this.checked?"bg-"+this.color+"-500":"bg-"+this.color+"-200"},knobClass(){return this.checked?"right-0":"left-0"},labelClass(){return"text-"+this.color+"-500"}}},V={class:"relative"},N=["value"];function $(t,l,o,c,a,r){return e.openBlock(),e.createElementBlock("div",{class:"flex cursor-pointer select-none items-center",onClick:l[0]||(l[0]=(...s)=>r.handleInput&&r.handleInput(...s))},[e.createElementVNode("div",V,[e.createElementVNode("input",{type:"checkbox",class:"sr-only",value:a.checked},null,8,N),e.createElementVNode("div",{class:e.normalizeClass([r.backClass,"h-5 w-10 rounded-full shadow-inner"])},null,2),e.createElementVNode("div",{class:e.normalizeClass([r.knobClass,"dot border border-slate-200 shadow-switch-1 absolute -top-0 h-5 w-5 rounded-full bg-white transition-transform transition-duration: 300ms"])},null,2)]),e.createElementVNode("div",{class:e.normalizeClass([r.labelClass,"mx-2"])},[e.renderSlot(t.$slots,"default")],2)])}const z=d(T,[["render",$]]);n.TwButton=C,n.TwPaginator=x,n.TwSwitch=z,n.TwTable=b,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})});
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "vue3-tailwind-components",
3
+ "version": "0.0.1",
4
+ "description": "A library of Vue 3 components that use Tailwind",
5
+ "license": "MIT",
6
+ "repository": "richardhulbert/vue3-tailwind-components",
7
+ "files": ["dist"],
8
+ "main": "./dist/vue3-tailwind-components.umd.js",
9
+ "module": "./dist/vue3-tailwind-componentses.js",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/vue3-tailwind-components.js",
13
+ "require": "./dist/vue3-tailwind-components.umd.js"
14
+ }
15
+ },
16
+ "scripts": {
17
+ "dev": "vite",
18
+ "build": "vite build",
19
+ "preview": "vite preview"
20
+ },
21
+ "dependencies": {
22
+ "vue": "^3.2.45"
23
+ },
24
+ "devDependencies": {
25
+ "@faker-js/faker": "^7.6.0",
26
+ "@vitejs/plugin-vue": "^4.0.0",
27
+ "autoprefixer": "^10.4.13",
28
+ "postcss": "^8.4.20",
29
+ "tailwindcss": "^3.2.4",
30
+ "vite": "^4.0.0"
31
+ }
32
+ }