Skip to content

A highly flexible rendering engine for virtual shelves, inventories, and catalog-like UIs, designed for Vue.js and powered by strict TypeScript models.

License

Notifications You must be signed in to change notification settings

tarobits/shelf-rendering-engine

Repository files navigation

Shelf Rendering Engine

License Version

A highly flexible rendering engine for virtual shelves, inventories, and catalog-like UIs, designed for Vue.js and powered by strict TypeScript models.

Warning

This is an early development release and currently not meant for production environments. All configuration options are subject to change at any point.

Installation

Just run the following command in your project to install the engine.

npm install @tarobits/shelf-rendering-engine

Then add the following two lines to the imports in the file you wish to use the engine:

import '@tarobits/shelf-rendering-engine/style.css';
import { RenderableShelf, Shelf, type ShelfType, type ViewableShelf } from '@tarobits/shelf-rendering-engine';

Usage

To create a shelf:

RenderableShelf.getShelfFromProps(shelfConfig).exportToViewable();

shelfConfig refers to an object matching the ShelfType type.

Or

RenderableShelf.getShelfFromProps(shelfDataConfig, shelfSizesConfig).exportToViewable();

shelfDataConfig and shelfSizesConfig refer to objects matching the ShelfData and ShelfSizes types respectively.

getShelfFromProps accepts either a full ShelfType object or a combination of ShelfData and ShelfSizes and returns a render-ready representation.

exportToViewable converts the class into a reactive class Vue can work with.

Minimal Example

const shelf = RenderableShelf.getShelfFromProps({
    innerWidth: 100,
    innerHeight: 50,
    backgroundColor: '#eee',
    outerColor: '#333',
    topWidth: 3,
    bottomWidth: 3,
    leftWidth: 3,
    rightWidth: 3,
    model: []
}).exportToViewable();

Data Types

Note

All widths and heights are relational. You may use centimeters, inches, or any other form of measurement. They will all be converted into pixels on rendering.

Main Types

ShelfType
{
  title: string, // (Optional) if you want a title to be displayed above your shelf
  subtitle: string, // (Optional) if you want a smaller text displayed below the title
  innerWidth: number, // (Required) how wide the shelf is from inner wall to inner wall
  innerHeight: number, // (Required) how tall the shelf is from inner bottom to inner top
  location: EntityLocation[], // (Optional) defines where the shelf is located (Purely meta data)
  backgroundColor: string, // (Required) what color to display in the background (Accepted: Any css color or an object with [r: 0-255, g: 0-255, b: 0-255])
  outerColor: string, // (Required) what color the shelf walls etc. are (Accepted: Any css color or an object with [r: 0-255, g: 0-255, b: 0-255])
  topWidth: number, // (Required) width of the top part of the shelf casing (0 if no top part exists)
  bottomWidth: number, // (Required) width of the bottom part of the shelf casing (0 if no bottom part exists)
  leftWidth: number, // (Required) width of the left part of the shelf casing (0 if no left part exists)
  rightWidth: number, // (Required) width of the right part of the shelf casing (0 if no right part exists)
  model: ShelfSection[] // (Required) an array of the shelf sections this shelf should contain.
}

Note

For shelf sections you can also use percentages for the height and width related to the shelf.

Warning

For shelf sections bottom.width and wall.width will count towards the absolute size of the shelf section.

ShelfSection
{
    width: number | string, // (Required) Width of the shelf section (Inner part)
    height: number | string, // (Required) Height of the shelf section (Inner part)
    x: number, // (Optional) If given the shelf will be at the given position inside the row. If left undefined, the section will be sorted at random
    y: number, // (Optional) If given the shelf will be inside the given row. If left undefined, the section will be sorted at random
    sortBooksInverted: boolean, // (Optional) If true the books will be sorted from right to left inside that section. Undefined or false will sort the books from left to right
    bottom: { // (Required) Section base definition
        width: number, // (Required) determines the thickness of the section base.
        color: string // (Optional) Color of the section base. If left undefined it will assume the value of the property outerColor of the parent shelf. (Accepted: Any css color or an object with [r: 0-255, g: 0-255, b: 0-255])
    }
    wall: { // (Optional) Section separation wall
        position: 'left' | 'right', // (Required) defines whether the wall will be rendered on the left or the right side of the section
        color: string, // (Optional) defines the color of the separation wall. If undefined it will assume the value of outerColor of the parent shelf (Accepted: Any css color or an object with [r: 0-255, g: 0-255, b: 0-255])
        width: number // (Required) defines how thick the wall is going to be
    }
    items: ShelfItem[] // (Required) an array of the shelf items this section contains
}
ShelfItem
{
    expandable: boolean, // (Required) determines whether the shelf item can be clicked on to display additional information
    width: number, // (Required) defines the width of the given item
    height: number, // (Required) defines the height of the given item
    depth: number, // (Required if expandable is true) defines the depth of the item when the detail view is opened
    frontView: FrontShelfView, // (Required) defines the view as it is displayed inside the shelf
    title: string, // (Required) defines the name of the item [Is displayed on the frontView if its type is "color" and it has not been disabled]
    subtitle: string, // (Optional) defines the subtitle of the item [Is displayed on the frontView if its type is "color" and it has not been disabled]
    description: string, // (Optional) defines the description of the item
    positionInRow: number, // (Optional) defines the position of the shelf item inside the section. If undefined the item will be sorted at random
    identificationCode: IdentificationCode[], // (Optional) defines the identification codes of the item (e.g. ISBN, Asset-ID, etc.)
    location: EntityLocation[], // (Optional) defines where the item is located (Purely meta data)
    availability: 'unlimited' | 'limited', // (Required) defines the availability of the item. If unlimited the item cannot be "out of stock"
    count: number, // (Required if availability is "limited") defines the number of available items
    sideView: SideShelfView, // (Required if expandable is true) defines the view as it is displayed when clicked on
}
FrontShelfView

