{"id":16712942,"url":"https://github.com/gabrielcsapo/psychic","last_synced_at":"2025-03-15T05:18:21.195Z","repository":{"id":70619827,"uuid":"77171232","full_name":"gabrielcsapo/psychic","owner":"gabrielcsapo","description":"🚫 Tiny single purpose view engine, help componentize your javascript.","archived":false,"fork":false,"pushed_at":"2017-11-02T07:03:15.000Z","size":1614,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-15T01:53:29.159Z","etag":null,"topics":["deprecated","framework","javascript"],"latest_commit_sha":null,"homepage":"https://gabrielcsapo.github.io/psychic","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gabrielcsapo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2016-12-22T19:42:29.000Z","updated_at":"2021-07-09T09:21:40.000Z","dependencies_parsed_at":"2023-08-30T05:32:33.110Z","dependency_job_id":null,"html_url":"https://github.com/gabrielcsapo/psychic","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrielcsapo%2Fpsychic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrielcsapo%2Fpsychic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrielcsapo%2Fpsychic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrielcsapo%2Fpsychic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gabrielcsapo","download_url":"https://codeload.github.com/gabrielcsapo/psychic/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243685742,"owners_count":20331011,"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":["deprecated","framework","javascript"],"created_at":"2024-10-12T20:44:47.391Z","updated_at":"2025-03-15T05:18:21.176Z","avatar_url":"https://github.com/gabrielcsapo.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003e DEPRECATED: THIS WILL NO LONGER BE UNDER DEVELOPMENT\n\n# psychic\n\n[![Build Status](https://travis-ci.org/gabrielcsapo/psychic.svg?branch=master)](https://travis-ci.org/gabrielcsapo/psychic)\n[![Coverage Status](https://coveralls.io/repos/github/gabrielcsapo/psychic/badge.svg?branch=master)](https://coveralls.io/github/gabrielcsapo/psychic?branch=master)\n\nTiny single purpose view engine, help componentize your javascript. Psychic will help you make super performant UI apps.\n\nNo abstractions, limit sugar. Keep your self close to the browser, but create compostable, and reusable UIs.\n\nCompatible with any template engine that accepts a model, and returns HTML. Use precompiled templates for blazing performance.\n\nCompatible with AMD, CJS, or can be found at c$ if no module loader is used.\n\nCompatible with Google Closure Compiler\n\n## Features\n\n* Reusable composition. (components, controls)\n* Universal, works under NodeJS and the Browser\n* Supports Progressive Enhancement, with Auto-Mounting\n    * Render the view on the server\n    * Run the client along side the server generated HTML\n    * Psychic upgrades the components on the page\n    * Mix with Webpack entry points for great perf\n* Sugar'd APIs to help get things done\n    * events\n    * component communication\n    * rendering\n* Blazing Fast\n* Tiny (1.5kb gzipped)\n\n## Get Started\n\n```bash\nnpm install psychic --save-dev\n```\n\n## Basics\n\nPsychic tries to be ultra fast by limiting the actual representation from the declarative api, to rendered DOM elements.\n\nWe generate HTML based on your outer Control's components. Events are wired to a single rendered container, utilizing a state machine like Redux - we can achieve some crazy performance.\n\nExtend any component at runtime using our declarative API, or leverage defining prototypes for parse time performance improvements!\n\nPsychic helps you manage events. We rely on native event implementations, but provide a small amount of sugar to abstract on them for you. Including condensing events to a single rendered root, detaching and reattaching at render time!\n\nPsychic has a full stack of lifeCycle events! You can listen for events that range from `afterRender`, to `beforeUpdate`.\n\nIt's amazing we fit all of this into less than 2kb of compressed space! For an additional 1kb you can bring our state machine with! That's only 3kb gzipped to get similar functionality as ReactJS + Redux!\n\nAnd yes, it is universal JS compatible, and views can be rendered on the server.\n\n## Usage\n\nGeneric Hello World\n\n```javascript\nvar Component = require('psychic');\n\nvar component = new Component({\n    template: function(data) { return data.message; },\n    message: 'Hello World'\n});\n\ncomponent.renderInto(document.body);\n```\n\nCompose components\n\n```javascript\nvar Component = require('psychic');\n\nvar component = new Component({\n    components: [\n        new Component({\n            template: function(){ return 'Hello World';}\n        })\n    ]\n});\n\ncomponent.renderInto(document.body);\n```\n\nAnother way to do hello world, we provide a default template\n\n```javascript\nvar Component = require('psychic');\n\nvar component = new Component({\n    innerHTML: 'Hello World'\n});\n\ncomponent.renderInto(document.body);\n```\n\nWe render components into this innerHTML for you. We collapse the representation of the DOM, and exploit the super fast innerHTML implementations developed over the years.\n\n\n```javascript\nvar Component = require('psychic');\n\nvar component = new Component({\n    template: function(data) {\n        return '\u003cchrome\u003e' + data.innerHTML + '\u003c/chrome\u003e';\n    },\n    components: [\n        new Component({\n            innerHTML: 'hello world'\n        })\n    ]\n});\n\ncomponent.renderInto(document.body);\n```\n\n# API\n\nPsychic currently has two core blocks to build with, `control` and `component`. A `control` is used when you expect a `component` to render. It adds a bit of extra decoration to a base component. The API is small and consists of these calls:\n\n* `component`\n * methods\n   * mix\n   * listen\n   * dispatch\n   * destroy\n * properties\n   * guid\n   * $ (hashmap of child components)\n* `control` (in addition to the above)\n * methods\n   * update\n   * renderInto\n   * render\n   * addClass\n   * removeClass\n\n`API EXAMPLES`\n\n\u003e addClass\n\n```\nvar Component = require('psychic').component;\nnew Component({\n  attributes: {\n    class: 'foo'\n  },\n  afterRender: function() {\n    this.addClass('bar');\n  }\n}).renderInto(document.body);\n```\n\n\n`var Component = require('psychic').component;`\n\n```javascript\n// mix\n// mixes data into\n// the component root\ncomponent.mix(data);\n\n\n// component hash\n// provides a quick and easy way to\n// access named components.\n//\n// components are only hashed on render\n// and not at contruction time\nvar component = new Component({\n        name: 'myComponent'\n});\ncomponent.render();\ncomponent.$.myComponent;\n\n\n// guid\n//\n// instanced components will be provided with a guid for eventing\n// this guid changes on page reload, but persists while the application\n// is loaded\ncomponent.guid\n\n// listen\n//\n// listen for browser events. Events are wired against outer container\n// nodes. Only the root rendered control will be listening, and delegating\n// to target child nodes when appropriate.\n//\n// listeners are tore down before every re-render. This is to encourage the\n// developer to think sparingly about event usage within the view library\ncomponent.listen('click', function(e){\n        console.log('this component was clicked!');\n});\n\n// listeners should be inserted using afterRender.\nvar component = new Component({\n        afterRender: function() {\n                this.listen('click', function(){});\n        }\n});\n\n// listeners attach to the parent node\nvar component = new Component({\n        components: [\n            var component = new Component({\n               afterRender: function() {\n                   // the root rendered parent will own the click\n                   // the click will be delegated to this handler\n                   this.listen('click', function(){});\n               }\n            });   \n        ]\n});\n\n\n/// dispatch\n///\n/// dispatches event that listeners are waiting to receive\n/// dispatch is throttled to 1 call per 80ms. Plan accordingly. The best use of this\n/// is to request the state machine to draw the view.\n/// this does not influence native event dispatches, only those sent you .dispatch\n///\ncomponent.listen('myevent', function(e){ console.log(e.data); });\ncomponent.dispatch('myevent', data);\n\n/// destroy\n///\n/// Tears down the component, child components, event handlers, but does not\n/// destroy the instance.\ncomponent.destroy();\n\n```\n\n`var Control = require('psychic').control;`\n\n```javascript\n/// update\n///\n/// updates the component's internal rendering\n/// if passed data, will also call .mix, before re-rendering.\n///\n/// if .update is called on a parent that node will be replaced\n/// in the DOM.\n\n// with no data, just ask for a re-render, and reinsertion\n// into the DOM if has a represented node.\ncontrol.update();\n\n// send data to use before rendering and DOM swap\ncontrol.update({foo: 'bar'});\n\n\n/// renderInto\n///\n/// Renders a control into a DOM target.\ncontrol.renderInto(document.body);\n\n\n/// render\n///\n/// Renders the control with the currently bound data set.\n/// Great for rendering on the server.\n/// We also provide a view engine that does this lifting for you.\ncontrol.render();\n\n```\n\n## Declarative Syntax API\n\nComponents are mainly composed in Psychic using the declarative syntax. This allows natural composition that most developers are familiar with in view libraries.\n\n```javascript\n// the base default declarative syntax for a control object\n\nvar definition = {\n    name: 'myComponent', // optional name for reference hashing\n    tag: 'div', // root node type, default is DIV\n    attributes: { // any DOM attribute to append to root node\n         'class': 'red',\n         'data-foo': 'bar'\n    },\n    afterRender: function(){}, // LifeCycle hooks\n    components: [ // composition block, add components for reuse\n        new Component()\n    ],\n    template: function(data) {\n        // the template provides the innerHTML structure of the component\n        // If a components block is defined on this component, data.innerHTML\n        // will be populated, so you can template chrome around your components\n        return 'Hello World'\n    },\n    innerHTML: '', // a simple string that is returned to the template, the default template renders this\n    myCustomFunction: function(){} // Methods you want to travel with the component\n};\n\n// instance a new component by passing it\n// the definition\nvar control = new Control(definition);\n```\n\n## Imperative Syntax API\n\nSometimes we want to extend components for reusability. We also want to get some performance gains when defining new components. Psychic leans heavily on prototypal inheritance to get some nice performance from our paradigm.\n\n```javascript\nvar Control = require('psychic').control;\n\nmodule.exports = function(data) {\n        // do some custom stuff here\n        Control.call(this, data);\n};\n```\n\n## LifeCycle\n\nPsychic provides component LifeCycle events. `wip`\n\nHere is a list of all the LifeCycle events that can be defined\n\n* `beforeUpdate` / `afterUpdate`\n* `beforeRender` / `afterRender`\n* `beforeDestroy` / `afterDestroy`\n* `beforeDispatch` / `afterDispatch`\n\n## Mounting\n\nPsychic allows you to render components on the server, and then mount them client side. It requires little to no effort on your part.\nSimply give your components a `name`.\n\n```jsx\nvar Control = require('psychic').control;\n\nmodule.exports = new Control({\n    name: 'myMountableComponent',\n    components: [\n        new Control({\n            name: 'myButton',\n            template: \u003cbutton\u003eClick Me\u003c/button\u003e,\n            handlers: {\n                'click': function(e) {\n                    alert('I was clicked!');\n                }\n            }\n        })\n    ]\n});\n```\n\n## Using a State Store / State Machine\n\nIt is preferential to use a State Store to maintain the state of your component. Utilizing the `FLUX` or one way data flow model, we can increase reliability and performance of our UI.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgabrielcsapo%2Fpsychic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgabrielcsapo%2Fpsychic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgabrielcsapo%2Fpsychic/lists"}