{"_id":"@asteo/nano-component","_rev":"4-f41653288b274851f5ad2bf7bcce64a2","name":"@asteo/nano-component","dist-tags":{"latest":"1.0.4"},"versions":{"1.0.0":{"name":"@asteo/nano-component","version":"1.0.0","license":"MIT","_id":"@asteo/nano-component@1.0.0","maintainers":[{"name":"oleasteo","email":"npm@stack.asteo.net"}],"dist":{"shasum":"96e3e0bd2a599e5eba1b35b3850fd0c44edd955f","tarball":"https://registry.npmjs.org/@asteo/nano-component/-/nano-component-1.0.0.tgz","fileCount":9,"integrity":"sha512-MJBpwpOOfHV9xsWVGTIEyj+f4vsnvpwCKUwbV9yHm09rsMRIDqwG+7zUzWhgbXeKbrzvEXN0GGydQ0asDZE0ww==","signatures":[{"sig":"MEUCIADa1KICqVwMI+UbYgMqxPyJUi5ML/4VumbabDqyvAIEAiEA7lRftzQ1ATejdjvLjW2ABy/F9xC2jQM+tS2Ly6/oXUQ=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":22612},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.js","gitHead":"bc0d25ea88b286e4ea98f94fda989fc04eab673c","scripts":{"build":"tsc","clean":"rm -rf dist"},"_npmUser":{"name":"oleasteo","email":"npm@stack.asteo.net"},"_npmVersion":"10.2.4","description":"A minimal component library to compose vanilla HTML + JS from multiple files.","directories":{},"_nodeVersion":"20.11.1","_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.0"},"_npmOperationalInternal":{"tmp":"tmp/nano-component_1.0.0_1724461723187_0.21828214391858758","host":"s3://npm-registry-packages"}},"1.0.1":{"name":"@asteo/nano-component","version":"1.0.1","author":{"name":"Ole Reglitzki","email":"ole@asteo.net"},"license":"MIT","_id":"@asteo/nano-component@1.0.1","maintainers":[{"name":"oleasteo","email":"npm@stack.asteo.net"}],"homepage":"https://gitlab.com/oleasteo/nano-component#readme","bugs":{"url":"https://gitlab.com/oleasteo/nano-component/-/issues"},"dist":{"shasum":"a7545b81d1783f72e0a37b1cfc700cf8b27f1daa","tarball":"https://registry.npmjs.org/@asteo/nano-component/-/nano-component-1.0.1.tgz","fileCount":10,"integrity":"sha512-19HAD7HXsB4xKESqclNrxIyBpC0wfF4cKWW1cxYR6lDlpztkNjhVuW4ne4mkIlOiQVy4tRSZHd7OkpVnM7c1eA==","signatures":[{"sig":"MEUCIQCHSuUuu57eAVNqJ8BM9+fwTaWH738rEBkB8FcxXuSZygIgIA9O7ojFcfy2t8kzhiDJnOvZZdP2sc0v7WdrkR9mdmw=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":23191},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.js","gitHead":"0b5a9733fc80fd7ed6a64652df0b2fe36e5bcdf8","scripts":{"build":"tsc","clean":"rm -rf dist"},"_npmUser":{"name":"oleasteo","email":"npm@stack.asteo.net"},"repository":{"url":"git+https://gitlab.com/oleasteo/nano-component.git","type":"git"},"_npmVersion":"10.2.4","description":"A minimal component library to compose vanilla HTML + JS from multiple files.","directories":{},"_nodeVersion":"20.11.1","_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.0"},"_npmOperationalInternal":{"tmp":"tmp/nano-component_1.0.1_1724462749621_0.4017835418222928","host":"s3://npm-registry-packages"}},"1.0.2":{"name":"@asteo/nano-component","version":"1.0.2","author":{"name":"Ole Asteo","email":"ole@pkg.asteo.net"},"license":"MIT","_id":"@asteo/nano-component@1.0.2","maintainers":[{"name":"oleasteo","email":"npm@stack.asteo.net"}],"homepage":"https://gitlab.com/oleasteo/nano-component#readme","bugs":{"url":"https://gitlab.com/oleasteo/nano-component/-/issues"},"dist":{"shasum":"d24d39ab57bce9446bf2bd8c73239f707a980e25","tarball":"https://registry.npmjs.org/@asteo/nano-component/-/nano-component-1.0.2.tgz","fileCount":17,"integrity":"sha512-93iOFS+tbFEN85aw4jPg8kx0YaG/hu6n2qSJMrQgFSY5wm2o0Z9og6cVPV6iUmbqGezxykKwbqkH3/0Jea3MGw==","signatures":[{"sig":"MEUCIQCfR5BXbV8tDTC4H/viX1o79QGbj/eyOTZSl5shUFqMFAIgA90a+jicCpSe+5bcMAdSd12XV3g4Q/bFN+nd5HsaGO4=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":24419},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.js","gitHead":"8b54abc70427411a0ab7fed5545955abea740dac","scripts":{"build":"tsc","clean":"rm -rf dist"},"_npmUser":{"name":"oleasteo","email":"npm@stack.asteo.net"},"repository":{"url":"git+https://gitlab.com/oleasteo/nano-component.git","type":"git"},"_npmVersion":"10.2.4","description":"A minimal component library to compose vanilla HTML + JS from multiple files.","directories":{},"_nodeVersion":"20.11.1","_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.0"},"_npmOperationalInternal":{"tmp":"tmp/nano-component_1.0.2_1724506208530_0.3425244692835727","host":"s3://npm-registry-packages"}},"1.0.3":{"name":"@asteo/nano-component","version":"1.0.3","keywords":["components","simple","vanillajs","tiny"],"author":{"name":"Ole Asteo","email":"ole@pkg.asteo.net"},"license":"MIT","_id":"@asteo/nano-component@1.0.3","maintainers":[{"name":"oleasteo","email":"npm@stack.asteo.net"}],"homepage":"https://gitlab.com/oleasteo/nano-component#readme","bugs":{"url":"https://gitlab.com/oleasteo/nano-component/-/issues"},"dist":{"shasum":"c77e3b7b407acef145bb8a1e35aedce6c28ffd35","tarball":"https://registry.npmjs.org/@asteo/nano-component/-/nano-component-1.0.3.tgz","fileCount":9,"integrity":"sha512-cIIrEVaWAF6D2BRGcHeHZQT5qXeTe07Suu2vbPpZEg3JRBjYuwKpt2QVQv8oUxPVUuQrrTRa1dUB2Lfe6+GBLw==","signatures":[{"sig":"MEUCIB1ityTpfDJUWSuMDokzB4daEJS7ymrysEv5MfJGQZcTAiEA+ODFYPr7z0owpmrR/KMP57tw6ji4taOpbgrnE7Hpq+w=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":22552},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.js","gitHead":"f106ddf118c5334d942c583cb9a84b572f353637","scripts":{"build":"tsc","clean":"rm -rf dist"},"_npmUser":{"name":"oleasteo","email":"npm@stack.asteo.net"},"repository":{"url":"git+https://gitlab.com/oleasteo/nano-component.git","type":"git"},"_npmVersion":"10.2.4","description":"A minimal component library to compose vanilla HTML + JS from multiple files.","directories":{},"_nodeVersion":"20.11.1","_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.0"},"_npmOperationalInternal":{"tmp":"tmp/nano-component_1.0.3_1724611148327_0.4493647534087768","host":"s3://npm-registry-packages"}},"1.0.4":{"name":"@asteo/nano-component","version":"1.0.4","description":"A minimal component library to compose vanilla HTML + JS from multiple files.","license":"MIT","author":{"name":"Ole Asteo","email":"ole@pkg.asteo.net"},"keywords":["components","simple","vanillajs","tiny"],"repository":{"type":"git","url":"git+https://gitlab.com/oleasteo/nano-component.git"},"bugs":{"url":"https://gitlab.com/oleasteo/nano-component/-/issues"},"type":"module","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsc","clean":"rm -rf dist"},"devDependencies":{"typescript":"^5.5.0"},"_id":"@asteo/nano-component@1.0.4","gitHead":"d2ce3b32e911a735924d3db19848f93815a30e94","homepage":"https://gitlab.com/oleasteo/nano-component#readme","_nodeVersion":"20.11.1","_npmVersion":"10.2.4","dist":{"integrity":"sha512-BgXYs6Dpi3DpJBV7DM/JjFFNGDSHSUhF2uMpSDgQ2pFJsL8D592uVzIQI+KbY6AuNlNWvsFlL1LhbzSNqu5bLg==","shasum":"bbaafcd0a130b619125fb61e079dc7b579086ebd","tarball":"https://registry.npmjs.org/@asteo/nano-component/-/nano-component-1.0.4.tgz","fileCount":10,"unpackedSize":33677,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGrDI4+ugqA2ksAXy7ML1EWGlq5oheW+dPZW46Q1GFVDAiBDNtYke5g6ifNYra22epF8PO5z3hGaH87vhNo62gdLBw=="}]},"_npmUser":{"name":"oleasteo","email":"npm@stack.asteo.net"},"directories":{},"maintainers":[{"name":"oleasteo","email":"npm@stack.asteo.net"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/nano-component_1.0.4_1724618240970_0.4187091037384707"},"_hasShrinkwrap":false}},"time":{"created":"2024-08-24T01:08:43.089Z","modified":"2024-08-25T20:37:21.427Z","1.0.0":"2024-08-24T01:08:43.391Z","1.0.1":"2024-08-24T01:25:49.794Z","1.0.2":"2024-08-24T13:30:08.691Z","1.0.3":"2024-08-25T18:39:08.515Z","1.0.4":"2024-08-25T20:37:21.208Z"},"bugs":{"url":"https://gitlab.com/oleasteo/nano-component/-/issues"},"author":{"name":"Ole Asteo","email":"ole@pkg.asteo.net"},"license":"MIT","homepage":"https://gitlab.com/oleasteo/nano-component#readme","keywords":["components","simple","vanillajs","tiny"],"repository":{"type":"git","url":"git+https://gitlab.com/oleasteo/nano-component.git"},"description":"A minimal component library to compose vanilla HTML + JS from multiple files.","maintainers":[{"name":"oleasteo","email":"npm@stack.asteo.net"}],"readme":"# NanoComponent\n\n[![NPM Version](https://img.shields.io/npm/v/@asteo/nano-component)](https://www.npmjs.com/package/@asteo/nano-component)\n[![JSR Version](https://img.shields.io/jsr/v/%40asteo/nano-component)](https://jsr.io/@asteo/nano-component)\n[![Minimized gzipped size](https://badgen.net/bundlephobia/minzip/@asteo/nano-component?color=green)](https://bundlephobia.com/package/@asteo/nano-component)\n[![Runtime Dependencies](https://img.shields.io/badge/dependencies-0-X?color=%233C1)](./package.json)\n[![NPM License](https://img.shields.io/npm/l/%40asteo%2Fnano-component?color=%233C1)](./LICENSE)\n\n**NanoComponent** is a very lightweight, vanilla TypeScript / JavaScript utility library that allows you to create and manage simple, reusable components in your web applications.\nThis library allows for a straightforward way to split your HTML and JavaScript into small, manageable pieces without a full-fledged framework.\nIt is best used with a bundler like [vite](https://vitejs.dev/).\n\n![NanoComponent Logo](assets/nano-component.o.svg)\n\n## Features\n\n- **Simple HTML parsing**: A template literal formatter can be used to parse HTML fragments within JS.\n- **Component Properties**: Re-use component factories with different properties (non-reactive).\n- **Component as Property**: Use components or HTML fragments as component properties.\n- **Element References**: Easily get a JS reference to tagged DOM elements (e.g. mount slots).\n- **Lightweight**: No dependencies, pure vanilla TypeScript, tiny package size.\n\n## Not a feature\n\nThis library **does not** provide any reactivity, async components, component lifecycles, template syntax, scoped styles or server-side rendering.\nIt solely provides basics to glue together multiple HTML + JS fragments. This is by design.\n\nThis library is intended to help quickly bootstrap simple web pages without the need for heavy frameworks or verbose web components.\n\n## Installation\n\nYou can install NanoComponent via npm (or any tool of your choice):\n\n```bash\nnpm i @asteo/nano-component\n```\n\n## Usage\n\n### Example: Counter Component\n\nA simple example would look like this:\n\n```typescript\n// MyCounter.ts\n\nimport { component, useMount, useRef, useRefMount, html, Mountable } from \"@asteo/nano-component\";\n\ninterface Props {\n  label: Mountable;\n  value: number;\n}\n\nexport default component<Props>(({ props: { label, value } }) => {\n  // append a parsed DocuemntFragment to the component DOM\n  useMount(html`\n    <div class=\"my-first-component\">\n      <template class=\"ref:label\"></template>\n      is:\n      <span class=\"ref:value\">${value}</span>\n      <button type=\"button\"\" class=\"ref:btn\">Increase!</button>\n    </div>\n  `);\n\n  // mount label prop to the \"ref:label\" position marker\n  useRefMount(\"label\", label);\n\n  // query by \"ref:value\" and \"ref:btn\" classes respectively\n  const valueEl = useRef(\"value\");\n  const btnEl = useRef(\"btn\");\n\n  // add click listener to button; just some vanilla js\n  btnEl.addEventListener(\"click\", () => {\n    valueEl.textContent = `${++value}`;\n  });\n});\n\n```\n\n### Mounting the root component\n\nYou'll want your root component to be mounted with the `mount` function:\n\n```typescript\n// index.ts\n\nimport { mount, html } from \"@asteo/nano-component\";\nimport MyCounter from \"./MyCounter.ts\";\n\nmount(\n  MyCounter({\n    label: html`The <span style=\"color:red\">answer</span>`,\n    value: 42,\n  }),\n  document.body,\n);\n```\n\n### Nested components\n\nAs you can see in the example with the `label` property, just use `Mountable` and `useRefMount(...)` for nested components or HTML fragments.\nWe could've passed in any component(s) to the `label` property in the example above.\nThe global `mount` function accepts `Mountable` as well, so we can mount multiple components at the same time, for example.\n\n```typescript\nmount(\n  [\n    MyCounter({\n      label: html`The <span style=\"color:red\">answer</span>`,\n      value: 42,\n    }),\n    // feature flag use-case\n    showMultiple\n      ? [\n          MyCounter({ label: \"First\", value: -1 }),\n          MyCounter({ label: \"Second\", value: 0 }),\n        ]\n      : null,\n  ],\n  document.body,\n);\n```\n\nThis simple structure allows a lot of flexibility. Feel free to experiment!\n\n## API\n\n### Types\n\n#### `Mountable`\n\nThe `Mountable` type should primarily be used to define nested content properties.\nIt is accepted by all mount functions below.\n\n```typescript\ntype Mountable =\n  | null // accept \"no content\" values\n  | Node // accept vanilla DOM Nodes (including html`...` template literals)\n  | string // accept text content (**not** HTML)\n  | Component // accept components\n  | Mountable[]; // accept lists of all the above (including recursive lists of course)\n```\n\n### Globals\n\n#### `component<Props>(setup: fn)`\n\nCreates a ComponentFactory that uses the passed setup function for component initialization.\nThe setup function receives a single argument of `{ props: Props, doc: DocumentFragment }`.\nThe `doc` is the root DOM fragment to be filled by the setup function.\nThis is mainly supposed to be done by the component-scoped helper functions below.\n\n#### `mount(content: Mountable, mountTarget: Element | DocumentFragment)`\n\nMounts the passed content onto the passed mount target.\n\n**Caution**: For `<template>` mount targets, the content is moved in front of the template element instead (useful for `useRefMount`; see below).\n\n#### `html` template literal\n\nThe `html` template literal formatter parses the string into a DocumentFragment; ready to be used with mount functions.\n\n### Component-Scoped helpers\n\nThese helper functions must be used synchronously within the setup function of components. The use the components DOM inherently for convenience.\n\n#### `useRef<T>(name: string)`\n\nRetrieves an element reference from the component DOM. The element must have the class `ref:<name>` (e.g. `ref:button`).\nThe default return type is `HTMLElement`. This can be further specified by the generic parameter `T`.\n\n**Caution**: Refences are simply resolved via `querySelector` at that moment. If nested content is already mounted, it will _pollute_ the DOM that is searched. Consider collecting references before any nested mounting.\n\n#### `useMount(content: Mountable)`\n\nAppends the passed content to the component DOM.\n\n#### `useRefMount(name: string, content: Mountable)`\n\nAppends the passed content to the specified reference element within the component DOM.\n\nFor `<template>` mount targets, the content is moved in front of the template element instead.\nThis allows to easily use `<template class=\"ref:slot\">` to act as pure reference points in the DOM (no useless container elements).\n\n## Recommendations\n\n### HTML Files\n\nIt is recommended to use vite or a similar bundler. This allows to simply import HTML files as strings (`?raw` with vite) within your ts/js file. Those can be parsed to `Mountable`s via the `html` template literal.\n\n```typescript\nimport MyFragment from \"./MyFragment.html?raw\";\n\n// use with any mount function via the template literal parser; e.g.\nmount(html`${MyFragment}`, document.body);\n```\n\nIt is not recommended to move component templates into dedicated HTML files. But dumb (no js) HTML fragments can easily be split into dedicated files in this manner.\n\n### Refs first\n\nMounting sub-content _pollutes_ the component DOM with arbitrary children. Thus, it is recommended to query `useRef` first for complex nested components. You can always use the global `mount` function onto the refs later on.\n\n### Singleton Components\n\nIf a component is only to exist once, you should export the component instance directly, not the factory.\n\n```typescript\n// TheHeader.ts\n\nexport default component<void>(() => {\n\n  // [component logic]\n\n})();\n// the trailing `()` immediately creates and exports just an instance\n```\n\n### File Naming\n\nIt is recommended to name component files in TitleCase (e.g. `MyCounter.ts`, `TheHeader.ts`, `TheFooter.html`).\nSingleton names are recommended to be prefixed with \"The\".\n\n## Contributing\n\nContributions are welcome! If you find a bug or have a feature request, please open an issue or submit a pull request.\n\n## License\n\nNanoComponent is licensed under the MIT License. See the [LICENSE](./LICENSE) file for more information.\n","readmeFilename":"README.md"}