From dc7b3195d21a3d9cebc0a7a368d49612d1239a06 Mon Sep 17 00:00:00 2001 From: Brayan-724 Date: Sat, 28 Jun 2025 12:45:33 -0700 Subject: [PATCH 01/37] chore(styles): Change `tailwindcss` to peer dependencies --- pnpm-lock.yaml | 7 ++++--- styles/package.json | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5fa8586..a9c0c23 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -92,11 +92,12 @@ importers: version: 4.5.4(@types/node@22.15.29)(rollup@4.41.1)(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.29)(jiti@2.4.2)(lightningcss@1.30.1)) styles: - devDependencies: - '@tailwindcss/cli': + dependencies: + tailwindcss: specifier: ^4.1.8 version: 4.1.8 - tailwindcss: + devDependencies: + '@tailwindcss/cli': specifier: ^4.1.8 version: 4.1.8 diff --git a/styles/package.json b/styles/package.json index 82f7787..531689a 100644 --- a/styles/package.json +++ b/styles/package.json @@ -34,10 +34,11 @@ "scripts": { "build": "npx @tailwindcss/cli -i tailwindcss.css -o dist/bundled.css --minify" }, - "peerDependencies": {}, - "devDependencies": { - "@tailwindcss/cli": "^4.1.8", + "peerDependencies": { "tailwindcss": "^4.1.8" }, + "devDependencies": { + "@tailwindcss/cli": "^4.1.8" + }, "dependencies": {} } From fbfea4814cee031f2b78007251a1ff4b28d65469 Mon Sep 17 00:00:00 2001 From: Brayan-724 Date: Sat, 28 Jun 2025 17:56:15 -0700 Subject: [PATCH 02/37] chore(prettier): Ignore dist folder --- .prettierignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.prettierignore b/.prettierignore index 1e07bed..a1edbb2 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,5 @@ .github/ +dist/ *.md pnpm-lock.yaml From 2a151c4aa301ba7cb8737a3f7217e8ff148bfdd8 Mon Sep 17 00:00:00 2001 From: Brayan-724 Date: Sat, 28 Jun 2025 21:02:44 -0700 Subject: [PATCH 03/37] wip: make showcase agnostic --- .../lib/components/button/button.showcase.tsx | 27 + js/react/package.json | 4 + js/react/showcase/App.tsx | 485 ------------------ js/react/showcase/ErrorBoundary.ts | 23 - js/react/showcase/main.tsx | 21 +- js/react/showcase/styles.css | 6 +- js/react/vite.config.ts | 2 +- js/showcase/.gitignore | 25 + js/showcase/package.json | 61 +++ .../src}/ShowComponent/Container.tsx | 0 .../src}/ShowComponent/Error.tsx | 0 .../src}/ShowComponent/Field.tsx | 0 js/showcase/src/ShowComponent/error.ts | 20 + .../src}/ShowComponent/index.tsx | 0 .../src}/ShowComponent/types.ts | 0 js/{react/showcase => showcase/src}/icons.tsx | 0 js/showcase/src/index.ts | 1 + js/showcase/src/main.tsx | 12 + js/showcase/src/miniui/index.ts | 87 ++++ js/showcase/src/react/ErrorBoundary.ts | 88 ++++ js/showcase/src/react/index.ts | 1 + js/showcase/src/styles.css | 6 + js/showcase/src/vite-env.d.ts | 1 + js/showcase/tsconfig.json | 11 + js/showcase/tsconfig.lib.json | 27 + js/showcase/tsconfig.node.json | 13 + js/showcase/vite.config.ts | 50 ++ pnpm-lock.yaml | 84 +++ pnpm-workspace.yaml | 1 + 29 files changed, 525 insertions(+), 531 deletions(-) create mode 100644 js/react/lib/components/button/button.showcase.tsx delete mode 100644 js/react/showcase/App.tsx delete mode 100644 js/react/showcase/ErrorBoundary.ts create mode 100644 js/showcase/.gitignore create mode 100644 js/showcase/package.json rename js/{react/showcase => showcase/src}/ShowComponent/Container.tsx (100%) rename js/{react/showcase => showcase/src}/ShowComponent/Error.tsx (100%) rename js/{react/showcase => showcase/src}/ShowComponent/Field.tsx (100%) create mode 100644 js/showcase/src/ShowComponent/error.ts rename js/{react/showcase => showcase/src}/ShowComponent/index.tsx (100%) rename js/{react/showcase => showcase/src}/ShowComponent/types.ts (100%) rename js/{react/showcase => showcase/src}/icons.tsx (100%) create mode 100644 js/showcase/src/index.ts create mode 100644 js/showcase/src/main.tsx create mode 100644 js/showcase/src/miniui/index.ts create mode 100644 js/showcase/src/react/ErrorBoundary.ts create mode 100644 js/showcase/src/react/index.ts create mode 100644 js/showcase/src/styles.css create mode 100644 js/showcase/src/vite-env.d.ts create mode 100644 js/showcase/tsconfig.json create mode 100644 js/showcase/tsconfig.lib.json create mode 100644 js/showcase/tsconfig.node.json create mode 100644 js/showcase/vite.config.ts diff --git a/js/react/lib/components/button/button.showcase.tsx b/js/react/lib/components/button/button.showcase.tsx new file mode 100644 index 0000000..36a292f --- /dev/null +++ b/js/react/lib/components/button/button.showcase.tsx @@ -0,0 +1,27 @@ +import { Button } from "./button.component"; + +export default { + title: "Button", + propsDef: { + variant: { + type: "string", + options: ["primary", "secondary", "text", "icon"], + default: "primary", + }, + label: { + type: "string", + default: "Botón", + }, + disabled: { + type: "boolean", + default: false, + }, + icon: { + type: "function", + }, + className: { + type: "string", + }, + }, + component: Button, +}; diff --git a/js/react/package.json b/js/react/package.json index 4decec3..386467f 100644 --- a/js/react/package.json +++ b/js/react/package.json @@ -10,6 +10,9 @@ }, "./styles.css": { "default": "./dist/styles.css" + }, + "./dev": { + "default": "./lib/index.ts" } }, "files": [ @@ -35,6 +38,7 @@ "devDependencies": { "@eslint/js": "^9.28.0", "@rustlanges/styles": "file:../../styles", + "@rustlanges/showcase": "file:../showcase", "@tailwindcss/cli": "^4.1.8", "@tailwindcss/vite": "^4.1.8", "@types/node": "^22.15.29", diff --git a/js/react/showcase/App.tsx b/js/react/showcase/App.tsx deleted file mode 100644 index 033ff89..0000000 --- a/js/react/showcase/App.tsx +++ /dev/null @@ -1,485 +0,0 @@ -import { - Button, - ContactForm, - Example, - Github, - Tag, - Telegram, - Flap, - Chip, - Level, - Collaborators, - Radio, - Badge, - DropdownState, - Calendar, - CalendarRangeDate, - DropdownTree, -} from "@rustlanges/react"; -import { ShowComponent } from "./ShowComponent"; -import { Fragment, useState } from "react"; - -const collaborator = { - avatarUrl: - "https://images.unsplash.com/photo-1575936123452-b67c3203c357?fm=jpg&q=60&w=3000&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8aW1hZ2V8ZW58MHx8MHx8fDA%3D", - nickname: "Colaborador", -}; - -const tree = { - title: "Introducción a Rust", - state: "completed" as const, - level: "n1" as const, - subjects: [ - { - title: "Aprende lo básico", - state: "completed" as const, - level: "n1" as const, - topics: [ - { - title: "Sintaxis básica", - state: "completed" as const, - level: "n1" as const, - subtopics: [ - { - title: "Variables y declaraciones", - state: "completed" as const, - level: "n1" as const, - }, - { - title: "Constantes y variables estáticas", - state: "completed" as const, - level: "n1" as const, - }, - { - title: "Shadowing", - state: "completed" as const, - level: "n1" as const, - }, - { - title: "Control de flujo", - state: "completed" as const, - level: "n1" as const, - }, - ], - }, - { - title: "Ownership y Borrowing", - state: "completed" as const, - level: "n1" as const, - }, - { - title: "Tipos de datos primitivos", - state: "completed" as const, - level: "n1" as const, - }, - { - title: "Tipos de datos complejos", - state: "completed" as const, - level: "n1" as const, - }, - ], - }, - { - title: "Manejo de errores", - state: "completed" as const, - level: "n2" as const, - topics: [], - }, - { - title: "Cargo", - state: "completed" as const, - level: "n1" as const, - topics: [], - }, - { - title: "Traits", - state: "completed" as const, - level: "n1" as const, - topics: [], - }, - { - title: "Punteros inteligentes", - state: "completed" as const, - level: "n2" as const, - topics: [], - }, - { - title: "Concurrencia y Paralelismo", - state: "completed" as const, - level: "n2" as const, - topics: [], - }, - { - title: "Interoperabilidad", - state: "completed" as const, - level: "op" as const, - topics: [], - }, - { - title: "Ecosistemas y librerías", - state: "completed" as const, - level: "op" as const, - topics: [], - }, - ], -}; - -export function App() { - const [single, setSingle] = useState(new Date()); - const [multiple, setMultiple] = useState | null>(null); - const [range, setRange] = useState(null); - - return ( -
-

- RustLangES Components -

-

- Change your computer theme to explore the different styles (light, dark) -

- - - - -
- ); -} diff --git a/js/react/showcase/ErrorBoundary.ts b/js/react/showcase/ErrorBoundary.ts deleted file mode 100644 index 8ac98b7..0000000 --- a/js/react/showcase/ErrorBoundary.ts +++ /dev/null @@ -1,23 +0,0 @@ -import React, { Component, PropsWithChildren } from "react"; - -export class ErrorBoundary extends Component< - PropsWithChildren<{ fallback(err: Error): React.ReactNode }>, - { error?: Error } -> { - componentDidCatch(error: Error): void { - console.error(error); - this.setState({ - error, - }); - } - - static getDerivedStateFromError(error: Error) { - return { error }; - } - - render(): React.ReactNode { - return this.state?.error - ? this.props.fallback(this.state.error) - : this.props.children; - } -} diff --git a/js/react/showcase/main.tsx b/js/react/showcase/main.tsx index db7b4ab..6d0d440 100644 --- a/js/react/showcase/main.tsx +++ b/js/react/showcase/main.tsx @@ -1,18 +1,5 @@ -import ReactDOM from "react-dom/client"; -import React from "react"; -import "./styles.css"; +import { setupShowcase } from "@rustlanges/showcase/react"; -import { App } from "./App"; - -const root = document.getElementById("root"); - -if (!root) { - alert("No root element"); - throw "No root element"; -} - -ReactDOM.createRoot(root).render( - - - -); +setupShowcase({ + src: "../lib/", +}); diff --git a/js/react/showcase/styles.css b/js/react/showcase/styles.css index 6842d94..b96e1f0 100644 --- a/js/react/showcase/styles.css +++ b/js/react/showcase/styles.css @@ -1,6 +1,2 @@ +@import "@rustlanges/showcase/styles.css"; @import "@rustlanges/react/styles.css"; -@import "tailwindcss"; - -html { - background: var(--color-gray-300); -} diff --git a/js/react/vite.config.ts b/js/react/vite.config.ts index 5ed78f4..65f5170 100644 --- a/js/react/vite.config.ts +++ b/js/react/vite.config.ts @@ -34,7 +34,7 @@ export default defineConfig({ // https://rollupjs.org/configuration-options/#input glob .sync("lib/**/*.{ts,tsx}", { - ignore: ["lib/**/*.d.ts"], + ignore: ["lib/**/*.showcase.{ts,tsx}", "lib/**/*.d.ts"], }) .map(file => [ // 1. The name of the entry point diff --git a/js/showcase/.gitignore b/js/showcase/.gitignore new file mode 100644 index 0000000..c0fbd91 --- /dev/null +++ b/js/showcase/.gitignore @@ -0,0 +1,25 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +workspace.code-workspace diff --git a/js/showcase/package.json b/js/showcase/package.json new file mode 100644 index 0000000..bb4a5a0 --- /dev/null +++ b/js/showcase/package.json @@ -0,0 +1,61 @@ +{ + "name": "@rustlanges/showcase", + "private": true, + "version": "0.0.1", + "type": "module", + "exports": { + ".": { + "types": "./dist/lib/index.d.ts", + "default": "./dist/index.js" + }, + "./styles.css": { + "default": "./dist/styles.css" + } + }, + "files": [ + "dist" + ], + "repository": { + "type": "git", + "url": "https://github.com/RustLangES/design-system-components", + "directory": "js/showcase" + }, + "scripts": { + "build": "tsc -b ./tsconfig.lib.json && vite build && npm run check:tsc && npm run build:tailwindcss", + "build:tailwindcss": "npx @tailwindcss/cli -i lib/styles.css -o dist/styles.css --minify", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0 && npm run check:tsc", + "check:tsc": "tsc --noEmit -p tsconfig.lib.json" + }, + "peerDependencies": { + "react": "^19.1.0", + "react-dom": "^19.1.0" + }, + "devDependencies": { + "@eslint/js": "^9.28.0", + "@rustlanges/styles": "file:../../styles", + "@tailwindcss/cli": "^4.1.8", + "@tailwindcss/vite": "^4.1.8", + "@types/node": "^22.15.29", + "@types/react": "^19.1.6", + "@types/react-dom": "^19.1.5", + "@vitejs/plugin-react-swc": "^3.10.0", + "ajv": "^8.17.1", + "eslint": "^9.28.0", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.20", + "glob": "^11.0.2", + "globals": "^16.2.0", + "jiti": "^2.4.2", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "tailwindcss": "^4.1.8", + "typescript": "^5.8.3", + "typescript-eslint": "^8.33.0", + "vite": "^6.3.5", + "vite-plugin-dts": "^4.5.4" + }, + "dependencies": { + "alien-signals": "^2.0.5", + "clsx": "^2.1.1" + } +} diff --git a/js/react/showcase/ShowComponent/Container.tsx b/js/showcase/src/ShowComponent/Container.tsx similarity index 100% rename from js/react/showcase/ShowComponent/Container.tsx rename to js/showcase/src/ShowComponent/Container.tsx diff --git a/js/react/showcase/ShowComponent/Error.tsx b/js/showcase/src/ShowComponent/Error.tsx similarity index 100% rename from js/react/showcase/ShowComponent/Error.tsx rename to js/showcase/src/ShowComponent/Error.tsx diff --git a/js/react/showcase/ShowComponent/Field.tsx b/js/showcase/src/ShowComponent/Field.tsx similarity index 100% rename from js/react/showcase/ShowComponent/Field.tsx rename to js/showcase/src/ShowComponent/Field.tsx diff --git a/js/showcase/src/ShowComponent/error.ts b/js/showcase/src/ShowComponent/error.ts new file mode 100644 index 0000000..99147b2 --- /dev/null +++ b/js/showcase/src/ShowComponent/error.ts @@ -0,0 +1,20 @@ +export type ErrorDef = { + line: number; + column: number; + name: string; + source: string; +}; + +function renderError() { + + // + // {name} + // + // {source} + // + // +} diff --git a/js/react/showcase/ShowComponent/index.tsx b/js/showcase/src/ShowComponent/index.tsx similarity index 100% rename from js/react/showcase/ShowComponent/index.tsx rename to js/showcase/src/ShowComponent/index.tsx diff --git a/js/react/showcase/ShowComponent/types.ts b/js/showcase/src/ShowComponent/types.ts similarity index 100% rename from js/react/showcase/ShowComponent/types.ts rename to js/showcase/src/ShowComponent/types.ts diff --git a/js/react/showcase/icons.tsx b/js/showcase/src/icons.tsx similarity index 100% rename from js/react/showcase/icons.tsx rename to js/showcase/src/icons.tsx diff --git a/js/showcase/src/index.ts b/js/showcase/src/index.ts new file mode 100644 index 0000000..06fe364 --- /dev/null +++ b/js/showcase/src/index.ts @@ -0,0 +1 @@ +console.log("INDEX"); diff --git a/js/showcase/src/main.tsx b/js/showcase/src/main.tsx new file mode 100644 index 0000000..3d80b44 --- /dev/null +++ b/js/showcase/src/main.tsx @@ -0,0 +1,12 @@ +import ReactDOM from "react-dom/client"; +import React from "react"; +import "./styles.css"; + +const root = document.getElementById("root"); + +if (!root) { + alert("No root element"); + throw "No root element"; +} + +ReactDOM.createRoot(root).render(); diff --git a/js/showcase/src/miniui/index.ts b/js/showcase/src/miniui/index.ts new file mode 100644 index 0000000..2d21ad9 --- /dev/null +++ b/js/showcase/src/miniui/index.ts @@ -0,0 +1,87 @@ +import { signal as alienSignal, effect } from "alien-signals"; + +export namespace MiniUI { + export const SIGNAL = Symbol("Signal"); + + export interface WritableSignal extends Signal { + (value: T): void; + } + + export interface Signal { + (): T; + [SIGNAL]: typeof SIGNAL; + } + + export type MaybeSignal = Signal | T; + + export type Component

= ( + props?: P, + ...children: MiniUI.Node[] + ) => HTMLElement; + export type HTMLElementType = keyof HTMLElementTagNameMap; + export type HTMLElementProps = OmitNeverValue< + MapToSignals + >; + export type Element

= HTMLElementType | Component

; + export type Node = HTMLElement | WeakRef; + + export type MapToSignals

= { + [K in keyof P]: ((ev: Event) => void) extends P[K] ? P[K] + : P[K] extends ((...args: infer _) => infer __) ? never + : MaybeSignal; + }; + + type OmitNeverValue = { + [ + Key in (keyof Base & {}) as [Base[Key]] extends [never] | [undefined] + ? never + : Key + ]: Base[Key]; + }; +} + +export function isSignal(s: unknown): s is MiniUI.Signal { + return typeof s === "object" && s !== null && MiniUI.SIGNAL in s; +} + +export function createSignal(value: T): MiniUI.WritableSignal { + const newSignal = alienSignal(value) as MiniUI.WritableSignal; + newSignal[MiniUI.SIGNAL] = MiniUI.SIGNAL; + return newSignal; +} + +export function h( + elemType: K, + props: MiniUI.HTMLElementProps, + ...children: MiniUI.Node[] +): MiniUI.Node; + +export function h

( + elemType: MiniUI.Component

, + props: P, + ...children: MiniUI.Node[] +): MiniUI.Node; + +export function h( + elemType: MiniUI.Element, + props: unknown, + ...children: MiniUI.Node[] +): MiniUI.Node { + if (typeof elemType !== "string") { + return elemType(props, ...children); + } + + const elem = new WeakRef(document.createElement(elemType)); + + let effects: Array<() => void> = []; + + for (const [propKey, propValue] of Object.entries(props as Record)) { + if (isSignal(propValue)) { + effects.push(effect(() => { + if (elem.deref()) {} + })); + } + } + + return elem; +} diff --git a/js/showcase/src/react/ErrorBoundary.ts b/js/showcase/src/react/ErrorBoundary.ts new file mode 100644 index 0000000..a8d8e97 --- /dev/null +++ b/js/showcase/src/react/ErrorBoundary.ts @@ -0,0 +1,88 @@ +import React, { Component } from "react"; +import { jsxs } from "react/jsx-runtime"; +import { ErrorDef } from "../ShowComponent/error"; + +export function createErrorBoundary( + render: () => React.ReactNode, + renderError: (error: ErrorDef[]) => HTMLElement +): React.ReactElement { + return jsxs(ErrorBoundary, { render, renderError }); +} + +export class ErrorBoundary extends Component< + { renderError(error: ErrorDef[]): HTMLElement; render(): React.ReactNode }, + { error?: Error } +> { + componentDidCatch(error: Error): void { + console.error(error); + this.setState({ + error, + }); + } + + static getDerivedStateFromError(error: Error) { + return { error }; + } + + render(): React.ReactNode { + return this.state?.error + ? jsxs("div", { + styles: "display: contents;", + ref: (elem: HTMLElement) => + elem.appendChild( + this.props.renderError(errorToDef(this.state.error!)) + ), + }) + : this.props.render(); + } +} + +function errorToDef(error: Error): ErrorDef[] { + return (error.stack?.split?.("\n") ?? []) + .map(line => { + // split by really last @ + const [, name, source_ = ""] = line.match(/(.*)@([^@]*)$/) ?? [, line]; + + // This is separated because of eslint + let source = source_; + + // Ignore all the internal functions of react and vite + if ( + source.startsWith("vite/client") || + source.startsWith("react-refresh") || + name.includes("/node_modules/") || + name.startsWith("__require") || + name.trim().length === 0 + ) { + return; + } + + // Remove any URL prefix, leave just path + source = source.startsWith(location.origin) + ? source.substring(location.origin.length) + : source; + + // match to ?:: + const [, sourceFile, lineN, columnN] = source.match( + /^(.+)?(?:t=\d+|v=\w+):(\d+):(\d+)$/ + ) ?? [, source, "", ""]; + + return { + line: parseInt(lineN), + column: parseInt(columnN), + name: name, + source: sourceFile, + } satisfies ErrorDef; + // + // {name} + // + // {source} + // + // + }) + .filter((e): e is ErrorDef => !!e); +} diff --git a/js/showcase/src/react/index.ts b/js/showcase/src/react/index.ts new file mode 100644 index 0000000..a7d2534 --- /dev/null +++ b/js/showcase/src/react/index.ts @@ -0,0 +1 @@ +console.log("REACT"); diff --git a/js/showcase/src/styles.css b/js/showcase/src/styles.css new file mode 100644 index 0000000..6842d94 --- /dev/null +++ b/js/showcase/src/styles.css @@ -0,0 +1,6 @@ +@import "@rustlanges/react/styles.css"; +@import "tailwindcss"; + +html { + background: var(--color-gray-300); +} diff --git a/js/showcase/src/vite-env.d.ts b/js/showcase/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/js/showcase/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/js/showcase/tsconfig.json b/js/showcase/tsconfig.json new file mode 100644 index 0000000..0e3110e --- /dev/null +++ b/js/showcase/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/js/showcase/tsconfig.lib.json b/js/showcase/tsconfig.lib.json new file mode 100644 index 0000000..4c25e96 --- /dev/null +++ b/js/showcase/tsconfig.lib.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable", "ES2021.WeakRef"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/js/showcase/tsconfig.node.json b/js/showcase/tsconfig.node.json new file mode 100644 index 0000000..3afdd6e --- /dev/null +++ b/js/showcase/tsconfig.node.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "strict": true, + "noEmit": true + }, + "include": ["vite.config.ts"] +} diff --git a/js/showcase/vite.config.ts b/js/showcase/vite.config.ts new file mode 100644 index 0000000..5429803 --- /dev/null +++ b/js/showcase/vite.config.ts @@ -0,0 +1,50 @@ +import { defineConfig } from "vite"; +import { extname, relative, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { glob } from "glob"; +import react from "@vitejs/plugin-react-swc"; +import dts from "vite-plugin-dts"; +import tailwindcss from "@tailwindcss/vite"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + react(), + tailwindcss(), + dts({ + tsconfigPath: resolve(__dirname, "tsconfig.lib.json"), + }), + ], + build: { + copyPublicDir: false, + lib: { + entry: { + index: resolve(__dirname, "src/index.ts"), + react: resolve(__dirname, "src/react/index.ts"), + }, + formats: ["es"], + }, + rollupOptions: { + external: ["react", "react/jsx-runtime"], + input: Object.fromEntries( + // https://rollupjs.org/configuration-options/#input + glob + .sync("src/**/*.{ts,tsx}", { + ignore: ["src/**/*.d.ts"], + }) + .map(file => [ + // 1. The name of the entry point + // lib/nested/foo.js becomes nested/foo + relative("src", file.slice(0, file.length - extname(file).length)), + // 2. The absolute path to the entry file + // lib/nested/foo.ts becomes /project/lib/nested/foo.ts + fileURLToPath(new URL(file, import.meta.url)), + ]) + ), + output: { + assetFileNames: "assets/[name][extname]", + entryFileNames: "[name].js", + }, + }, + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a9c0c23..54b2e26 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,85 @@ importers: tailwind-merge: specifier: ^3.3.1 version: 3.3.1 + devDependencies: + '@eslint/js': + specifier: ^9.28.0 + version: 9.28.0 + '@rustlanges/showcase': + specifier: file:../showcase + version: link:../showcase + '@rustlanges/styles': + specifier: file:../../styles + version: link:../../styles + '@tailwindcss/cli': + specifier: ^4.1.8 + version: 4.1.8 + '@tailwindcss/vite': + specifier: ^4.1.8 + version: 4.1.8(vite@6.3.5(@types/node@22.15.29)(jiti@2.4.2)(lightningcss@1.30.1)) + '@types/node': + specifier: ^22.15.29 + version: 22.15.29 + '@types/react': + specifier: ^19.1.6 + version: 19.1.6 + '@types/react-dom': + specifier: ^19.1.5 + version: 19.1.5(@types/react@19.1.6) + '@vitejs/plugin-react-swc': + specifier: ^3.10.0 + version: 3.10.0(vite@6.3.5(@types/node@22.15.29)(jiti@2.4.2)(lightningcss@1.30.1)) + ajv: + specifier: ^8.17.1 + version: 8.17.1 + eslint: + specifier: ^9.28.0 + version: 9.28.0(jiti@2.4.2) + eslint-plugin-react-hooks: + specifier: ^5.2.0 + version: 5.2.0(eslint@9.28.0(jiti@2.4.2)) + eslint-plugin-react-refresh: + specifier: ^0.4.20 + version: 0.4.20(eslint@9.28.0(jiti@2.4.2)) + glob: + specifier: ^11.0.2 + version: 11.0.2 + globals: + specifier: ^16.2.0 + version: 16.2.0 + jiti: + specifier: ^2.4.2 + version: 2.4.2 + react: + specifier: ^19.1.0 + version: 19.1.0 + react-dom: + specifier: ^19.1.0 + version: 19.1.0(react@19.1.0) + tailwindcss: + specifier: ^4.1.8 + version: 4.1.8 + typescript: + specifier: ^5.8.3 + version: 5.8.3 + typescript-eslint: + specifier: ^8.33.0 + version: 8.33.0(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3) + vite: + specifier: ^6.3.5 + version: 6.3.5(@types/node@22.15.29)(jiti@2.4.2)(lightningcss@1.30.1) + vite-plugin-dts: + specifier: ^4.5.4 + version: 4.5.4(@types/node@22.15.29)(rollup@4.41.1)(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.29)(jiti@2.4.2)(lightningcss@1.30.1)) + + js/showcase: + dependencies: + alien-signals: + specifier: ^2.0.5 + version: 2.0.5 + clsx: + specifier: ^2.1.1 + version: 2.1.1 devDependencies: '@eslint/js': specifier: ^9.28.0 @@ -920,6 +999,9 @@ packages: alien-signals@0.4.14: resolution: {integrity: sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==} + alien-signals@2.0.5: + resolution: {integrity: sha512-PdJB6+06nUNAClInE3Dweq7/2xVAYM64vvvS1IHVHSJmgeOtEdrAGyp7Z2oJtYm0B342/Exd2NT0uMJaThcjLQ==} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -2554,6 +2636,8 @@ snapshots: alien-signals@0.4.14: {} + alien-signals@2.0.5: {} + ansi-regex@5.0.1: {} ansi-regex@6.1.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index fc52176..bdbce8a 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,5 +1,6 @@ packages: - js/react + - js/showcase - styles onlyBuiltDependencies: - "@parcel/watcher" From bf6b906e299dd4ed219d6c2b66da98963886e6a6 Mon Sep 17 00:00:00 2001 From: Brayan-724 Date: Sun, 29 Jun 2025 23:21:49 -0700 Subject: [PATCH 04/37] wip: MiniUI is working, simple cases working --- .../lib/components/button/button.showcase.tsx | 25 +- js/react/lib/showcases.ts | 1 + js/react/showcase/main.tsx | 7 +- js/react/showcase/styles.css | 1 - js/showcase/package.json | 14 +- js/showcase/src/ShowComponent/Container.tsx | 17 +- js/showcase/src/ShowComponent/Error.tsx | 63 ---- js/showcase/src/ShowComponent/Field.tsx | 28 +- js/showcase/src/ShowComponent/error.ts | 20 -- js/showcase/src/ShowComponent/error.tsx | 35 ++ js/showcase/src/ShowComponent/index.tsx | 323 +++++++++--------- js/showcase/src/case.tsx | 128 +++++++ js/showcase/src/icons.tsx | 12 +- js/showcase/src/index.ts | 44 ++- js/showcase/src/main.tsx | 12 - js/showcase/src/miniui/index.ts | 161 +++++++-- js/showcase/src/react/ErrorBoundary.ts | 42 +-- js/showcase/src/react/index.ts | 1 - js/showcase/src/react/index.tsx | 18 + js/showcase/src/react/render.ts | 25 ++ js/showcase/src/styles.css | 5 +- js/showcase/src/vite-env.d.ts | 10 + js/showcase/tsconfig.lib.json | 4 +- js/showcase/vite.config.ts | 4 +- pnpm-lock.yaml | 59 +++- 25 files changed, 679 insertions(+), 380 deletions(-) create mode 100644 js/react/lib/showcases.ts delete mode 100644 js/showcase/src/ShowComponent/Error.tsx delete mode 100644 js/showcase/src/ShowComponent/error.ts create mode 100644 js/showcase/src/ShowComponent/error.tsx create mode 100644 js/showcase/src/case.tsx delete mode 100644 js/showcase/src/main.tsx delete mode 100644 js/showcase/src/react/index.ts create mode 100644 js/showcase/src/react/index.tsx create mode 100644 js/showcase/src/react/render.ts diff --git a/js/react/lib/components/button/button.showcase.tsx b/js/react/lib/components/button/button.showcase.tsx index 36a292f..6651105 100644 --- a/js/react/lib/components/button/button.showcase.tsx +++ b/js/react/lib/components/button/button.showcase.tsx @@ -1,27 +1,20 @@ +import { registerCase } from "@rustlanges/showcase"; import { Button } from "./button.component"; -export default { - title: "Button", - propsDef: { +registerCase("Button", { + props: { variant: { - type: "string", + kind: "string", options: ["primary", "secondary", "text", "icon"], default: "primary", }, label: { - type: "string", + kind: "string", default: "Botón", }, - disabled: { - type: "boolean", - default: false, - }, - icon: { - type: "function", - }, - className: { - type: "string", - }, + disabled: "boolean", + icon: "function", + className: "string", }, component: Button, -}; +}); diff --git a/js/react/lib/showcases.ts b/js/react/lib/showcases.ts new file mode 100644 index 0000000..1f0115f --- /dev/null +++ b/js/react/lib/showcases.ts @@ -0,0 +1 @@ +import "./components/button/button.showcase"; diff --git a/js/react/showcase/main.tsx b/js/react/showcase/main.tsx index 6d0d440..398ce84 100644 --- a/js/react/showcase/main.tsx +++ b/js/react/showcase/main.tsx @@ -1,5 +1,6 @@ import { setupShowcase } from "@rustlanges/showcase/react"; +import "@rustlanges/showcase/styles.css"; +import "./styles.css"; +import "../lib/showcases"; -setupShowcase({ - src: "../lib/", -}); +setupShowcase({}); diff --git a/js/react/showcase/styles.css b/js/react/showcase/styles.css index b96e1f0..f5cfbe3 100644 --- a/js/react/showcase/styles.css +++ b/js/react/showcase/styles.css @@ -1,2 +1 @@ -@import "@rustlanges/showcase/styles.css"; @import "@rustlanges/react/styles.css"; diff --git a/js/showcase/package.json b/js/showcase/package.json index bb4a5a0..e860a8d 100644 --- a/js/showcase/package.json +++ b/js/showcase/package.json @@ -5,9 +5,13 @@ "type": "module", "exports": { ".": { - "types": "./dist/lib/index.d.ts", + "types": "./dist/src/index.d.ts", "default": "./dist/index.js" }, + "./react": { + "types": "./dist/src/react/index.d.ts", + "default": "./dist/react/index.js" + }, "./styles.css": { "default": "./dist/styles.css" } @@ -22,7 +26,7 @@ }, "scripts": { "build": "tsc -b ./tsconfig.lib.json && vite build && npm run check:tsc && npm run build:tailwindcss", - "build:tailwindcss": "npx @tailwindcss/cli -i lib/styles.css -o dist/styles.css --minify", + "build:tailwindcss": "npx @tailwindcss/cli -i src/styles.css -o dist/styles.css --minify", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0 && npm run check:tsc", "check:tsc": "tsc --noEmit -p tsconfig.lib.json" }, @@ -38,16 +42,12 @@ "@types/node": "^22.15.29", "@types/react": "^19.1.6", "@types/react-dom": "^19.1.5", - "@vitejs/plugin-react-swc": "^3.10.0", "ajv": "^8.17.1", + "dom-expressions": "^0.39.10", "eslint": "^9.28.0", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.20", "glob": "^11.0.2", "globals": "^16.2.0", "jiti": "^2.4.2", - "react": "^19.1.0", - "react-dom": "^19.1.0", "tailwindcss": "^4.1.8", "typescript": "^5.8.3", "typescript-eslint": "^8.33.0", diff --git a/js/showcase/src/ShowComponent/Container.tsx b/js/showcase/src/ShowComponent/Container.tsx index 1c5eb55..51c4d23 100644 --- a/js/showcase/src/ShowComponent/Container.tsx +++ b/js/showcase/src/ShowComponent/Container.tsx @@ -1,30 +1,29 @@ import { PropsWithChildren } from "react"; import { ChevronDown } from "../icons"; +import { h } from "../miniui"; export function ShowComponentContainer( props: PropsWithChildren<{ title: React.ReactNode; - className?: string; + class?: string; contentClassName?: string; }> ) { return (

- - {props.title} - + + {props.title} + -
+
{props.children}
diff --git a/js/showcase/src/ShowComponent/Error.tsx b/js/showcase/src/ShowComponent/Error.tsx deleted file mode 100644 index 5ba60f2..0000000 --- a/js/showcase/src/ShowComponent/Error.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { BombIcon } from "../icons"; -import { ShowComponentContainer } from "./Container"; - -export function ShowComponentError({ - title, - error: err, -}: { - title: string; - error: Error; -}) { - return ( - - {title} - - } - className="bg-red-300" - contentClassName="flex-col" - > - {err.message} - {(err.stack?.split?.("\n") ?? []).map(line => { - // really last @ - const [, name, source_ = ""] = line.match(/(.*)@([^@]*)$/) ?? [, line]; - - let source = source_; - - if ( - source.startsWith("vite/client") || - source.startsWith("react-refresh") || - name.includes("/node_modules/") || - name.startsWith("__require") || - name.trim().length === 0 - ) { - return; - } - - source = source.startsWith(location.origin) - ? source.substring(location.origin.length) - : source; - - // match to ?:: - const [, sourceFile, lineN, columnN] = source.match( - /^(.+)?(?:t=\d+|v=\w+):(\d+):(\d+)$/ - ) ?? [, source, "", ""]; - source = `${sourceFile}${lineN}:${columnN}`; - - return ( - - {name} - - {source} - - - ); - })} - - ); -} diff --git a/js/showcase/src/ShowComponent/Field.tsx b/js/showcase/src/ShowComponent/Field.tsx index dd95fb0..61ff589 100644 --- a/js/showcase/src/ShowComponent/Field.tsx +++ b/js/showcase/src/ShowComponent/Field.tsx @@ -1,5 +1,6 @@ import { useEffect } from "react"; import { NormalizedProps } from "./types"; +import { h } from "../miniui"; export function ShowComponentField({ name, @@ -26,16 +27,16 @@ export function ShowComponentField({ }); return ( -
-