npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ulysseswbdv

v1.1.74

Published

Ulysses Web(BDV)

Readme

Ulysses Web BDV Library

Install the Web BDV Ulysses library to quickly build Web BDVs with:

  • shared header toolbar
  • page navigation sidebar
  • footer action bar
  • iframe lifecycle helpers (close, save & close, etc.)
  • built-in "Copy URL" deep link action (copyurl)

📦 Installation

npm i ulysseswbdv

⚙️ Configuration Objects

Your BDV defines three config arrays and passes them to the library.

export const toolbarActions = [
  {
    id: '',
    name: '',
    ico: '',        // icon font class (e.g. "material-icons")
    className: '',  // css class for <a>
    iconName: '',   // icon name or text shown inside <span>
    event: '',      // e.g. 'closewindow', 'copyurl'
    codeName: '',   // internal key (e.g. 'save', 'menu', 'copyurl')
    enabled: true,
    visible: true
  }
];

export const pages = [
  {
    id: '',
    name: '',
    url: '',
    ComponentName: '', // e.g. 'PreviewForm'
    active: false,
    display: 'block'   // or 'none' to hide in menu
  }
];

export const footerActions = [
  {
    codeName: '',
    id: '',
    name: '',
    page: '',      // which page this action belongs to
    iconName: '',  // material icon name
    enabled: true
  }
];

🧠 What the Library (<Index />) Does

ulysseswbdv/lib/Iframe:

  • Renders the standard BDV chrome (header / sidebar / footer).

  • Handles toolbar events like:

    • close window
    • close & refresh
    • previous / next page
    • copyurl
  • Copies the deep link to clipboard for you.

  • Shows success/error toast or fallback alert.

You don't reimplement this logic in each BDV.


🔌 What Your BDV Must Do

Your BDV:

  1. Listen for window.postMessage from TA Web.
  2. Save that raw payload into state as callerDataRaw (literally event.data).
  3. Pass callerDataRaw into <Index />.
  4. Control which sub-page is currently displayed and which buttons are enabled.

You do not build the share URL yourself. You do not expose getCopyUrl. You do not manage clipboard logic.

All of that is handled inside the library based on callerDataRaw.


🛰 Getting callerDataRaw from postMessage

When TA Web opens your BDV in an <iframe>, it sends a message event that includes everything the BDV needs:

  • token
  • user info
  • role / task / BU
  • selected row(s)
  • context selection
  • etc.

You just store it.

class ManageInspectionInstance extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      callerDataRaw: null,        // 👈 full event.data goes here
      componentName: 'PreviewForm',
      btnHeaderEnabled: [],
      btnEnabled: [],
      menuPages: true,
      // ...other state...
    };
  }

  componentDidMount() {
    window.addEventListener('message', this.onIncomingMessage);
  }

  componentWillUnmount() {
    window.removeEventListener('message', this.onIncomingMessage);
  }

  onIncomingMessage = (event) => {
    // we only care about real TA Web data objects
    if (typeof event.data !== 'object' || !event.data) return;
    if ('type' in event.data) return; // ignore framework/system noise

    // optional: store token for FetchData
    if (event.data.Token) {
      localStorage.setItem('authToken', event.data.Token);
    }

    // 🔴 IMPORTANT:
    // We no longer reshape or normalize fields. We keep it RAW.
    this.setState({
      callerDataRaw: event.data
    });

    // ...anything else you already do on load (fetch inspection, etc)...
  };

  // ...
}

That’s all. callerDataRaw is literally event.data.


🔗 Deep Link / Copy URL (copyurl)

What the user does

User clicks the "Copy URL" (or similar) button in the BDV header toolbar.

What happens

Inside the library:

  1. It reads this.props.callerDataRaw.

  2. It builds a deep link back into the same BDV, using fields like:

    • parentURL
    • FolderId, Folder
    • RoleId, TaskId
    • directoryId
    • SelectedRows[0].idIndex / identifiers
    • contextselection (joined if multiple)
    • ActionId, etc.
  3. It strips /iframe from parentURL and appends the correct query string.

  4. It copies the final URL to the clipboard.

  5. It shows success or error feedback (toast or alert).

You don’t write any of this logic.


🧩 Rendering <Index /> in Your BDV

