# @burdenoff/fe-libs

Frontend primitives and domain libraries for all Burdenoff products.

## Architecture

This is a **Layer 1 package** - a monolithic package with subpath exports for all primitives.

## Package Structure

```
@burdenoff/fe-libs/
├── /workflow    - Workflow primitives (Node, Canvas, Edge)
├── /tag         - Tag components
├── /form        - Form components
├── /button      - Button primitives
└── /shared      - Shared utilities (cn, types)
```

## Usage

```typescript
import { Button } from '@burdenoff/fe-libs/button';
import { WorkflowNode, WorkflowCanvas } from '@burdenoff/fe-libs/workflow';
import { cn } from '@burdenoff/fe-libs/shared';
```

## Development

```bash
# Install dependencies
bun install

# Build library
bun run build

# Type check
bun run type:check

# Run all checks
bun run sanity
```

## Components

### Workflow Primitives

- **WorkflowNode** - Renders a workflow node with status indicators
- **WorkflowCanvas** - Canvas component for workflow builder with grid background

### Button

- **Button** - Versatile button component with variants (default, destructive, outline, secondary, ghost, link)

### Shared

- **cn** - Utility for merging Tailwind classes

## shell-native (app shells only)

`@burdenoff/fe-libs/shell-native` is the shell-side native runtime: Capacitor
(iOS/Android), Electron desktop and PWA wiring in one entry point. **App shells
import it; microfrontends never do** — MFEs talk to the shell through
`window.__burdenoffNativeBridge` (`@burdenoff/fe-libs/shared/native`).

Boot it once in `main.tsx`, before React mounts:

```ts
import { bootNativeShell, registerDeepLinkNavigator } from '@burdenoff/fe-libs/shell-native';

const shell = bootNativeShell({
  product: 'vibecontrols',
  appName: 'VibeControls',
  // Optional plugins are loaded ONLY through these loaders, so web-only shells
  // never bundle them.
  plugins: {
    updater: () => import('@capgo/capacitor-updater'),
    pushNotifications: () => import('@capacitor/push-notifications'),
  },
  push: { enabled: true, onToken: (token) => void registerDevice(token) },
  runtimeHooks: { syncPendingOperations: refetchAll, saveState: flushDrafts },
});

// Inside the router:
registerDeepLinkNavigator((path) => navigate(path));
// After the first meaningful paint:
void shell.markAppReady();
```

Boot order (each step is individually try/caught — boot never throws): preview →
OTA `notifyAppReady` → auth-redirect intercept → external URL opener → native
bridge + platform classes → device info → status-bar theme listener → keyboard →
Android back button → deep links → network → app-state hooks → push listeners →
splash safety timer (native) → PWA service worker (web) → desktop shell boot.

Contracts the shells and MFEs can rely on:

- **Window globals** — `__burdenoffNativeBridge`, `__burdenoffDeviceInfo`,
  `__burdenoffOpenExternal(url)`, `__burdenoffPushToken`,
  `__burdenoffPwaInstallPrompt`.
- **Body classes** — `platform-ios | platform-android | platform-web`,
  `platform-native`, `platform-preview`, `keyboard-open`.
  `<html>` carries `data-platform` and (in preview) `data-native-preview`.
- **CSS var** — `--keyboard-height` (0px when closed).
- **Window events** — `burdenoff:appReady`, `burdenoff:appStateChange`,
  `burdenoff:networkStatusChange`, `burdenoff:keyboardWillShow|DidShow|WillHide|DidHide`,
  `burdenoff:pushToken`, `burdenoff:pwaUpdateReady`, `burdenoff:pwaInstalled`,
  `burdenoff:pwaInstallAvailable`. The shell listens for `burdenoff:statusBarTheme`.

### Native preview flag

`?__nativePreview=ios|android|pwa|desktop` renders the installed-app chrome in a
plain browser (persisted in `sessionStorage`, cleared with `off`). It is
**presentation only** — real plugin calls stay gated on
`Capacitor.isPluginAvailable`, and the flag is ignored inside a real native app.

### Build-time config generators

`defineCapacitorConfig(nativeConfig)`, `defineWebManifest(nativeConfig)` and
`renderServiceWorker(nativeConfig, version)` are pure functions (no
`@capacitor/*` imports) that emit each product's `capacitor.config.ts`,
`public/manifest.json` and `public/sw.js` from its `native.config.json`
(`NativeConfig`).

## Tech Stack

- React 19
- TypeScript 5.9+
- TailwindCSS v4
- Radix UI (for accessible primitives)
- Vite 7 (for building)
