{"id":27464794,"url":"https://github.com/thybag/lump.js","last_synced_at":"2026-04-29T15:40:40.860Z","repository":{"id":48869327,"uuid":"297326580","full_name":"thybag/lump.js","owner":"thybag","description":"A simple component and reactive model library built for modern JS.","archived":false,"fork":false,"pushed_at":"2021-10-14T17:04:50.000Z","size":105,"stargazers_count":0,"open_issues_count":3,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-15T23:15:31.606Z","etag":null,"topics":["hacktoberfest","javascript"],"latest_commit_sha":null,"homepage":"","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/thybag.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}},"created_at":"2020-09-21T12:02:03.000Z","updated_at":"2021-10-11T19:18:27.000Z","dependencies_parsed_at":"2022-09-06T23:40:10.963Z","dependency_job_id":null,"html_url":"https://github.com/thybag/lump.js","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thybag%2Flump.js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thybag%2Flump.js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thybag%2Flump.js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thybag%2Flump.js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thybag","download_url":"https://codeload.github.com/thybag/lump.js/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249167457,"owners_count":21223508,"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":["hacktoberfest","javascript"],"created_at":"2025-04-15T23:15:36.549Z","updated_at":"2026-04-29T15:40:40.789Z","avatar_url":"https://github.com/thybag.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Lump.js\r\n\r\nA simple component and reactive model library built for modern JS. \r\nThis library is being created out of personal interest and is not meant for production use. \r\n\r\nThis library is entirely stand alone and has no dependencies. Only modern browsers are supported.\r\n\r\nLump is currency composed of two key elements.\r\n\r\n - **Components** - Defines logic for managing a selected area of the DOM. Heavily inspired by some of my favorite backbone.js features/approaches in terms of deferred event listeners and none perspective approach. \r\n - **Models** - A wrapper for arbitrary data, implementing a reactive layer using proxies. Interaction with the model is done primarily by registering event listens, that will trigger whenever a change is detected on its data path. The key change types are `create` `update`,`remove`. Changes from subobjects will automatically bubble to their parents.\r\n\r\n\r\n## Usage\r\n\r\nInstall using NPM or Yarn\r\n\r\n```\r\nnpm i lumpjs\r\n```\r\n```\r\nyarn add lumpjs\r\n```\r\n\r\nThen import either Component or Model where you want them.\r\n\r\n```\r\nimport Component from 'lumpjs/src/component.js';\r\nimport Model from 'lumpjs/src/model.js';\r\n```\r\n\r\n## Component\r\nA simple wrapper around some rendered markup, using delegated events.\r\n\r\n**Key features**\r\n* Delegated events setup in {events}. These can be both DOM events, or custom ones you trigger manually.\r\n* Functions can be async, if you want to load data\r\n* on/off/trigger to fire events.\r\n\r\n`Component` implements two key methods\r\n* **Make** - Create a new component using a given config\r\n* **Define** - setup a reusable component. This can be invoked by calling make on them with the data/overrides you would like to use.\r\n\r\n```js     \r\nComponent.make({\r\n    el: document.body,\r\n    template: (count) =\u003e `Count ${count} \u003cbutton\u003eClick\u003c/button\u003e`,\r\n    data: {\r\n        count: 0\r\n    }, \r\n    events: {\r\n        'click button': 'increment'\r\n    },\r\n    increment() { \r\n        this.data.count++; \r\n    },\r\n    render() {\r\n        this.setEl(this.tpl(this.data.count));\r\n    }\r\n});\r\n```\r\n\r\n## Model\r\nCreate reactive models for arbitrary data. Changes are managed via delegated data paths ensuring information can never become orphaned or out of sync.\r\n\r\nData is managed by an underlying tracker proxy, and exposed via an accessor proxy to allow you to interact with the model as if its a normal JavaScript.\r\n\r\nYou can detect changes by registering listeners against given data paths. Changes to sub-objects will bubble back up the parent.\r\n\r\n**Key data events.**\r\n\r\n* `on('create:{datapath}', (newValue) =\u003e {})` - New data created at datapath\r\n* `on('update:{datapath}', (newValue, previousValue) =\u003e {})` - Data at datapath has been changed to a new value\r\n* `on('remove:{datapath}', (previousValue) =\u003e {})` - Data at datapath no longer exists\r\n* `on('unchanged:{datapath}', (previousValue) =\u003e {})` - datapath was updated to an identical value\r\n* `on('change:{datapath}', (changeType, newValue, oldValue) =\u003e {})` - Change of any type to datapath\r\n* `on('all', (changeType, datapath, newValue, oldValue) =\u003e {})`- Change to any data\r\n\r\n**Datapath** is a dot notation representation of the path to the data you want to watch.\r\ne.g. `title`, `company.name`, `company.employees.0.name` or `company.employees[0].name`\r\n\r\nEach object in the Model supports the magic methods `on`, `get` and `set`. Adding a `on('update')` to one of these will register a model listener for the objects current datapath.\r\n\r\n```js\r\nlet model = Model({'test': {'hello': 'world'},'info': 'test box'});\r\n\r\n// Add listeners\r\nmodel.on('create:test.goodbye', function(prop, value){\r\n    console.log(\"Created goodbye value\");\r\n});\r\nmodel.on('remove:test.hello', function(prop, value){\r\n    console.log(\"Goodbye hello\");\r\n});\r\nmodel.on('change', function(prop, value){\r\n    console.log(\"changed\", prop, value);\r\n});\r\nmodel.on('read', function(prop){\r\n    console.log(\"read\", prop);\r\n});\r\n\r\n// Add listeners directly to sub objects\r\nlet test = model.test;\r\n\r\ntest.on('update', () =\u003e {console.log(\"I've been changed\");} )\r\n\r\n// Change via getter/setter or directly\r\nmodel.test.goodbye = 'value');\r\nmodel.test.hello = 'new value';\r\n\r\n// of full object replacement \r\nmodel.test = {'newObject': 'hi', 'hello': 'you'};\r\n\r\nconsole.log(test.hello); // will return you\r\n ```\r\nChange to `model.info = 'abc'` will trigger `changed info abc`\r\nChange to `model.test.hello = 'me'` will trigger `changed test.hello me`\r\n\r\n### Planned features\r\n\r\n * Templates helper library to abstract basic markup templates away.\r\n\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthybag%2Flump.js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthybag%2Flump.js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthybag%2Flump.js/lists"}