npm package: @guidejs/ui
Description: UI components for GuideJS, including the `Guide` tour component.
Latest version: 0.0.61

# @guidejs/ui

UI components for GuideJS, including the `Guide` tour component.

## Install

```sh
pnpm add @guidejs/ui
# or
npm i @guidejs/ui
```

Peer dependencies required in your app:

- react (>=18)
- react-dom (>=18)
- zod (^3.24.1)

## Usage

```tsx
import React from "react"
import { Guide } from "@guidejs/ui@latest"

export default function App() {
  const steps = [
    {
      id: "welcome",
      description: "Welcome to GuideJS",
      configuration: {
        type: "popover",
        popover: { side: "bottom", align: "start" }
      }
    }
  ]

  return (
    <Guide
      steps={steps}
      isActive={true}
      nextBtnText="Next"
      prevBtnText="Previous"
      doneBtnText="Done"
      onComplete={handleComplete}
      onDismiss={handleDismiss}
    />
  )
}
```

## Exports

- `Guide` from `@guidejs/ui`
- Additional UI components and helpers used by the tour system

## Development

Build the package locally:

```sh
pnpm -F @guidejs/ui build
ls -la packages/ui/dist
```

You should see `index.js`, `index.mjs`, and `index.d.ts`.

## Paste-Only Autorun

If you record a tour and paste the exported snippet that sets `window.__GuideJs_Tour__`, installing this package is enough to auto-run the tour without manually rendering.

Steps:

1. Install the package:

```bash
pnpm add @guidejs/ui
```

1. Paste your exported snippet anywhere after your app loads. Example shape:

```html
<script>
  window.__GuideJs_Tour__ = {
    isActive: true,
    steps: [
      { type: "pointer", selector: "#start-button", title: "Click Start" },
      { type: "banner", title: "Welcome", description: "Quick walkthrough" }
    ],
    tour: { id: "welcome-tour" }
  };
</script>
```

1. The package detects `window.__GuideJs_Tour__` and automatically mounts the guide using React 18 `createRoot`.

### React App Minimal Example

```tsx
// main.tsx
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";

const root = createRoot(document.getElementById("root")!);
root.render(<App />);

// Paste the snippet after your app renders (e.g., in index.html or a bootstrap file)
```

### Vanilla HTML Example

```html
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>GuideJS Autorun Demo</title>
  </head>
  <body>
    <button id="start-button">Start</button>

    <!-- Your app scripts here -->

    <script>
      window.__GuideJs_Tour__ = {
        isActive: true,
        steps: [{ type: "pointer", selector: "#start-button", title: "Click Start" }],
        tour: { id: "welcome-tour" }
      };
    </script>
  </body>
  </html>
```

## Verify publish

```sh
npm view @guidejs/ui versions --json
# optional: inspect published types/code on npm website (Code tab)
```

## Notes

- Ensure `react` and `react-dom` peer ranges match your app (React 18/19 supported).
- Positioning uses `@floating-ui/react-dom`; ensure CSS resets don’t interfere with overlays.
- Theme opacity: Exported tours ensure `overlayColorOpacity` is a finite number (defaults to 30). If setting it manually, provide a number (0–100) to avoid React NaN opacity warnings.

## React Integration

Safe initialization, event-driven updates, and one-time run:

```tsx
import React, { useEffect, useState } from "react";
import { Guide } from "@guidejs/ui";

export default function App() {
  const [steps, setSteps] = useState(window.__GuideJs_Tour__?.steps || []);
  const [hasRun, setHasRun] = useState(
    typeof window !== "undefined" && window.localStorage?.getItem("guidejs_tour_run") === "1"
  );

  useEffect(() => {
    const onLoaded = () => {
      try { setSteps(window.__GuideJs_Tour__?.steps || []); } catch {}
    };
    window.addEventListener("guidejs:tourLoaded", onLoaded);
    return () => window.removeEventListener("guidejs:tourLoaded", onLoaded);
  }, []);

  const handleFinish = () => {
    try {
      window.localStorage?.setItem("guidejs_tour_run", "1");
      setHasRun(true);
    } catch {}
  };

  const handleComplete = () => {
    // Called ONLY when user completes the tour (clicks Done on last step)
    console.log("Tour completed successfully");
    setHasRun(true);
  };

  const handleDismiss = () => {
    // Called when user dismisses the tour early (clicks X button)
    console.log("Tour dismissed");
    setHasRun(true);
  };

  return (
    <>
      {Array.isArray(steps) && steps.length > 0 && !hasRun && (
        <Guide 
          steps={steps} 
          onComplete={handleComplete} 
          onDismiss={handleDismiss}
          isActive={true} 
        />
      )}
    </>
  );
}
```

Overlay note: opacity defaults to 0 (no dimming). Set `overlayColorOpacity: 0` to be explicit.

## License

MIT