jaredgorski / StructUI

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

StructUI npm bundle size

NOTE: This repository is not actively maintained, largely because React Router is far superior and there's very little need for a component like this. However, below is the documentation in case you feel a desire to use this package. It's should be available as long as npm is up and running.

Install

npm i structui

What is it?

StructUI is a React component which consumes a configuration object and generates a web application UI in the form of a file explorer.

Conceptually, individual webpages on a website can be thought of as files, and groups of files can be organized into directories. This means that a file explorer interface, like Finder on MacOS or Explorer on Windows, can be a natural user-experience for website navigation. The primary benefit of a component like this for React is that it enables a developer to configure an entire website structure from one file, loading pages/components as lambdas while handling server configuration separately for any pages that need to be navigable from the address bar. In other words, entire pages can be loaded as higher-order React components underneath StructUI with very little configuration, allowing for fast and light SPA-like navigation (no server middleware). If address-bar navigation (server middleware) is needed, StructUI can be easily loaded and configured per-page. StructUI also supports wrapping file/directory navigation links with framework router components (like Link from Next.js), which enables pre-fetching and other framework-specific features.

Usage

StructUI is meant to contain an entire user experience, so it will be among the first components invoked in a React application. The below examples provide insight into how the code might actually look, though different applications may vary. Take note that, since the configuration object for StructUI is a JavaScript object, it can be generated programmatically (as long as this is done synchronously) to improve code organization and maintainability.

See the /examples directory for examples you can run locally.

Simple usage

structui-config.js:

// These imported components render "displays", AKA "views" or webpages. A display is loaded by StructUI 
// when its corresponding navigation element is activated, much like single-clicking a file in MacOS' 
// Finder opens a display pane with details about the file. Nesting files in directories (via `childNodes`) 
// results in nested panes within StructUI.
import FileDisplay from '../components/FileDisplay';
import SubFile1Display from './components/SubFile1Display';
import SubFile2Display from './components/SubFile2Display';

export const structUIConfig = {
  nodes: {                                // -> `nodes` are directories and files
    myDirectory: {                        // -> directories can hold multiple directories and/or files within them
      label: 'my directory',              // -> `label` defines the node's title in StructUI
      childNodes: {                       // -> `childNodes` is where sub-directories/files are defined for a given
        subfile1: {                       //     directory
          label: 'subfile1',
          display: {                      // -> files are denoted by the lack of `childNodes` and the presence of `display`
            component: SubFile1Display,   // -> the `display`property can load an imported component (class or function) 
          },                              //    when its node is selected
        },
        subfile2: {
          label: 'subfile2',
          display: {
            component: SubFile2Display,
          },
        },
      },
    },
    file: {
      label: 'file',
      display: {
        component: FileDisplay,
      },
    },
  },
};

index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import StructUI from 'structui';
import {structUIConfig} from './structui-config';

class App extends React.Component {
  render () {
    return (
      <StructUI {...structUIConfig} />
    );
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

Advanced usage (with Next.js)

structui-config.js:

import Link from 'next/link';

import FileDisplay from '../components/FileDisplay';
import SubFileDisplay from '../components/SubFileDisplay';

export const structUIConfig = {
  config: {                               // -> `config` allows for customizing global StructUI settings
    toggleIcon: <svg height="18" width="18" viewBox="0 0 30 30"><use href="/static/toggle-icon.svg"></use></svg>,
  },
  nodes: {
    myDirectory: {
      icon: {                             // -> `icon`s can be configured to denote open or closed directories and files
        closed: <svg height="18" width="18" viewBox="0 0 30 30"><use href="/static/closed-icon.svg"></use></svg>,
        open: <svg height="18" width="18" viewBox="0 0 30 30"><use href="/static/open-icon.svg></use></svg>,
      },
      label: 'directory',
      link: {                             // -> the `link` property defines the props/attributes of a node's anchor element
        props: {
          href: '/directory',             // -> when this `directory`'s item in StructUI is clicked, the browser will 
        },                                //    navigate to '/directory'
      },
      childNodes: {
        subfile: {
          icon: {
            closed: <svg height="18" width="18" viewBox="0 0 30 30"><use href="/static/closed-icon.svg"></use></svg>,
            open: <svg height="18" width="18" viewBox="0 0 30 30"><use href="/static/open-icon.svg></use></svg>,
          },
          label: 'subfile',
          link: {
            element: Link,                // -> this `link` will be wrapped by the `Link` routing element from Next.js 
            props: {                      //    imported at the top of this document, allowing for pre-fetching
              href: '/directory/subfile',
            },
          },
          display: {
            component: SubFileDisplay,
            props: {
              title: 'My Subfile',        // -> props can be passed into the display component from StructUI, though 
            },                            //    it's important to note that StructUI only supports synchronous behavior.
          },                              //    any asynchronous data can be loaded and managed on the component itself 
        },                                //    when it is activated by StructUI
      },
    },
    file: {
      icon: {
        closed: <svg height="18" width="18" viewBox="0 0 30 30"><use href="/static/closed-icon.svg"></use></svg>,
        open: <svg height="18" width="18" viewBox="0 0 30 30"><use href="/static/open-icon.svg></use></svg>,
      },
      label: 'file',
      link: {
        element: Link,
        props: {
          href: '/file',
        },
      },
      display: {
        component: FileDisplay,
        props: {
          color: 'firebrick',
        },
      },
    },
  },
};

_app.js:

import App from 'next/app';
import React from 'react';

import 'structui/styles.css';             // -> default StructUI stylesheet exists in the root of the module

class Site extends App {
  render() {
    const {Component, pageProps} = this.props;
    return <Component {...pageProps} />;
  }
}

pages/subfile.js:

import Head from 'next/head'
import StructUI from 'structui';
import {structUIConfig} from '../props/structui-config';

function SubFile() {
  const initialProps = Object.assign({}, structUIConfig);
  initialProps.activeNodePath = ['directory', 'subfile'];   // -> defines the active filepath 
                                                            //    within StructUI for this page
  return (
    <>
      <Head>
        <title>My Subfile</title>
      </Head>
      <StructUI {...initialProps} />
    </>
  );
}

Try it out

To see a full implentation of StructUI in action, check out https://jaredgorski.org

Here's a gif of what a basic example can do:

About


Languages

Language:JavaScript 85.8%Language:CSS 14.2%