diff --git a/README.md b/README.md index 208808d..76f14a5 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,23 @@ -# Vue Web Component Library +# Vue Web Component Library (WIP) A Vue-based accessible design system with headless web components. This library provides accessible, customizable components that can be imported individually to optimize bundle size. +> This library is WIP (Work-In-Progress) + +## Is This Library Right For You? + +This library is framework agnostic at the component level, but requires Vue.js as a dependency to function. Consider this library if: + +- Your application doesn't have a framework yet and you're looking for a solid foundation to build on +- Your application is already built with Vue.js and you need consistent, accessible components +- You want to use the same components across multiple projects with different technologies + +Note that if your main application uses React, Angular, or another non-Vue framework, you might want to consider a framework-specific component library instead for better integration: + +- For **React** applications: [shadcn/ui](https://ui.shadcn.com/) offers beautifully designed components that you can copy and paste into your apps +- For **Angular** applications: [Angular Material](https://material.angular.io/) provides a comprehensive suite of UI components following Material Design principles + + ## Features - 🧩 **Web Components**: Use anywhere, framework-agnostic diff --git a/apps/documentation/.vitepress/config.mjs b/apps/documentation/.vitepress/config.mjs index c393ff8..47ce6bb 100644 --- a/apps/documentation/.vitepress/config.mjs +++ b/apps/documentation/.vitepress/config.mjs @@ -1,4 +1,5 @@ import { defineConfig } from 'vitepress' +import { resolve } from 'path' // https://vitepress.dev/reference/site-config export default defineConfig({ @@ -36,6 +37,16 @@ export default defineConfig({ vite: { optimizeDeps: { include: ['marked'] - } + }, + // resolve: { + // alias: { + // '@devbyray/vue-wc-components': resolve(__dirname, '../../../packages/components') + // } + // }, + // build: { + // commonjsOptions: { + // strictRequires: true + // } + // } } }) diff --git a/apps/documentation/.vitepress/theme/index.js b/apps/documentation/.vitepress/theme/index.js index 1d35d0f..91c52f8 100644 --- a/apps/documentation/.vitepress/theme/index.js +++ b/apps/documentation/.vitepress/theme/index.js @@ -2,7 +2,9 @@ import { h } from 'vue' import DefaultTheme from 'vitepress/theme' import MarkdownImporter from '../../components/MarkdownImporter.vue' +import ComponentExample from '../../components/ComponentExample.vue' import './style.css' +import '@devbyray/vue-wc-components' /** @type {import('vitepress').Theme} */ export default { @@ -15,5 +17,7 @@ export default { enhanceApp({ app, router, siteData }) { // ... app.component('MarkdownImporter', MarkdownImporter) + app.component('ComponentExample', ComponentExample) + } } diff --git a/apps/documentation/.vitepress/theme/style.css b/apps/documentation/.vitepress/theme/style.css index 1a61cb1..a608733 100644 --- a/apps/documentation/.vitepress/theme/style.css +++ b/apps/documentation/.vitepress/theme/style.css @@ -42,7 +42,7 @@ * - `danger`: Used to show error, or dangerous message to the users. Used * in custom container, badges, etc. * -------------------------------------------------------------------------- */ - + @import url('https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded'); :root { --vp-c-default-1: var(--vp-c-gray-1); --vp-c-default-2: var(--vp-c-gray-2); diff --git a/apps/documentation/components/ComponentExample.vue b/apps/documentation/components/ComponentExample.vue new file mode 100644 index 0000000..dd443f7 --- /dev/null +++ b/apps/documentation/components/ComponentExample.vue @@ -0,0 +1,453 @@ + + + \ No newline at end of file diff --git a/apps/documentation/components/MarkdownImporter.vue b/apps/documentation/components/MarkdownImporter.vue index 84ab663..aaad8d6 100644 --- a/apps/documentation/components/MarkdownImporter.vue +++ b/apps/documentation/components/MarkdownImporter.vue @@ -57,53 +57,74 @@ const fetchMarkdown = async (path) => { } } -// Function to apply syntax highlighting after the content is rendered +// Function to safely apply syntax highlighting const applySyntaxHighlighting = () => { // Select all code blocks const codeBlocks = document.querySelectorAll('.markdown-content pre code') // Apply highlighting to each code block codeBlocks?.forEach((block) => { - // Make sure block has a className property - if (!block || typeof block.className !== 'string') { + // Make sure block exists and has content + if (!block || !block.textContent) { return } - // Check if a language class is present - const classList = block.className.split(' ') - const langClass = classList.find(cls => typeof cls === 'string' && cls.startsWith('language-')) - - if (langClass) { - // Extract the language name - const lang = typeof langClass === 'string' ? langClass.replace('language-', '') : '' + try { + // Check if a language class is present + const classList = block.className ? block.className.split(' ') : [] + const langClass = classList.find(cls => typeof cls === 'string' && cls.startsWith('language-')) - // Apply highlighting if the language is supported - if (lang && hljs.getLanguage(lang)) { - hljs.highlightElement(block) + if (langClass) { + // Extract the language name + const lang = langClass.replace('language-', '') + + // Apply highlighting if the language is supported + if (lang && hljs.getLanguage(lang)) { + hljs.highlightElement(block) + } else { + // Only apply auto-detection if we have content + if (block.textContent.trim()) { + hljs.highlightElement(block) + } + } } else { - // Try auto-detection for unknown languages - hljs.highlightAuto(block) + // Only apply auto-detection if we have content + if (block.textContent.trim()) { + hljs.highlightElement(block) + } } - } else { - // No language specified, use auto-detection - hljs.highlightAuto(block) + } catch (error) { + // Log the error but don't break the rendering + console.warn('Error highlighting code block:', error) + + // Apply basic styling if highlighting fails + block.classList.add('plain-code') } }) } onMounted(async () => { - // Get the base URL - const baseUrl = import.meta.env.BASE_URL || '/' - // Create a path that's relative to the public directory - const fullPath = `${baseUrl}${props.path}` - - // Fetch and process the markdown - const markdownContent = await fetchMarkdown(fullPath) - htmlContent.value = marked.parse(markdownContent) - - // Use nextTick to ensure the content is in the DOM before highlighting - await nextTick() - applySyntaxHighlighting() + try { + // Get the base URL + const baseUrl = import.meta.env.BASE_URL || '/' + // Create a path that's relative to the public directory + const fullPath = `${baseUrl}${props.path}` + + // Fetch and process the markdown + const markdownContent = await fetchMarkdown(fullPath) + + // Only parse if we have content + if (markdownContent && typeof markdownContent === 'string') { + htmlContent.value = marked.parse(markdownContent) + + // Use nextTick to ensure the content is in the DOM before highlighting + await nextTick() + applySyntaxHighlighting() + } + } catch (error) { + console.error('Error rendering markdown:', error) + htmlContent.value = '
Error loading content
' + } }) @@ -175,4 +196,19 @@ onMounted(async () => { color: #ddd; } } + +/* Style for error messages */ +.error-message { + color: #e74c3c; + padding: 1rem; + border: 1px solid #e74c3c; + border-radius: 4px; + background-color: rgba(231, 76, 60, 0.1); + margin: 1rem 0; +} + +/* Style for plain code when highlighting fails */ +.plain-code { + color: #e6e6e6; +} \ No newline at end of file diff --git a/apps/documentation/docs/components/button.md b/apps/documentation/docs/components/button.md index 6832e04..d305d4c 100644 --- a/apps/documentation/docs/components/button.md +++ b/apps/documentation/docs/components/button.md @@ -1 +1,8 @@ + + Primary Button + + \ No newline at end of file diff --git a/apps/documentation/docs/components/icon.md b/apps/documentation/docs/components/icon.md index 52a7a79..9a3e420 100644 --- a/apps/documentation/docs/components/icon.md +++ b/apps/documentation/docs/components/icon.md @@ -1 +1,8 @@ + + + + \ No newline at end of file diff --git a/apps/documentation/docs/components/index.md b/apps/documentation/docs/components/index.md index d796870..28aef24 100644 --- a/apps/documentation/docs/components/index.md +++ b/apps/documentation/docs/components/index.md @@ -1 +1,38 @@ +# Components + + + Primary Button + + + + + + + + + + \ No newline at end of file diff --git a/apps/documentation/docs/components/input.md b/apps/documentation/docs/components/input.md index 3c9cfee..710f803 100644 --- a/apps/documentation/docs/components/input.md +++ b/apps/documentation/docs/components/input.md @@ -1 +1,8 @@ + + + + \ No newline at end of file diff --git a/apps/documentation/index.md b/apps/documentation/index.md index aca4404..2e1982c 100644 --- a/apps/documentation/index.md +++ b/apps/documentation/index.md @@ -13,11 +13,32 @@ hero: features: - title: Button component link: /docs/components/button - details: Lorem ipsum dolor sit amet, consectetur adipiscing elit + details: A versatile button component with support for different styles, sizes, and states to enhance user interactions. + - title: Input component link: /docs/components/input - details: Lorem ipsum dolor sit amet, consectetur adipiscing elit + details: A customizable input field component designed for accessibility and seamless data entry. + - title: Icon component link: /docs/components/icon - details: Lorem ipsum dolor sit amet, consectetur adipiscing elit + details: A library of scalable and accessible icons to complement your design system. --- + + +
+

