Skip to content

ihasq/strix

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GitHub Repo stars npm

GitHub License npm package minimized gzipped size (select exports)


import { html, $ } from "@strix/std"
import { on } from "@strix/attr"

const Counter = () => {

    const count = $(0);

    return html`
        <h1>${count}</h1>
        <button ${{ [on.click]: () => $[count]++ }}>
            Increment
        </button>
    `;
};


document.body = Counter()();

Strix is a selfish library to provide some weirder, but simpler ways to building web interface.
Visit strix.sh for more infomation.

Open in StackBlitz

Directories

directory about
mod Modules
pkg Packages
kit Developnent Kits
web Publications
repl Playground REPL

Packages

package about exports
html HTML in JavaScript library html
write Client-side HTML Writer write
define Defining Web Components define
set Signal-like Hook set
layout Layout manager layout
nitro Design systems nitro
material3 Material Design 3 port m3
md Markdown-to-HTML Plugin md
react React compatibility hook React

SDK

project about
Trixel Fullstack Strix Framework
Create Project template generator
Analyzer VSCode analyzer

Modules

module about
html HTML template parser
attr Attribute template parser
event Event router

Installation

CDN via ESM.SH

import html from 'https://esm.sh/jsr/@strix/html';
const html = await import('https://esm.sh/jsr/@strix/html');

Create Project

npm create strix my-project
cd my-project
npm start

Add Packages (for Pros)

npx jsr run @strix/create
deno add @strix/html

Build From Source

git clone https://github.com/ihasq/strix
deno task build

Smart Attributes on strix-HTML

html`
    <!-- text -->
    <label>${text}</label>

    <!-- attribute -->
    <iframe src=${formURL}; />

    <!-- identifier (not the id attribute) -->
    <img #mainImgRef/>

    <!-- event listener -->
    <button @click=${() => console.log('clicked')}; />
    <input @@keydown=${() => console.log('cancelled')}; /> <!-- preventDefault() -->
    
    <!-- StrixEffectEvent - triggered when the value changes -->
    <h1 @effect=${() => console.log('changed')};>${count}</h1>
    
    <!-- style -->
    <h1 *color=${titleColor}>with color!</h1>
    <h1 .style.color=${titleColor}>same as above</h1>
    
    <!-- property -->
    <input #inputWithProp type=text; value=ok; />
    <input type=checkbox; value=${true}; /> <!-- CORRECT type -->
    <input type=checkbox; value=true; /> <!-- This is NOT boolean, this is string -->
    <div someprop.deeper='more deeper'; />
    
    <!-- embedding component -->
    <${DefinedComponent} my-attribute=1; />
    
    <!-- custom attribute -->
    <div ${name}=taro></div>
    
    <!-- to child elements -->
    <div value&input=${inputvalue}>...</div>
    
    <!-- branching with psuedo class or booleanish -->
    <button *color:hover=red; *color${Date.now() % 2}=blue></button>
    
    <!-- nesting -->
    <div
        #hasNested
        :hover {
            *color=red;
        };
        ${window.clientHeight >= 100} {
            *color=blue;
        };
    ></div>
`;

Usage

import { $, html } from "@strix/std";

const Count = () => {

    const count = $(0),
        buttonText = $('Hover me!');

    return html`
        <p>You clicked ${count} times</p>
        <button ${{
            onclick() {
                $[count]++
            },
            onmouseenter() {
                $[buttonText] = "Click me!"
            },
            onmouseout() {
                $[buttonText] = "Hover me!"
            }
        }};>
            ${buttonText}
        </button>
    `;
};

export default Count;
<body onload='
    import("https://strix.sh/write").then(write => write(this, import(this.src)))