If you wish you item to be displayed as a colored "block" use the following

{
    type: 'color', // (Required) defines that the color view type should be used
    color: string, // (Required) defines the color that the item should be displayed as (Accepted: Any css color or an object with [r: 0-255, g: 0-255, b: 0-255]) 
    exclude: { // (Optional) determines whether to display certain information on that cover
        title: boolean, // (Optional) determines whether the title should be rendered on the view
        subtitle: boolean // (Optional) determines whether the subtitle should be rendered on the view
    }
}

If you wish for the item to be displayed with an image use the following

{
    type: 'image', // (Required) defines that the image view type should be used
    url: string // (Required) defines the url of the image to display
}
SideShelfView

If you wish you item to be displayed as a colored "block" use the following

{
    type: 'color', // (Required) defines that the color view type should be used
    color: string, // (Required) defines the color that the item should be displayed as (Accepted: Any css color or an object with [r: 0-255, g: 0-255, b: 0-255]) 
    exclude: { // (Optional) determines whether to display certain information on that cover
        title: boolean, // (Optional) determines whether the title should be rendered on the view
        subtitle: boolean // (Optional) determines whether the subtitle should be rendered on the view
    },
    sideView: { // (Optional) defines how the sideView should be rendered
        style: { // (Optional) if you wish to change the display styles of the given properties
            background: DisplayStyle, // (Optional) if you wish to change the display background
            title: DisplayStyle, // (Optional) if you wish to change how the title is displayed
            subtitle: DisplayStyle, // (Optional) if you wish to change how the subtitle is displayed
            description: DisplayStyle, // (Optional) if you wish to change how the description is displayed
            location: Record<string, {
                key: DisplayStyle, // (Optional) if you wish to change how the key is displayed for this location
                value: DisplayStyle // (Optional) if you wish to change how the value is displayed for this location
            }> | {
                key: DisplayStyle, // (Optional) if you wish to change how the key is displayed for all locations
                value: DisplayStyle // (Optional) if you wish to change how the value is displayed for all locations
            }, // (Optional) if you wish to change how all the locations are displayed or how specific locations are displayed. [This setting will override the individual location configuration]
            identificationCode: Record<string, {
                name: DisplayStyle, // (Optional) if you wish to change how the name is displayed for this identification code
                value: DisplayStyle // (Optional) if you wish to change how the value is displayed for this identification code
            }> | {
                name: DisplayStyle, // (Optional) if you wish to change how the name is displayed for all identification codes
                value: DisplayStyle // (Optional) if you wish to change how the value is displayed for all identification codes
            } // (Optional) if you wish to change how all the identification codes are displayed or how specific identification codes are displayed.
        },
        exclude: { // (Optional) if you wish to exclude specific properties from rendering
            title: boolean, // (Optional) determines whether to render the title of the book [On the sideView]
            subtitle: boolean, // (Optional) determines whether to render the subtitle of the book [On the sideView]
            description: boolean, // (Optional) determines whether to render the description of the book
            location: boolean, // (Optional) determines whether to render the location of the item
            identificationCode: boolean | Array<string> // (Optional) determines whether to render identification codes at all or if specific ones should be excluded
        }
    }
}

If you wish for the item to be displayed with an image use the following

