{"id":25177496,"url":"https://github.com/webfruits/core","last_synced_at":"2026-04-30T10:32:45.159Z","repository":{"id":143829651,"uuid":"178063091","full_name":"webfruits/core","owner":"webfruits","description":"A TypeScript library for building user interfaces using the real DOM","archived":false,"fork":false,"pushed_at":"2022-06-06T20:34:55.000Z","size":128,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-04-26T01:22:05.120Z","etag":null,"topics":["library","typescript","user-interface"],"latest_commit_sha":null,"homepage":"https://webfruits.io","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/webfruits.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-03-27T19:40:42.000Z","updated_at":"2024-04-19T20:37:07.000Z","dependencies_parsed_at":"2023-10-23T01:45:39.202Z","dependency_job_id":null,"html_url":"https://github.com/webfruits/core","commit_stats":null,"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webfruits%2Fcore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webfruits%2Fcore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webfruits%2Fcore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webfruits%2Fcore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/webfruits","download_url":"https://codeload.github.com/webfruits/core/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247112739,"owners_count":20885605,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["library","typescript","user-interface"],"created_at":"2025-02-09T14:25:32.692Z","updated_at":"2026-04-30T10:32:40.125Z","avatar_url":"https://github.com/webfruits.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"https://webfruits.io/assets/wf-small-core-logo.svg\" alt=\"wf core logo\" height=\"50px\"\u003e\n\n# webfruits/core \u0026nbsp; [![Language TypeScript](https://img.shields.io/badge/language-TypeScript-green.svg)](https://www.typescriptlang.org) [![GitHub license](https://img.shields.io/badge/license-MIT-green.svg)](./LICENSE) ![GitHub package.json version](https://img.shields.io/github/package-json/v/webfruits/core.svg?color=green\u0026label=master\u0026logo=github) [![npm version](https://img.shields.io/npm/v/@webfruits/core.svg?color=green)](https://www.npmjs.com/package/@webfruits/core) \n... is all about creating highly customized, fast and interactive user interfaces using the real DOM and not a virtual one. It is super slim, modular and has no dependencies. All declarations and coding can be done with TypeScript. There is no need to learn any proprietary template language.\n\nTo make things easy, webfruits/core provides mainly one class with an easy API to work with: [`UIComponent`](src/UIComponent.ts). \n\nA `UIComponent` combines the creation of HTMLElements, the styling of those elements and any kind of logic. UIComponents can be combined and extended in any way to create simple to complex reusable custom components.\n\nHere comes a little snippet of how webfruits/core looks on [Reacts HelloMessage](https://reactjs.org) example:\n```typescript\nclass HelloMessage extends UIComponent {\n    constructor(message: string) {\n        super(\"hello-message\");\n        this.view.innerHTML = message;\n    }\n}\n\nlet helloMessage = new HelloMessage(\"Taylor\");\ndocument.body.appendChild(helloMessage.view);\n```\nThe above example outputs following to the DOM:\n```html\n\u003cbody\u003e\n    \u003chello-message\u003eTaylor\u003c/hello-message\u003e\n\u003c/body\u003e\n```\n    \n\n\n## Features\n* **Flexible.** With `UIComponent` you can create CustomElements, use existing or native HTMLElements.\n* **All in one place.** Elements, styles and logic are defined within each `UIComponent`.\n* **Inline styling to have fun with.** All styles are defined with TypeScript and will be processed and updated automatically. Use transform properties like `x`, `y`, `scale` or `rotate` as direct styling properties.\n* **Signals.** webfruits/core uses its own implemenation of [`Signals`](src/signal/Signal.ts) with the same API like [js-signals](https://millermedeiros.github.io/js-signals/).\n* **DOMObserver.** With `UIComponent` you can subscribe to signals like ``onAddedToStageSignal`` or ``onRemovedFromStageSignal``.\n* **Extended support for native events.** Adding and removing (!) native events has never been easier.\n* **Modular.** `UIComponent` uses a handful classes, which all can be used indepedently like [`DeviceUtils`](src/utils/DeviceUtils.ts), [`NativeEventsController`](src/controller/NativeEventsController.ts) or [`DOMObserver`](src/observer/DOMObserver.ts).\n\n\n## Benefits\n* **No dependencies.** webfruits/core is a simple, super lightweight and modular ui library written in TypeScript.\n* **No virtual DOM.** Create and access the real DOM. This brings you in full control and best performance.\n* **It's not a framework.** It's a library. So it's up to your needs how to structure your application. But there is a recommondation for a best practice at [webfruits/best-practice](https://github.com/webfruits/best-practice)\n* **It's vanilla coding.** Just use pure TypeScript to code your UI.\n* **Easy to learn and work with.** Even the source code itself should be understandable within minutes. So you are in full control to fix or extend webfruits/core for your needs.\n\n## Installation\nwebfruits/core is intended to use with npm and [webpack or similar module-handler](https://github.com/webfruits/webpack-starterkit).  \n\n    npm install @webfruits/core --save\n\n\n## Documentation\nThere is no documention available at the moment. Meanwhile, please have look at the source code, which should not that hard to understand.\n\n\n## Usage\nAfter installation you have to import `UIComponent` to make use of it:\n```typescript\nimport {UIComponent} from \"@webfruits/core\";\n```\n\n### Direct use of UIComponent\n_The direct use of a UIComponent are mostly done within an extended UIComponent._\n#### Create an UIComponent from an existing HTMLElement:\nIn this case `UIComponent` acts like a controller. It doesn't create a view, but instead it uses an existing HTMLElement as its view. For a WebApp this should be a rare use case, but with server side rendered pages this could get very handy to create additional features.\n```typescript\nlet bodyComponent = new UIComponent(document.body);\nlet headerComponent = new UIComponent(document.getElementById('header')); \n```\n#### Create an UIComponent with a CustomElement:\n[CustomElements are part of the WC3 WebComponents Standard](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). Using them makes reading and understanding of the DOM much more specific. Instead of having something like this: `\u003cdiv class=\"ui-component\"\u003e` you are getting `\u003cui-component\u003e`.  \n If `UIComponent` is getting constructed with no argument, it will create the default CustomElement `\u003cui-component\u003e`. If a element name is giving as an argument, this will create a individual CustomElement like: `\u003cELEMENT-NAME\u003e`. The element name has to contain a hyphen (\"-\") to meet the specification for creating CustomElements.   \n```typescript\n// creates the webfruits default CustomElement for UIComponent.view (\"\u003cui-component\u003e\")\nlet defaultComponent = new UIComponent();\n\n// creates a individual CustomElement for UIComponent.view (\"\u003ccustom-component\u003e\")\nlet customComponent = new UIComponent(\"custom-component\");\n```\n#### Create an UIComponent with a native HTMLElement:\nIf you need native APIs of specific HTMLElements like `HTMLImageElement` or `HTMLAnchorElement`, you can do that by using a native tag name as element name. \n _Tip: In TypeScript you can pass the type of the `view` to offer full code support._\n```typescript\n// creates a native HTMLImageElement for UIComponent.view (\"\u003cimg\u003e\")\nlet imageComponent = new UIComponent\u003cHTMLImageElement\u003e(\"img\");\nimageComponent.view.src = \"image.jpg\";\n\n// creates a native HTMLAnchorElement for UIComponent.view (\"\u003ca\u003e\")\nlet imageComponent = new UIComponent\u003cHTMLAnchorElement\u003e(\"a\");\nimageComponent.view.href = \"https://github.com\";\n```\n\n### Extending UIComponent\n`UIComponent` gets really powerful by extending it to create reusable, encapsuled custom components.  \nThe following snippet ports [Reacts Timer example](https://reactjs.org) to webfruits:\n```typescript\nclass Timer extends UIComponent {\n    \n    private _intervalID;\n    private _time = 0;\n    \n    constructor() {\n        super(\"timer-component\");\n        this.onAddedToStageSignal.add(() =\u003e this.start());\n        this.onRemovedFromStageSignal.add(() =\u003e this.stop());\n        this.render();\n    }\n    \n    public start() {\n        this._intervalID = setInterval(() =\u003e this.tick(), 1000);\n    }\n    \n    public stop() {\n        clearInterval(this._intervalID);\n    }\n    \n    private tick() {\n        this._time += 1;\n        this.render();\n    }\n    \n    private render() {\n        this.view.innerHTML = \"Seconds: \" + this._time;\n    }\n}\nlet timer = new Timer();\ndocument.body.appendChild(timer.view);\n```\n\n### Styling a UIComponent\n```typescript\nclass StyledComponent extends UIComponent {\n    \n    private _childComponent: UIComponent;\n    \n    constructor() {\n        super(\"styled-component\");\n        this._childComponent = new UIComponent(\"child-component\");\n        this.addChild(this._childComponent);\n    }\n    \n    // override UIComponent.updateStyles\n    // updateStyles will be called after adding this component to DOM\n    // and on every window resize event\n    public updateStyles() {\n        \n        // styling of this view\n        this.applyStyle({\n            backgroundColor: 0xFF0000,\n            userSelect: \"none\" \n        });\n        \n        // styling of a childComponent view\n        this._childComponent.applyStyle({\n            position: \"relative\",\n            left: 100, // numeric value are in pixels (px)\n            x: 100,\n            top: \"50%\", // use string values\n            y: \"-50%\",\n            width: this.calcChildWidth(), // use functions to calculate complex values \n            height: 50 + \"vh\"\n        })\n    }\n    \n    private calcChildWidth(): number {\n        return window.innerWidth \u003e 500 ? 300 : 200;\n    }\n}\n```\n\n## more webfruits\n\n- **[webfruits/toolbox](https://github.com/webfruits/toolbox)**  \nprovides additional features like SVGComponent, GridLayout and a lot of utilities.\n\n- **[webfruits/best-practice](https://github.com/webfruits/best-practice)**  \nour recommondation of how to structure an application using webfruits.\n\n- **[webfruits/webpack-starterkit](https://github.com/webfruits/webpack-starterkit)**  \nis a basic webpack setup and skeleton for an webfruits application.\n\n\n## Licence\nwebfruits/core is [MIT licensed](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebfruits%2Fcore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwebfruits%2Fcore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebfruits%2Fcore/lists"}