@allsrvsonline/vue-component-library 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,242 @@
1
+ # Vue Component Library
2
+
3
+ A modern, type-safe Vue 3 component library built with TypeScript and Vite. This library provides reusable, well-tested components that follow best practices and strict coding standards.
4
+
5
+ ## Features
6
+
7
+ - ✅ **TypeScript First** - Full TypeScript support with strict type checking
8
+ - ✅ **Vue 3 Composition API** - Built with modern Vue patterns using `<script setup>`
9
+ - ✅ **Tree-shakeable** - Only import what you need
10
+ - ✅ **Fully Tested** - Comprehensive test coverage with Vitest
11
+ - ✅ **ESLint & Prettier** - Enforced code quality and formatting
12
+ - ✅ **Type Definitions** - Auto-generated `.d.ts` files
13
+ - ✅ **Documented** - JSDoc comments on all public APIs
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @your-org/vue-component-library
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ### Importing Components
24
+
25
+ ```typescript
26
+ import { BaseButton, BaseInput, BaseCard } from '@your-org/vue-component-library'
27
+ import '@your-org/vue-component-library/style.css'
28
+ ```
29
+
30
+ ### Component Examples
31
+
32
+ #### BaseButton
33
+
34
+ ```vue
35
+ <template>
36
+ <BaseButton variant="primary" size="medium" @click="handleClick"> Click Me </BaseButton>
37
+ </template>
38
+
39
+ <script setup lang="ts">
40
+ import { BaseButton } from '@your-org/vue-component-library'
41
+
42
+ const handleClick = () => {
43
+ console.log('Button clicked!')
44
+ }
45
+ </script>
46
+ ```
47
+
48
+ **Props:**
49
+
50
+ - `variant`: `'primary' | 'secondary' | 'success' | 'danger' | 'warning'` (default: `'primary'`)
51
+ - `size`: `'small' | 'medium' | 'large'` (default: `'medium'`)
52
+ - `disabled`: `boolean` (default: `false`)
53
+ - `loading`: `boolean` (default: `false`)
54
+ - `fullWidth`: `boolean` (default: `false`)
55
+
56
+ #### BaseInput
57
+
58
+ ```vue
59
+ <template>
60
+ <BaseInput
61
+ v-model="email"
62
+ type="email"
63
+ label="Email Address"
64
+ placeholder="Enter your email"
65
+ :error="emailError"
66
+ required
67
+ />
68
+ </template>
69
+
70
+ <script setup lang="ts">
71
+ import { ref } from 'vue'
72
+ import { BaseInput } from '@your-org/vue-component-library'
73
+
74
+ const email = ref('')
75
+ const emailError = ref('')
76
+ </script>
77
+ ```
78
+
79
+ **Props:**
80
+
81
+ - `modelValue`: `string` - The input value (v-model)
82
+ - `type`: `'text' | 'email' | 'password' | 'number' | 'tel' | 'url'` (default: `'text'`)
83
+ - `label`: `string` - Input label
84
+ - `placeholder`: `string` - Placeholder text
85
+ - `error`: `string` - Error message to display
86
+ - `disabled`: `boolean` (default: `false`)
87
+ - `required`: `boolean` (default: `false`)
88
+
89
+ #### BaseCard
90
+
91
+ ```vue
92
+ <template>
93
+ <BaseCard title="User Profile" elevated>
94
+ <p>Card content goes here</p>
95
+
96
+ <template #footer>
97
+ <BaseButton variant="primary">Save</BaseButton>
98
+ </template>
99
+ </BaseCard>
100
+ </template>
101
+
102
+ <script setup lang="ts">
103
+ import { BaseCard, BaseButton } from '@your-org/vue-component-library'
104
+ </script>
105
+ ```
106
+
107
+ ### Using Composables
108
+
109
+ ```typescript
110
+ import { useValidation, useClickOutside } from '@your-org/vue-component-library'
111
+
112
+ // Form validation
113
+ const { value, error, validate } = useValidation('', (val) =>
114
+ val.length > 0 ? null : 'Field is required'
115
+ )
116
+
117
+ // Click outside detection
118
+ const dropdownRef = ref<HTMLElement>()
119
+ useClickOutside(dropdownRef, () => {
120
+ // Close dropdown
121
+ })
122
+ ```
123
+
124
+ ### Using Utilities
125
+
126
+ ```typescript
127
+ import { cn, debounce, generateId } from '@your-org/vue-component-library'
128
+
129
+ // Combine class names
130
+ const classes = cn('btn', isActive && 'btn--active')
131
+
132
+ // Debounce function calls
133
+ const debouncedSearch = debounce(search, 300)
134
+
135
+ // Generate unique IDs
136
+ const id = generateId('input')
137
+ ```
138
+
139
+ ## Development
140
+
141
+ ### Prerequisites
142
+
143
+ - Node.js 18+
144
+ - npm or pnpm
145
+
146
+ ### Setup
147
+
148
+ ```bash
149
+ # Install dependencies
150
+ npm install
151
+
152
+ # Run development server
153
+ npm run dev
154
+
155
+ # Run tests
156
+ npm run test
157
+
158
+ # Run tests with UI
159
+ npm run test:ui
160
+
161
+ # Build library
162
+ npm run build:lib
163
+
164
+ # Lint code
165
+ npm run lint
166
+
167
+ # Format code
168
+ npm run format
169
+
170
+ # Type check
171
+ npm run type-check
172
+ ```
173
+
174
+ ### Project Structure
175
+
176
+ ```
177
+ src/
178
+ ├── components/ # Vue components
179
+ │ ├── BaseButton.vue
180
+ │ ├── BaseButton.spec.ts
181
+ │ ├── BaseInput.vue
182
+ │ ├── BaseInput.spec.ts
183
+ │ └── BaseCard.vue
184
+ ├── composables/ # Composable functions
185
+ │ ├── useValidation.ts
186
+ │ └── useClickOutside.ts
187
+ ├── utils/ # Utility functions
188
+ │ └── index.ts
189
+ ├── types/ # TypeScript definitions
190
+ │ └── index.ts
191
+ └── index.ts # Main export file
192
+ ```
193
+
194
+ ## Design Patterns & Best Practices
195
+
196
+ This library follows strict coding standards:
197
+
198
+ ### Component Patterns
199
+
200
+ 1. **Composition API with `<script setup>`** - All components use the modern Composition API
201
+ 2. **TypeScript Strict Mode** - Full type safety with no `any` types
202
+ 3. **Props Validation** - All props are properly typed with interfaces
203
+ 4. **Typed Events** - Event emitters use TypeScript interfaces
204
+ 5. **Single Responsibility** - Each component has a clear, focused purpose
205
+
206
+ ### Code Quality
207
+
208
+ - **ESLint** - Enforces code quality rules
209
+ - **Prettier** - Consistent code formatting
210
+ - **Vitest** - Unit testing with good coverage
211
+ - **JSDoc** - Comprehensive documentation
212
+
213
+ ### Naming Conventions
214
+
215
+ - Components: `PascalCase` (e.g., `BaseButton`)
216
+ - Composables: `camelCase` starting with `use` (e.g., `useValidation`)
217
+ - Utilities: `camelCase` (e.g., `generateId`)
218
+ - Types: `PascalCase` (e.g., `ButtonVariant`)
219
+
220
+ ## Contributing
221
+
222
+ When contributing components:
223
+
224
+ 1. Follow the existing patterns
225
+ 2. Add TypeScript types
226
+ 3. Write unit tests
227
+ 4. Document with JSDoc
228
+ 5. Run linting and formatting
229
+
230
+ ## License
231
+
232
+ MIT
233
+
234
+ ## Publishing
235
+
236
+ To publish to npm:
237
+
238
+ 1. Update version in `package.json`
239
+ 2. Build the library: `npm run build:lib`
240
+ 3. Publish: `npm publish --access public`
241
+
242
+ Make sure to update `@your-org/vue-component-library` in package.json with your actual organization/package name.
@@ -0,0 +1 @@
1
+ export {}
package/dist/vite.svg ADDED
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
@@ -0,0 +1 @@
1
+ :root{--base-button-primary-bg: #3b82f6;--base-button-primary-bg-hover: #2563eb;--base-button-primary-text: white;--base-button-secondary-bg: #6b7280;--base-button-secondary-bg-hover: #4b5563;--base-button-secondary-text: white;--base-button-success-bg: #10b981;--base-button-success-bg-hover: #059669;--base-button-success-text: white;--base-button-danger-bg: #ef4444;--base-button-danger-bg-hover: #dc2626;--base-button-danger-text: white;--base-button-warning-bg: #f59e0b;--base-button-warning-bg-hover: #d97706;--base-button-warning-text: white;--base-button-disabled-opacity: .6;--base-button-loading-opacity: .7}.base-button[data-v-a4a5350a]{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;border:none;border-radius:.375rem;font-weight:500;cursor:pointer;transition:all .2s ease-in-out;font-family:inherit;position:relative}.base-button[data-v-a4a5350a]:focus-visible{outline:2px solid currentColor;outline-offset:2px}.base-button--small[data-v-a4a5350a]{padding:.375rem .75rem;font-size:.875rem}.base-button--medium[data-v-a4a5350a]{padding:.5rem 1rem;font-size:1rem}.base-button--large[data-v-a4a5350a]{padding:.75rem 1.5rem;font-size:1.125rem}.base-button--primary[data-v-a4a5350a]{background-color:var(--base-button-primary-bg);color:var(--base-button-primary-text)}.base-button--primary[data-v-a4a5350a]:hover:not(:disabled){background-color:var(--base-button-primary-bg-hover)}.base-button--secondary[data-v-a4a5350a]{background-color:var(--base-button-secondary-bg);color:var(--base-button-secondary-text)}.base-button--secondary[data-v-a4a5350a]:hover:not(:disabled){background-color:var(--base-button-secondary-bg-hover)}.base-button--success[data-v-a4a5350a]{background-color:var(--base-button-success-bg);color:var(--base-button-success-text)}.base-button--success[data-v-a4a5350a]:hover:not(:disabled){background-color:var(--base-button-success-bg-hover)}.base-button--danger[data-v-a4a5350a]{background-color:var(--base-button-danger-bg);color:var(--base-button-danger-text)}.base-button--danger[data-v-a4a5350a]:hover:not(:disabled){background-color:var(--base-button-danger-bg-hover)}.base-button--warning[data-v-a4a5350a]{background-color:var(--base-button-warning-bg);color:var(--base-button-warning-text)}.base-button--warning[data-v-a4a5350a]:hover:not(:disabled){background-color:var(--base-button-warning-bg-hover)}.base-button--full-width[data-v-a4a5350a]{width:100%}.base-button--disabled[data-v-a4a5350a],.base-button[data-v-a4a5350a]:disabled{opacity:var(--base-button-disabled-opacity);cursor:not-allowed}.base-button--loading[data-v-a4a5350a]{cursor:wait}.base-button__spinner[data-v-a4a5350a]{width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:spin-a4a5350a .6s linear infinite}.base-button__content--loading[data-v-a4a5350a]{opacity:var(--base-button-loading-opacity)}@keyframes spin-a4a5350a{to{transform:rotate(360deg)}}:root{--base-input-label-color: #374151;--base-input-required-color: #ef4444;--base-input-border: #d1d5db;--base-input-border-focus: #3b82f6;--base-input-border-error: #ef4444;--base-input-bg-disabled: #f3f4f6;--base-input-placeholder-color: #9ca3af;--base-input-focus-shadow: 0 0 0 3px rgba(59, 130, 246, .1);--base-input-error-focus-shadow: 0 0 0 3px rgba(239, 68, 68, .1);--base-input-error-color: #ef4444;--base-input-disabled-opacity: .6}.base-input[data-v-52f8a6e5]{display:flex;flex-direction:column;gap:.375rem}.base-input__label[data-v-52f8a6e5]{font-size:.875rem;font-weight:500;color:var(--base-input-label-color)}.base-input__required[data-v-52f8a6e5]{color:var(--base-input-required-color)}.base-input__field[data-v-52f8a6e5]{padding:.5rem .75rem;font-size:1rem;border:1px solid var(--base-input-border);border-radius:.375rem;transition:all .2s ease-in-out;font-family:inherit}.base-input__field[data-v-52f8a6e5]:focus{outline:none;border-color:var(--base-input-border-focus);box-shadow:var(--base-input-focus-shadow)}.base-input__field[data-v-52f8a6e5]::placeholder{color:var(--base-input-placeholder-color)}.base-input__field--error[data-v-52f8a6e5]{border-color:var(--base-input-border-error)}.base-input__field--error[data-v-52f8a6e5]:focus{border-color:var(--base-input-border-error);box-shadow:var(--base-input-error-focus-shadow)}.base-input__field--disabled[data-v-52f8a6e5],.base-input__field[data-v-52f8a6e5]:disabled{background-color:var(--base-input-bg-disabled);cursor:not-allowed;opacity:var(--base-input-disabled-opacity)}.base-input__error[data-v-52f8a6e5]{font-size:.875rem;color:var(--base-input-error-color)}:root{--base-card-bg: white;--base-card-footer-bg: #f9fafb;--base-card-border: #e5e7eb;--base-card-title-color: #111827;--base-card-shadow: 0 4px 6px -1px rgba(0, 0, 0, .1), 0 2px 4px -1px rgba(0, 0, 0, .06)}.base-card[data-v-80b8fdda]{background-color:var(--base-card-bg);border-radius:.5rem;border:1px solid var(--base-card-border);overflow:hidden}.base-card--elevated[data-v-80b8fdda]{box-shadow:var(--base-card-shadow);border:none}.base-card__header[data-v-80b8fdda]{padding:1rem 1.5rem;border-bottom:1px solid var(--base-card-border)}.base-card__title[data-v-80b8fdda]{margin:0;font-size:1.125rem;font-weight:600;color:var(--base-card-title-color)}.base-card__body[data-v-80b8fdda]{padding:1.5rem}.base-card--no-padding .base-card__body[data-v-80b8fdda]{padding:0}.base-card__footer[data-v-80b8fdda]{padding:1rem 1.5rem;border-top:1px solid var(--base-card-border);background-color:var(--base-card-footer-bg)}
@@ -0,0 +1,182 @@
1
+ import { defineComponent as m, computed as p, createElementBlock as l, openBlock as o, normalizeClass as b, createCommentVNode as i, createElementVNode as f, renderSlot as c, unref as g, createTextVNode as C, toDisplayString as v, ref as $, onMounted as I, onUnmounted as V } from "vue";
2
+ function _(...e) {
3
+ return e.filter(Boolean).join(" ");
4
+ }
5
+ function A(e, s) {
6
+ let t;
7
+ return function(...a) {
8
+ clearTimeout(t), t = setTimeout(() => e.apply(this, a), s);
9
+ };
10
+ }
11
+ function q(e = "id") {
12
+ return `${e}-${Math.random().toString(36).substr(2, 9)}`;
13
+ }
14
+ const E = ["disabled", "type"], z = {
15
+ key: 0,
16
+ class: "base-button__spinner"
17
+ }, N = /* @__PURE__ */ m({
18
+ __name: "BaseButton",
19
+ props: {
20
+ variant: { default: "primary" },
21
+ size: { default: "medium" },
22
+ disabled: { type: Boolean, default: !1 },
23
+ fullWidth: { type: Boolean, default: !1 },
24
+ loading: { type: Boolean, default: !1 },
25
+ type: { default: "button" }
26
+ },
27
+ emits: ["click"],
28
+ setup(e, { emit: s }) {
29
+ const t = e, a = s, n = p(
30
+ () => _(
31
+ "base-button",
32
+ `base-button--${t.variant}`,
33
+ `base-button--${t.size}`,
34
+ t.fullWidth && "base-button--full-width",
35
+ t.loading && "base-button--loading",
36
+ t.disabled && "base-button--disabled"
37
+ )
38
+ ), r = (d) => {
39
+ !t.disabled && !t.loading && a("click", d);
40
+ };
41
+ return (d, y) => (o(), l("button", {
42
+ class: b(n.value),
43
+ disabled: e.disabled || e.loading,
44
+ type: e.type,
45
+ onClick: r
46
+ }, [
47
+ e.loading ? (o(), l("span", z)) : i("", !0),
48
+ f("span", {
49
+ class: b({ "base-button__content--loading": e.loading })
50
+ }, [
51
+ c(d.$slots, "default", {}, void 0, !0)
52
+ ], 2)
53
+ ], 10, E));
54
+ }
55
+ }), h = (e, s) => {
56
+ const t = e.__vccOpts || e;
57
+ for (const [a, n] of s)
58
+ t[a] = n;
59
+ return t;
60
+ }, G = /* @__PURE__ */ h(N, [["__scopeId", "data-v-a4a5350a"]]), S = { class: "base-input" }, T = ["for"], F = {
61
+ key: 0,
62
+ class: "base-input__required"
63
+ }, L = ["id", "value", "type", "placeholder", "disabled", "required"], M = {
64
+ key: 1,
65
+ class: "base-input__error"
66
+ }, O = /* @__PURE__ */ m({
67
+ __name: "BaseInput",
68
+ props: {
69
+ modelValue: { default: "" },
70
+ type: { default: "text" },
71
+ placeholder: {},
72
+ disabled: { type: Boolean, default: !1 },
73
+ required: { type: Boolean, default: !1 },
74
+ label: {},
75
+ error: {}
76
+ },
77
+ emits: ["update:modelValue", "focus", "blur"],
78
+ setup(e, { emit: s }) {
79
+ const t = e, a = s, n = q("base-input"), r = p(
80
+ () => _(
81
+ "base-input__field",
82
+ t.error && "base-input__field--error",
83
+ t.disabled && "base-input__field--disabled"
84
+ )
85
+ ), d = (u) => {
86
+ const B = u.target;
87
+ a("update:modelValue", B.value);
88
+ }, y = (u) => {
89
+ a("focus", u);
90
+ }, k = (u) => {
91
+ a("blur", u);
92
+ };
93
+ return (u, B) => (o(), l("div", S, [
94
+ e.label ? (o(), l("label", {
95
+ key: 0,
96
+ for: g(n),
97
+ class: "base-input__label"
98
+ }, [
99
+ C(v(e.label) + " ", 1),
100
+ e.required ? (o(), l("span", F, "*")) : i("", !0)
101
+ ], 8, T)) : i("", !0),
102
+ f("input", {
103
+ id: g(n),
104
+ value: e.modelValue,
105
+ type: e.type,
106
+ placeholder: e.placeholder,
107
+ disabled: e.disabled,
108
+ required: e.required,
109
+ class: b(r.value),
110
+ onInput: d,
111
+ onFocus: y,
112
+ onBlur: k
113
+ }, null, 42, L),
114
+ e.error ? (o(), l("span", M, v(e.error), 1)) : i("", !0)
115
+ ]));
116
+ }
117
+ }), H = /* @__PURE__ */ h(O, [["__scopeId", "data-v-52f8a6e5"]]), W = {
118
+ key: 0,
119
+ class: "base-card__header"
120
+ }, j = { class: "base-card__title" }, w = { class: "base-card__body" }, x = {
121
+ key: 1,
122
+ class: "base-card__footer"
123
+ }, D = /* @__PURE__ */ m({
124
+ __name: "BaseCard",
125
+ props: {
126
+ title: {},
127
+ elevated: { type: Boolean, default: !1 },
128
+ padding: { type: Boolean, default: !0 }
129
+ },
130
+ setup(e) {
131
+ const s = e, t = p(
132
+ () => _(s.elevated && "base-card--elevated", !s.padding && "base-card--no-padding")
133
+ );
134
+ return (a, n) => (o(), l("div", {
135
+ class: b(["base-card", t.value])
136
+ }, [
137
+ a.$slots.header || e.title ? (o(), l("div", W, [
138
+ c(a.$slots, "header", {}, () => [
139
+ f("h3", j, v(e.title), 1)
140
+ ], !0)
141
+ ])) : i("", !0),
142
+ f("div", w, [
143
+ c(a.$slots, "default", {}, void 0, !0)
144
+ ]),
145
+ a.$slots.footer ? (o(), l("div", x, [
146
+ c(a.$slots, "footer", {}, void 0, !0)
147
+ ])) : i("", !0)
148
+ ], 2));
149
+ }
150
+ }), J = /* @__PURE__ */ h(D, [["__scopeId", "data-v-80b8fdda"]]);
151
+ function K(e, s) {
152
+ const t = $(e), a = $(null), n = p(() => a.value === null);
153
+ return {
154
+ value: t,
155
+ error: a,
156
+ isValid: n,
157
+ validate: () => (a.value = s(t.value), n.value),
158
+ reset: () => {
159
+ t.value = e, a.value = null;
160
+ }
161
+ };
162
+ }
163
+ function P(e, s) {
164
+ const t = (a) => {
165
+ e.value && !e.value.contains(a.target) && s();
166
+ };
167
+ I(() => {
168
+ document.addEventListener("click", t);
169
+ }), V(() => {
170
+ document.removeEventListener("click", t);
171
+ });
172
+ }
173
+ export {
174
+ G as BaseButton,
175
+ J as BaseCard,
176
+ H as BaseInput,
177
+ _ as cn,
178
+ A as debounce,
179
+ q as generateId,
180
+ P as useClickOutside,
181
+ K as useValidation
182
+ };
@@ -0,0 +1 @@
1
+ (function(o,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(o=typeof globalThis<"u"?globalThis:o||self,e(o.VueComponentLibrary={},o.Vue))})(this,(function(o,e){"use strict";function i(...t){return t.filter(Boolean).join(" ")}function p(t,l){let a;return function(...n){clearTimeout(a),a=setTimeout(()=>t.apply(this,n),l)}}function f(t="id"){return`${t}-${Math.random().toString(36).substr(2,9)}`}const B=["disabled","type"],_={key:0,class:"base-button__spinner"},h=e.defineComponent({__name:"BaseButton",props:{variant:{default:"primary"},size:{default:"medium"},disabled:{type:Boolean,default:!1},fullWidth:{type:Boolean,default:!1},loading:{type:Boolean,default:!1},type:{default:"button"}},emits:["click"],setup(t,{emit:l}){const a=t,n=l,s=e.computed(()=>i("base-button",`base-button--${a.variant}`,`base-button--${a.size}`,a.fullWidth&&"base-button--full-width",a.loading&&"base-button--loading",a.disabled&&"base-button--disabled")),r=d=>{!a.disabled&&!a.loading&&n("click",d)};return(d,m)=>(e.openBlock(),e.createElementBlock("button",{class:e.normalizeClass(s.value),disabled:t.disabled||t.loading,type:t.type,onClick:r},[t.loading?(e.openBlock(),e.createElementBlock("span",_)):e.createCommentVNode("",!0),e.createElementVNode("span",{class:e.normalizeClass({"base-button__content--loading":t.loading})},[e.renderSlot(d.$slots,"default",{},void 0,!0)],2)],10,B))}}),u=(t,l)=>{const a=t.__vccOpts||t;for(const[n,s]of l)a[n]=s;return a},k=u(h,[["__scopeId","data-v-a4a5350a"]]),y={class:"base-input"},C=["for"],g={key:0,class:"base-input__required"},V=["id","value","type","placeholder","disabled","required"],$={key:1,class:"base-input__error"},E=u(e.defineComponent({__name:"BaseInput",props:{modelValue:{default:""},type:{default:"text"},placeholder:{},disabled:{type:Boolean,default:!1},required:{type:Boolean,default:!1},label:{},error:{}},emits:["update:modelValue","focus","blur"],setup(t,{emit:l}){const a=t,n=l,s=f("base-input"),r=e.computed(()=>i("base-input__field",a.error&&"base-input__field--error",a.disabled&&"base-input__field--disabled")),d=c=>{const b=c.target;n("update:modelValue",b.value)},m=c=>{n("focus",c)},j=c=>{n("blur",c)};return(c,b)=>(e.openBlock(),e.createElementBlock("div",y,[t.label?(e.openBlock(),e.createElementBlock("label",{key:0,for:e.unref(s),class:"base-input__label"},[e.createTextVNode(e.toDisplayString(t.label)+" ",1),t.required?(e.openBlock(),e.createElementBlock("span",g,"*")):e.createCommentVNode("",!0)],8,C)):e.createCommentVNode("",!0),e.createElementVNode("input",{id:e.unref(s),value:t.modelValue,type:t.type,placeholder:t.placeholder,disabled:t.disabled,required:t.required,class:e.normalizeClass(r.value),onInput:d,onFocus:m,onBlur:j},null,42,V),t.error?(e.openBlock(),e.createElementBlock("span",$,e.toDisplayString(t.error),1)):e.createCommentVNode("",!0)]))}}),[["__scopeId","data-v-52f8a6e5"]]),I={key:0,class:"base-card__header"},N={class:"base-card__title"},S={class:"base-card__body"},q={key:1,class:"base-card__footer"},z=u(e.defineComponent({__name:"BaseCard",props:{title:{},elevated:{type:Boolean,default:!1},padding:{type:Boolean,default:!0}},setup(t){const l=t,a=e.computed(()=>i(l.elevated&&"base-card--elevated",!l.padding&&"base-card--no-padding"));return(n,s)=>(e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(["base-card",a.value])},[n.$slots.header||t.title?(e.openBlock(),e.createElementBlock("div",I,[e.renderSlot(n.$slots,"header",{},()=>[e.createElementVNode("h3",N,e.toDisplayString(t.title),1)],!0)])):e.createCommentVNode("",!0),e.createElementVNode("div",S,[e.renderSlot(n.$slots,"default",{},void 0,!0)]),n.$slots.footer?(e.openBlock(),e.createElementBlock("div",q,[e.renderSlot(n.$slots,"footer",{},void 0,!0)])):e.createCommentVNode("",!0)],2))}}),[["__scopeId","data-v-80b8fdda"]]);function T(t,l){const a=e.ref(t),n=e.ref(null),s=e.computed(()=>n.value===null);return{value:a,error:n,isValid:s,validate:()=>(n.value=l(a.value),s.value),reset:()=>{a.value=t,n.value=null}}}function O(t,l){const a=n=>{t.value&&!t.value.contains(n.target)&&l()};e.onMounted(()=>{document.addEventListener("click",a)}),e.onUnmounted(()=>{document.removeEventListener("click",a)})}o.BaseButton=k,o.BaseCard=z,o.BaseInput=E,o.cn=i,o.debounce=p,o.generateId=f,o.useClickOutside=O,o.useValidation=T,Object.defineProperty(o,Symbol.toStringTag,{value:"Module"})}));
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@allsrvsonline/vue-component-library",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/vue-component-library.umd.js",
6
+ "module": "./dist/vue-component-library.es.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/vue-component-library.es.js",
12
+ "require": "./dist/vue-component-library.umd.js"
13
+ },
14
+ "./style.css": "./dist/style.css"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "dev": "vite",
21
+ "build": "vue-tsc -b && vite build",
22
+ "build:lib": "vue-tsc -b && vite build --mode lib",
23
+ "preview": "vite preview",
24
+ "lint": "eslint . --ext .vue,.ts,.tsx --fix",
25
+ "format": "prettier --write \"src/**/*.{ts,tsx,vue,json}\"",
26
+ "test": "vitest",
27
+ "test:ui": "vitest --ui",
28
+ "type-check": "vue-tsc --noEmit"
29
+ },
30
+ "dependencies": {
31
+ "vue": "^3.5.24"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^24.10.1",
35
+ "@typescript-eslint/eslint-plugin": "^8.51.0",
36
+ "@typescript-eslint/parser": "^8.51.0",
37
+ "@vitejs/plugin-vue": "^6.0.1",
38
+ "@vue/test-utils": "^2.4.6",
39
+ "@vue/tsconfig": "^0.8.1",
40
+ "eslint": "^8.57.1",
41
+ "eslint-config-prettier": "^10.1.8",
42
+ "eslint-plugin-prettier": "^5.5.4",
43
+ "eslint-plugin-vue": "^10.6.2",
44
+ "happy-dom": "^20.0.11",
45
+ "prettier": "^3.7.4",
46
+ "typescript": "~5.9.3",
47
+ "vite": "^7.2.4",
48
+ "vite-plugin-dts": "^4.5.4",
49
+ "vitest": "^4.0.16",
50
+ "vue-eslint-parser": "^10.2.0",
51
+ "vue-tsc": "^3.1.4"
52
+ }
53
+ }