vegarringdal / simple-html

MIT License
3 stars 0 forks source link

Version 5.0 in React #54

Open VegarRingdalAibel opened 1 year ago

VegarRingdalAibel commented 1 year ago

Sample of grid as component and theme component Took some work at work removed some parts. Update for : https://github.com/vegarringdal/simple-html/issues/29

SimpleHtmlGrid.tsx

import { GridInterface } from "@simple-html/grid";
import "@simple-html/grid";
import "@simple-html/grid/dist/grid.css";
import "@simple-html/grid/dist/date.css";
import React, { useEffect, useRef } from "react";

/**
 * This is just a grid container, so I can use the vanilla grid in react
 * this also added some features like double click on grid row
 * PS! editing this with hot reloading will create weird behavior
 */
export function SimpleHtmlGrid(props: {
    id: string;
    style?: { width?: string; height?: string };
    interface: GridInterface<any>;
    className?: string;
    date?: any;
}) {
    const ref = useRef<any>(null);

    useEffect(() => {
        if (ref.current) {
            // dom element does not have final size on first call to useEffect
            setTimeout(() => {
                ref.current.enableCleanup = true; // fixes issue hmr can generate/or just bad cleanup from react
                ref.current.connectInterface(props.interface);
            }, 0);
        }
        return () => {
            if (ref.current) {
                console.log("unexpected behavior, duplicate grid", ref.current);
            }
        };
    }, []);

    return (
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore
        <simple-html-grid
            id={props.id}
            ref={ref}
            style={{
                width: props.style?.width,
                height: props.style?.height
            }}
            class={props.className}
        />
    );
}

SetGridTheme.tsx

import React, { useEffect, useRef } from "react";

/**
 * dark theme helper for grid
 * this also overrides some defaults in grid so it fits better within the application
 */

