All Projects → alshdavid → Crayon

alshdavid / Crayon

Licence: mit
Simple framework agnostic UI router for SPAs

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to Crayon

svelte-router
Router component for Svelte
Stars: ✭ 63 (-79.68%)
Mutual labels:  router, svelte
Svelte Router
Svelte Router adds routing to your Svelte apps. It's designed for Single Page Applications (SPA). Includes localisation, guards and nested layouts.
Stars: ✭ 310 (+0%)
Mutual labels:  router, svelte
Abstract State Router
Like ui-router, but without all the Angular. The best way to structure a single-page webapp.
Stars: ✭ 288 (-7.1%)
Mutual labels:  router, svelte
Svelte Store Router
Store-based router for Svelte
Stars: ✭ 54 (-82.58%)
Mutual labels:  router, svelte
svelte-micro
Light & reactive one-component router for Svelte
Stars: ✭ 81 (-73.87%)
Mutual labels:  router, svelte
Yrv
Your routing! (for Svelte)
Stars: ✭ 143 (-53.87%)
Mutual labels:  router, svelte
Svelte Router
Simple Svelte Router for Single Page Applications (SPA).
Stars: ✭ 44 (-85.81%)
Mutual labels:  router, svelte
svelte-starter-kit
Svelte starter kit — router, state management and testing included.
Stars: ✭ 16 (-94.84%)
Mutual labels:  router, svelte
Curi
A JavaScript router for single-page applications
Stars: ✭ 262 (-15.48%)
Mutual labels:  router, svelte
Angular
UI-Router for Angular: State-based routing for Angular (v2+)
Stars: ✭ 287 (-7.42%)
Mutual labels:  router
Elasticluster
Create clusters of VMs on the cloud and configure them with Ansible.
Stars: ✭ 298 (-3.87%)
Mutual labels:  spark
Spark Druid Olap
Sparkline BI Accelerator provides fast ad-hoc query capability over Logical Cubes. This has been folded into our SNAP Platform(http://bit.ly/2oBJSpP) an Integrated BI platform on Apache Spark.
Stars: ✭ 282 (-9.03%)
Mutual labels:  spark
Cortex
Routing system for WordPress
Stars: ✭ 300 (-3.23%)
Mutual labels:  router
React Overdrive
Super easy magic-move transitions for React apps
Stars: ✭ 3,001 (+868.06%)
Mutual labels:  router
Routing Controllers
Create structured, declarative and beautifully organized class-based controllers with heavy decorators usage in Express / Koa using TypeScript and Routing Controllers Framework.
Stars: ✭ 3,557 (+1047.42%)
Mutual labels:  router
Wouter
🥢 A minimalist-friendly ~1.5KB routing for React and Preact. Nothing else but HOOKS.
Stars: ✭ 3,654 (+1078.71%)
Mutual labels:  router
Link
A PHP router that helps you create webapps and APIs effortlessly
Stars: ✭ 282 (-9.03%)
Mutual labels:  router
Svelvet
🧵 An experimental svelte compiler & watcher that works with snowpack
Stars: ✭ 310 (+0%)
Mutual labels:  svelte
Eventline
Micro-framework for routing and handling events for bots and applications 🤖. IFTTT for developers 👩‍💻👨‍💻
Stars: ✭ 305 (-1.61%)
Mutual labels:  router
Mpvue Router Patch
🛴在 mpvue 中使用 vue-router 兼容的路由写法
Stars: ✭ 298 (-3.87%)
Mutual labels:  router













SPA Router, for all Frameworks

version size coverage dependencies coverage

  • Clientside Router
  • Express like syntax
  • Select your framework with middleware
  • Select your animations with middleware
  • No dependencies

Example

import React from 'react'
import crayon from 'crayon'
import react from 'crayon-react'

const app = crayon.create()

app.use(react.router())

app.path('/', ctx => {
    return ctx.mount(() => <h1>Hello World</h1>)
})

app.path('/users/:id', ctx => {
    return ctx.mount(() => <div>Hi { ctx.params.id }!</div>)
})

app.path('/**', ctx => {
    return ctx.mount(() => <div>Not Found!</div>)
})

app.load()

To nagivate use:

app.navigate('/users/27')

Introduction and Explanation

Crayon is a simple client-side UI router that uses a time-tested and familiar pattern to route actions based on browser paths.

The routing style is seen in serverside frameworks like Express in Node and Gin in Go, so it's nothing new - but a tool I felt browser-based applications were lacking.

While the router itself is only responsible for running a callback which it selects based on pattern matching the browser's path, you are able to compose behaviours using middleware.

This means that the front-end framework or animations you choose are a middleware concern, not a routing concern.

The philosophy behind Crayon is to ask less of our front-end frameworks, but get more

Contributing Guide

Installing

npm install --save crayon

Framework Middlewares



npm install --save crayon-react
import react from 'crayon-react'
app.use(react.router())


npm install --save crayon-preact
import preact from 'crayon-preact'
app.use(preact.router())


npm install --save crayon-vue
import vue from 'crayon-vue'
app.use(vue.router())


npm install --save crayon-svelte
import svelte from 'crayon-svelte'
app.use(svelte.router())

Coming soon




Route Groups

Groups are created using the crayon.group function, which creates a middleware of groups that you can use later

const items = crayon.group('/items')

items.use(your.middleware())

// This will be "/items"
items.path('/', ctx =>
    ctx.mount(views.ItemsView)
)

// This will be "/items/add"
items.path('/add', ctx =>
    ctx.mount(views.ItemsAddView)
)

app.use(items)
app.load()

It also supplies an optional callback with the group object. This allows you to define variables within a scope dedicated to that group.

const items = crayon.group('/items', group => {
    group.use(your.middleware())

    group.path('/', ctx =>
        ctx.mount(views.ItemsView)
    )

    group.path('/add', ctx =>
        ctx.mount(views.ItemsAddView)
    )
})

app.use(items)
app.load()

Route parameters and observing changes

You can add paramaters in the route path and observe the changes. The observe method is used to prevent rerenders which can cause problems when dealing with nested routers and components that require preserved state

For the sake of reducing external dependencies and package size, I am not using rxjs. This uses a portion of the rxjs API to enable dealing with event streams.

In future, I intend to create a middleware that implements rxjs, allowing you to pipe the stream into their operators/utilities (like .map() and .filter())

app.path('/users/:id', ctx => {
    let id = ctx.params.id

    // subscribe to the event steam and pull out the
    // "ProgressEnd" event
    const sub = app.events.subscribe(event => {
       if (event.type === RouterEventType.ProgressEnd) {
           id = ctx.params.id
       }
    })

    // A callback the router fires when you
    // navigate away from this page
    ctx.onLeave(() => sub.unsubscribe())
})

Nested routers

They work just fine, just be sure to destroy a router before leaving a page

const app = crayon.create('main')
app.path('/dashboard/:tab', handler)

const nested = crayon.create('tab-view')
nested.path('/dashboard/tab-a', handler)
nested.path('/dashboard/tab-b', handler)
nested.destroy()

You would setup the nested router inside your component, targeting an element reference to obtain a mount-point

Take a look at the example in /examples/crayon-react-app. It is the demo in the readme gif and features a nested router as the tab view.

Animations Middleware

This works on all frameworks

Route Transitions are done using a middleware that applies/removes CSS styles over the course of a routing event.

You specify the "name" of the CSS class and the middleware will add/remove the following classes:

.name
.name-exit
.name-enter
.name-enter-done
.name-enter-first

The middleware can be placed on the global level, on a group or inline on the route itself. To declare defaults, use the following:

npm install --save crayon-animate
import animate from 'crayon-animate'

app.use(animate.defaults({
    name: 'css-class-name',
    duration: 350
}))

You can specify custom rules for a few routes:

import animate from 'crayon-animate'

app.use(animate.routes([
    { from: '/a',  to: '/b',  name: 'slide-left' },
    { from: '/b',  to: '/a',  name: 'slide-right' },
    { from: '/**', to: '/c',  name: 'fade' },
    { from: '/c',  to: '/**', name: 'fade' }
]))

When provided inline on a route, you can omit the respecive to/from

import animate from 'crayon-animate'

app.use(animate.defaults({
    name: 'fade',
    duration: 350
}))

app.path('/a', ctx => ctx.mount(() => <div>Route A</div>))
app.path('/b', ctx => ctx.mount(() => <div>Route B</div>))

// If you come from anywhere to /c slide-right
// If you go to anywhere from /c slide-left
app.path('/c',
    animate.route([
        { from: '/**', name: 'slide-right' },
        { to:   '/**', name: 'slide-left' }
    ]),
    ctx => {
        return ctx.mount(() => <div>Animated</div>)
    }
)

Animations package

For those who don't want to spend time writing animations, Crayon comes bundled with a bunch.

npm install --save crayon-transition

Just use the middleware

import animate from 'crayon-animate'
import transition from 'crayon-transition'

app.use(transition.loader())
app.use(animate.defaults({
    name: transition.pushLeft,
    duration: 350
}))

Available bundled animations

transition.fade

transition.pushUp
transition.pushDown
transition.pushLeft
transition.pushRight

transition.popUp
transition.popDown
transition.popLeft
transition.popRight

transition.slideUp
transition.slideDown
transition.slideLeft
transition.slideRight

Code Spliting and Lazy Loading

Just use the dynamic import() feature. It's baked into modern browsers and available through module bundlers.

Loading a route

app.path('/', async ctx => {
    const HomeView = await import('./home-view')
    ctx.mount(HomeView)
})

Code splitting a group

First create a group in a file

// my-group.js
export const myGroup = crayon.group('/my-group', myGroup => {
    myGroup.path('/',
        ctx => ctx.mount(MyView)
    )
})

Then load it in and use it

// main.js
void async function main() {
    const app = crayon.create()
    app.use(framework.loader())

    const { myGroup } = await import('./my-group')
    app.use(myGroup)

    app.load()
}()

Lazy loading a group just requires you to trigger the load action inside a route handler

// main.js
void async function main() {
    const app = crayon.create()
    app.use(framework.loader())

    // This will wait until the user is on /my-group
    // before fetching and loading the routes into
    // the browser
    app.path('/my-group', async ctx => {
        const { myGroup } = await import('./my-group')
        app.use(myGroup)
        app.load()
    })

    app.load()
}()
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].