From a658e571ef245a200884ea96198c54188ae650da Mon Sep 17 00:00:00 2001 From: Josh Kingsley Date: Sat, 25 Oct 2025 16:24:53 +0300 Subject: feat(web): setup components --- package.json | 1 + pnpm-lock.yaml | 57 ++++++++++++++++++++++++++++++++++++++++++++ prettier.config.ts | 2 +- web/components/app/index.ts | 13 ++++++++++ web/components/grid/index.ts | 14 +++++++++++ web/components/index.ts | 2 ++ web/global.d.ts | 9 +++++++ web/html.ts | 26 ++++++++++++++++++++ web/index.css | 10 ++++++++ web/index.html | 4 +++- web/index.ts | 38 ++++++++++++++++++++++++++--- web/package.json | 3 +++ web/tsconfig.json | 12 ++++++++++ 13 files changed, 186 insertions(+), 5 deletions(-) create mode 100644 web/components/app/index.ts create mode 100644 web/components/grid/index.ts create mode 100644 web/components/index.ts create mode 100644 web/global.d.ts create mode 100644 web/html.ts create mode 100644 web/index.css create mode 100644 web/tsconfig.json diff --git a/package.json b/package.json index 5bd7887..d5a1cb5 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "type": "module", "devDependencies": { "prettier": "^3.6.2", + "prettier-plugin-css-order": "^2.1.2", "prettier-plugin-packagejson": "^2.5.19", "turbo": "^2.5.8", "typescript": "^5.9.3" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c7c7c6b..6a01457 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: prettier: specifier: ^3.6.2 version: 3.6.2 + prettier-plugin-css-order: + specifier: ^2.1.2 + version: 2.1.2(postcss@8.5.6)(prettier@3.6.2) prettier-plugin-packagejson: specifier: ^2.5.19 version: 2.5.19(prettier@3.6.2) @@ -22,6 +25,10 @@ importers: version: 5.9.3 web: + dependencies: + open-color: + specifier: ^1.9.1 + version: 1.9.1 devDependencies: vite: specifier: ^7.1.12 @@ -302,6 +309,12 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + css-declaration-sorter@7.3.0: + resolution: {integrity: sha512-LQF6N/3vkAMYF4xoHLJfG718HRJh34Z8BnNhd6bosOMIVjMlhuZK5++oZa3uYAgrI5+7x2o27gUqTR2U/KjUOQ==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.0.9 + detect-indent@7.0.2: resolution: {integrity: sha512-y+8xyqdGLL+6sh0tVeHcfP/QDd8gUgbasolJJpY7NgeQGSZ739bDtSiaiDgtoicy+mtYB81dKLxO9xRhCyIB3A==} engines: {node: '>=12.20'} @@ -341,6 +354,9 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + open-color@1.9.1: + resolution: {integrity: sha512-vCseG/EQ6/RcvxhUcGJiHViOgrtz4x0XbZepXvKik66TMGkvbmjeJrKFyBEx6daG5rNyyd14zYXhz0hZVwQFOw==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -348,10 +364,28 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} + postcss-less@6.0.0: + resolution: {integrity: sha512-FPX16mQLyEjLzEuuJtxA8X3ejDLNGGEG503d2YGZR5Ask1SpDN8KmZUMpzCvyalWRywAn1n1VOA5dcqfCLo5rg==} + engines: {node: '>=12'} + peerDependencies: + postcss: ^8.3.5 + + postcss-scss@4.0.9: + resolution: {integrity: sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.4.29 + postcss@8.5.6: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} + prettier-plugin-css-order@2.1.2: + resolution: {integrity: sha512-vomxPjHI6pOMYcBuouSJHxxQClJXaUpU9rsV9IAO2wrSTZILRRlrxAAR8t9UF6wtczLkLfNRFUwM+ZbGXOONUA==} + engines: {node: '>=16'} + peerDependencies: + prettier: 3.x + prettier-plugin-packagejson@2.5.19: resolution: {integrity: sha512-Qsqp4+jsZbKMpEGZB1UP1pxeAT8sCzne2IwnKkr+QhUe665EXUo3BAvTf1kAPCqyMv9kg3ZmO0+7eOni/C6Uag==} peerDependencies: @@ -624,6 +658,10 @@ snapshots: '@types/estree@1.0.8': {} + css-declaration-sorter@7.3.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + detect-indent@7.0.2: {} detect-newline@4.0.1: {} @@ -670,16 +708,35 @@ snapshots: nanoid@3.3.11: {} + open-color@1.9.1: {} + picocolors@1.1.1: {} picomatch@4.0.3: {} + postcss-less@6.0.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-scss@4.0.9(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss@8.5.6: dependencies: nanoid: 3.3.11 picocolors: 1.1.1 source-map-js: 1.2.1 + prettier-plugin-css-order@2.1.2(postcss@8.5.6)(prettier@3.6.2): + dependencies: + css-declaration-sorter: 7.3.0(postcss@8.5.6) + postcss-less: 6.0.0(postcss@8.5.6) + postcss-scss: 4.0.9(postcss@8.5.6) + prettier: 3.6.2 + transitivePeerDependencies: + - postcss + prettier-plugin-packagejson@2.5.19(prettier@3.6.2): dependencies: sort-package-json: 3.4.0 diff --git a/prettier.config.ts b/prettier.config.ts index a097245..b7b1bc5 100644 --- a/prettier.config.ts +++ b/prettier.config.ts @@ -1,7 +1,7 @@ import { type Config } from "prettier"; const config: Config = { - plugins: ["prettier-plugin-packagejson"], + plugins: ["prettier-plugin-packagejson", "prettier-plugin-css-order"], }; export default config; diff --git a/web/components/app/index.ts b/web/components/app/index.ts new file mode 100644 index 0000000..f4eaff1 --- /dev/null +++ b/web/components/app/index.ts @@ -0,0 +1,13 @@ +import ntvGrid from "../grid"; + +class NotiveAppElement extends HTMLElement { + connectedCallback() { + this.append( + ...window.notive.doc.grids.map((_grid) => { + return ntvGrid({ foo: "1" }); + }), + ); + } +} + +customElements.define("ntv-app", NotiveAppElement); diff --git a/web/components/grid/index.ts b/web/components/grid/index.ts new file mode 100644 index 0000000..7faf6b1 --- /dev/null +++ b/web/components/grid/index.ts @@ -0,0 +1,14 @@ +import h, { type CreateElement } from "../../html"; + +class NotiveGridElement extends HTMLElement { + foo: string; + + connectedCallback() { + this.appendChild(h.p("OK: " + this.foo)); + } +} + +customElements.define("ntv-grid", NotiveGridElement); + +export default ((...args: any[]): NotiveGridElement => + (h as any)["ntv-grid"](...args)) as CreateElement; diff --git a/web/components/index.ts b/web/components/index.ts new file mode 100644 index 0000000..8bc14e7 --- /dev/null +++ b/web/components/index.ts @@ -0,0 +1,2 @@ +import "./app"; +import "./grid"; diff --git a/web/global.d.ts b/web/global.d.ts new file mode 100644 index 0000000..3b6d980 --- /dev/null +++ b/web/global.d.ts @@ -0,0 +1,9 @@ +import type Notive from "./index"; + +declare global { + interface Window { + notive: Notive; + } +} + +export {}; diff --git a/web/html.ts b/web/html.ts new file mode 100644 index 0000000..5bfff21 --- /dev/null +++ b/web/html.ts @@ -0,0 +1,26 @@ +export type CreateElement = { + (...children: (Node | string)[]): T; + (attrs: Partial, ...children: (Node | string)[]): T; +}; + +type ElementCreator = { + [K in keyof HTMLElementTagNameMap]: CreateElement; +}; + +const h = new Proxy({} as ElementCreator, { + get: + (_, tag: string) => + (...args: any[]) => { + const el = document.createElement(tag); + + if (typeof args[0] === "object") { + Object.assign(el, args.shift()); + } + + el.append(...args.flat()); + + return el; + }, +}); + +export default h; diff --git a/web/index.css b/web/index.css new file mode 100644 index 0000000..f578562 --- /dev/null +++ b/web/index.css @@ -0,0 +1,10 @@ +@import "open-color"; + +body { + background: var(--oc-gray-9); + color: var(--oc-white); + font-weight: normal; + font-family: + Seravek, "Gill Sans Nova", Ubuntu, Calibri, "DejaVu Sans", source-sans-pro, + sans-serif; +} diff --git a/web/index.html b/web/index.html index b7231ea..846f5be 100644 --- a/web/index.html +++ b/web/index.html @@ -3,9 +3,11 @@ Notive + + -

Hello, World!

+ diff --git a/web/index.ts b/web/index.ts index a34c8b4..1524b04 100644 --- a/web/index.ts +++ b/web/index.ts @@ -1,5 +1,37 @@ -console.log("OK"); +interface Cell { + value: string; +} + +interface Row { + cells: Cell[]; +} + +interface Part { + rows: Row[]; +} + +interface Grid { + parts: Part[]; +} -function foo() { - return "foo"; +interface Doc { + grids: Grid[]; } + +function defaultDoc(): Doc { + const defaultCells = Array(16).map(() => ({ value: "1" })); + + return { + grids: [ + { parts: [{ rows: Array(4).map(() => ({ cells: [...defaultCells] })) }] }, + ], + }; +} + +export default class Notive { + doc: Doc = defaultDoc(); +} + +window.notive = new Notive(); + +window.dispatchEvent(new CustomEvent("ntv:initialized")); diff --git a/web/package.json b/web/package.json index bc3b744..e0b674d 100644 --- a/web/package.json +++ b/web/package.json @@ -6,5 +6,8 @@ }, "devDependencies": { "vite": "^7.1.12" + }, + "dependencies": { + "open-color": "^1.9.1" } } diff --git a/web/tsconfig.json b/web/tsconfig.json new file mode 100644 index 0000000..7ef66ad --- /dev/null +++ b/web/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "moduleResolution": "bundler", + "strict": true, + "skipLibCheck": true, + "esModuleInterop": true + }, + "include": ["*.ts", "**/*.ts"] +} -- cgit v1.2.3