{
    type: 'image', // (Required) defines that the image view type should be used
    url: string, // (Required) defines the url of the image to display
    sideView: { // (Optional) defines how the sideView should be rendered
        style: { // (Optional) if you wish to change the display styles of the given properties
            background: DisplayStyle, // (Optional) if you wish to change the display background
            title: DisplayStyle, // (Optional) if you wish to change how the title is displayed
            subtitle: DisplayStyle, // (Optional) if you wish to change how the subtitle is displayed
            description: DisplayStyle, // (Optional) if you wish to change how the description is displayed
            location: Record<string, {
                key: DisplayStyle, // (Optional) if you wish to change how the key is displayed for this location
                value: DisplayStyle // (Optional) if you wish to change how the value is displayed for this location
            }> | {
                key: DisplayStyle, // (Optional) if you wish to change how the key is displayed for all locations
                value: DisplayStyle // (Optional) if you wish to change how the value is displayed for all locations
            }, // (Optional) if you wish to change how all the locations are displayed or how specific locations are displayed. [This setting will override the individual location configuration]
            identificationCode: Record<string, {
                name: DisplayStyle, // (Optional) if you wish to change how the name is displayed for this identification code
                value: DisplayStyle // (Optional) if you wish to change how the value is displayed for this identification code
            }> | {
                name: DisplayStyle, // (Optional) if you wish to change how the name is displayed for all identification codes
                value: DisplayStyle // (Optional) if you wish to change how the value is displayed for all identification codes
            } // (Optional) if you wish to change how all the identification codes are displayed or how specific identification codes are displayed.
        },
        exclude: { // (Optional) if you wish to exclude specific properties from rendering
            title: boolean, // (Optional) determines whether to render the title of the book [On the sideView]
            subtitle: boolean, // (Optional) determines whether to render the subtitle of the book [On the sideView]
            description: boolean, // (Optional) determines whether to render the description of the book
            location: boolean, // (Optional) determines whether to render the location of the item
            identificationCode: boolean | Array<string> // (Optional) determines whether to render identification codes at all or if specific ones should be excluded
        }
    }
}
DisplayStyle
{
    color: string, // (Optional) if you wish to change the color of the given property (Accepted: Any css color or an object with [r: 0-255, g: 0-255, b: 0-255])
    fontWeight: number, // (Optional) if you wish to change the fontWeight of the given property
    classes: Array<string> // (Optional) if you wish to apply specific CSS classes to the given property
}
EntityLocation

Display: {key}: {value}

Example: Shelf: 7 Row: 5

{
    key: string, // (Required) defines the location key
    value: string, // (Required) defines the value of the location
    order: number, // (Required) defines the order the location is displayed in
    style: { // (Optional) if you wish to change how this location is displayed
        key: DisplayStyle, // (Optional) if you wish to change how the key is displayed
        value: DisplayStyle // (Optional) if you wish to change how the value is displayed
    }
}
IdentificationCode

Display: {name or display_name}: {value} or if value is an array {name or display_name}: {value[0]} {name or display_name}: {value[1]} ...

{
    name: string, // (Required) defines the name of the location (Can also be used in the sideView exclude)
    display_name: string, // (Optional) if you wish to change the name that is displayed
    order: number, // (Optional) defines the order in which to display the identification codes
    value: string | Array<string> // (Required) can be a single string or an array of strings and defines the values of the given identification code
}

Other Types

ShelfData
{
  title: string, // (Optional) if you want a title to be displayed above your shelf
  subtitle: string, // (Optional) if you want a smaller text displayed below the title
  location: EntityLocation[], // (Optional) defines where the shelf is located (Purely meta data)
  backgroundColor: string, // (Required) what color to display in the background (Accepted: Any css color or an object with [r: 0-255, g: 0-255, b: 0-255])
  outerColor: string, // (Required) what color the shelf walls etc. are (Accepted: Any css color or an object with [r: 0-255, g: 0-255, b: 0-255])
  model: ShelfSection[] // (Required) an array of the shelf sections this shelf should contain.
}
ShelfSizes

If you wish to use ShelfSizes you have to add getShelfSizes to the imports.

getShelfSizes(
    innerHeight: number,
    innerWidth: number,
    tbWidth: number,
    lrWidth: number
);

getShelfSizes(
    innerHeight: number,
    innerWidth: number,
    topWidth: number,
    bottomWidth: number,
    rightWidth: number,
    leftWidth: number
);

getShelfSizes(
    innerHeight: number,
    innerWidth: number,
    totalHeight: number,
    totalWidth: number
);

getShelfSizes(
    totalHeight: number,
    totalWidth: number,
    tbWidth: number,
    lrWidth: number
);

getShelfSizes(
    totalHeight: number,
    totalWidth: number,
    topWidth: number,
    bottomWidth: number,
    leftWidth: number,
    rightWidth: number
);

License

Copyright © 2026 Tarobits Licensed under the Mozilla Public License 2.0 (MPL-2.0). See https://mozilla.org/MPL/2.0/

About

A highly flexible rendering engine for virtual shelves, inventories, and catalog-like UIs, designed for Vue.js and powered by strict TypeScript models.

Topics

Resources

License

Stars

Watchers

Forks