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 🙏

© 2024 – Pkg Stats / Ryan Hefner

apphouse

v0.1.260

Published

Component library for React that uses observable state management and theme-able components.

Downloads

879

Readme

Apphouse

** THIS LIBRARY IS UNDER DEVELOPMENT - API MIGHT CHANGE SIGNIFICANTLY **

  • A highly efficient method for creating a React + Typescript application.
  • Comprehensive reusable components that can look completely different based on a configurable theme
  • Models that support observability for faster and more efficient rendering

Why Apphouse?

  • Apphouse simplifies the pain of writing themes, forms, popups, routes, feedback, etc., providing a comprehensive solution for all these essential components that you always need. Although it can handle a lot, using Apphouse is incredibly easy and user-friendly.

Usage

Via CLI

With our cli app, you can effortlessly start an entire project in just two simple commands.

Note: You must use node v18.0.0 nvm use v18.0.0

npm install -g apphouse-cli
apphouse-cli your-project-name

Manually

npm install apphouse

Sample App

Initialize Apphouse

import React from 'react';
import ReactDOM from 'react-dom/client';
import { initApphouse } from 'apphouse';

const store = initApphouse(routes);

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <ApphouseApp store={store} />
);

Setting Up Routes

To define specific routes for your app, simple create a route object and use it when initializing apphouse

import React from 'react';
import ReactDOM from 'react-dom/client';
import { initApphouse, ApphouseApp } from 'apphouse';

const routes: Route[] = [
  {
    path: '/',
    title: 'Home',
    component: () => {
      return <App />;
    }
  }
];

const store = initApphouse(routes);

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <ApphouseApp store={store} />
);

Setting Up Restricted Routes

To define a restricted route, simply wrap it with RequiresFirebaseAuthentication component. We currently only support firebase simple email & password authentication.

import React from 'react';
import ReactDOM from 'react-dom/client';
import { initApphouse } from 'apphouse';

const routes: Route[] = [
  {
    path: '/',
    title: 'Home',
    component: () => {
      return <App />;
    }
  },
  {
    path: '/account',
    title: 'Account',
    component: (
      <RequiresFirebaseAuthentication showSignInButton showSignOutButton>
        <MySecretContentComponent />
      </RequiresFirebaseAuthentication>
    )
  }
];

const firebaseConfig = {
  apiKey: 'yourApiKey',
  authDomain: 'yourAuthDomain',
  projectId: 'yourProjectId',
  storageBucket: 'yourStorageBucket',
  messagingSenderId: 'yourMessagingSenderId',
  appId: 'yourAppId',
  measurementId: 'yourmeasurementId'
};

const appStore = new AppStoreWithUser(firebaseConfig);
const store = initApphouse(
  Routes,
  appStore as IStoreWithBase<AppStoreWithUser>
);

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <ApphouseApp store={store} />
);

Setting Up Routes With Params

We also accept parametrized routing

import React from 'react';
import ReactDOM from 'react-dom/client';
import { initApphouse } from 'apphouse';

const routes: Route[] = [
  {
    path: '/account/:id',
    title: 'My Account',
    component: ({ id }) => <MyComponentForPage1 id={id} />
  }
];

const store = initApphouse(routes);

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <ApphouseApp store={store} />
);

Extending Theme

You can change your app theme simply by extending apphouse's default theme or making your own from scratch

Extending Theme

const BRAND_COLOR = 'rgb(236, 0, 138)';
const customTheme: ApphouseTheme = extendTheme(DarkTheme, {
  colors: {
    brand: BRAND_COLOR
  },
  tokens: {
    radius: {
      default: '30px'
    }
  },
  styles: {
    input: {
      default: {
        borderRadius: '30px'
      }
    }
  }
});
const store = initApphouse(routes);

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <ApphouseApp store={store} theme={customTheme} />
);

Check out our demo app to get a sneak peek at how you can easily customize your theme. Simply visit this link to explore and experiment with various customization options.

Personalized Not Found Page

Every time a user tries to access a route that doesn't exist, they will be redirected to this page. By default Apphouse offers a standard 404 Not Found page. If you want to overwrite this page with your own 404 page add your 404 substitute when defining the route