'></body>
const Todo = () => {

    const todoArray = [];

    const TodoRow = ({ todoContent, swapRow, deleteRow }) => {

        let isEditable = false;
        let isDone = false;

        return () => html`
            <li
                contenteditable=${isEditable? 'plaintext-only' : undefined}
                @input=${async ({ target }) => todoData = (await target).data}
                @blur=${() => isEditable = false}
                *text-decoration=${isDone? 'line-through' : 'none'}
                *font-style=${isDone? 'italic' : 'normal'}
            >
                ${todoContent}
            </li>
            <button @click=${() => isEditable = true}>edit</button>
            <button @click=${() => isDone = true}>done</button>
            <button @click=${() => deleteRow()}>delete</button>
            <button @click=${() => swapRow(1)}>swap above</button>
            <button @click=${() => swapRow(-1)}>swap below</button>
        `
    }

    return () => html`
        <ul>${todoArray}</ul>
        <input @@keydown.Enter=${({ target }) => {
            const newRow = html.new`
                <div
                    *width=100%
                    @dragover=${({ target }) => {
                    }}
                ></div>
                <${TodoRow}
                    strix.draggable=${true}
                    todoContent=${target.value}
                    swapRow=${(direction) => {
                        const i = todoArray.indexOf(newRow);
                        [todoArray[i], todoArray[i + direction]] = [todoArray[i + direction],todoArray[i]];
                    }}
                    deleteRow=${() => delete todoArray[todoArray.indexOf(newRow)]}
                />
            `;
            todoArray.push(newRow);
            target.value = "";
        }} />
    `
}
const ReverseStr = () => {

    const
        text = $(''),
        reversed = $(text, (newText) => newText.split("").reverse().join(""));

    return html`
        <input type=text; strix.bind=${text};/>
        <h2>${reversed}</h2>
    `;
};
const Parent = () => {
    return html`
        <${Child} ${{ someProp: "hi" }}>
    `;
}

const Child = ({ someProp }) => {
    return html`
        <label>${someProp}</label>
    `;
}
const C2DApp = html`
    <canvas @load=${({ target: canvas }) => {
        const ctx = canvas.getContext('2d');
        // ...
    }};></canvas>
`;
import nitro from 'https://esm.sh/strix-nitro';
// Nitro Design - The Design System By Strix

const StyleImport = () => {
    return () => html`
        <button ${nitro}>I am themed by Nitro Design!</button>
    `;
};
const sampleAttrModule = () => attr`
    *background-color=${attr.value === 'system' ? '#000' : attr.value === 'dark' ? '#fff' : '#000'}
    *color=red;
    ${anotherAttrModule}=${true}
    :hover {
        *color=blue;
        @click=${() => alert('I am hovered')}
    };
    button {
        @@click=${() => alert('prevented by parent!')}
    };
    &div[${someAttrModule}=${true}] {
        &span {
            amIDeeperChild=${true}
        };
    };
    ::selection {
        *background-color=black; 
    };
`; // psuedo elements are style attributes only

const WithAttributeModule = () => () => html`
    <div ${sampleAttrModule}=system;>
        <button></button>
    </div>
`;
import { center } from 'strix-layout';

const HowToCenterADiv = () => () => html`
    <div ${center}>Now I am a centered div!</div>
`;
import { react } from 'strix-react';

import * as React from 'react@latest';
import { Button } from '@shadcn/ui/components/ui/button';

react.use(React);

const ReactEmbedded = () => () => html`
    <${Button} ${react}>I am the Button from @shadcn/ui in Strix!</${Button}>
`;
const withJsxImportSource = () => {
    let count = 0;
    return () => (
        <div>{count}</div>
        <button @click={() => count++}></button>
    );
}
const primitive = html`<div>Hi</div>`;

const samePrimitive = primitive;
alert(primitive === samePrimitive); // true

const regeneratedPrimitive = primitive.new();
alert(primitive === regeneratedPrimitive); // false

const anotherPrimitive = html`<div>Hi</div>`;
alert(primitive === anotherPrimitive); // false
html`<input type=text; @input=${({ target: { value } }) => alert(value)} />`
html`<input type=text; @input.target.value=${value => alert(value)} />`
const animation = async ({ frame }) => {

    let rgbValue = 0;

    for(let i = 0; i < 60; i++) {
        rgbValue++
        await frame(html`
            *background-color=#${rgbValue.toString(16).padStart(6, "0")}
        `);
    }
}

html`<div @click=${animation}>woooaaah</div>`
const Bidirectional = () => {

    const name = ['JAMES', (newName) => console.log(`Name just changed to ${newName}`)];

    return () => html`
        <input type=text strix.bind=${name} />
        <h1>${name}</h1>
    `
}
const VCSS = ({ $ }) => {
    return () => html`
        <div *width=100px>
            <div *width=calc(super-width / 2)></div>
        </div>
    `
}

License

Strix is MIT Licensed.