export function SetGridTheme(props: { enabled: boolean }) {
    const ref = useRef<any>(null);
    const darkEnabled = props.enabled;

    useEffect(() => {
        if (ref.current) {
            if (darkEnabled === true) {
                let children = ref.current.childNodes;
                while (children.length) {
                    children[0]?.parentNode.removeChild(children[0]);
                    children = ref.current.childNodes;
                }
                /**
                 * dark mode overrides
                 */
                ref.current.append(
                    document.createTextNode(`
                    body,
                    .simple-html-grid-menu,
                    .simple-html-grid {
                        --simple-html-grid-main-bg-color: #374151;
                        --simple-html-grid-sec-bg-color: #4b5563;
                        --simple-html-grid-alt-bg-color: #4b5563;
                        --simple-html-grid-main-bg-border: #1f2937;
                        --simple-html-grid-main-bg-even: #59606a;
                        --simple-html-grid-main-bg-odd: #6b7178;
                        --simple-html-grid-sec-bg-border: #1f2937;
                        --simple-html-grid-pinned-border: #1f2937;
                        --simple-html-grid-main-bg-selected-odd: #234882;
                        --simple-html-grid-main-bg-selected-even: #274e8f;
                        --simple-html-grid-main-font-color: #f9f7f7;
                        --simple-html-grid-sec-font-color: #979494;
                        --simple-html-grid-dropzone-color: rgb(151, 148, 148, 0.4);
                        --simple-html-grid-grouping-border: #1f2937;
                        --simple-html-grid-boxshadow: #4b5563;
                        --simple-html-grid-main-hr-border: #4b5563;
                    }
                    .simple-html-grid ul.dialog-row {
                        box-shadow: none;

                    }
                    .simple-html-grid li.dialog-row {
                        border-left: 1px dotted rgb(100, 100, 100);
                    } 
                    .simple-html-grid .grid-edit-button {
                        border-color: #374151;
                    }
                    .simple-html-grid .filter-dialog-bottom-row{
                        border-top: 0px;
                    }
                    .simple-html-grid .filter-dialog-bottom-row button{
                        border: 1px solid #515458;
                    }
                    .simple-html-grid-header input::placeholder {
                        filter: opacity(1);
                    }
                    .simple-html-grid-menu {
                        z-index: 70000 !important;
                    }
                    .simple-html-grid-drag {
                        z-index: 70000 !important;
                    }

                    .simple-html-grid input[readonly] {
                        cursor: pointer;
                    }

                    .simple-html-grid input[type='checkbox']{
                        margin: 2px;
                    }

                    body,
                    .simple-html-date {

                        --simple-html-date-main-bg-color: #374151;
                        --simple-html-date-main-color: #f9f7f7;
                        --simple-html-date-dimmed-color: #979494;
                        --simple-html-date-week-color: #8b8b8b;
                        --simple-html-date-header-bg-border: #8b8b8b;
                        --simple-html-date-main-bg-border:  #979494;
                        --simple-html-date-main-bg-selected: #234882;

                    }
                    .simple-html-date button, .icon {
                        color: #60a5fa
                    }

                    .simple-html-grid .simple-html-grid-icon-group-svg {
                        color: #60a5fa;
                    }

                    .simple-html-grid .filter-editor-content .grid-button-small {
                        color: #60a5fa;
                    }

                    .simple-html-grid .filter-editor-content .grid-button {
                        color: #60a5fa;
                    }

                    `)
                );
            } else {
                let children = ref.current.childNodes;
                while (children.length) {
                    children[0]?.parentNode.removeChild(children[0]);
                    children = ref.current.childNodes;
                }
                /**
                 * light mode overrides
                 */
                ref.current.append(
                    document.createTextNode(`
                    body,
                    .simple-html-grid-header input::placeholder {
                        filter: opacity(1);
                    }
                    .simple-html-grid-menu {
                        z-index: 70000 !important;
                    }
                    .simple-html-grid-drag {
                        z-index: 70000 !important;
                    }
                    .simple-html-grid input[readonly] {
                        cursor: pointer;
                    }
                    .simple-html-grid input[type='checkbox']{
                        margin: 2px;
                    }
                    .simple-html-date button, .icon {
                        color: #4f46e5;
                    }

                    .simple-html-grid .simple-html-grid-icon-group-svg {
                        color: #4f46e5;
                    }

                    .simple-html-grid .filter-editor-content .grid-button-small {
                        color: #4f46e5;
                    }

                    .simple-html-grid .filter-editor-content .grid-button {
                        color: #4f46e5;
                    }
                  `)
                );
            }
        }
    });

    return <style ref={ref}></style>;
}
vegarringdal commented 1 year ago

page.tsx

import { Datasource, GridInterface } from "@simple-html/grid";
import React from "react";
import { SimpleHtmlGrid } from "./components/SimpleHtmlGrid";
import { SetGridTheme } from "./components/SetGridTheme";

/**
 * dummy data
 */
let DummyRow = {
    ID: 0,
    STATUS: "Issued for IDC",
    DISCIPLINE: "PROCESS",
    TAG_NO: "A-20VA001",
    DESCRIPTION: "INLET SEP",
    DOCID: "C232-AI-R-DS-0001",
    LINE_EQUIPMENT: "KJSD"
};

let DummyRows = [];

for (let i = 1; i < 1000; i++) {
    const x = structuredClone(DummyRow);
    x.ID = i;
    DummyRows.push(x);
}
/**
 * datasource
 */
const dataSource = new Datasource();
dataSource.setData(DummyRows);

/**
 * grid interface
 */
const gridInterface = new GridInterface(
    {
        columnsCenter: [
            { width: 250, rows: ["STATUS"] },
            { width: 150, rows: ["DISCIPLINE"] },
            { width: 250, rows: ["TAG_NO"] },
            { width: 350, rows: ["DESCRIPTION"] },
            { width: 250, rows: ["DOCID"] },
            { width: 250, rows: ["LINE_EQUIPMENT"] }
        ],
        attributes: [/* will generate default to text type if empty */]
    },
    dataSource
);

/**
 * page
 * @returns
 */
export function ObjectAll() {
    return (
        <div className="flex flex-1 m-2">
           <SetGridTheme={true} />
            <SimpleHtmlGrid className="simple-html-grid w-full" interface={gridInterface} />
        </div>
    );
}