const routes: Route[] = [
  {
    path: '/404',
    title: 'Not Found',
    component: () => <MyCustom404Page />
  }
];

Handling Alerts

Anywhere inside of your components you can fire the feedback by calling the alert method

const { alert } = useApphouse();

alert({
  type: FeedbackType.success,
  message: 'Success message',
  duration: 3000
});

Handling Forms

Apphouse provides a simple and efficient way to handle very complex forms. To create a form, simply create a new instance of Form class and pass in the form configuration object.

const form = new Form({
  id: "signUp", // you will use this id to retrieve this form later
  title: 'Sign Up!',
  fields: {
    // initial value for this field can be set here
    name: "",
    // initial value for this field can be set here
    email: ""
  },
  validations: {
    email: (value: string) => {
      // do email validation
      return true if valid, return false if invalid
    }
  },
  options: {},  // no options
  required: ['name', 'email'], // both name and email fields are required

Updating Values

To update form field value simply:

form.setValue('name', 'updatedName');

Accessing form values

const name = form.getValue('name');

Get all form data

To get current form data

const formData = form.data;

For more detailed information on how to use the form view the form documentation

Using the ApphouseForm Component

If you just want to create a simple form, you can use the ApphouseForm component.

Below is an example that showcases the usage of ApphouseForm component along with the Popup component to create a prompt that asks the user to enter a file name.

import { ApphouseForm } from '../components/Form/ApphouseForm';
import { Popup } from '../components/popup/Popup';

/**
 * A prompt that will ask the user to enter a file name
 */
export const PromptFilename = ApphouseComponent((props: { onConfirm }) => {
  const { onConfirm } = props;

  const onSubmission = (formData) => {
    onConfirm(formData.filename);
  };
  return (
    <Popup
      id="PromptFilenamePopup"
      title="Save theme as"
      closeOnClickOutside
      hideFooterActions
      showCloseButton
      width="320px"
      gutters={4}
    >
      <ApphouseForm
        id="PromptFilenameForm"
        fields={[
          {
            id: 'filename',
            label: 'File name',
            type: 'text',
            required: true,
            value: undefined,
            styleOverwrites: {
              container: {
                width: '100%'
              },
              input: {
                width: '100%'
              }
            }
          }
        ]}
        submitButtonLabel="Save"
        onSubmission={onSubmission}
      />
    </Popup>
  );
});

Registering Shortcuts

Apphouse can handle shortcuts anywhere in the app. You can register a global shortcut by:

app.shortcuts.register('escape', callback);

Similarly you can unregister a global shortcut by

app.shortcuts.unregister('escape', callback);

If you want to register multiple shortcuts you can do so by using the registerAppShortcuts method

app.shortcuts.registerAppShortcuts([
  {
    combo: 'cmd+s',
    action: () => {
      console.log('save');
    }
  }
]);

Shortcut in Text fields

By default all keyboard events will not fire if you are inside of a textarea, input, or select to prevent undesirable things from happening.

Partial Views

A partial view refers to any view within the application that does not take up the entire page or is considered "transient" within a flow. Examples of partial views include modals, tabs, popups, pickers, and so on.

There are several scenarios in which you would want to set a partial view:

  1. When you want to provide the option for users to quickly close the view by using the 'escape' shortcut.
  2. When you want to enable users to access the view via a specific URL.
  3. When you want to allow the opening and closing of the view through a trigger located in a completely different place from where the view will be displayed.
// set up route in routes and set openPartial: true

  {
    path: '/demo/:themeEditor',
    title: 'Theme Editor Drawer Open',
    openPartial: true,
    component: () => {
      return <Demo />;
    }
  }
export const DrawerDemo = observer(() => {
  const { app } = useApphouse();
  const { view } = app;

  return (
    <React.Fragment>
      <div>
        <Button
          onClick={() => {
            // this will open the drawer below and also update the url
            // to be demo/themeEditor
            view.setView('themeEditor', true);
          }}
        >
          Edit theme
        </Button>
      </div>

      <Drawer
        id="theme-editor"
        open={view.getViewStatus('themeEditor')}
        onClose={() => view.setView('themeEditor', false)}
      >
        drawer content
      </Drawer>
    </React.Fragment>
  );
});