import Index from 'ulysseswbdv/lib/Iframe';
import { toolbarActions } from './Utils/dataToolbar';
import { footerActions } from './Utils/actionsFooter';
import { pages } from './Utils/pagesInspection';

class ManageInspectionInstance extends React.Component {
  // ...state, lifecycle, etc...

  render() {
    return (
      <Index
        toolbaractions={toolbarActions}
        onSelectEvent={this.eventsHandler}             // you still get custom toolbar events
        pages={pages}
        pageActions={footerActions}
        onSelectPage={this.pagesHandler}               // sidebar navigation click
        onSelectPageActions={this.pagesActionsHandler} // footer button click
        btnHeaderEnabled={this.state.btnHeaderEnabled} // runtime enable/disable for header actions
        btnEnabled={this.state.btnEnabled}             // runtime enable/disable for footer actions
        pagesEnabled={this.state.menuPages}            // show/hide left sidebar
        callerDataRaw={this.state.callerDataRaw}       // 👈 just pass event.data here
      >
        {this.state.componentName === 'PreviewForm' ? (
          <PreviewForm
            /* ...props... */
          />
        ) : this.state.componentName === 'FormInformation' ? (
          <FormInformation
            /* ...props... */
          />
        ) : null}

        {/* example modals/popups managed by BDV */}
        <Error
          popupVisible={this.state.popupVisible}
          OneventsHandlerCloseSave={this.eventsHandlerCloseSave}
          OnhideInfo={this.hideInfo}
        />
        <Queries /* ... */ />
        <Warning /* ... */ />
      </Index>
    );
  }
}

Key points:

  • You must pass callerDataRaw to <Index />.
  • You NO LONGER pass getCopyUrl.
  • You NO LONGER set generatedUrl yourself.

🔁 Toolbar Events in Your BDV

Your BDV may still keep logic like this:

eventsHandler = (item) => {
  // The library now intercepts 'copyurl' internally,
  // so you do NOT have to handle it here.

  if (item.event === 'closewindow') {
    PostCloseEvent();
    return;
  }

  if (item.event === 'closewindowandrefresh') {
    PostCloseAndRefreshEvent();
    return;
  }

  if (item.event === 'forward') {
    const idx = pages.findIndex(p => p.ComponentName === this.state.componentName);
    if (pages[idx + 1]) {
      this.setState({ componentName: pages[idx + 1].ComponentName });
    }
    return;
  }

  if (item.event === 'back') {
    const idx = pages.findIndex(p => p.ComponentName === this.state.componentName);
    if (pages[idx - 1]) {
      this.setState({ componentName: pages[idx - 1].ComponentName });
    }
    return;
  }

  // custom BDV actions can go here...
};

If the toolbar item is copyurl, you don’t need code. <Index /> already handled it using callerDataRaw.


🖼 Host Page Requirements

Make sure the container page (the page where React mounts) includes the fonts/icons the library expects:

<head>
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <link rel="stylesheet"
        href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
  <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
</head>
<body class="skin-orange-light">
  <div id="root"></div>
</body>

✅ Summary

  • ulysseswbdv gives you a ready-made BDV shell (<Index />).

  • Your BDV still controls:

    • which internal page/component is showing,
    • button enable/disable state,
    • side menu visibility.
  • TA Web sends an initialization message to the iframe.

  • You store that message as-is:

    this.state.callerDataRaw = event.data;
  • You pass callerDataRaw into <Index />.

  • The library:

    • understands that payload,
    • builds the deep link,
    • handles copyurl,
    • copies to clipboard,
    • shows feedback.

You stop doing:

  • manual URL assembly,
  • generatedUrl state,
  • custom clipboard code

🗓️ Change Log

v1.1.74 — Unified Caller Data + Automatic Copy URL

Date: 2025-10-30 Highlights:

  • The library now fully handles Copy URL (copyurl) internally.
  • BDVs no longer need to pass getCopyUrl or build their own URL.
  • The only requirement is to pass callerDataRaw={event.data} to <Index />.
  • buildShareUrl and clipboard logic are automatically applied by the library.
  • Added internal feedback via ToastService or fallback alert().
  • Simplified developer setup — fewer props, less boilerplate per BDV.