1.4.1 • Published 3 years ago

@gabrielphala/stem v1.4.1

Weekly downloads
-
License
MIT
Repository
github
Last release
3 years ago

Stem.js

A JavaScript Single Page Application (SPA) Framework

Installation

Intall using npm package manager

npm i @gabrielphala/stem

Usage


Src\app.js

import layouts from './layouts';
import groups from './groups';
import components from './components';
import pages from './pages';
import transitions from './transitions';
import events from './events';

export default () => {
    layouts();
    groups();
    components();
    pages();
    transitions();
    events();
};

Src\index.js

import stem from '@gabrielphala/stem';
import app from './app.js';

app();

stem.config({
    logs: {
        info: true, // Default false
        warn: true, // Default true
    },
    page: {
        title: 'Web title'
    }
});

stem.load();

Layouts

Define the layout of components to use on page load


Src\layouts.js

import Layouts from '@gabrielphala/stem/layouts';

Layouts.create('layout.one', {
    html: `
        <div class="page-wrapper__main">
            {{component.one}}

            <!-- dynamic component (multiple components merged into one to change according to the page) -->
            <div class="page-wrapper__main__center">
                {{tag.group.one}}
            </div>
        </div>
    `
});

Groups

Tag Groups

Used for changing content dynamically on page reload


Src\groups\tags.js

import Groups from "@gabrielphala/stem/Groups";

export default () => {
    // Tag groups load components based on the page the user is currently on
    Groups.use('tag').make('tag.group.one', [
        // this component will be loaded when on the page '/u/:user/page-one'
        { name: 'page.one.component', uri: '/u/:user/page-one' },

        // this component will be loaded when on the page '/u/:user/page-two'
        { name: 'page.two.component', uri: '/a/:user/page-two' },
    ]);

    // match one tag component to multiple page URIs
    Groups.use('tag').make('page.title', [
        {
            name: 'customer.page.titles',
            uris: [
                '/u/:username/profile',
                '/u/:username/profile/tab-one',
                '/u/:username/profile/tab-two',
            ] 
        },
    ]);

    // or use page tags
    Groups.use('tag').make('page.title', [
        {
            name: 'customer.page.titles',
            uris: Pages.getPagesByTag('customer.page.titles')
        },
    ]);
};

Transition Groups

Used for changing content dynamically when switching pages without reloading


Src\groups\transitions.js

import Groups from "@gabrielphala/stem/Groups";

export default () => {
    // Transition groups replace the innerHTML of elements with specific components base on the page the user is switching to
    Groups.use('transition').make('transition.group.one', [
        {
            name: 'page.one',
            targets: [    
                // replaces the innerHTML of this element with the contents of the component ('page.one.component')
                { target: 'page-wrapper__main__center', component: 'page.one.component' },
            ]
        },
        {
            name: 'page.two',
            targets: [
                // replaces the innerHTML of this element with the contents of the component ('page.two.component')
                { target: 'page-wrapper__main__center', component: 'page.two.component' },
            ]
        }
    ]);
};

Components

Building blocks of the application, they are loaded individually and cached and re-used where necessary


Src\groups\components.js

Instantiate all components at once

import Components from "@gabrielphala/stem/Components";

export default () => {
    Components.all([
        {
            name: 'page.one.component',
            uri: '/c/page-one-component',
        },
        {
            name: 'page.two.component',
            uri: '/c/page-two-component',
        }
    ]);
}

Instantiate components one at a time

Components.create('page.one.component', {
    uri: '/c/page-one-component',
});

Components.create('page.two.component', {
    uri: '/c/page-two-component',
});

Components with navigation

Components.create('sidenav', {
    uri: '/c/sidenav',
    nav: {
            parent: 'sidenav',

            /**
                classes or class that can be clicked | Array | String
            */
            targets: 'sidenav__item',

            /**
                Highlights the main page on a navigation element like a header or sidebar while the current page is within a sub directory
            */
            linkmultiple: {

                /**
                    can be named anything really
                */
                mainPage: ['page.main.tab.one', 'page.main.tab.two']
            }
        },

    /**
        The navigation is limited to pages within the scope
    */
    scope: [
        'page.one',
        'page.two'
    ]
});

Components with beforeLoad

Pages.create('customer.profile', {
    title: 'Profile',
    uri: '/u/:username/profile',
    layout: Layouts.use('customer.profile')
});

const profileOverview = Components.create('profile.overview', {
    uri: '/c/profile/overview',
});

