npm package: @mk-labs/ui
Description: Universal UI components as Web Components + React proxies (Next-ready).
Latest version: 0.1.10

# @mk-labs/ui

Universal UI components built as Web Components, with first-class **React/Next.js** support.

[![npm](https://img.shields.io/npm/v/%40mk-labs%2Fui)](https://www.npmjs.com/package/@mk-labs/ui)
[![license](https://img.shields.io/badge/license-MIT-blue.svg)](#license)

---

## ✨ Features

- Framework-agnostic Web Components
- Zero-config **React** proxies for **Next.js**
- Accessible by default (proper ARIA roles + live regions)
- Simple theming via CSS variables
- Initial component: **`<u-alert />`**

> Today the package ships **Web Components + React**. Vue/Angular wrappers are planned.

---

## 📦 Installation

```bash
npm i @mk-labs/ui
# or: yarn add @mk-labs/ui
# or: pnpm add @mk-labs/ui
```

### Next.js config (recommended)

For Next 13+ (App Router) / Next 15+ (Turbopack):

```js
// next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
  // Ensures our tiny React proxy module is compiled when needed
  transpilePackages: ['@mk-labs/ui', '@stencil/react-output-target'],
};
export default nextConfig;
```

---

## ⚡ Quick Start (Next.js / React)

1) Define the custom element **once on the client**:

```tsx
// app/ui-provider.tsx
'use client';
import '@mk-labs/ui/define';

export default function UIProvider({ children }: { children: React.ReactNode }) {
  return <>{children}</>;
}
```

2) Wrap your app with the provider:

```tsx
// app/layout.tsx
import type { Metadata } from 'next';
import './globals.css';
import UIProvider from './ui-provider';

export const metadata: Metadata = { title: '@mk-labs/ui Demo' };

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <UIProvider>{children}</UIProvider>
      </body>
    </html>
  );
}
```

3) Use the **React proxy**:

```tsx
// app/page.tsx
'use client';
import { UAlert } from '@mk-labs/ui/react';

export default function Page() {
  return (
    <div style={{ padding: 24 }}>
      <UAlert variant="info" heading="Hello">@mk-labs/ui in Next</UAlert>
      <UAlert
        variant="danger"
        dismissible
        heading="Closable"
        onUClose={() => console.log('closed')}
      >
        Click × and check the console
      </UAlert>
    </div>
  );
}
```

---

## ⚛️ React (Vite) Example

```bash
npm create vite@latest mk-ui-react-sandbox -- --template react-ts
cd mk-ui-react-sandbox
npm i @mk-labs/ui
```

```tsx
// src/App.tsx
import '@mk-labs/ui/define';
import { UAlert } from '@mk-labs/ui/react';

export default function App() {
  return (
    <>
      <UAlert variant="info" heading="Hello">From @mk-labs/ui</UAlert>
      <UAlert variant="danger" dismissible heading="Closable" onUClose={() => console.log('closed')}>
        Click ×
      </UAlert>
    </>
  );
}
```

---

## 🌐 Plain HTML / Vanilla JS

```html
<script type="module">
  /* Auto-defines all components when loaded */
  import 'https://unpkg.com/@mk-labs/ui@latest/dist/define.js';
</script>

<u-alert heading="Heads up" variant="info">This is an informational alert.</u-alert>
<u-alert heading="All good" variant="success" dismissible>Your changes were saved.</u-alert>

<script>
  document.querySelector('u-alert[dismissible]')
    .addEventListener('u-close', () => console.log('closed'));
</script>
```

---

## 🧩 Components

### `<u-alert />`

**Props**

| Prop          | Type                                                   | Default | Description                                   |
|---------------|--------------------------------------------------------|---------|-----------------------------------------------|
| `variant`     | `'info' \| 'success' \| 'warning' \| 'danger'`      | `'info'`| Visual style                                  |
| `heading`     | `string` (optional)                                    | —       | Optional heading (avoid reserved `title`)     |
| `dismissible` | `boolean`                                              | `false` | Shows a close button (×)                      |

**Events**

| Event     | Detail | Description                        | React prop |
|-----------|--------|------------------------------------|------------|
| `u-close` | `void` | Fired when the alert is dismissed  | `onUClose` |

**Slots**  
- _default_: alert body content

**Accessibility**  
- `role="status"` + `aria-live="polite"` for `info/success`  
- `role="alert"` + `aria-live="assertive"` for `warning/danger`  
- Close button includes `aria-label="Close alert"`

---

## 🎨 Theming

Override CSS vars (per-instance or globally). Tokens per variant (`info`, `success`, `warning`, `danger`):

- `--u-alert-bg-<variant>`
- `--u-alert-fg-<variant>`
- `--u-alert-border-<variant>`

**Example**

```css
/* Info overrides */
u-alert {
  --u-alert-bg-info: #e6fffa;
  --u-alert-fg-info: #03543f;
  --u-alert-border-info: #bcf0da;
}
```

---

## 🧠 TypeScript

- React entry (`@mk-labs/ui/react`) ships `.d.ts` types.
- Web Component types live under `dist/types/**`.

If your editor can’t find types after an update, try a clean install:

```bash
rm -rf node_modules package-lock.json .next
npm i
```

---

## 🧭 Entry Points

| Import path               | What it does                                              |
|--------------------------|------------------------------------------------------------|
| `@mk-labs/ui`            | Package root (web component bundle)                        |
| `@mk-labs/ui/define`     | Defines all custom elements globally (side-effect import)  |
| `@mk-labs/ui/react`      | React proxies (e.g., `UAlert`)                             |
| `@mk-labs/ui/dist/*`     | (Advanced) deep imports used by proxies                    |

> For **Next.js/React**, import `@mk-labs/ui/define` once (client), then use components from `@mk-labs/ui/react`.

---

## 🛠️ Troubleshooting

**Nothing renders; you see raw `<u-alert>` text**  
Make sure `@mk-labs/ui/define` is imported in a **client** component (e.g., `app/ui-provider.tsx`) before rendering `<UAlert />`.

**Next.js: “Module not found: Can’t resolve '@mk-labs/ui/react'”**  
Upgrade to the latest `@mk-labs/ui`. Also ensure your `next.config.mjs` includes:
```js
transpilePackages: ['@mk-labs/ui', '@stencil/react-output-target']
```

**React event not firing**  
Use the React prop: `onUClose={() => ...}` (maps to `u-close`).

**Type declarations not found**  
Update to the latest version. If local cache is messy, do a clean install:
```bash
rm -rf node_modules package-lock.json .next
npm i
```

---

## 🧪 Local Development

```bash
# dev server (http://localhost:3333)
npm start

# build (emits dist + React proxies)
npm run build

# tests
npm test
```

> During dev, Stencil serves the library from `/build`. In plain HTML demos, load:
> ```html
> <script type="module" src="/build/mklabsui.esm.js"></script>
> <script nomodule src="/build/mklabsui.js"></script>
> ```

---

## 🚀 Release & Publish

We use semver. Typical release:

```bash
npm run build
npm version patch -m "docs: update README"   # or minor/major
npm publish --access public
```

(If you use CI, publish on git tag via GitHub Actions.)

---

## 🗺️ Roadmap

- Additional components (`<u-badge>`, `<u-button>`, …)
- Vue / Angular wrappers
- SSR hydration helpers for Next

---

## 🤝 Contributing

PRs welcome! Please open issues/PRs with:
- a clear description,
- minimal reproduction (if bug),
- and tests when possible.

---

## 📄 License

MIT © mk-labs