Try our Button component

+ + Click Me + +
+ + diff --git a/apps/documentation/package.json b/apps/documentation/package.json index 2e22c7b..77cb8c6 100644 --- a/apps/documentation/package.json +++ b/apps/documentation/package.json @@ -4,8 +4,9 @@ "description": "A Vue-based accessible design system with headless web components", "private": false, "scripts": { + "build:deps": "pnpm --filter @devbyray/vue-wc-components run build", "dev": "npm run copy-readme && vitepress dev", - "build": "npm run copy-readme && vitepress build", + "build": "npm run build:deps && npm run copy-readme && vitepress build", "preview": "vitepress preview", "copy-readme": "node scripts/copy-readme.js" }, @@ -14,6 +15,7 @@ "vitepress": "^1.6.3" }, "dependencies": { + "@devbyray/vue-wc-components": "workspace:^", "highlight.js": "^11.11.1" } } \ No newline at end of file diff --git a/package.json b/package.json index a0f60b2..baf75f9 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,9 @@ "lint": "pnpm -r lint", "test": "pnpm -r test", "docs:dev": "pnpm --filter @devbyray/vue-wc-documentation dev", - "docs:build": "pnpm --filter @devbyray/vue-wc-documentation build" + "docs:build": "pnpm --filter @devbyray/vue-wc-documentation build", + "vercel-build": "pnpm build:deps && pnpm docs:build", + "build:deps": "pnpm --filter @devbyray/vue-wc-core build && pnpm --filter ./packages/components/button build && pnpm --filter ./packages/components/input build && pnpm --filter ./packages/components/icon build && pnpm --filter @devbyray/vue-wc-components build" }, "keywords": [ "vue", diff --git a/packages/components/button/README.md b/packages/components/button/README.md index 74a324e..48b5977 100644 --- a/packages/components/button/README.md +++ b/packages/components/button/README.md @@ -20,7 +20,7 @@ import '@devbyray/vue-wc-button'; -Click me +Click me Primary Button diff --git a/packages/components/package.json b/packages/components/package.json index cb89d30..3102395 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -2,9 +2,17 @@ "name": "@devbyray/vue-wc-components", "version": "0.0.12", "description": "All accessible Vue web components in one package", - "main": "dist/index.js", - "module": "dist/index.mjs", - "types": "dist/index.d.ts", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.js", + "default": "./dist/index.js" + } + }, "files": [ "dist" ], diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0131e18..17984c4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -57,6 +57,9 @@ importers: apps/documentation: dependencies: + '@devbyray/vue-wc-components': + specifier: workspace:^ + version: link:../../packages/components highlight.js: specifier: ^11.11.1 version: 11.11.1 diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..b5d649f --- /dev/null +++ b/vercel.json @@ -0,0 +1,13 @@ +{ + "version": 2, + "builds": [ + { + "src": "package.json", + "use": "@vercel/node", + "config": { + "buildCommand": "pnpm run vercel-build" + } + } + ], + "installCommand": "pnpm install" +} \ No newline at end of file