profileOverview.beforeLoad((Component) => {
    Component.URI = Component.URI + '/' + Pages.currentParams.username;

    Component.modified = true;
});

Properties to take note of

  • nav (Optional) Indicates that a component is of type navigation, makes things easier for the developer in such a way that the Framework detects an active page, adds event listeners, highlights active pages and sub-pages / sub-directories (linkmultiple is required for sub-pages / sub-directories)

  • linkmultiple (Optional) Each sub property like mainPage defined above correspondes to data-linkmultiple on the HTML side of things. The array elements represent sub-pages or sub-directories

  • scope (Optional but required for nav) Navigation is limited to pages defined in the scope

Example of a nav component

    <div class="sidenav">
        <div class="sidenav__item" data-linkmultiple="mainPage" data-linkaddress='/u/johndoe/page-one' data-linkactive='sidenav__item--active'>
            <p>Page one</p>
        </div>
        <div class="sidenav__item" data-linkaddress='/u/johndoe/page-two' data-linkactive='sidenav__item--active'>
            <p>Page two</p>
        </div>
    </div>

Pages

Pages are pages :)


Src\pages.js

import Pages from '@gabrielphala/stem/Pages';
import Layouts from '@gabrielphala/stem/Layouts';

export default () => {
    Pages.create('page.one', {
        title: 'Page one',
        uri: '/u/:user/page-one',
        tags: ['type.of.tag.one', 'page.name', 'another.tag'],
        layout: Layouts.use('layout.one')
    });

    Pages.create('page.two', {
        title: 'Page two',
        uri: '/u/:user/page-two',
        tags: ['type.of.tag.two', 'page.name', 'another.tag'],
        layout: Layouts.use('layout.one')
    });
};

Page Params, Params can be defined in a page URI and resolved when that page is loaded by the brower

Pages.currentParams; // returns params of the current page

Pages.use('page.name').params // returns params

Page Tags. Group pages into multiple categories and return their names when they are used

export default () => {
    const allPages = Pages.getPagesByTag('another.tag');

    console.log(allPages[0], allPages[1]) // page.one, page.two

    // tags can used to limit components to certain pages effeciently
    Components.create('sidenav', {
        uri: '/c/sidenav',
        nav: {
            linkmultiple: {
                links: Pages.getPagesByTag('links'),
                linksTwo: Pages.getPagesByTag('linksTwo')
            }
        }
        scope: Pages.getPagesByTag('page.name')
    });
};

Transitions

Relationships between pages, what must happen when a user moves from page 1 to 2


Src\transitions.js

import Transitions from '@gabrielphala/stem/Transitions';

export default () => {
    const transitionOne = Transitions.create('transition.one', {
        from: ['page.one', 'page.two'],
        to: ['page.two', 'page.two'],
        group: 'transition.group.one'
    });

    transitionOne.updates((page) => {
        // remove some elements and stuff
    });
};

Events


Component events, will be fired when something happens to the component, like when it is loaded

Src\events\sign-in.js

import Components from '@gabrielphala/stem/Components';
import Stem from '@gabrielphala/stem';

import userAuth from '../../auth/User';

export default () => {
    Components.use('customer.sign.in').onShow((Component) => {
        $('.customer__login__form').on('submit', async (e) => {
            e.preventDefault();

            const response = await userAuth.signIn('customer');

            if (response.successful)
                Stem.load(response.redirect);
        });
    });
};

Page events, will be fired when something happens to the page, like when it is loaded

Src\events\profile.js

import Pages from '@gabrielphala/stem/Pages';

export default () => {
    Pages.use('customer.profile').onShow((Page) => {
        // Do something when customer profile is shown
    });
};

Default page events, will be fired when something happens to a group of pages, like when they are loaded

Src\events\default.js

import Pages from '@gabrielphala/stem/Pages';

export default () => {
    const defaultPage = Pages.use();

    defaultPage
        .create('customerForms', Pages.getPagesByTag('customerForms'))
        .onShow((Page) => {
            // Do something whenever a customer forms related page is shown
        });

    defaultPage
        .create('sellerForms', Pages.getPagesByTag('sellerForms'))
        .onShow((Page) => {
            // Do something whenever a seller forms related page is shown
        });
};
1.4.1

3 years ago

1.4.0

3 years ago

1.3.0

3 years ago

1.2.0

3 years ago

1.1.2

4 years ago

1.1.1

4 years ago

1.1.0

4 years ago

1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago