JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 18
  • Score
    100M100P100Q42657F

Package Exports

  • yapperjs
  • yapperjs/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (yapperjs) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

YapperJS

npm version License: MIT

A modern and declarative API for managing dialogs in React applications.

Introduction

YapperJS revolutionizes how you handle dialogs in React by treating them as what they truly are: requests for user input. Instead of breaking your code flow with imperative dialog rendering, YapperJS lets you simply await dialogs and continue your logic naturally.

// Instead of callbacks and state management...
// Just await your dialog's result!
const userConfirmed = await yapperApi.showDialog({ content: ConfirmationDialog });
if (userConfirmed) {
  // Continue your flow here!
}

Installation

npm install yapperjs
# or
yarn add yapperjs
# or
pnpm add yapperjs
# or
bun add yapperjs

Important: Don't forget to import the CSS styles in your application:

import 'yapperjs/dist/index.css';

This import is required for the dialogs to display properly.

Key Benefits

  • Promise-based API: Treat dialogs as awaitable operations
  • Flow-preserving: Keep your logic flowing naturally without callbacks
  • Type-safe: Full TypeScript support for dialog responses
  • Flexible: Easily customize the appearance and behavior of dialogs
  • Composable: Create nested dialogs simply by using the API recursively

Basic Usage

Here's a simple example of how to use YapperJS:

import { useYapperDialog } from 'yapperjs';

function MyComponent({ submitData }) {
  const yapperApi = useYapperDialog();
  
  const handleSubmit = async () => {
    // Show a confirmation dialog and await its result
    if (!await yapperApi.showDialog({ content: ConfirmationDialog })) {
      return; // User declined
    }
    
    // Continue with submission if user confirmed
    await submitData();
  };
  
  return (
    <>
      <button onClick={handleSubmit}>Submit</button>
      {/* This renders your dialogs when they're active */}
      <yapperApi.renderer />
    </>
  );
}

API Reference

useYapperDialog()

A React hook that creates and returns a YapperAPI instance.

YapperApi

Method Description
showDialog<TData, TArgs>(dialog) Shows a dialog and returns a promise that resolves with the dialog's result
cancelActiveDialog() Cancels the currently active dialog
renderer React component that renders the active dialog

Dialog Definition

The showDialog method accepts a dialog definition object:

type YapperDialogDefinition<TData, TArgs> = {
  // Required: Component to render as dialog content
  content: FC<YapperDialogContentProps<TData> & TArgs>;
  
  // Optional: Args passed to the content component
  args?: TArgs;
  
  // Optional: Styling and behavior customization
  backdropClassname?: string;
  backdropStyle?: CSSProperties;
  backdrop?: ReactNode;
  positionerClassname?: string;
  postionerStyle?: CSSProperties;
  wrapper?: FC<PropsWithChildren>;
};

Creating Dialog Components

To create a dialog component, define a React component that accepts YapperDialogContentProps<T>:

import { YapperDialogContentProps } from 'yapperjs';

type MyDialogProps = YapperDialogContentProps<string> & {
  initialValue?: string;
};

function MyDialog({ resolve, reject, cancel, api, initialValue = '' }: MyDialogProps) {
  const [value, setValue] = useState(initialValue);
  
  return (
    <div className="dialog">
      <h2>Enter a value</h2>
      <input 
        value={value} 
        onChange={(e) => setValue(e.target.value)} 
      />
      <div className="actions">
        <button onClick={() => cancel()}>Cancel</button>
        <button onClick={() => resolve(value)}>Submit</button>
      </div>
    </div>
  );
}

Advanced Usage

Using Dialog Content Props

Each dialog content component receives these props:

Prop Type Description
resolve (value: T) => void Call to resolve the dialog with a value
reject (error: Error) => void Call to reject the dialog with an error
cancel () => void Call to cancel the dialog (same as resolving with undefined)
api YapperApi The YapperApi instance that created this dialog

Passing Arguments to Dialogs

You can pass additional props to your dialog components:

const result = await yapperApi.showDialog({
  content: UserFormDialog,
  args: {
    userId: '123',
    initialName: 'John Doe',
  }
});

Nested Dialogs

You can easily create nested dialogs by using the api prop:

function ConfirmDeleteDialog({ resolve, api, itemName }) {
  const handleDelete = async () => {
    // Show another dialog within this dialog
    const password = await api.showDialog({
      content: PasswordDialog,
      args: { prompt: 'Enter your password to confirm deletion' }
    });
    
    if (!password) {
      return;
    }
    
    // Continue with deletion
    resolve(true);
  };
  
  return (
    <div className="dialog">
      <h2>Delete {itemName}?</h2>
      <p>This action cannot be undone.</p>
      <div className="actions">
        <button onClick={() => resolve(false)}>Cancel</button>
        <button onClick={handleDelete}>Delete</button>
      </div>
    </div>
  );
}

Custom Dialog Styling

YapperJS provides several options for styling:

const result = await yapperApi.showDialog({
  content: MyDialog,
  backdropClassname: 'custom-backdrop',
  backdropStyle: { backgroundColor: 'rgba(0, 0, 0, 0.8)' },
  positionerClassname: 'dialog-positioner',
  wrapper: ({ children }) => (
    <ThemeProvider theme={darkTheme}>
      {children}
    </ThemeProvider>
  )
});

For global styling, YapperJS provides these CSS classes that you can override:

  • .yapper__dialog_backdrop - The backdrop/overlay behind the dialog
  • .yapper__dialog_positioner - The container that positions the dialog content

Note: These classes already have default styles applied by YapperJS. To override them, ensure your CSS has higher specificity or is loaded after the YapperJS styles:

/* Example: Override default dialog styling */
/* Option 1: Use higher specificity */
body .yapper__dialog_backdrop {
  background-color: rgba(0, 0, 0, 0.75) !important;
  backdrop-filter: blur(2px);
}

/* Option 2: Ensure your CSS loads after YapperJS styles */
.yapper__dialog_backdrop {
  background-color: rgba(0, 0, 0, 0.75) !important;
  backdrop-filter: blur(2px);
}

.yapper__dialog_positioner {
  padding: 2rem !important;
  display: flex;
  align-items: center;
  justify-content: center;
}

TypeScript Support

YapperJS is built with TypeScript and provides full type safety:

// Define the return type of your dialog
type UserFormData = {
  name: string;
  email: string;
};

// The showDialog call will be properly typed
const userData = await yapperApi.showDialog<UserFormData, { initialEmail: string }>({
  content: UserFormDialog,
  args: { initialEmail: 'user@example.com' }
});

// userData will be typed as UserFormData | undefined

License

MIT