{"id":15784646,"url":"https://github.com/atomita/xatto","last_synced_at":"2025-03-14T10:33:22.905Z","repository":{"id":57400987,"uuid":"134704856","full_name":"atomita/xatto","owner":"atomita","description":"xatto is View Layer Library based on Function and Context using VirtualDOM. This is developed by forking from jorgebucaran/superfine.","archived":false,"fork":false,"pushed_at":"2019-09-13T08:56:33.000Z","size":510,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-05T08:43:31.431Z","etag":null,"topics":["frontend","hyperapp","jsx","superfine","ultradom","vdom","view","virtual-dom","web","xatto"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/atomita.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-05-24T11:20:43.000Z","updated_at":"2020-12-23T05:16:38.000Z","dependencies_parsed_at":"2022-09-19T01:00:36.648Z","dependency_job_id":null,"html_url":"https://github.com/atomita/xatto","commit_stats":null,"previous_names":[],"tags_count":44,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomita%2Fxatto","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomita%2Fxatto/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomita%2Fxatto/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomita%2Fxatto/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/atomita","download_url":"https://codeload.github.com/atomita/xatto/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243562325,"owners_count":20311262,"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":["frontend","hyperapp","jsx","superfine","ultradom","vdom","view","virtual-dom","web","xatto"],"created_at":"2024-10-04T20:04:43.909Z","updated_at":"2025-03-14T10:33:22.643Z","avatar_url":"https://github.com/atomita.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# xatto\nxatto is View Layer Library based on Function and Context using VirtualDOM.  \nThis is developed by forking from [jorgebucaran/superfine](https://github.com/jorgebucaran/superfine).\n\n## Getting Started\n\n\u003e Note: The example in this document assumes that you are using a JavaScript compiler such as [Babel](https://babeljs.io/) or [TypeScript](https://www.typescriptlang.org/), a JSX (TSX) transpiler, and a module bundle such as [Parcel](https://parceljs.org/), [Webpack](https://webpack.js.org/).\n\n\nThe main APIs of `xatto` are two.  \nThe first one is `xatto.x`. It returns a new virtual DOM node tree.  \nThe other is `xatto.atto`. It returns a function that mount (or update) a component in the specified DOM element. (`mutate` function)\n\n\nexample: A counter that can be incremented or decremented.\n\n```jsx\nimport { x, atto } from \"xatto\"\n\nconst down = context =\u003e ({ count: context.count - 1 })\nconst up = context =\u003e ({ count: context.count + 1 })\n\nconst Component = (props, children, context) =\u003e (\n  \u003cdiv\u003e\n    \u003ch1\u003e{context.count}\u003c/h1\u003e\n    \u003cbutton onclick={down}\u003e-\u003c/button\u003e\n    \u003cbutton onclick={up}\u003e+\u003c/button\u003e\n  \u003c/div\u003e\n)\n\natto(Component, document.getElementById(\"app\"))({\n  count: 10\n})\n```\n\n\n## Installation\n\nxatto is available as a package on [npm](https://www.npmjs.com/). \n\n```\nnpm install xatto\n```\n\n```js\nimport { x, atto } from \"xatto\"\n```\n\nIt is also available on a [CDN](https://unpkg.com).\n\n```html\n\u003cscript src=\"https://unpkg.com/xatto\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  var x = window.xatto.x;\n  var atto = window.xatto.atto;\n  // ...\n\u003c/script\u003e\n```\n\n### Easier\n\n```sh\ngit clone https://github.com/atomita/xatto-starter-kit.git project\ncd project\nnpm install\nnpm run serve\n```\n\n## Overview\n\n### Context\n\nA context is a JavaScript object that describes a component.  \nIt consists of dynamic data that moves within a component during execution.  \nTo change the context you need to use the mutate function (or event handler in the components).\n\n### Mutate function\n\nIt is a function returned by `xatto.atto`.\n\nPassing the context mount the component specified by xatto.atto on the specified container together.  \nFrom the second time on, it update.\n\n### Components\n\nThe component returns the specification in the form of a plain JavaScript object called virtual DOM, and xatto is updates the actual DOM accordingly.  \nEach time the context changes the component is invoked so you can specify the appearance of the DOM based on the new context.\n\nThe context can be referenced in the third arguments.\n\n```jsx\nimport { x, atto } from \"xatto\"\n\nconst Component = (props, children, context) =\u003e (\n  \u003cdiv\u003e{context.name}\u003c/div\u003e\n)\n\natto(Component, document.getElementById(\"app\"))({\n  name: \"foo\"\n})\n```\n\n**Fragments supported**\n\n```jsx\nconst Component = (props, children) =\u003e (\n  \u003c\u003e\n    \u003cdiv\u003efoo\u003c/div\u003e\n    \u003cdiv\u003ebar\u003c/div\u003e\n  \u003c/\u003e\n)\n```\n\n#### Sliced context and fill\n\nThe child component can treat a part of the context as if it were the root context by using `\u003cContext slice=\"path\"\u003e` in the parent component.\n\nAlso, the `fill` attribute can specify a value to use if part of the sliced context is undefined.\n\n```jsx\nimport { x, atto, Context } from \"xatto\"\n\nconst Parent = (props, children, context) =\u003e (\n  \u003cdiv\u003e\n    \u003cspan\u003e{context.name}\u003c/span\u003e\n    \u003cul\u003e\n      \u003cli\u003e\u003cContext slice=\"children.0\"\u003e\u003cChild /\u003e\u003c/Context\u003e\u003c/li\u003e\n      \u003cli\u003e\u003cContext slice=\"children.1\" fill={{ name: \"baz\" }}\u003e\u003cChild /\u003e\u003c/Context\u003e\u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/div\u003e\n)\n\nconst Child = (props, children, context) =\u003e (\n  \u003cspan\u003e{context.name}\u003c/span\u003e\n)\n\natto(Parent, document.getElementById(\"app\"))({\n  name: \"foo\",\n  children: {\n    0: {\n      name: \"bar\"\n    }\n  }\n})\n```\n\n\n### Events\n\nEvent handlers are wrapped by xatto.  \nUsually, the event object passed in the first argument is the fourth argument.  \nThe return value is passed to the mutate function.\n\nEvent handler arguments:\n\n1. context\n2. `{ ...extra, ...detail, dispatch }`\n    - `detail` is [CustomEvent.detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail)\n    - `dispatch` is function for dispatch a [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent)\n3. props\n4. [event](https://developer.mozilla.org/en-US/docs/Web/API/Event)\n\n\n#### Lifecycle Events\n\nLifecycle events can be used to be notified when an element managed by the virtual DOM is created, updated, or deleted.  \nIt can be used for animation, data fetching, third party library wrapping, resource cleanup, etc.\n\n##### oncreate\nThis event occurs after an element is created and attached to the DOM.\n\n##### onupdate\nThis event will occur each time you update an element's attributes.\n\n##### onremove\nThis event occurs before an element is dettached from the DOM.  \n`detail.done` is passed a function to detach the element.\n\n##### ondestroy\nThis event occurs just before an element is dettached from the DOM.\n\n##### onlifecycle\nThis event occurs just before each life cycle event occurs.  \n`detail.type` is passed the life cycle event name.\n\n\n### Keys\n\nThe key helps to identify the node each time xatto update the DOM.  \nThis allows you to rearrange the elements to a new position if you change the position.\n\nThe key must be unique among sibling nodes.\n\n\n### Extra\nIf you want to pass values from the parent component to all descendant components, try using `Extra`.\nYou can refer to the same value regardless of `context`.\n\n```jsx\nimport { x, atto, Context, Extra } from \"xatto\"\n\nconst Parent = (props, children, context) =\u003e (\n  \u003cdiv\u003e\n    \u003cspan\u003e{context.name}\u003c/span\u003e\n    \u003cExtra parentName={context.name}\u003e\n      \u003cul\u003e\n        \u003cli\u003e\u003cContext slice=\"children.child1\"\u003e\u003cChild /\u003e\u003c/Context\u003e\u003c/li\u003e\n        \u003cli\u003e\u003cContext slice=\"children.child2\" fill={{ name: \"baz\" }}\u003e\u003cChild /\u003e\u003c/Context\u003e\u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/Extra\u003e\n  \u003c/div\u003e\n)\n\nconst Child = (props, children, context, extra) =\u003e (\n  \u003cdiv\u003e\n    \u003cp\u003e{extra.parentName + ' - ' + context.name}\u003c/p\u003e\n    {context.children \u0026\u0026 Object.entries(context.children).map(([k, child]) =\u003e (\n      \u003cContext slice={'children.' + k}\u003e\n        \u003cGrandchild /\u003e\n      \u003c/Context\u003e\n    ))}\n  \u003c/div\u003e\n)\n\nconst Grandchild = (props, children, context, extra) =\u003e (\n  \u003cp\u003e{extra.parentName + ' - ' + context.name}\u003c/p\u003e\n)\n\natto(Parent, document.getElementById(\"app\"))({\n  name: \"foo\",\n  children: {\n    child1: {\n      name: \"bar\",\n      children: {\n        grandChild1: {\n          name: \"barbaz\"\n        }\n      }\n    }\n  }\n})\n```\n\n\n## Polyfill which may be needed\n\n- [Promise](https://caniuse.com/#search=promise)\n  - [es6-promise - npm](https://www.npmjs.com/package/es6-promise)\n- [CustomEvent](https://caniuse.com/#feat=customevent)\n  - [custom-event-polyfill - npm](https://www.npmjs.com/package/custom-event-polyfill)\n- [WeakMap](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap#Browser_compatibility)\n  - [weakmap-polyfill - npm](https://www.npmjs.com/package/weakmap-polyfill)\n\n## License\n\nxatto is MIT licensed. See [LICENSE](LICENSE.md).\n\n## Other examples\n\n### The counters.\n\n```jsx\nimport { x, atto, Context } from \"xatto\"\n\nconst down = context =\u003e ({ count: context.count - 1 })\nconst up = context =\u003e ({ count: context.count + 1 })\n\nconst Counter = (props, children, context) =\u003e (\n  \u003cdiv\u003e\n    \u003ch1\u003e{context.count}\u003c/h1\u003e\n    \u003cbutton onclick={down}\u003e-\u003c/button\u003e\n    \u003cbutton onclick={up}\u003e+\u003c/button\u003e\n  \u003c/div\u003e\n)\n\nlet idx = 2\n\nconst add = context =\u003e ({\n  counters: { ...context.counters, ...(Object.fromEntries([[idx++, {count: 0}]])) }\n})\n\nconst cut = context =\u003e {\n  const entry = Object.entries(context.counters).slice(-1)[0]\n  if (entry == null) {\n    return\n  }\n  delete context.counters[entry[0]]\n  return {\n    counters: { ...context.counters }\n  }\n}\n\nconst Main = (props, children, context) =\u003e (\n  \u003cdiv\u003e\n    \u003cbutton onclick={add}\u003eadd\u003c/button\u003e\n    \u003cbutton onclick={cut}\u003ecut\u003c/button\u003e\n\n    {Object.entries(context.counters)\n      .map(([i, v]) =\u003e (\u003cContext slice={'counters.' + i}\u003e\u003cCounter /\u003e\u003c/Context\u003e))}\n\n    \u003cpre\u003e{JSON.stringify(context, null, '  ')}\u003c/pre\u003e\n  \u003c/div\u003e\n)\n\natto(Main, document.getElementById(\"app\"))({\n  counters: {\n    0: { count: 0 },\n    1: { count: 10 }\n  }\n})\n```\n\nhttps://codepen.io/atomita/pen/OaLxwP\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatomita%2Fxatto","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fatomita%2Fxatto","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatomita%2Fxatto/lists"}