{"_id":"vanilla-milk","_rev":"32-65c38962f8c3860ecf84bedffc22e1bf","name":"vanilla-milk","dist-tags":{"latest":"0.4.0-beta.0","beta":"0.3.2-beta.4","next":"0.4.0-alpha.0"},"versions":{"0.0.1":{"name":"vanilla-milk","version":"0.0.1","description":"Simple library for build web component","main":"index.js","repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"},"license":"MIT","keywords":["vanilla milk","web component"],"_id":"vanilla-milk@0.0.1","dist":{"shasum":"f5cd4ab140b69ad1021e833b3ead1137baaf0412","integrity":"sha512-0iwgM0+DOkZhu/Ubh2hO41LKVc/IgwXW+Cx6lJjldHJNQqZlgogIVGe3beJ2o79Nw8EHm1i38q0G7z7fH7yNig==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.0.1.tgz","fileCount":6,"unpackedSize":67402,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeCMwlCRA9TVsSAnZWagAAajsP/1rriVXDiPTKFRTrlytA\n7VPZY0AZKXZaoa9TKUSaY9oxgD2h6X4NbVhd240FViOukph/2MR7TREFYeWR\nKGs7A9cs0ZUo3s3lftlFounAybmtu+ngIUNm7PKliovhdyR2Zh7HQNIQ5wbs\nr28V8MkZQWmBlYRJjjnGXoiih7Ouz1gWNXqeCm9Ole3H4Pw0wZRgQ/8lryyT\nan0ZWnz2kejJjnCshG1WY2JhthJSF69Sr6h6IfYRAag/XLtbtlsptVGXwtdb\nBw2Xrqh5e1KqkNDd8bZkRVV2N6s10VulpEgyG0Mqt50B9pIyDZkUBSRLs3gd\ntc1QnTL6+xp4YVNxKwoDv7PqViyAnKcCGqmkSpuhSihpjlmmzMM9FriNNrVa\nwegQXymM6CysVEIMYNtw5N00W5MnODjnGjboRF5fL2nLR3es8Om2t1f1Acij\nbuYYyWIJid9yNoIF2S5slONoG71dNJ4W8tqYKGAExARi9L71CBWrHPyiEU0j\ntiXx9mp4kM4VTc0wvC++BJYyLm19EhawLdWwLFl/EDbMXX6rH91mX3dplJLy\nx5Foaz85H0C5CpEQ7paWBxsHso9nHtxazOnHeKew4jG4jq6jEKKgfpu+tLyh\n3GFunkhIDQIPHovtWCTEx/27F3ynZhpb2N/e9PN6xMf0Fpofcne2s0yUwcWO\n7g2t\r\n=n72f\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCqJE8CDg58dq2WTYDcneEtCTpwJd7b4qQoawOmc2gZpwIgSBhVBT00m+j5YPCZvNMv3CP3bMeO2p8tP6OXUeSzlcE="}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.0.1_1577634852759_0.5741325325110032"},"_hasShrinkwrap":false},"0.1.0":{"name":"vanilla-milk","version":"0.1.0","description":"Simple library for build web component","main":"index.js","repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"},"license":"MIT","keywords":["vanilla milk","web component"],"_id":"vanilla-milk@0.1.0","dist":{"shasum":"f00d3b87547c45c93393f74abc8c53e6d0620056","integrity":"sha512-8QUVRQsM2W3enoQq6IGHYU8DejXzwNjGt05YZbiXMKqZRWmNmW6fhpJ9Gn1OaUwlkr1VyjOEBWQhYuC7cRSyjA==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.1.0.tgz","fileCount":6,"unpackedSize":34892,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeCa5QCRA9TVsSAnZWagAAxdsP/2LSsdS1k+uAK9/pTTbJ\nf5b2tmdj5REfzcRs/UDaMyufQFDI86G3zE7DSk50jOBK3piXQV+bERUsQyrV\nYGzB8jXZpdZdAZRZ54NnUntbSF0/j2ZfqyWsobwEcdMAg+/KMCcqfn6ASDMh\ny4MjSEpyObBe46kpNsfydJBd1ZS8R5We27yr/C7VzwSCsV+XDYaB1NiF/qhx\n3z7AjyeQPFFwHKV7Qo/u7rATILVzwiVd5yN4tT1sffF1b0zbV9Hp036XJ7yn\nwI+YPoGuguoLRz6p+HwR6T7STuK0HmqC/KDJ5VRpprgAGz4BCEdXfhCbyPsj\nR2YP7l2Av/gKCY3r69umXxbv/CXVz/xRQnJL5YXUuY1utU9Rexi9M0HqEjUb\nBTqNRhUBhxw7LpxiZyvGoFbT7ifjuhTR/V0+ycxDzzOEwYnLX6qETZJaJgQR\n3QSrJRaXePVslJLvVjQcoTyuu1BJTgp0BICui8cwJR7NtmrdJ7A4PRkkIMEd\nox6JHVNb1dnw1rmMweE2FvNinpxgLDoC16tjlMCXBR345EEyEY+qeMNFAAFb\nxl7PKh1uhyDKfrp9jIzKrfodxGlwjRacBr3OQXHY4GOBxfjZVKnQkDIp19sf\n/XMTVvTDQ7aX0GemUpal2n491ZQ/wY/vfdklj0cRmb3ZNcRXA7fCuO1sVegP\nu3+c\r\n=7Ng7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD+qdORLpEv4m1BKcZZYeJbWSRXN3zgFRdv/fEMzs2KDgIhAP966eCZw/AXmhTTgVy/3iOcRGTY94zXhyfybff3rcCs"}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.1.0_1577692751812_0.43799361079542853"},"_hasShrinkwrap":false},"0.1.1":{"name":"vanilla-milk","version":"0.1.1","description":"Simple library for build web component","main":"index.js","repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"},"license":"MIT","keywords":["vanilla milk","web component","vanilla milk js"],"_id":"vanilla-milk@0.1.1","dist":{"shasum":"8f3c926a3ac14e25b0d8e6e4b516d613db0b8d4b","integrity":"sha512-YjIcp7kSSV8BAoLLNjIizNyYNGodmv/WqRmCtgXYNuyHQHUxRIvMXNvcKKW/3Po3mGxQw02JvsFKYGnIfEyRNw==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.1.1.tgz","fileCount":6,"unpackedSize":35289,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeCgyICRA9TVsSAnZWagAAxVEP/2edPCiZK2dn0a5lHO33\nN94hpsulLBkFybe4gcxJHATyMgS2FM1va3FieCLtlqtWOoqV8E/mRph4KW8p\nP0mlQsAKK3SbAw/hmGURPlBfu3xP/IS08QcoWPbCXqHjMix/Y/CrwlkSJFdq\n1/yCw0JrK5bo8Zt+QLIXGN+PorrUXh+CvwNJatBShQ4la4R2GbP1K2EGdaxi\n7vKwdmeEmlL6ucTZefw+AKvcGvhjV0K56IgH5wUSsFeAuBDb16yf04q7+vGj\n8aHEM+ZtTU9efVwDp3EAId2c8DYtsVjnVZNEU358aFgU8GcnIGM/75bacZkJ\nADue1ZU3sAMX3m+tU/qpPLfHwMcBc8R3oJ81wCqTqqvZ2dcpyQtoVQI4L1/9\nwx5G3c4ZVU0ualGiPe4XUkkN9ZvKwU1p7R8puwEqZ0FAF2X9bOIav9wq1I8j\n+LyvciSV9ZQ3LVnAkyXlMkm/6DNeGltbcdlPDnuo6iqAxs1pRq4stcJVPXNW\nMIWSfuYulfFXLKTv0lShBishZSmeuIcmyTE2ZX3KNhJGm4zWh5nEzzvexGaq\nUiTXReyN0t+Ir6pnE2zZQeI9sHUbcnbza0zrNw2Nd5/x69gR6169qnhOJjmB\nbUa+vDoNLePRhzf8UapRyRT/UpWtaCCExLBcYqb6asd63SqTmH/koQFUQzSi\ngfnM\r\n=yJuQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFYF8p2qVQNSufge1MHTch8Ri0K89XvZUCGWWyyXdH1hAiBqGkw9TfGT/JlV61KDlrBeAnFjWZ8sXY2x7WUyPK74Pw=="}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.1.1_1577716871910_0.04151846629207978"},"_hasShrinkwrap":false},"0.1.2-beta.0":{"name":"vanilla-milk","version":"0.1.2-beta.0","description":"Simple library for build web component","main":"index.js","repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"},"license":"MIT","keywords":["vanilla milk","web component","vanilla milk js"],"readmeFilename":"README.md","readme":"# Vanilla Milk\nSimple library for building simple reactive web components.\n  \n## What is...\nVanilla Milk is a library which helps create to web component which can be used on anywhere! Embrace future of web-component made it future-proof. Built-in reactive state and props but also is very small and fast.\n\nVanilla Milk feature:\n* Reusable component.\n* Simple way for creating web components.\n* Milk DOM, update only neccessary.\n* Reactive state and props.\n* No class, just function.\n* Life-cycle hooks.\n* Expressive Vanilla like API structure.\n* Very small (1kB gzipped on production).\n* Encapsulated style, ID and class name.\n* Zero dependencies.\n* TypeScript support.\n\n## Milk DOM\nVanilla Milk doesn't use Virtual DOM, instead it Milk DOM which share the same idea with Virtual Dom, update where neccessary. Unlike VDOM, Milk DOM use a collection of Native Browser API to perform diffing instead of creating long list of object which also prevent heavy recursion.\nDrawback is diffing algorithm isn't as deep as Virtual DOM does but Milk DOM is blazing fast and has less memory consumption.\n###### Note: Milk DOM is in an very early stage of development, you might experience some bug and when that time came, you can always open the issue on this repo.\n  \n## Getting started\nGlad you're interested in! Let's get over quick start! Let us add library just for creating a component, after the component has been built, you don't have to install it anymore! Just moved the built components to your any project~\n\n### Install Vanilla Milk\nLet install this real quick with package manager of your choice.\n```bash\n// Using npm\nnpm install vanilla-milk --save\n\n// Using yarn\nyarn add vanilla-milk\n```\nWell done! Now you're ready to create a Milk Component! (Shortname for Vanilla Milk Component for the greater good.)\n  \n### Hello World! It's Milk Component!\nLet's start by building `milk-component', a traditional hello world for programmer but as web component.\n\nMilk Component are separated into 2 step:\n1) Define it with `create`\n2) Create it with `define`\n\nJust 2 step, that's all for building reactive web component.\n\n#### Create\nFirst of all, import `create` function from vanilla-milk. This function is responsible to create a model of component.\n```javascript\nimport { create } from \"vanilla-milk\"\n```\n\nFirst parameter is a callback to display HTML Element.\n```javascript\nimport { create } from \"vanilla-milk\"\n\nconst MilkComponent = create((display) => \n\tdisplay(`<h1>Hello World! Milk Component!</h1>`)\n)\n```\nWe have just create `MilkComponent` which will return `<h1>Hello World</h1>`  \n\n### Define\nNext we just have to `define` this component, so it can work like every HTML Element.  \nBut first, import `define` from `vanilla-milk`\n```javascript\nimport { define } from \"vanilla-milk\"\n```\n\nNow let's name the component `milk-element`, so it can be use in HTML. (Web Component need `-` to be declared, like `milk-component` which has `-` in it)\n```javascript\nimport { create, define } from \"vanilla-milk\"\n\nconst MilkComponent = create((display) => \n\tdisplay(`<h1>Hello World! Milk Component!</h1>`)\n)\n\ndefine(\"milk-component\", MilkComponent)\n```\nThat's it! You have just created a Milk Component!! :tada::tada:\n  \n#### Milk Component in action\nSoooo~ We have just created a web component, let's see it in action!  \nJust add `<milk-component></milk-component>` in HTML. Make sure you've link the JavaScript file which contain milk component in it. You can use quick set-up like `parcel`.\n```html\n<!-- Any HTML here -->\n<html>\n<head>\n\t<title>Hello Milk Component</title>\n    <script src=\"milk_component_here.js\"></script>\n</head>\n<body>\n\t<milk-component></milk-component>\n</body>\n</html>\n```\nAnd it should display something like this.\n    \n#### But that's not what make Vanilla Milk special...\nIn Vanilla Milk, component are reactive which mean every time `state` or `props` changed, Milk Component will know it.\n\n## State\nLike `angular`, `react` and `vue`, Vanilla Milk also has `state`.  \nState is like a variable which are responsible for storing data and display it to view.\n\nLet's say we want to create a counter and display count to view. In Vanilla Milk we do like this.\n  \nIf you're familiar with React, we have `useState`. But it's not like what you might think.\n```javascript\nimport { useState } from 'vanilla-milk'\n```\nVanilla Milk are designed to be expressive. So we separate the state, props and life-cycle to the second parameter of `create` like this.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\tlet { count } = state\n    \n\treturn display(`<h1>Count ${count}</h1>`)\n},\n{\n\tcounter: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nSo, what's happend here?\n  \nThe second parameter of `create` are responsible for handling data, so we can separate and focus on each part.\n```\n{\n\tcount: useState(0)\n}\n```\nHere we defined state name `count` with value of `0`. `useState` is a function that say, \"Hey! We want a state name 'count' with value of 0\" to Vanilla Milk or something like that. Vanilla Milk will just handle the rest of that and pass the `count` to the `second parameter` of the view callback.\n```\nconst MilkComponent = create((display, state) => {\n\tconsole.log(state) // { count: 0 }\n},\n{\n\tcount: useState(0)\n})\n```\nLastly, we display counter to the view.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\treturn display(`<h1>Count ${state.count}</h1>`)\n},\n{\n\tcount: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nNow that will display `count` to HTML, so... how do we set it in Vanilla Milk?\n  \nAs an early state of development of Vanilla Milk that's where the last parameter of `create` kick in!  \nWe add button and attach event in to it, so we can change the value of `counter`. // Hey don't make face of disappointment like that! I'll fix it in some next update, I promise! It's quite hard to create something like that ya know.\n  \nLet add a button.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\treturn display(`\n\t\t<h1>Count ${state.count}</h1>\n    \t<button id=\"increase-count\">Increase count</button>\n\t`)\n},\n{\n\tcount: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nLike in Vanilla JavaScript, we `query` an element, add `event` in to it `then` create a callback to do what we want! That's also how it work in Vanilla Milk but it's shorten!\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\treturn display(`\n\t\t<h1>Count ${state.count}</h1>\n    \t<button id=\"increase-count\">Increase count</button>\n\t`)\n},\n{\n\tcount: useState(0)\n},\n{\n\tquery: \"#increase-count\",\n\tevent: \"click\",\n\tthen: ([state, set]) => {\n\t\tset.count(state.count + 1)\n    }\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nWe have just said something like `when ID 'increase-count' is clicked then do something`.\nNotice that we have `[state, set]` in callback of `then`, this is where you can `access and set value of state`.\n```javascript\nthen: ([state, set]) => {\n\tset.count(state.count + 1)\n}\n```\nAt here we get value of `count` from `state.count` and set it with `set.count` which came out with something like this:\n```javascript\nset.count(0 + 1) // Count is now 1\n```\nNow it should increase the value of count everytime we click it!\n\nThat's it! You've just achieve an advance concept like state of Vanilla Milk :tada::tada:\n\n## Props\nContrast to state, it's super simple. props is shorten for `properties`. A property is like a HTML attribute. For a button like:\n```html\n<button class=\"nice-button\">Hello! I'm a button</button>\n```\nclass is a props of this button and it's value is \"nice-button\".\n  \nAs Milk Component, we also can have something like that! and guess what? You can create any attribute you like effortlessly!\n  \nAll you have to do is import `useProps` from `vanilla-milk` and set it like `useState`.\n```javascript\nimport { useProps } from \"vanilla-milk\"\n```\nNow let's say that we want to have a prop name `hello`. Like `useState` we do it like this:\n```javascript\n{\n\tcount: useState(0),\n\thello: useProps()\n}\n```\nAnd access it like state\n```javascript\ncreate((display, state, props) => {\n\tconsole.log(props.hello) // null if there's no value passed\n})\n```\nSo let's define the component real quick to see how it work.\n```javascript\nimport { create, define, useProps } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state, props) => {\n\treturn display(`<h1>hello ${props.hello}</h1>`)\n},{\n\thello: useProps()\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nAnd in HTML\n```html\n<milk-component hello=\"world\"></milk-component> // hello world\n```\nThe reason we have to define `props` so that Vanilla Milk can just update and listen only to the props you used! \n  \nBut there's one special props which is always available... `children`\nChildren is any text or HTML Element between the Milk Component.\nIn HTML:\n```html\n<milk-component>Hello World</milk-component>\n```\nAnd access it:\n```javascript\nconst MilkComponent = create((display, state, props) => {\n\tconsole.log(props.children) // Hello World\n})\n```\nThat's it! Unlike `useState`, `useProps` is super to use! :tada::tada:\n\n## useEffect\nLike React, you can defined lifecycle with `useEffect`.\n  \nLet's say, that you want to `console.log()` everytime prop `hello` change. You just have to import `useEffect` from `vanilla-milk`.\n```javascript\nimport { useEffect } from \"vanilla-milk\"\n```\nAgain, add it to second paramter of `create` like `useState` and `useProps`\n```javascript\n{\n\thello: useProps(),\n\tlogHello: useEffect((state, props) => {\n\t\tconsole.log(props.hello) // Log everytime hello changed\n    }, [\"hello\"])\n}\n```\nNotice that we add array contain \"hello\" as string as the second parameter of useEffect.\nBecause we can't directly access value of hello so we just add it as string, Vanilla Milk will take care of the rest (In fact, we can add it as variable but it takes an extra effort and performance cost).\n\nYou can express name of `useEffect` as anything, It just easier to remind you lifecycle with name if there are too much lifecycle.\n\nNow we hello is changed, first callback will run. Like view callback, useEffect is paired with `(state, props)`. You can directly access it in the callback.\n\n`useEffect` is not only limited to state but props too! You can also add `useEffect` as much as you want or many listener as much as you need!\n```javascript\n// State and Props\n{\n    hello: useProps(),\n    count: useState(),\n\tlogHello: useEffect((state, props) => {\n    \tconsole.log(props)\n    }, [\"count\"])\n}\n  \n// Multiple listener\n{\n    hello: useProps(),\n    count: useProps(),\n\tlogHello: useEffect((state, props) => {\n    \tconsole.log(props)\n    }, [\"count\", \"count\"])\n}\n```\n  \nThat's pretty much it of Vanilla Milk 0.1.2. :tada::tada:\nI'm looking for implement more functionality to this project soon! ps. vdom are also planned to be added in the future~ Stay tuned!","_id":"vanilla-milk@0.1.2-beta.0","dist":{"shasum":"73aa6f6709c28bfb038366cd40f1bf4b635e6f74","integrity":"sha512-7JK7ChxK0D4dSp37RroT0SMOiHx3dd54/wICZ5TCTA3aI54bIW+hsxiAOu59GsG4zU706YThfU6U+1ORadR1zA==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.1.2-beta.0.tgz","fileCount":6,"unpackedSize":133537,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeDOQrCRA9TVsSAnZWagAASeEP/RKSvWV1KUSsDgNXxavB\nRo8g2f7f/jvLyQj4bsjdGFWBXfWkMF2f7//oZUOWJCjjQ3dq8MzYjbZ7bXGb\nsjXCkAB4LeFsEqiA+C2vclw26TSXE6tjHaSOZGBTouQb0zyS+l3JyuquKKN2\nDsE+DDSG+Tl0eajiT0EUmJ+Lhlq4nqcuLzfaBq1VyqeNFZhonBGRTRfgJ1p2\n/bTM5Vt/n0Sk1F7rP7YsdlXVVxTCfcmsDxUUSheRJiFo3gU5ECPVUT3coIez\nmtqF4Z1F8lC3YW6Kqr485FK87oR14wDX7/5DzAvMaex7nbLtARiXgQNoZRIY\nAXmWQWKddcZx7PEykYiq677tLVcjZvs3u6Xq1Pzqh3X8qXMXY1zbzdN0RUza\npXozxz75oZ5H6/fxA9O8DJI7QnS0TDLBAv++u6bP5J+sSqjR6ukUet+yRk6n\nxhsjYW2akNNpmzgHP5McMvD/8VHwMBnNnUH4ID2UYPjx3nYkLIFYfSWed218\nagBSGrTEkxEjANovFL5c0vECMl6QrJ9HkVNBhq5AeN+DryB9oYCZRHmzsdzJ\nb4EykPDckBq44566Y6uS3ZrzMohoPJuU6WoULSvcK67X4kLTokLpq886b5Y2\nPwGfvs5JHsIi/ylHKYazObZvM/GI0SHrxOND6Stfx7tmDJpzO1yxG8x92S+d\nHS4/\r\n=5y88\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCLuM8gkMLsETxBx3Y4JJmZsFVdppbewSGOD0Ok2Jkh9gIhALXDhznWWmz31N251WrcYcvO3HEOnf/8a8FqX+t2m9rE"}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.1.2-beta.0_1577903146500_0.3475239515080144"},"_hasShrinkwrap":false},"0.2.0":{"name":"vanilla-milk","version":"0.2.0","description":"Simple library for building simple reactive web components.","main":"index.js","license":"MIT","dependencies":{},"scripts":{"build":"rm -rf dist && tsc --build && terser dist/index.js -o dist/index.js --compress --mangle && cp project/package.json dist/package.json && cp README.md dist/README.md"},"devDependencies":{"terser":"^4.4.3","typescript":"^3.7.4"},"_id":"vanilla-milk@0.2.0","dist":{"shasum":"b747ffa3ef84189de14511764efb3c1dfea4db39","integrity":"sha512-GDPPb/AUYHL/sWNN4fN+R+yIqyOWOCRv87EKC8MRuWtiAx0NZ81FLYnfu/FTS239yd5Dv/y4ek3xPtHO8ObaDw==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.2.0.tgz","fileCount":8,"unpackedSize":24388,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeDeQLCRA9TVsSAnZWagAA3bIP/00a+GXg9fLEK2DUSGvY\n8rdNdDhWRReJF8L51AItBUNUYJ5nYCHCJ7FsAZFBmtnlF45q2UZ6AkbBIuFm\nxXej4kpxu6L+9bwwe5OVURDxE79ymADd7iBHGczjLBSfVqAuAzZKnHP4PHHS\nLRcbqBQ2oBFgYP33SJbnOOHYigvqJJM6xWSfNU4Mk4mR0cIChUzx2JCdQNts\nO0xRHRXCCRHsolf0prNMT6W/o2U2pWWgdxDiKGp7oiNB/v9faHAOmNw2E+Cy\nsJyCwsiJ1zMejVmEe6tmRm8ovbb5VvF7IR14EJtCmG8y/4WBs1+EHD+vXz8A\nbUbvCeraiKK2riBg6WIzZV8JTpcjjEg6nDT1MWZB6HVRpHQaUDn3H6DbCbs/\nL5DFfWgR4COyt8e9zT1soLtG5+dhXO5nGtKJAJ27G0xdKO9ry1rcJ4xYZzH7\ncBdHOD4prOzOwKX00+ZmlIUZVffqLGTLUS+qHB4fpj1ilBqcap6JHo16K89V\nSNQ589WTEfCOP9tqHyybn4+CeMKsSvECxVnc282ce5rulAeCmpg+NxlZe7Pq\nxQCWYXxDrwoYFxkvK7odWty6iW4TMwX4H1DSc7wn71j/c+EBGuJPG3RxjyyA\nhY3h+6OR0BSFm4tHX3URuJ3BRKLm9+e1d+EqdLbxH2IrLvElpqQjHLbahp5P\nxJD4\r\n=D59S\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFk4o14mD/8ipDdFZCqnPZsSt3urDbnZwJJGZ3wCyV7qAiEA1ZLXv1nIdu8H3K2cqgI2Nk/F/LBZQcQcNeBIq2jKaB4="}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.2.0_1577968650965_0.8290949081441283"},"_hasShrinkwrap":false},"0.3.0-beta.3":{"name":"vanilla-milk","version":"0.3.0-beta.3","description":"Simple library for building simple reactive web components.","main":"index.js","repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"},"license":"MIT","keywords":["vanilla milk","web component","vanilla milk js"],"readmeFilename":"README.md","readme":"# Vanilla Milk\nSimple library for building simple reactive web components.\n  \n## What is...\nVanilla Milk is a library which helps create to web component which can be used on anywhere! Embrace future of web-component made it future-proof. Built-in reactive state and props but also is very small and fast.\n\nVanilla Milk feature:\n* Reusable component.\n* Simple way for creating web components.\n* Milk DOM, a special implementation of DOM manipulation.\n* Reactive state and props.\n* No class, just function.\n* Life-cycle hooks.\n* Expressive Vanilla like API structure.\n* Very small (1kB gzipped on production).\n* Encapsulated style, ID and class name.\n* Zero dependencies.\n* TypeScript support.\n\n## Milk DOM\nVanilla Milk doesn't use Virtual DOM, instead it has its own `Milk DOM` which share the same idea with Virtual Dom, update where neccessary. Unlike VDOM, Milk DOM use a collection of Native Browser API to perform diffing instead of creating long list of object which also prevent heavy recursion.\nDrawback is diffing algorithm isn't as deep as Virtual DOM does but Milk DOM is blazing fast and has less memory consumption.\n###### Note: Milk DOM is in an very early stage of development, you might experience some bug and when that time came, you can always open the issue on this repo.\n  \n## Getting started\nGlad you're interested in! Let's get over quick start! Let us add library just for creating a component, after the component has been built, you don't have to install it anymore! Just moved the built components to your any project~\n\n### Install Vanilla Milk\nLet install this real quick with package manager of your choice.\n```bash\n// Using npm\nnpm install vanilla-milk --save\n\n// Using yarn\nyarn add vanilla-milk\n```\nWell done! Now you're ready to create a Milk Component! (Shortname for Vanilla Milk Component for the greater good.)\n  \n### Hello World! It's Milk Component!\nLet's start by building `milk-component', a traditional hello world for programmer but as web component.\n\nMilk Component are separated into 2 step:\n1) Define it with `create`\n2) Create it with `define`\n\nJust 2 step, that's all for building reactive web component.\n\n#### Create\nFirst of all, import `create` function from vanilla-milk. This function is responsible to create a model of component.\n```javascript\nimport { create } from \"vanilla-milk\"\n```\n\nFirst parameter is a callback to display HTML Element.\n```javascript\nimport { create } from \"vanilla-milk\"\n\nconst MilkComponent = create((display) => \n\tdisplay(`<h1>Hello World! Milk Component!</h1>`)\n)\n```\nWe have just create `MilkComponent` which will return `<h1>Hello World</h1>`  \n\n### Define\nNext we just have to `define` this component, so it can work like every HTML Element.  \nBut first, import `define` from `vanilla-milk`\n```javascript\nimport { define } from \"vanilla-milk\"\n```\n\nNow let's name the component `milk-element`, so it can be use in HTML. (Web Component need `-` to be declared, like `milk-component` which has `-` in it)\n```javascript\nimport { create, define } from \"vanilla-milk\"\n\nconst MilkComponent = create((display) => \n\tdisplay(`<h1>Hello World! Milk Component!</h1>`)\n)\n\ndefine(\"milk-component\", MilkComponent)\n```\nThat's it! You have just created a Milk Component!! :tada::tada:\n  \n#### Milk Component in action\nSoooo~ We have just created a web component, let's see it in action!  \nJust add `<milk-component></milk-component>` in HTML. Make sure you've link the JavaScript file which contain milk component in it. You can use quick set-up like `parcel`.\n```html\n<!-- Any HTML here -->\n<html>\n<head>\n\t<title>Hello Milk Component</title>\n    <script src=\"milk_component_here.js\"></script>\n</head>\n<body>\n\t<milk-component></milk-component>\n</body>\n</html>\n```\nAnd it should display something like this.\n    \n#### But that's not what make Vanilla Milk special...\nIn Vanilla Milk, component are reactive which mean every time `state` or `props` changed, Milk Component will know it.\n\n## State\nLike `angular`, `react` and `vue`, Vanilla Milk also has `state`.  \nState is like a variable which are responsible for storing data and display it to view.\n\nLet's say we want to create a counter and display count to view. In Vanilla Milk we do like this.\n  \nIf you're familiar with React, we have `useState`. But it's not like what you might think.\n```javascript\nimport { useState } from 'vanilla-milk'\n```\nVanilla Milk are designed to be expressive. So we separate the state, props and life-cycle to the second parameter of `create` like this.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\tlet { count } = state\n    \n\treturn display(`<h1>Count ${count}</h1>`)\n},\n{\n\tcounter: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nSo, what's happend here?\n  \nThe second parameter of `create` are responsible for handling data, so we can separate and focus on each part.\n```\n{\n\tcount: useState(0)\n}\n```\nHere we defined state name `count` with value of `0`. `useState` is a function that say, \"Hey! We want a state name 'count' with value of 0\" to Vanilla Milk or something like that. Vanilla Milk will just handle the rest of that and pass the `count` to the `second parameter` of the view callback.\n```\nconst MilkComponent = create((display, state) => {\n\tconsole.log(state) // { count: 0 }\n},\n{\n\tcount: useState(0)\n})\n```\nLastly, we display counter to the view.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\treturn display(`<h1>Count ${state.count}</h1>`)\n},\n{\n\tcount: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nNow that will display `count` to HTML, so... how do we set it in Vanilla Milk?\n  \nAs an early state of development of Vanilla Milk that's where the last parameter of `create` kick in!  \nWe add button and attach event in to it, so we can change the value of `counter`. // Hey don't make face of disappointment like that! I'll fix it in some next update, I promise! It's quite hard to create something like that ya know.\n  \nLet add a button.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\treturn display(`\n\t\t<h1>Count ${state.count}</h1>\n    \t<button id=\"increase-count\">Increase count</button>\n\t`)\n},\n{\n\tcount: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nVanilla Milk is declarative, this is where the last parameter come in!  \nYou define any `events` you want here! It's take callback function so you're free to define everything like normal JavaScript here. Vanilla Milk called this parameters as `useEvents`.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state, _, events) => {\n\tconsole.log(events) // { increaseCount: \"increaseCount\" }\n\n\treturn display(`\n\t\t<h1>Count ${state.count}</h1>\n    \t<button id=\"increase-count\" @click=\"${events.increaseCount}\">Increase count</button>\n\t`)\n},\n{\n\tcount: useState(0)\n},\n([state, set], _) => {\n\tlet increaseCount = () => set.count(state.count + 1)\n    \n    return { increaseCount }\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\n`useEvents` take an callback which pass `[state, set]` which are used to access state and set the state. Receive `props` and second parameter. \n###### *props will be explained in next section.\n```javascript\n([state, set], props) => {\n\tlet increaseCount = () => set.count(state.count + 1)\n    \n    return { increaseCount }\n})\n```\nYou might notice something there's `@click` in `button`, Vanilla Milk use pseudo attribute and match event to the node. This pseudo attribute take an export events name in `useEvents`.\n```javascript\n<button id=\"increase-count\" @click=\"${events.increaseCount}\">\n    Increase count\n</button>\n```\nNow everytime the button that as `@click` will run the function match to exports in `useEvents`, in this case it's `increaseCount`\n```javascript\nlet increaseCount = () => set.count(state.count + 1)\n\nreturn { increaseCount }\n```\nAt here we get value of `count` from `state.count` and set it with `set.count` which came out with something like this:\n```javascript\nset.count(0 + 1) // Count is now 1\n```\nNow it should increase the value of count everytime we click it!\n\nThat's it! You've just achieve an advance concept like state of Vanilla Milk :tada::tada:\n\n## Props\nContrast to state, it's super simple. props is shorten for `properties`. A property is like a HTML attribute. For a button like:\n```html\n<button class=\"nice-button\">Hello! I'm a button</button>\n```\nclass is a props of this button and it's value is \"nice-button\".\n  \nAs Milk Component, we also can have something like that! and guess what? You can create any attribute you like effortlessly!\n  \nAll you have to do is import `useProps` from `vanilla-milk` and set it like `useState`.\n```javascript\nimport { useProps } from \"vanilla-milk\"\n```\nNow let's say that we want to have a prop name `hello`. Like `useState` we do it like this:\n```javascript\n{\n\tcount: useState(0),\n\thello: useProps()\n}\n```\nAnd access it like state\n```javascript\ncreate((display, state, props) => {\n\tconsole.log(props.hello) // null if there's no value passed\n})\n```\nSo let's define the component real quick to see how it work.\n```javascript\nimport { create, define, useProps } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state, props) => {\n\treturn display(`<h1>hello ${props.hello}</h1>`)\n},{\n\thello: useProps()\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nAnd in HTML\n```html\n<milk-component hello=\"world\"></milk-component> // hello world\n```\nThe reason we have to define `props` so that Vanilla Milk can just update and listen only to the props you used! \n  \nBut there's one special props which is always available... `children`\nChildren is any text or HTML Element between the Milk Component.\nIn HTML:\n```html\n<milk-component>Hello World</milk-component>\n```\nAnd access it:\n```javascript\nconst MilkComponent = create((display, state, props) => {\n\tconsole.log(props.children) // Hello World\n})\n```\nThat's it! Unlike `useState`, `useProps` is super to use! :tada::tada:\n\n## useEffect\nLike React, you can defined lifecycle with `useEffect`.\n  \nLet's say, that you want to `console.log()` everytime prop `hello` change. You just have to import `useEffect` from `vanilla-milk`.\n```javascript\nimport { useEffect } from \"vanilla-milk\"\n```\nAgain, add it to second paramter of `create` like `useState` and `useProps`\n```javascript\n{\n\thello: useProps(),\n\tlogHello: useEffect((state, props) => {\n\t\tconsole.log(props.hello) // Log everytime hello changed\n    }, [\"hello\"])\n}\n```\nNotice that we add array contain \"hello\" as string as the second parameter of useEffect.\nBecause we can't directly access value of hello so we just add it as string, Vanilla Milk will take care of the rest (In fact, we can add it as variable but it takes an extra effort and performance cost).\n\nYou can express name of `useEffect` as anything, It just easier to remind you lifecycle with name if there are too much lifecycle.\n\nNow we hello is changed, first callback will run. Like view callback, useEffect is paired with `(state, props)`. You can directly access it in the callback.\n\n`useEffect` is not only limited to state but props too! You can also add `useEffect` as much as you want or many listener as much as you need!\n```javascript\n// State and Props\n{\n    hello: useProps(),\n    count: useState(),\n\tlogHello: useEffect((state, props) => {\n    \tconsole.log(props)\n    }, [\"count\"])\n}\n  \n// Multiple listener\n{\n    hello: useProps(),\n    count: useProps(),\n\tlogHello: useEffect((state, props) => {\n    \tconsole.log(props)\n    }, [\"count\", \"count\"])\n}\n```\n  \n## Milk DOM In depth\nMilk DOM cover a lot of thing under the cover but the main concept is to compare and diff DOM Node aimming for lesser iteration as possible (Same idea with VDOM). Instead of constructing an object node representation of DOM for comparing between two. Vanilla Milk heavily use Native Browser API comparing between each node instead of DOM and update it directly instead.\n\nSince Milk DOM is written in template string, it's very hard for Vanilla Milk to identify which textNode should replace Node or vice-versa. In this case, you shouldn't replace existed dom with blank text (\"\") like how React, Vue, other library does (which will sometime, occured an unexpected error). Instead Vanilla Milk offter a way to replace Node with blank Node by putting any element with attribute of `__hidden__`\n```javascript\nconst MilkCard = create(\n\t(display, { isOpen }, { title, cover, children }, events) => {\n\t\treturn display(`\n\t\t\t<main id=\"card\" tabIndex=0>\n\t\t\t\t<img id=\"cover\" src=\"${cover}\" alt=\"${title}\" />\n\t\t\t\t<section id=\"body\">\n\t\t\t\t\t<header id=\"header\">\n\t\t\t\t\t\t<h1 id=\"title\">${title}</h1>\n\t\t\t\t\t\t<button id=\"toggle\" @click=\"${events.toggleCard}\">+</button>\n\t\t\t\t\t</header>\n\t\t\t\t\t${\n\t\t\t\t\t\tisOpen\n\t\t\t\t\t\t\t? `<section id=\"detail\">${children}</section>`\n\t\t\t\t\t\t\t: `<input @hidden />`\n\t\t\t\t\t}\n\t\t\t\t</section>\n\t\t\t</main>\n\t\t`)\n\t},\n\t{\n\t\ttitle: useProps(),\n\t\tcover: useProps(),\n\t\tisOpen: useState(false),\n\t\tcardStyle: useStyleSheet(\"/card.css\")\n\t},\n\t([state, set], props) => {\n\t\tlet toggleCard = () => set.isOpen(!state.isOpen)\n\n\t\treturn { toggleCard }\n\t}\n)\n\n```\n\nMilk DOM's diffing algorithm are seperated into 3 parts.\n* Diff - Diffing for the different attribute, child node, etc.\n* Hard Diff - When tagName are different, whole element node have to be replaced. Hard Diff take care of that preventing child node for being recursion.\n* Text Diff - Diffing for text different.\n  \n### Best practice\nTo prevent an unexpected update, it's recommend to contained textNode in an element where textNode is state.\n```javascript\nimport { create, useState } from \"vanilla-milk\"\n\n// Please don't\nlet notSoGood = create((display, { counter }) => {\n\treturn display(`\n\t\t<section>\n\t\t\t<h1>Counter: </h1>\n\t\t\t{counter}\n\t\t</section>\n\t`)\n})\n\n// Better~\nlet wellDone = create((display) => {\n\treturn display(`\n\t\t<section>\n\t\t\t<h1>\n\t\t\t\tCounter: {state}\n\t\t\t</h1>\n\t\t</section>\n\t`)\n})\n```\nNot only that storing textNode in an element are safer but also has better performance from prevent recursion between each node.\n  \n### Multiple node on root\nUnlike VDOM, Vanilla Milk use native DOM for diffing freeing root node from stucking with only one node on the top.\n\n```javascript\nimport { create } from \"vanilla-milk\"\n\n// This is ok\nlet multipleRootNode = create((display, { counter }) => {\n\treturn display(`\n\t\t<h1>Hello! I'm the root node!</h1>\n\t\t<h2>No way! I'm the root node too!</h2>\n\t\t<p>It's ok to use multiple root node in Vanilla Milk</p>\n\t`)\n})\n```\n\n## Encapsulation\nVanilla Milk use Shadow DOM to encapsulate logic and style. Preventing an unexpected change while working in multiple library.\n  \nTo use external stylesheet in Milk Component, you can assign stylesheet in the component instead\n```javascript\nimport { create, useStyleSheet } from \"vanilla-milk\"\n\n// Link stylesheet in component.\nlet coolCard = create((display, { counter }) => {\n\treturn display(`\n\t\t<div class=\"card\"></div>\n\t`)\n},\n{\n\tcardStyle: useStyleSheet(\"/card.css\")\n})\n\n// Or even define style tag inside\nlet coolCard = create(\n\t(display) => display(`\n\t\t<style>\n\t\t\t.card {\n\t\t\t\tdisplay: flex;\n\t\t\t\tflex-direction: column;\n\t\t\t\twidth: 300px;\n\t\t\t\tpadding: 20px 12px;\n\t\t\t\tborderRadius: 4px;\n\t\t\t\tbox-shadow: 0 4px 8px rgba(0,0,0,.25);\n\t\t\t}\n\t\t</style>\n\t\t<div class=\"card\">\n\t\t</div>\n\t`)\n)\n```\n  \nThat's pretty much it of Vanilla Milk. :tada::tada:","_id":"vanilla-milk@0.3.0-beta.3","dist":{"shasum":"6d5428fd80a568c2cdd91d9ef9100bc8ce9afbeb","integrity":"sha512-JhgwZ15F/6042yMG5S7Squ6j/VghDQ/rymfpK0hXp24u6/hX7Yu/evscvTQ2iNo9xkt7TqKMx2uKv+2j7if79g==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.3.0-beta.3.tgz","fileCount":6,"unpackedSize":145041,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeEf1wCRA9TVsSAnZWagAADswQAIT5Z1lHTUbZpz1urWT5\nD2FCRVtvak0wY+4fEaQ1M+f6GI6M4pDQy/coh6Bl7uZOF5yvhePSLTbY3BYK\nWxXik4W5n6u77cw6r1p9i1nXTeEoxg5zH4UkGdmh7POYo4pAhSmdI6rVJW2B\n1o/4uK8IW7SRahRMhq6ZQiyoaZUjsvVPBnfoF8Wi6Ny1Xa49QTjI30zQuudq\n9KlAcgugu+XBJd67Q2beQDpJZ/e1tkfRc6duDT4IDZF6kvCwyQxbrXHFzt3T\nW8Hb2F+F5yVhwl5mkUZn4YAU4Kq3mgt2npLB/c6DbtccLYRI1G/aRPCEg1P1\npKdST1PxCbGf+LKMeVKs27BdfYsTvkjsx8tR7/gg6FsXs6OGKd/ImOp1WLZX\nvaoF21xN9YPgWLFkR5lDCg1vQ7fMRCG6obBHuoeUq0Yc3IiO9fdjH5MrdLVk\nBzbYjkCR3wIeTCjgvI25vRbdCnWv/atLMZYJE7NYsxKoeQKtAidZ7exD93t9\nVbVXct0tTSyh2eJVvCCl5qRIr11NZcIV6CupXR2s79wCWiktDPthpr3TpU7s\nGOIIS2v1LrDg2T7Wj0megOQkGzrvLpgIFEl7mN+DcVECwvXgVQtdgDdYlTgU\nPgfjci536uu2uX1pevEzbbREF2DX0+8dEnwwD6TYwfOm9IH/cAUPtG1IHCjY\nY5wd\r\n=OvOQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCXlElycUePtrIDarWLFnB1r5ZZiimNT8SWOS6V0pnSKAIhALLY4uOqNsXcX+RD2BVey4T+NGkIUSdp6SQzwHSuL4ak"}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.3.0-beta.3_1578237295645_0.945931366660572"},"_hasShrinkwrap":false},"0.3.0-beta.4":{"name":"vanilla-milk","version":"0.3.0-beta.4","description":"Simple library for building simple reactive web components.","main":"index.js","repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"},"license":"MIT","keywords":["vanilla milk","web component","vanilla milk js"],"readmeFilename":"README.md","readme":"# Vanilla Milk\nSimple library for building simple reactive web components.\n  \n## What is...\nVanilla Milk is a library which helps create to web component which can be used on anywhere! Embrace future of web-component made it future-proof. Built-in reactive state and props but also is very small and fast.\n\nVanilla Milk feature:\n* Reusable component.\n* Simple way for creating web components.\n* Milk DOM, a special implementation of DOM manipulation.\n* Reactive state and props.\n* No class, just function.\n* Life-cycle hooks.\n* Expressive Vanilla like API structure.\n* Very small (1kB gzipped on production).\n* Encapsulated style, ID and class name.\n* Zero dependencies.\n* TypeScript support.\n\n## Milk DOM\nVanilla Milk doesn't use Virtual DOM, instead it has its own `Milk DOM` which share the same idea with Virtual Dom, update where neccessary. Unlike VDOM, Milk DOM use a collection of Native Browser API to perform diffing instead of creating long list of object which also prevent heavy recursion.\nDrawback is diffing algorithm isn't as deep as Virtual DOM does but Milk DOM is blazing fast and has less memory consumption.\n###### Note: Milk DOM is in an very early stage of development, you might experience some bug and when that time came, you can always open the issue on this repo.\n  \n## Getting started\nGlad you're interested in! Let's get over quick start! Let us add library just for creating a component, after the component has been built, you don't have to install it anymore! Just moved the built components to your any project~\n\n### Install Vanilla Milk\nLet install this real quick with package manager of your choice.\n```bash\n// Using npm\nnpm install vanilla-milk --save\n\n// Using yarn\nyarn add vanilla-milk\n```\nWell done! Now you're ready to create a Milk Component! (Shortname for Vanilla Milk Component for the greater good.)\n  \n### Hello World! It's Milk Component!\nLet's start by building `milk-component', a traditional hello world for programmer but as web component.\n\nMilk Component are separated into 2 step:\n1) Define it with `create`\n2) Create it with `define`\n\nJust 2 step, that's all for building reactive web component.\n\n#### Create\nFirst of all, import `create` function from vanilla-milk. This function is responsible to create a model of component.\n```javascript\nimport { create } from \"vanilla-milk\"\n```\n\nFirst parameter is a callback to display HTML Element.\n```javascript\nimport { create } from \"vanilla-milk\"\n\nconst MilkComponent = create((display) => \n\tdisplay(`<h1>Hello World! Milk Component!</h1>`)\n)\n```\nWe have just create `MilkComponent` which will return `<h1>Hello World</h1>`  \n\n### Define\nNext we just have to `define` this component, so it can work like every HTML Element.  \nBut first, import `define` from `vanilla-milk`\n```javascript\nimport { define } from \"vanilla-milk\"\n```\n\nNow let's name the component `milk-element`, so it can be use in HTML. (Web Component need `-` to be declared, like `milk-component` which has `-` in it)\n```javascript\nimport { create, define } from \"vanilla-milk\"\n\nconst MilkComponent = create((display) => \n\tdisplay(`<h1>Hello World! Milk Component!</h1>`)\n)\n\ndefine(\"milk-component\", MilkComponent)\n```\nThat's it! You have just created a Milk Component!! :tada::tada:\n  \n#### Milk Component in action\nSoooo~ We have just created a web component, let's see it in action!  \nJust add `<milk-component></milk-component>` in HTML. Make sure you've link the JavaScript file which contain milk component in it. You can use quick set-up like `parcel`.\n```html\n<!-- Any HTML here -->\n<html>\n<head>\n\t<title>Hello Milk Component</title>\n    <script src=\"milk_component_here.js\"></script>\n</head>\n<body>\n\t<milk-component></milk-component>\n</body>\n</html>\n```\nAnd it should display something like this.\n    \n#### But that's not what make Vanilla Milk special...\nIn Vanilla Milk, component are reactive which mean every time `state` or `props` changed, Milk Component will know it.\n\n## State\nLike `angular`, `react` and `vue`, Vanilla Milk also has `state`.  \nState is like a variable which are responsible for storing data and display it to view.\n\nLet's say we want to create a counter and display count to view. In Vanilla Milk we do like this.\n  \nIf you're familiar with React, we have `useState`. But it's not like what you might think.\n```javascript\nimport { useState } from 'vanilla-milk'\n```\nVanilla Milk are designed to be expressive. So we separate the state, props and life-cycle to the second parameter of `create` like this.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\tlet { count } = state\n    \n\treturn display(`<h1>Count ${count}</h1>`)\n},\n{\n\tcounter: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nSo, what's happend here?\n  \nThe second parameter of `create` are responsible for handling data, so we can separate and focus on each part.\n```\n{\n\tcount: useState(0)\n}\n```\nHere we defined state name `count` with value of `0`. `useState` is a function that say, \"Hey! We want a state name 'count' with value of 0\" to Vanilla Milk or something like that. Vanilla Milk will just handle the rest of that and pass the `count` to the `second parameter` of the view callback.\n```\nconst MilkComponent = create((display, state) => {\n\tconsole.log(state) // { count: 0 }\n},\n{\n\tcount: useState(0)\n})\n```\nLastly, we display counter to the view.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\treturn display(`<h1>Count ${state.count}</h1>`)\n},\n{\n\tcount: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nNow that will display `count` to HTML, so... how do we set it in Vanilla Milk?\n  \nAs an early state of development of Vanilla Milk that's where the last parameter of `create` kick in!  \nWe add button and attach event in to it, so we can change the value of `counter`. // Hey don't make face of disappointment like that! I'll fix it in some next update, I promise! It's quite hard to create something like that ya know.\n  \nLet add a button.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\treturn display(`\n\t\t<h1>Count ${state.count}</h1>\n    \t<button id=\"increase-count\">Increase count</button>\n\t`)\n},\n{\n\tcount: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nVanilla Milk is declarative, this is where the last parameter come in!  \nYou define any `events` you want here! It's take callback function so you're free to define everything like normal JavaScript here. Vanilla Milk called this parameters as `useEvents`.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state, _, events) => {\n\tconsole.log(events) // { increaseCount: \"increaseCount\" }\n\n\treturn display(`\n\t\t<h1>Count ${state.count}</h1>\n    \t<button id=\"increase-count\" @click=\"${events.increaseCount}\">Increase count</button>\n\t`)\n},\n{\n\tcount: useState(0)\n},\n([state, set], _) => {\n\tlet increaseCount = () => set.count(state.count + 1)\n    \n    return { increaseCount }\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\n`useEvents` take an callback which pass `[state, set]` which are used to access state and set the state. Receive `props` and second parameter. \n###### *props will be explained in next section.\n```javascript\n([state, set], props) => {\n\tlet increaseCount = () => set.count(state.count + 1)\n    \n    return { increaseCount }\n})\n```\nYou might notice something there's `@click` in `button`, Vanilla Milk use pseudo attribute and match event to the node. This pseudo attribute take an export events name in `useEvents`.\n```javascript\n<button id=\"increase-count\" @click=\"${events.increaseCount}\">\n    Increase count\n</button>\n```\nNow everytime the button that as `@click` will run the function match to exports in `useEvents`, in this case it's `increaseCount`\n```javascript\nlet increaseCount = () => set.count(state.count + 1)\n\nreturn { increaseCount }\n```\nAt here we get value of `count` from `state.count` and set it with `set.count` which came out with something like this:\n```javascript\nset.count(0 + 1) // Count is now 1\n```\nNow it should increase the value of count everytime we click it!\n\nThat's it! You've just achieve an advance concept like state of Vanilla Milk :tada::tada:\n\n## Props\nContrast to state, it's super simple. props is shorten for `properties`. A property is like a HTML attribute. For a button like:\n```html\n<button class=\"nice-button\">Hello! I'm a button</button>\n```\nclass is a props of this button and it's value is \"nice-button\".\n  \nAs Milk Component, we also can have something like that! and guess what? You can create any attribute you like effortlessly!\n  \nAll you have to do is import `useProps` from `vanilla-milk` and set it like `useState`.\n```javascript\nimport { useProps } from \"vanilla-milk\"\n```\nNow let's say that we want to have a prop name `hello`. Like `useState` we do it like this:\n```javascript\n{\n\tcount: useState(0),\n\thello: useProps()\n}\n```\nAnd access it like state\n```javascript\ncreate((display, state, props) => {\n\tconsole.log(props.hello) // null if there's no value passed\n})\n```\nSo let's define the component real quick to see how it work.\n```javascript\nimport { create, define, useProps } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state, props) => {\n\treturn display(`<h1>hello ${props.hello}</h1>`)\n},{\n\thello: useProps()\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nAnd in HTML\n```html\n<milk-component hello=\"world\"></milk-component> // hello world\n```\nThe reason we have to define `props` so that Vanilla Milk can just update and listen only to the props you used! \n  \nBut there's one special props which is always available... `children`\nChildren is any text or HTML Element between the Milk Component.\nIn HTML:\n```html\n<milk-component>Hello World</milk-component>\n```\nAnd access it:\n```javascript\nconst MilkComponent = create((display, state, props) => {\n\tconsole.log(props.children) // Hello World\n})\n```\nThat's it! Unlike `useState`, `useProps` is super to use! :tada::tada:\n\n## useEffect\nLike React, you can defined lifecycle with `useEffect`.\n  \nLet's say, that you want to `console.log()` everytime prop `hello` change. You just have to import `useEffect` from `vanilla-milk`.\n```javascript\nimport { useEffect } from \"vanilla-milk\"\n```\nAgain, add it to second paramter of `create` like `useState` and `useProps`\n```javascript\n{\n\thello: useProps(),\n\tlogHello: useEffect((state, props) => {\n\t\tconsole.log(props.hello) // Log everytime hello changed\n    }, [\"hello\"])\n}\n```\nNotice that we add array contain \"hello\" as string as the second parameter of useEffect.\nBecause we can't directly access value of hello so we just add it as string, Vanilla Milk will take care of the rest (In fact, we can add it as variable but it takes an extra effort and performance cost).\n\nYou can express name of `useEffect` as anything, It just easier to remind you lifecycle with name if there are too much lifecycle.\n\nNow we hello is changed, first callback will run. Like view callback, useEffect is paired with `(state, props)`. You can directly access it in the callback.\n\n`useEffect` is not only limited to state but props too! You can also add `useEffect` as much as you want or many listener as much as you need!\n```javascript\n// State and Props\n{\n    hello: useProps(),\n    count: useState(),\n\tlogHello: useEffect((state, props) => {\n    \tconsole.log(props)\n    }, [\"count\"])\n}\n  \n// Multiple listener\n{\n    hello: useProps(),\n    count: useProps(),\n\tlogHello: useEffect((state, props) => {\n    \tconsole.log(props)\n    }, [\"count\", \"count\"])\n}\n```\n  \n## Milk DOM In depth\nMilk DOM cover a lot of thing under the cover but the main concept is to compare and diff DOM Node aimming for lesser iteration as possible (Same idea with VDOM). Instead of constructing an object node representation of DOM for comparing between two. Vanilla Milk heavily use Native Browser API comparing between each node instead of DOM and update it directly instead.\n\nSince Milk DOM is written in template string, it's very hard for Vanilla Milk to identify which textNode should replace Node or vice-versa. In this case, you shouldn't replace existed dom with blank text (\"\") like how React, Vue, other library does (which will sometime, occured an unexpected error). Instead Vanilla Milk offter a way to replace Node with blank Node by putting any element with attribute of `__hidden__`\n```javascript\nconst MilkCard = create(\n\t(display, { isOpen }, { title, cover, children }, events) => {\n\t\treturn display(`\n\t\t\t<main id=\"card\" tabIndex=0>\n\t\t\t\t<img id=\"cover\" src=\"${cover}\" alt=\"${title}\" />\n\t\t\t\t<section id=\"body\">\n\t\t\t\t\t<header id=\"header\">\n\t\t\t\t\t\t<h1 id=\"title\">${title}</h1>\n\t\t\t\t\t\t<button id=\"toggle\" @click=\"${events.toggleCard}\">+</button>\n\t\t\t\t\t</header>\n\t\t\t\t\t${\n\t\t\t\t\t\tisOpen\n\t\t\t\t\t\t\t? `<section id=\"detail\">${children}</section>`\n\t\t\t\t\t\t\t: `<input @hidden />`\n\t\t\t\t\t}\n\t\t\t\t</section>\n\t\t\t</main>\n\t\t`)\n\t},\n\t{\n\t\ttitle: useProps(),\n\t\tcover: useProps(),\n\t\tisOpen: useState(false),\n\t\tcardStyle: useStyleSheet(\"/card.css\")\n\t},\n\t([state, set], props) => {\n\t\tlet toggleCard = () => set.isOpen(!state.isOpen)\n\n\t\treturn { toggleCard }\n\t}\n)\n\n```\n\nMilk DOM's diffing algorithm are seperated into 3 parts.\n* Diff - Diffing for the different attribute, child node, etc.\n* Hard Diff - When tagName are different, whole element node have to be replaced. Hard Diff take care of that preventing child node for being recursion.\n* Text Diff - Diffing for text different.\n  \n### Best practice\nTo prevent an unexpected update, it's recommend to contained textNode in an element where textNode is state.\n```javascript\nimport { create, useState } from \"vanilla-milk\"\n\n// Please don't\nlet notSoGood = create((display, { counter }) => {\n\treturn display(`\n\t\t<section>\n\t\t\t<h1>Counter: </h1>\n\t\t\t{counter}\n\t\t</section>\n\t`)\n})\n\n// Better~\nlet wellDone = create((display) => {\n\treturn display(`\n\t\t<section>\n\t\t\t<h1>\n\t\t\t\tCounter: {state}\n\t\t\t</h1>\n\t\t</section>\n\t`)\n})\n```\nNot only that storing textNode in an element are safer but also has better performance from prevent recursion between each node.\n  \n### Multiple node on root\nUnlike VDOM, Vanilla Milk use native DOM for diffing freeing root node from stucking with only one node on the top.\n\n```javascript\nimport { create } from \"vanilla-milk\"\n\n// This is ok\nlet multipleRootNode = create((display, { counter }) => {\n\treturn display(`\n\t\t<h1>Hello! I'm the root node!</h1>\n\t\t<h2>No way! I'm the root node too!</h2>\n\t\t<p>It's ok to use multiple root node in Vanilla Milk</p>\n\t`)\n})\n```\n\n## Encapsulation\nVanilla Milk use Shadow DOM to encapsulate logic and style. Preventing an unexpected change while working in multiple library.\n  \nTo use external stylesheet in Milk Component, you can assign stylesheet in the component instead\n```javascript\nimport { create, useStyleSheet } from \"vanilla-milk\"\n\n// Link stylesheet in component.\nlet coolCard = create((display, { counter }) => {\n\treturn display(`\n\t\t<div class=\"card\"></div>\n\t`)\n},\n{\n\tcardStyle: useStyleSheet(\"/card.css\")\n})\n\n// Or even define style tag inside\nlet coolCard = create(\n\t(display) => display(`\n\t\t<style>\n\t\t\t.card {\n\t\t\t\tdisplay: flex;\n\t\t\t\tflex-direction: column;\n\t\t\t\twidth: 300px;\n\t\t\t\tpadding: 20px 12px;\n\t\t\t\tborderRadius: 4px;\n\t\t\t\tbox-shadow: 0 4px 8px rgba(0,0,0,.25);\n\t\t\t}\n\t\t</style>\n\t\t<div class=\"card\">\n\t\t</div>\n\t`)\n)\n```\n  \nThat's pretty much it of Vanilla Milk. :tada::tada:","_id":"vanilla-milk@0.3.0-beta.4","dist":{"shasum":"41c2954c817a3c25480061267167e702fb551820","integrity":"sha512-GrGvBkpNbgemBdgdvuNMTtZ4IrbVposT2V/W/NYjtVkDgsZj0zgrQ6eQdcPlWjInkw/YcQdtwc5HKczN/Ll06Q==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.3.0-beta.4.tgz","fileCount":6,"unpackedSize":145164,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeEgBZCRA9TVsSAnZWagAAyxsP/Ag8R6PMq9OJXdfAECoQ\nmip96iMq6d9ngrMmVyfGhTVieaZNpwH6p1WwDKwEVzIP48i2Ey79j1WxUnXh\nEwI0EES9vJPIDJPXDBp+gh87yT9uXN86+4DgnLLOqWjet3RQYYTkmEBd8u8e\n0xdkSn3FTszPtYMV/fi4BPceB2jmf9wb+UbvBzR51bo3q+hUciXFJ+jTSceE\nF/hWZWoGZ3e6aVpmP+puPPYQkg6x9gd2opNYBUO88o6WA9A+SUKJLKG77pSZ\nxgA4YBFT9rYa/FaCztMjq1aSetKqV1HLYq/GTkUeq38SEbK6zEMqDAhi1pVj\nZS+HMCNDbaLHEFz8u6TtJGoDksT2BfRfUMU2b/wJ0O8FXQVwmHlFTQ8f9EO1\nJjAJamDq/US3VVStFU03qwMEOdar7p4rK4kb4DMc4CuzscMyERZUUSLMMvHX\n/Ie7JyAOka+MSvS6ioFtbDFbE1WlTb86REHQ7jZDrodLhaUMlv4HSJqm8A6x\nLczWyb3lz4vtZE3fefB9gnRBXi90JFADZya23QPmEsazqYj3hBq5HFyuIlcg\nctGbbhn6BC7m59SU/TlMI4On3wJUaU5afWYSILKa6aD5dcUhmpCiykjT8PwL\np7D3b/802BHkZeayXi9rH57hOwoF5MyAyB99/BglxF1zTGxMJIy+VmZQth+Q\nXzdI\r\n=FkyN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBNn11x+fsMtdeboe/kZ2f+SquDGrWQL3avywjKrAYQSAiEA3qQVMDNYifHFP52WjPfgjKbTy+D9nMJVkPgWOba6w6s="}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.3.0-beta.4_1578238041221_0.940294524355282"},"_hasShrinkwrap":false},"0.3.0-beta.5":{"name":"vanilla-milk","version":"0.3.0-beta.5","description":"Simple library for building simple reactive web components.","main":"index.js","repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"},"license":"MIT","keywords":["vanilla milk","web component","vanilla milk js"],"readmeFilename":"README.md","readme":"# Vanilla Milk\nSimple library for building simple reactive web components.\n  \n## What is...\nVanilla Milk is a library which helps create to web component which can be used on anywhere! Embrace future of web-component made it future-proof. Built-in reactive state and props but also is very small and fast.\n\nVanilla Milk feature:\n* Reusable component.\n* Simple way for creating web components.\n* Milk DOM, a special implementation of DOM manipulation.\n* Reactive state and props.\n* No class, just function.\n* Life-cycle hooks.\n* Expressive Vanilla like API structure.\n* Very small (1kB gzipped on production).\n* Encapsulated style, ID and class name.\n* Zero dependencies.\n* TypeScript support.\n\n## Milk DOM\nVanilla Milk doesn't use Virtual DOM, instead it has its own `Milk DOM` which share the same idea with Virtual Dom, update where neccessary. Unlike VDOM, Milk DOM use a collection of Native Browser API to perform diffing instead of creating long list of object which also prevent heavy recursion.\nDrawback is diffing algorithm isn't as deep as Virtual DOM does but Milk DOM is blazing fast and has less memory consumption.\n###### Note: Milk DOM is in an very early stage of development, you might experience some bug and when that time came, you can always open the issue on this repo.\n  \n## Getting started\nGlad you're interested in! Let's get over quick start! Let us add library just for creating a component, after the component has been built, you don't have to install it anymore! Just moved the built components to your any project~\n\n### Install Vanilla Milk\nLet install this real quick with package manager of your choice.\n```bash\n// Using npm\nnpm install vanilla-milk --save\n\n// Using yarn\nyarn add vanilla-milk\n```\nWell done! Now you're ready to create a Milk Component! (Shortname for Vanilla Milk Component for the greater good.)\n  \n### Hello World! It's Milk Component!\nLet's start by building `milk-component', a traditional hello world for programmer but as web component.\n\nMilk Component are separated into 2 step:\n1) Define it with `create`\n2) Create it with `define`\n\nJust 2 step, that's all for building reactive web component.\n\n#### Create\nFirst of all, import `create` function from vanilla-milk. This function is responsible to create a model of component.\n```javascript\nimport { create } from \"vanilla-milk\"\n```\n\nFirst parameter is a callback to display HTML Element.\n```javascript\nimport { create } from \"vanilla-milk\"\n\nconst MilkComponent = create((display) => \n\tdisplay(`<h1>Hello World! Milk Component!</h1>`)\n)\n```\nWe have just create `MilkComponent` which will return `<h1>Hello World</h1>`  \n\n### Define\nNext we just have to `define` this component, so it can work like every HTML Element.  \nBut first, import `define` from `vanilla-milk`\n```javascript\nimport { define } from \"vanilla-milk\"\n```\n\nNow let's name the component `milk-element`, so it can be use in HTML. (Web Component need `-` to be declared, like `milk-component` which has `-` in it)\n```javascript\nimport { create, define } from \"vanilla-milk\"\n\nconst MilkComponent = create((display) => \n\tdisplay(`<h1>Hello World! Milk Component!</h1>`)\n)\n\ndefine(\"milk-component\", MilkComponent)\n```\nThat's it! You have just created a Milk Component!! :tada::tada:\n  \n#### Milk Component in action\nSoooo~ We have just created a web component, let's see it in action!  \nJust add `<milk-component></milk-component>` in HTML. Make sure you've link the JavaScript file which contain milk component in it. You can use quick set-up like `parcel`.\n```html\n<!-- Any HTML here -->\n<html>\n<head>\n\t<title>Hello Milk Component</title>\n    <script src=\"milk_component_here.js\"></script>\n</head>\n<body>\n\t<milk-component></milk-component>\n</body>\n</html>\n```\nAnd it should display something like this.\n    \n#### But that's not what make Vanilla Milk special...\nIn Vanilla Milk, component are reactive which mean every time `state` or `props` changed, Milk Component will know it.\n\n## State\nLike `angular`, `react` and `vue`, Vanilla Milk also has `state`.  \nState is like a variable which are responsible for storing data and display it to view.\n\nLet's say we want to create a counter and display count to view. In Vanilla Milk we do like this.\n  \nIf you're familiar with React, we have `useState`. But it's not like what you might think.\n```javascript\nimport { useState } from 'vanilla-milk'\n```\nVanilla Milk are designed to be expressive. So we separate the state, props and life-cycle to the second parameter of `create` like this.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\tlet { count } = state\n    \n\treturn display(`<h1>Count ${count}</h1>`)\n},\n{\n\tcounter: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nSo, what's happend here?\n  \nThe second parameter of `create` are responsible for handling data, so we can separate and focus on each part.\n```\n{\n\tcount: useState(0)\n}\n```\nHere we defined state name `count` with value of `0`. `useState` is a function that say, \"Hey! We want a state name 'count' with value of 0\" to Vanilla Milk or something like that. Vanilla Milk will just handle the rest of that and pass the `count` to the `second parameter` of the view callback.\n```\nconst MilkComponent = create((display, state) => {\n\tconsole.log(state) // { count: 0 }\n},\n{\n\tcount: useState(0)\n})\n```\nLastly, we display counter to the view.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\treturn display(`<h1>Count ${state.count}</h1>`)\n},\n{\n\tcount: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nNow that will display `count` to HTML, so... how do we set it in Vanilla Milk?\n  \nAs an early state of development of Vanilla Milk that's where the last parameter of `create` kick in!  \nWe add button and attach event in to it, so we can change the value of `counter`. // Hey don't make face of disappointment like that! I'll fix it in some next update, I promise! It's quite hard to create something like that ya know.\n  \nLet add a button.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\treturn display(`\n\t\t<h1>Count ${state.count}</h1>\n    \t<button id=\"increase-count\">Increase count</button>\n\t`)\n},\n{\n\tcount: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nVanilla Milk is declarative, this is where the last parameter come in!  \nYou define any `events` you want here! It's take callback function so you're free to define everything like normal JavaScript here. Vanilla Milk called this parameters as `useEvents`.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state, _, events) => {\n\tconsole.log(events) // { increaseCount: \"increaseCount\" }\n\n\treturn display(`\n\t\t<h1>Count ${state.count}</h1>\n    \t<button id=\"increase-count\" @click=\"${events.increaseCount}\">Increase count</button>\n\t`)\n},\n{\n\tcount: useState(0)\n},\n([state, set], _) => {\n\tlet increaseCount = () => set.count(state.count + 1)\n    \n    return { increaseCount }\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\n`useEvents` take an callback which pass `[state, set]` which are used to access state and set the state. Receive `props` and second parameter. \n###### *props will be explained in next section.\n```javascript\n([state, set], props) => {\n\tlet increaseCount = () => set.count(state.count + 1)\n    \n    return { increaseCount }\n})\n```\nYou might notice something there's `@click` in `button`, Vanilla Milk use pseudo attribute and match event to the node. This pseudo attribute take an export events name in `useEvents`.\n```javascript\n<button id=\"increase-count\" @click=\"${events.increaseCount}\">\n    Increase count\n</button>\n```\nNow everytime the button that as `@click` will run the function match to exports in `useEvents`, in this case it's `increaseCount`\n```javascript\nlet increaseCount = () => set.count(state.count + 1)\n\nreturn { increaseCount }\n```\nAt here we get value of `count` from `state.count` and set it with `set.count` which came out with something like this:\n```javascript\nset.count(0 + 1) // Count is now 1\n```\nNow it should increase the value of count everytime we click it!\n\nThat's it! You've just achieve an advance concept like state of Vanilla Milk :tada::tada:\n\n## Props\nContrast to state, it's super simple. props is shorten for `properties`. A property is like a HTML attribute. For a button like:\n```html\n<button class=\"nice-button\">Hello! I'm a button</button>\n```\nclass is a props of this button and it's value is \"nice-button\".\n  \nAs Milk Component, we also can have something like that! and guess what? You can create any attribute you like effortlessly!\n  \nAll you have to do is import `useProps` from `vanilla-milk` and set it like `useState`.\n```javascript\nimport { useProps } from \"vanilla-milk\"\n```\nNow let's say that we want to have a prop name `hello`. Like `useState` we do it like this:\n```javascript\n{\n\tcount: useState(0),\n\thello: useProps()\n}\n```\nAnd access it like state\n```javascript\ncreate((display, state, props) => {\n\tconsole.log(props.hello) // null if there's no value passed\n})\n```\nSo let's define the component real quick to see how it work.\n```javascript\nimport { create, define, useProps } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state, props) => {\n\treturn display(`<h1>hello ${props.hello}</h1>`)\n},{\n\thello: useProps()\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nAnd in HTML\n```html\n<milk-component hello=\"world\"></milk-component> // hello world\n```\nThe reason we have to define `props` so that Vanilla Milk can just update and listen only to the props you used! \n  \nBut there's one special props which is always available... `children`\nChildren is any text or HTML Element between the Milk Component.\nIn HTML:\n```html\n<milk-component>Hello World</milk-component>\n```\nAnd access it:\n```javascript\nconst MilkComponent = create((display, state, props) => {\n\tconsole.log(props.children) // Hello World\n})\n```\nThat's it! Unlike `useState`, `useProps` is super to use! :tada::tada:\n\n## useEffect\nLike React, you can defined lifecycle with `useEffect`.\n  \nLet's say, that you want to `console.log()` everytime prop `hello` change. You just have to import `useEffect` from `vanilla-milk`.\n```javascript\nimport { useEffect } from \"vanilla-milk\"\n```\nAgain, add it to second paramter of `create` like `useState` and `useProps`\n```javascript\n{\n\thello: useProps(),\n\tlogHello: useEffect((state, props) => {\n\t\tconsole.log(props.hello) // Log everytime hello changed\n    }, [\"hello\"])\n}\n```\nNotice that we add array contain \"hello\" as string as the second parameter of useEffect.\nBecause we can't directly access value of hello so we just add it as string, Vanilla Milk will take care of the rest (In fact, we can add it as variable but it takes an extra effort and performance cost).\n\nYou can express name of `useEffect` as anything, It just easier to remind you lifecycle with name if there are too much lifecycle.\n\nNow we hello is changed, first callback will run. Like view callback, useEffect is paired with `(state, props)`. You can directly access it in the callback.\n\n`useEffect` is not only limited to state but props too! You can also add `useEffect` as much as you want or many listener as much as you need!\n```javascript\n// State and Props\n{\n    hello: useProps(),\n    count: useState(),\n\tlogHello: useEffect((state, props) => {\n    \tconsole.log(props)\n    }, [\"count\"])\n}\n  \n// Multiple listener\n{\n    hello: useProps(),\n    count: useProps(),\n\tlogHello: useEffect((state, props) => {\n    \tconsole.log(props)\n    }, [\"count\", \"count\"])\n}\n```\n  \n## Milk DOM In depth\nMilk DOM cover a lot of thing under the cover but the main concept is to compare and diff DOM Node aimming for lesser iteration as possible (Same idea with VDOM). Instead of constructing an object node representation of DOM for comparing between two. Vanilla Milk heavily use Native Browser API comparing between each node instead of DOM and update it directly instead.\n\nSince Milk DOM is written in template string, it's very hard for Vanilla Milk to identify which textNode should replace Node or vice-versa. In this case, you shouldn't replace existed dom with blank text (\"\") like how React, Vue, other library does (which will sometime, occured an unexpected error). Instead Vanilla Milk offter a way to replace Node with blank Node by putting any element with attribute of `__hidden__`\n```javascript\nconst MilkCard = create(\n\t(display, { isOpen }, { title, cover, children }, events) => {\n\t\treturn display(`\n\t\t\t<main id=\"card\" tabIndex=0>\n\t\t\t\t<img id=\"cover\" src=\"${cover}\" alt=\"${title}\" />\n\t\t\t\t<section id=\"body\">\n\t\t\t\t\t<header id=\"header\">\n\t\t\t\t\t\t<h1 id=\"title\">${title}</h1>\n\t\t\t\t\t\t<button id=\"toggle\" @click=\"${events.toggleCard}\">+</button>\n\t\t\t\t\t</header>\n\t\t\t\t\t${\n\t\t\t\t\t\tisOpen\n\t\t\t\t\t\t\t? `<section id=\"detail\">${children}</section>`\n\t\t\t\t\t\t\t: `<input @hidden />`\n\t\t\t\t\t}\n\t\t\t\t</section>\n\t\t\t</main>\n\t\t`)\n\t},\n\t{\n\t\ttitle: useProps(),\n\t\tcover: useProps(),\n\t\tisOpen: useState(false),\n\t\tcardStyle: useStyleSheet(\"/card.css\")\n\t},\n\t([state, set], props) => {\n\t\tlet toggleCard = () => set.isOpen(!state.isOpen)\n\n\t\treturn { toggleCard }\n\t}\n)\n\n```\n\nMilk DOM's diffing algorithm are seperated into 3 parts.\n* Diff - Diffing for the different attribute, child node, etc.\n* Hard Diff - When tagName are different, whole element node have to be replaced. Hard Diff take care of that preventing child node for being recursion.\n* Text Diff - Diffing for text different.\n  \n### Best practice\nTo prevent an unexpected update, it's recommend to contained textNode in an element where textNode is state.\n```javascript\nimport { create, useState } from \"vanilla-milk\"\n\n// Please don't\nlet notSoGood = create((display, { counter }) => {\n\treturn display(`\n\t\t<section>\n\t\t\t<h1>Counter: </h1>\n\t\t\t{counter}\n\t\t</section>\n\t`)\n})\n\n// Better~\nlet wellDone = create((display) => {\n\treturn display(`\n\t\t<section>\n\t\t\t<h1>\n\t\t\t\tCounter: {state}\n\t\t\t</h1>\n\t\t</section>\n\t`)\n})\n```\nNot only that storing textNode in an element are safer but also has better performance from prevent recursion between each node.\n  \n### Multiple node on root\nUnlike VDOM, Vanilla Milk use native DOM for diffing freeing root node from stucking with only one node on the top.\n\n```javascript\nimport { create } from \"vanilla-milk\"\n\n// This is ok\nlet multipleRootNode = create((display, { counter }) => {\n\treturn display(`\n\t\t<h1>Hello! I'm the root node!</h1>\n\t\t<h2>No way! I'm the root node too!</h2>\n\t\t<p>It's ok to use multiple root node in Vanilla Milk</p>\n\t`)\n})\n```\n\n## Encapsulation\nVanilla Milk use Shadow DOM to encapsulate logic and style. Preventing an unexpected change while working in multiple library.\n  \nTo use external stylesheet in Milk Component, you can assign stylesheet in the component instead\n```javascript\nimport { create, useStyleSheet } from \"vanilla-milk\"\n\n// Link stylesheet in component.\nlet coolCard = create((display, { counter }) => {\n\treturn display(`\n\t\t<div class=\"card\"></div>\n\t`)\n},\n{\n\tcardStyle: useStyleSheet(\"/card.css\")\n})\n\n// Or even define style tag inside\nlet coolCard = create(\n\t(display) => display(`\n\t\t<style>\n\t\t\t.card {\n\t\t\t\tdisplay: flex;\n\t\t\t\tflex-direction: column;\n\t\t\t\twidth: 300px;\n\t\t\t\tpadding: 20px 12px;\n\t\t\t\tborderRadius: 4px;\n\t\t\t\tbox-shadow: 0 4px 8px rgba(0,0,0,.25);\n\t\t\t}\n\t\t</style>\n\t\t<div class=\"card\">\n\t\t</div>\n\t`)\n)\n```\n  \nThat's pretty much it of Vanilla Milk. :tada::tada:","_id":"vanilla-milk@0.3.0-beta.5","dist":{"shasum":"4ec2a03bac2fa28dfa0f11afdb88c39bdebfa5be","integrity":"sha512-uUUqgneHIwhLrSFpvPie03YclQAVjLBFgvhjsp3TVl7oAM+EiKQtaAW9ozVEl7tMM5GLK8ceeI1LQehn82DZcA==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.3.0-beta.5.tgz","fileCount":6,"unpackedSize":145164,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeEgHaCRA9TVsSAnZWagAAiz8P/14ehf4YJBZpEHJrz+31\ndlL5FxLjSRrP1Np4K/G/XbS+p3CTfCS0zuz1aACqaSj55xvQxjpQzRLqg4ZQ\nHmxfWnE04XQ09l+P17hrz+HNZ/aCcgKbvt1QymjDXP6TbbdLdLGi5AB/yXh/\nltMXxRBhtBZHbXx+DM8finnVsnHUsjwV3lBRptK9Xtfwp2a9gqtYklXwf40/\nqIGfESfQH/XJmprYsb9ntD565HLa58Nl3zQ24Q0LHMsdFj/xjPDSwyPQ/PuT\nf+F4sfQMoWvSj64IwUQ+kF9MD2YCkHxlJhjn+IFo611OwryG+SWAtkJ8r+kJ\nGG9CSV1ldZJ/+cR0Jdt0kWJudd6tm6LJPzkZdKZZ3aLvtVME4KhO4U1OG9ui\n8c65oPRlPIZIwRq0pKz43k7DYGyC9GUraML8inBDhCQ/vtyN6WoosNyxiqXK\nTDl+C/OIe+6H5d072zuqw8cH0KtmRuHX/92BzRHjSI/7DyVGrWNbXvVXo7CU\nJgo4G1OrQy/ACh5dtjZYBeM4G7/bcAcm5RTEpgwu+HP5YGjNqzbLMbP1IwUo\nmClertp7WPIEmgJ0SmQSqEla/dryA6W/FlAc182E6FOaGt4J7RrG69AWvWzf\nAby4o22sYv9eidsNsIytLZ4ygx1Tg7dtZnQfJX2HBKgqrmCak+WNLH5tZpEH\nq1Zp\r\n=A2Vu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEaiimYxfomee9QaZCePtfrZlIIprvp3hIoN1vep88ROAiEAmvZkbHStEM5wj/qallRz3PFgaH1cMt8h5eaV218aM1w="}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.3.0-beta.5_1578238425637_0.5667840196214862"},"_hasShrinkwrap":false},"0.3.0":{"name":"vanilla-milk","version":"0.3.0","description":"Simple library for building simple reactive web components.","main":"index.js","repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"},"license":"MIT","keywords":["vanilla milk","web component","vanilla milk js"],"_id":"vanilla-milk@0.3.0","dist":{"shasum":"a8fd61b2c4433bd44335af1cebcfd6951d17e383","integrity":"sha512-obDFKW5DW7cmyl8WA/8sY7BPuX2waYHQmyRJ2WvCiWKf8Q8bnUKRosYorhpao+oPwfYt+EJyLrF1lp5MfijNJw==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.3.0.tgz","fileCount":6,"unpackedSize":145157,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeEgJLCRA9TVsSAnZWagAATpgP/1/VX1up9S3pWPV5k8av\nQD3lrFWoL0S/p5GV/ICTrsbJgzmGPLow7/Us0XqZxvODN+h3iEaxz4iTVtoO\nFgt6vzZr8SO4dI388HR4n7Q4xjKUGAZQFkU7vrKN8AYv4KaKPjTkUQmbLp4x\nRkL77L/ZleFNRdh3plNCjZ2/zqQA6uUi0UD3HAFkJXzhA2ZOjO7FqYEOFEam\n1HND7ke47yFKqN3N4BCcZqva9VZkf7PIK7XRmWRqbNzfQZmmKQ+eLV7fN4Yz\nRf/QwMqDgS1Of9UNNaln+th+YpoIx0aNkj/kpqU8HP6FGvyPmiQOvF0ZA930\nFAQkVPlov2j08DAA6FHa58wUxW7Ga2amP2TojRRhIwLan8wGcIvzHn4srrND\n6PEwDwqYSWHXC1t6MUX9W4hK4HG2V+4YPshHeoZ2tl7WCA7aw9fdrebqwieT\nrPDMjPF4WB3ayse5jXMBNJBjJiRpL3ZVLwqoJ6pbgXlyRs3GIxpUIKXzEIXY\n0ybOolOJa4HL0z9P5i0uAwBFjUT5kX3Q14UiBEXcpKTX0Nx6xG2w8aY7Xxq0\nlbT5MIDYyQpTcKqkgTqjhRwAGGfQ0p/bTgGMTNbmPQ244r1o/WCmIttCy5Lj\nIbWoxl86v0yCun4DmdwxrbAHAduDynifK27QLnQU53XrXcJPyotvaDbfj6ay\n5y0v\r\n=zsi/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID7cuOU4GP3pdB1oYMRYfOR1r6xu3H1OqdUQruplStXsAiEAmrn+OaTzu4NyXkhW6iojS7L+DqvH8v8BHRqx5k7BfSg="}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.3.0_1578238538795_0.7988183750718976"},"_hasShrinkwrap":false},"0.3.1":{"name":"vanilla-milk","version":"0.3.1","description":"Simple library for building simple reactive web components.","main":"index.js","repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"},"license":"MIT","keywords":["vanilla milk","web component","vanilla milk js"],"_id":"vanilla-milk@0.3.1","dist":{"shasum":"56b7e52747c6ca43a5363b107c546a9fd5beff80","integrity":"sha512-LAfl5zxG1s7UunVZHERKDtjfMYiP6FIbSK7xlvBJSR2PSmZIjMz2y4asvG027lRYM5ghyXgbHWqjDLhL8ftzPQ==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.3.1.tgz","fileCount":6,"unpackedSize":145270,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeEnt5CRA9TVsSAnZWagAAV20P/3ykohaNmnQ9hdsurde9\nNXrUBRP8RKi4GD7FFOwLHg/QTKC9UnU+4raxHcN7Sa4vmolrSMWpv8bYthPu\nBajBw57KdlVTyY6iYdkHSbdZt/A0205+BbYYMa+YlE0P7EeTVEycBlnc5uot\neJs/AMjLABWLx5B4IOaz+o/OCj4gbs01lTi/NfGxRGJpf822htxIwXk+M95P\n2SjzW0lk90lToCRafWt6bSuPrYemM56YHSvBBRlFR6C2h+TNDtEkkTSXGK3s\nloUS2h4RW4OnBd58Ct3bEMMWRTbbMcLWHdLfwadx/0sc3g6ZSyI78grdP0iA\n41/n+4cKUsoXwYHp9uYy7N+98yJdaynnUVyjNMHpRKbGk9RsEuvTMv1UnfDb\nSb8E8X2AlEpWSKe3574jMRitZ1kT5VCqyd52DpkROYe9sTuJGMNN8fAXutWq\nOWsC0/W3b3JOrdCz5gWMyIN2GphJXFtZxDeHxvNdDeczr20XqNA2PY6TmkNa\nVm+TaxCf4XD2u06Bc2S5Jmrg5j1kGJwvLDd93a7Na4VliZ845RUBhZBknSFb\nkmT0yxSoU8JnA0wI43yATkPxtdw7f7ida+Hwb0Y7XCP+Qg49O311UsaCeHyH\nZnMwMUTdjKBHkYYQncZGxAFtHvdgOEH1nmPLRG4ssv3GRz1KtSM2TLcxhk8h\nHr3s\r\n=n9hA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDcuJ9N8srCJzsziZfd1iHSTopd4GegXytuWrFAtyS0VgIhAIVVkpGc6zo6dWGjWW6d50Dq6sOPVzSiGKo7lcapM4U3"}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.3.1_1578269560722_0.9216806504752415"},"_hasShrinkwrap":false},"0.3.2-beta.0":{"name":"vanilla-milk","version":"0.3.2-beta.0","description":"Simple library for building simple reactive web components.","main":"index.js","repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"},"license":"MIT","keywords":["vanilla milk","web component","vanilla milk js"],"_id":"vanilla-milk@0.3.2-beta.0","dist":{"shasum":"db9867c13f67f29b602df6cea1b4668385ab25cd","integrity":"sha512-QLgdop3GNz8xtLubBlKX0w/V0MvLAfJJeRQiYlwfMc5Wv+KiNX/RI8CFPlsiJgJxioOT9NB7oMwK4/24FoLulA==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.3.2-beta.0.tgz","fileCount":6,"unpackedSize":146305,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeEx8rCRA9TVsSAnZWagAAhg4QAIJa+6LQrku4A625IwtH\n+rpGjfPbRpJTNljp2rMjBozog9S3NQNQgosvzou9pjzpgHOeSfl0CAplj8IZ\nURE8bfx2yoDTFbvwfL0Vx1Fi17wjQ8BN9SZqMR8d1u6WiW2Z+eYl6CvcRUUC\n50JzilCnaaBF3jHtmLs5NXe4MpECbuL9S3Vm1xZJAB2dVCBcFc9YfWHbQ6HV\nGntUcRTZewVL71//rXsU1cIQmXpFku+ZLLvwpS4ut+Uz7zwEclKmBXD388/7\nR+Bp3qEauy5C2FjXyYP+ZOrLSQxdODOIWACBLIcXnpxjO9Bx+KR7JBXOe0gU\n8d1J67/VCcZGhGhwY8vEeSKe0B5H5pTJStkSck2NN47olq6CPA/uYS50vkTJ\nyLcKCzf1kyixLpM5e4mMyrd4sPMc2EMBoiAME6334nPzXPeDl7gODNxh1p6E\nD5p3CZjX5tvN2PDbOcfSBSmiXfX6z293Mex6PKHrk6TIrKQQK0K1fUk+Lx1Y\n6ZyepONOi2F5/6PGfiheo+Mqe8AyKsB2+ptSuHbuq8jQ8ShpQtyNV+ZMc+lJ\naEdHqkEwUEeQLN4bw8sxihp7rJJn+zzfy43oF3ZxdDtvd7MSqAkoQu5rcfm3\nN/oZxwQen4cj38YY+A4KbOCHzHBtwJ5ZTN5a99mWyWch0/5sJ/z4g+JKfid7\nEC/h\r\n=bChm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDTeVsaAtp9seYlhkuZAiCfC8TJIKUihx8hv/lVVZtYGQIhAPt/Kd05xehnJpNM8IJ2LQzTnV8ys0e7Qr3SymNhcFhk"}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.3.2-beta.0_1578311466959_0.7585535542955157"},"_hasShrinkwrap":false},"0.3.2-beta.1":{"name":"vanilla-milk","version":"0.3.2-beta.1","description":"Simple library for building simple reactive web components.","main":"index.js","repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"},"license":"MIT","keywords":["vanilla milk","web component","vanilla milk js"],"_id":"vanilla-milk@0.3.2-beta.1","dist":{"shasum":"c9e4c449dee6ac8e3108bbddfab872cea425a99d","integrity":"sha512-F3V7Y7AqTjpbI/ADa1eMN9vGP6N6ki8Dsmjbpeh/ekVg+npYG4vrMWtFkhT9wuTVdqU6ZuRfSIisuuD+iVnmYA==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.3.2-beta.1.tgz","fileCount":6,"unpackedSize":146287,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeE1jGCRA9TVsSAnZWagAAjzwP/1lRTuEW0EaHsrXV7N4B\nCXNxJZeOEb3GGYicIx/AK2ndChr2kyRgU013/mwh3h5Z5e2SSjMtxVJRYRyo\nIbKpDWe3FcKdXf6FN28S52XGu3iqSUG2AC0/D4BqIE9obgXV6sSjqHPFOL8N\n9La4VCQ9GMBZnmb5WwqZVxdGynYOMQsb39zoSHFYC8BbMTorWodov2ddqvV8\nWfUmfrlmRHKUcYE2XdQTSSoQ09DpSPIYkNLwMcXXg4PKBr4aGAKk7QyiP9S5\n1dx0Cp3x7UIy5rqd93Pu7RvGJS8OnItX1GOFngvJkOTB7IkQOfZjwhiT7aFZ\nXzq0w1UcRN5IBc2LSlKZWXAZKRO0uQiE3M8qoCXCOq22zd0qhjqTeGtHEyfp\ns3jYX8qANewz7lECiBOCtfwL9RS4GdF5PY7xzEEXhUD3elV6j/rLhyIOaeVM\nwNJCrPAT8ZVYZfVMo3iV8RkAcP4IFpsdnTkBBf1QXcXWAcmRSQ0Sg+OPemkM\nePk4c6bdBT8p0q+m9Vb9AobUZxsCP49O/sdaUe0f5vxNWiFaFHhL9UsNte7c\nMZrnQh1IbCvXNTxtGgM0JKtvkzfAe5VUTWnpYRyUXaUk5fckXq6XVDRXaIR4\nFs2tgszb3PAblLKApvJZEhCys3TuHf02vbMgNZ0hSRtaD3K6cv5u/6crlVlZ\nH4pE\r\n=NcbC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDY2kOPhq4v0GBy+yd5hW9Fq9a0+rQqVb/dlyTDGSh1yAIgB9+jb40kHDOri47kkwSHwKEwjku2M3q6I9fkfvCBdRg="}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.3.2-beta.1_1578326214440_0.2873668651148267"},"_hasShrinkwrap":false},"0.3.2-beta.3":{"name":"vanilla-milk","version":"0.3.2-beta.3","description":"Simple library for building simple reactive web components.","main":"index.js","repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"},"license":"MIT","keywords":["vanilla milk","web component","vanilla milk js"],"readmeFilename":"README.md","readme":"# Vanilla Milk\nSimple library for building simple reactive web components.\n  \n## What is...\nVanilla Milk is a library which helps create to web component which can be used on anywhere! Embrace future of web-component made it future-proof. Built-in reactive state and props but also is very small and fast.\n\nVanilla Milk feature:\n* Reusable component.\n* Simple way for creating web components.\n* Milk DOM, a special implementation of DOM manipulation.\n* Reactive state and props.\n* No class, just function.\n* Life-cycle hooks.\n* Expressive Vanilla like API structure.\n* Very small (1kB gzipped on production).\n* Encapsulated style, ID and class name.\n* Zero dependencies.\n* TypeScript support.\n\n## Milk DOM\nVanilla Milk doesn't use Virtual DOM, instead it has its own `Milk DOM` which share the same idea with Virtual Dom, update where neccessary. Unlike VDOM, Milk DOM use a collection of Native Browser API to perform diffing instead of creating long list of object which also prevent heavy recursion.\nDrawback is diffing algorithm isn't as deep as Virtual DOM does but Milk DOM is blazing fast and has less memory consumption.\n###### Note: Milk DOM is in an very early stage of development, you might experience some bug and when that time came, you can always open the issue on this repo.\n  \n## Getting started\nGlad you're interested in! Let's get over quick start! Let us add library just for creating a component, after the component has been built, you don't have to install it anymore! Just moved the built components to your any project~\n\n### Install Vanilla Milk\nLet install this real quick with package manager of your choice.\n```bash\n// Using npm\nnpm install vanilla-milk --save\n\n// Using yarn\nyarn add vanilla-milk\n```\nWell done! Now you're ready to create a Milk Component! (Shortname for Vanilla Milk Component for the greater good.)\n  \n### Hello World! It's Milk Component!\nLet's start by building `milk-component', a traditional hello world for programmer but as web component.\n\nMilk Component are separated into 2 step:\n1) Define it with `create`\n2) Create it with `define`\n\nJust 2 step, that's all for building reactive web component.\n\n#### Create\nFirst of all, import `create` function from vanilla-milk. This function is responsible to create a model of component.\n```javascript\nimport { create } from \"vanilla-milk\"\n```\n\nFirst parameter is a callback to display HTML Element.\n```javascript\nimport { create } from \"vanilla-milk\"\n\nconst MilkComponent = create((display) => \n\tdisplay(`<h1>Hello World! Milk Component!</h1>`)\n)\n```\nWe have just create `MilkComponent` which will return `<h1>Hello World</h1>`  \n\n### Define\nNext we just have to `define` this component, so it can work like every HTML Element.  \nBut first, import `define` from `vanilla-milk`\n```javascript\nimport { define } from \"vanilla-milk\"\n```\n\nNow let's name the component `milk-element`, so it can be use in HTML. (Web Component need `-` to be declared, like `milk-component` which has `-` in it)\n```javascript\nimport { create, define } from \"vanilla-milk\"\n\nconst MilkComponent = create((display) => \n\tdisplay(`<h1>Hello World! Milk Component!</h1>`)\n)\n\ndefine(\"milk-component\", MilkComponent)\n```\nThat's it! You have just created a Milk Component!! :tada::tada:\n  \n#### Milk Component in action\nSoooo~ We have just created a web component, let's see it in action!  \nJust add `<milk-component></milk-component>` in HTML. Make sure you've link the JavaScript file which contain milk component in it. You can use quick set-up like `parcel`.\n```html\n<!-- Any HTML here -->\n<html>\n<head>\n\t<title>Hello Milk Component</title>\n    <script src=\"milk_component_here.js\"></script>\n</head>\n<body>\n\t<milk-component></milk-component>\n</body>\n</html>\n```\nAnd it should display something like this.\n    \n#### But that's not what make Vanilla Milk special...\nIn Vanilla Milk, component are reactive which mean every time `state` or `props` changed, Milk Component will know it.\n\n## State\nLike `angular`, `react` and `vue`, Vanilla Milk also has `state`.  \nState is like a variable which are responsible for storing data and display it to view.\n\nLet's say we want to create a counter and display count to view. In Vanilla Milk we do like this.\n  \nIf you're familiar with React, we have `useState`. But it's not like what you might think.\n```javascript\nimport { useState } from 'vanilla-milk'\n```\nVanilla Milk are designed to be expressive. So we separate the state, props and life-cycle to the second parameter of `create` like this.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\tlet { count } = state\n    \n\treturn display(`<h1>Count ${count}</h1>`)\n},\n{\n\tcounter: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nSo, what's happend here?\n  \nThe second parameter of `create` are responsible for handling data, so we can separate and focus on each part.\n```\n{\n\tcount: useState(0)\n}\n```\nHere we defined state name `count` with value of `0`. `useState` is a function that say, \"Hey! We want a state name 'count' with value of 0\" to Vanilla Milk or something like that. Vanilla Milk will just handle the rest of that and pass the `count` to the `second parameter` of the view callback.\n```\nconst MilkComponent = create((display, state) => {\n\tconsole.log(state) // { count: 0 }\n},\n{\n\tcount: useState(0)\n})\n```\nLastly, we display counter to the view.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\treturn display(`<h1>Count ${state.count}</h1>`)\n},\n{\n\tcount: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nNow that will display `count` to HTML, so... how do we set it in Vanilla Milk?\n  \nAs an early state of development of Vanilla Milk that's where the last parameter of `create` kick in!  \nWe add button and attach event in to it, so we can change the value of `counter`. // Hey don't make face of disappointment like that! I'll fix it in some next update, I promise! It's quite hard to create something like that ya know.\n  \nLet add a button.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\treturn display(`\n\t\t<h1>Count ${state.count}</h1>\n    \t<button id=\"increase-count\">Increase count</button>\n\t`)\n},\n{\n\tcount: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nVanilla Milk is declarative, this is where the last parameter come in!  \nYou define any `events` you want here! It's take callback function so you're free to define everything like normal JavaScript here. Vanilla Milk called this parameters as `useEvents`.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state, _, events) => {\n\tconsole.log(events) // { increaseCount: \"increaseCount\" }\n\n\treturn display(`\n\t\t<h1>Count ${state.count}</h1>\n    \t<button id=\"increase-count\" @click=\"${events.increaseCount}\">Increase count</button>\n\t`)\n},\n{\n\tcount: useState(0)\n},\n([state, set], _) => {\n\tlet increaseCount = () => set.count(state.count + 1)\n    \n    return { increaseCount }\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\n`useEvents` take an callback which pass `[state, set]` which are used to access state and set the state. Receive `props` and second parameter. \n###### *props will be explained in next section.\n```javascript\n([state, set], props) => {\n\tlet increaseCount = () => set.count(state.count + 1)\n    \n    return { increaseCount }\n})\n```\nYou might notice something there's `@click` in `button`, Vanilla Milk use pseudo attribute and match event to the node. This pseudo attribute take an export events name in `useEvents`.\n```javascript\n<button id=\"increase-count\" @click=\"${events.increaseCount}\">\n    Increase count\n</button>\n```\nNow everytime the button that as `@click` will run the function match to exports in `useEvents`, in this case it's `increaseCount`\n```javascript\nlet increaseCount = () => set.count(state.count + 1)\n\nreturn { increaseCount }\n```\nAt here we get value of `count` from `state.count` and set it with `set.count` which came out with something like this:\n```javascript\nset.count(0 + 1) // Count is now 1\n```\nNow it should increase the value of count everytime we click it!\n\nThat's it! You've just achieve an advance concept like state of Vanilla Milk :tada::tada:\n\n## Props\nContrast to state, it's super simple. props is shorten for `properties`. A property is like a HTML attribute. For a button like:\n```html\n<button class=\"nice-button\">Hello! I'm a button</button>\n```\nclass is a props of this button and it's value is \"nice-button\".\n  \nAs Milk Component, we also can have something like that! and guess what? You can create any attribute you like effortlessly!\n  \nAll you have to do is import `useProps` from `vanilla-milk` and set it like `useState`.\n```javascript\nimport { useProps } from \"vanilla-milk\"\n```\nNow let's say that we want to have a prop name `hello`. Like `useState` we do it like this:\n```javascript\n{\n\tcount: useState(0),\n\thello: useProps()\n}\n```\nAnd access it like state\n```javascript\ncreate((display, state, props) => {\n\tconsole.log(props.hello) // null if there's no value passed\n})\n```\nSo let's define the component real quick to see how it work.\n```javascript\nimport { create, define, useProps } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state, props) => {\n\treturn display(`<h1>hello ${props.hello}</h1>`)\n},{\n\thello: useProps()\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nAnd in HTML\n```html\n<milk-component hello=\"world\"></milk-component> // hello world\n```\nThe reason we have to define `props` so that Vanilla Milk can just update and listen only to the props you used! \n  \nBut there's one special props which is always available... `children`\nChildren is any text or HTML Element between the Milk Component.\nIn HTML:\n```html\n<milk-component>Hello World</milk-component>\n```\nAnd access it:\n```javascript\nconst MilkComponent = create((display, state, props) => {\n\tconsole.log(props.children) // Hello World\n})\n```\nThat's it! Unlike `useState`, `useProps` is super to use! :tada::tada:\n\n## useEffect\nLike React, you can defined lifecycle with `useEffect`.\n  \nLet's say, that you want to `console.log()` everytime prop `hello` change. You just have to import `useEffect` from `vanilla-milk`.\n```javascript\nimport { useEffect } from \"vanilla-milk\"\n```\nAgain, add it to second paramter of `create` like `useState` and `useProps`\n```javascript\n{\n\thello: useProps(),\n\tlogHello: useEffect((state, props) => {\n\t\tconsole.log(props.hello) // Log everytime hello changed\n    }, [\"hello\"])\n}\n```\nNotice that we add array contain \"hello\" as string as the second parameter of useEffect.\nBecause we can't directly access value of hello so we just add it as string, Vanilla Milk will take care of the rest (In fact, we can add it as variable but it takes an extra effort and performance cost).\n\nYou can express name of `useEffect` as anything, It just easier to remind you lifecycle with name if there are too much lifecycle.\n\nNow we hello is changed, first callback will run. Like view callback, useEffect is paired with `(state, props)`. You can directly access it in the callback.\n\n`useEffect` is not only limited to state but props too! You can also add `useEffect` as much as you want or many listener as much as you need!\n```javascript\n// State and Props\n{\n    hello: useProps(),\n    count: useState(),\n\tlogHello: useEffect((state, props) => {\n    \tconsole.log(props)\n    }, [\"count\"])\n}\n  \n// Multiple listener\n{\n    hello: useProps(),\n    count: useProps(),\n\tlogHello: useEffect((state, props) => {\n    \tconsole.log(props)\n    }, [\"count\", \"count\"])\n}\n```\n  \n## Milk DOM In depth\nMilk DOM cover a lot of thing under the cover but the main concept is to compare and diff DOM Node aimming for lesser iteration as possible (Same idea with VDOM). Instead of constructing an object node representation of DOM for comparing between two. Vanilla Milk heavily use Native Browser API comparing between each node instead of DOM and update it directly instead.\n\nSince Milk DOM is written in template string, it's very hard for Vanilla Milk to identify which textNode should replace Node or vice-versa. In this case, you shouldn't replace existed dom with blank text (\"\") like how React, Vue, other library does (which will sometime, occured an unexpected error). Instead Vanilla Milk offter a way to replace Node with blank Node by putting any element with attribute of `__hidden__`\n```javascript\nconst MilkCard = create(\n\t(display, { isOpen }, { title, cover, children }, events) => {\n\t\treturn display(`\n\t\t\t<main id=\"card\" tabIndex=0>\n\t\t\t\t<img id=\"cover\" src=\"${cover}\" alt=\"${title}\" />\n\t\t\t\t<section id=\"body\">\n\t\t\t\t\t<header id=\"header\">\n\t\t\t\t\t\t<h1 id=\"title\">${title}</h1>\n\t\t\t\t\t\t<button id=\"toggle\" @click=\"${events.toggleCard}\">+</button>\n\t\t\t\t\t</header>\n\t\t\t\t\t${\n\t\t\t\t\t\tisOpen\n\t\t\t\t\t\t\t? `<section id=\"detail\">${children}</section>`\n\t\t\t\t\t\t\t: `<input @hidden />`\n\t\t\t\t\t}\n\t\t\t\t</section>\n\t\t\t</main>\n\t\t`)\n\t},\n\t{\n\t\ttitle: useProps(),\n\t\tcover: useProps(),\n\t\tisOpen: useState(false),\n\t\tcardStyle: useStyleSheet(\"/card.css\")\n\t},\n\t([state, set], props) => {\n\t\tlet toggleCard = () => set.isOpen(!state.isOpen)\n\n\t\treturn { toggleCard }\n\t}\n)\n\n```\n\nMilk DOM's diffing algorithm are seperated into 3 parts.\n* Diff - Diffing for the different attribute, child node, etc.\n* Hard Diff - When tagName are different, whole element node have to be replaced. Hard Diff take care of that preventing child node for being recursion.\n* Text Diff - Diffing for text different.\n  \n### Best practice\nTo prevent an unexpected update, it's recommend to contained textNode in an element where textNode is state.\n```javascript\nimport { create, useState } from \"vanilla-milk\"\n\n// Please don't\nlet notSoGood = create((display, { counter }) => {\n\treturn display(`\n\t\t<section>\n\t\t\t<h1>Counter: </h1>\n\t\t\t{counter}\n\t\t</section>\n\t`)\n})\n\n// Better~\nlet wellDone = create((display) => {\n\treturn display(`\n\t\t<section>\n\t\t\t<h1>\n\t\t\t\tCounter: {state}\n\t\t\t</h1>\n\t\t</section>\n\t`)\n})\n```\nNot only that storing textNode in an element are safer but also has better performance from prevent recursion between each node.\n  \n### Multiple node on root\nUnlike VDOM, Vanilla Milk use native DOM for diffing freeing root node from stucking with only one node on the top.\n\n```javascript\nimport { create } from \"vanilla-milk\"\n\n// This is ok\nlet multipleRootNode = create((display, { counter }) => {\n\treturn display(`\n\t\t<h1>Hello! I'm the root node!</h1>\n\t\t<h2>No way! I'm the root node too!</h2>\n\t\t<p>It's ok to use multiple root node in Vanilla Milk</p>\n\t`)\n})\n```\n\n## Encapsulation\nVanilla Milk use Shadow DOM to encapsulate logic and style. Preventing an unexpected change while working in multiple library.\n  \nTo use external stylesheet in Milk Component, you can assign stylesheet in the component instead\n```javascript\nimport { create, useStyleSheet } from \"vanilla-milk\"\n\n// Link stylesheet in component.\nlet coolCard = create((display, { counter }) => {\n\treturn display(`\n\t\t<div class=\"card\"></div>\n\t`)\n},\n{\n\tcardStyle: useStyleSheet(\"/card.css\")\n})\n\n// Or even define style tag inside\nlet coolCard = create(\n\t(display) => display(`\n\t\t<style>\n\t\t\t.card {\n\t\t\t\tdisplay: flex;\n\t\t\t\tflex-direction: column;\n\t\t\t\twidth: 300px;\n\t\t\t\tpadding: 20px 12px;\n\t\t\t\tborderRadius: 4px;\n\t\t\t\tbox-shadow: 0 4px 8px rgba(0,0,0,.25);\n\t\t\t}\n\t\t</style>\n\t\t<div class=\"card\">\n\t\t</div>\n\t`)\n)\n```\n  \nThat's pretty much it of Vanilla Milk. :tada::tada:","_id":"vanilla-milk@0.3.2-beta.3","dist":{"shasum":"afbb787bf181f12dabcf74d6efc4c7e6ec74f22b","integrity":"sha512-zM5yVtTmxspH2DMWSC2eAmDXaK1algRCAlSVLj66I+1XDVIbx/BJqlUqqCe47dArRGahdy17vobCIbrU/KpDeQ==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.3.2-beta.3.tgz","fileCount":6,"unpackedSize":146273,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeE8y7CRA9TVsSAnZWagAAYVIP/3I4v6746feiUZ/V9nL7\nEwnd5iNRV6sUYMJ3Wbgk6AO4EJk0OhtTKDe80nt3MR/w4oQIKNIwMIDBW1kY\nb6eEf/mliLfZ7QBmEMasGv7J449qP2++pJ3G6X/azI4bVFJgGurkBBCVfRx8\nG/wWRyxaJ3P/Fyu7vEuUxZJDD7eH9SmaP5m8o0mM1G+KhDQTWmqMzCs8Pn3d\nrDonVp8D1m2ydywp1vQqX8KkhPsA7uDfx3bF3P/FzuD/eGp/UMGcezOgK/cU\n7240hgBjthTmoojZrhXvGhs+Q/2YucZxdfKqvjhVHGW6+KPNHqYiKOIDnS/7\n1v/t1pGGCMxDeUaBEU27uhAT75VWJIdqG9DpQCarbM4F9VEFWDR6tKx+QvSu\ngwOrHvDJNHXPd6tRJTNVFCMmxhB3bWNpyU40axBi/PT1G38s9N3+Q4Xrbs5o\ndyNOwfiR+K6aJTbcX/Z6UeWoaqEZyx9RjzX1fI2gNdZL5xHKaHmkFm0Wd5WT\nXq4tCb16dVIl1Hwrw2j/nxA7kgpwEr4C28s4R9q4jhhjPyTAnMhbl9KgzUW7\nHvZ1DP2U/mDEWX0bUI+DzOAX/+p6HfG4bp0T6GfwBNGPtlllX/BVtlxWucqU\nm/rYU1fBnGIZdXyi3Xrnvgr4Pz5o6h58XbZ6J1Y3Q1LhP1U6vyLi+HJdwABJ\n1vmp\r\n=GD+0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD8Z7E4zco1rnnhaWbEOy8lOryCRnhvK3ku+fepp81h4QIhAI9nrlx3yYT6CGQKaoO60y8dkiAz6MfPkkDquRv25mxX"}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.3.2-beta.3_1578355898709_0.7131093390131111"},"_hasShrinkwrap":false},"0.3.2-beta.4":{"name":"vanilla-milk","version":"0.3.2-beta.4","description":"Simple library for building simple reactive web components.","main":"index.js","repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"},"license":"MIT","keywords":["vanilla milk","web component","vanilla milk js"],"readmeFilename":"README.md","readme":"# Vanilla Milk\nSimple library for building simple reactive web components.\n  \n## What is...\nVanilla Milk is a library which helps create to web component which can be used on anywhere! Embrace future of web-component made it future-proof. Built-in reactive state and props but also is very small and fast.\n\nVanilla Milk feature:\n* Reusable component.\n* Simple way for creating web components.\n* Milk DOM, a special implementation of DOM manipulation.\n* Reactive state and props.\n* No class, just function.\n* Life-cycle hooks.\n* Expressive Vanilla like API structure.\n* Very small (1kB gzipped on production).\n* Encapsulated style, ID and class name.\n* Zero dependencies.\n* TypeScript support.\n\n## Milk DOM\nVanilla Milk doesn't use Virtual DOM, instead it has its own `Milk DOM` which share the same idea with Virtual Dom, update where neccessary. Unlike VDOM, Milk DOM use a collection of Native Browser API to perform diffing instead of creating long list of object which also prevent heavy recursion.\nDrawback is diffing algorithm isn't as deep as Virtual DOM does but Milk DOM is blazing fast and has less memory consumption.\n###### Note: Milk DOM is in an very early stage of development, you might experience some bug and when that time came, you can always open the issue on this repo.\n  \n## Getting started\nGlad you're interested in! Let's get over quick start! Let us add library just for creating a component, after the component has been built, you don't have to install it anymore! Just moved the built components to your any project~\n\n### Install Vanilla Milk\nLet install this real quick with package manager of your choice.\n```bash\n// Using npm\nnpm install vanilla-milk --save\n\n// Using yarn\nyarn add vanilla-milk\n```\nWell done! Now you're ready to create a Milk Component! (Shortname for Vanilla Milk Component for the greater good.)\n  \n### Hello World! It's Milk Component!\nLet's start by building `milk-component', a traditional hello world for programmer but as web component.\n\nMilk Component are separated into 2 step:\n1) Define it with `create`\n2) Create it with `define`\n\nJust 2 step, that's all for building reactive web component.\n\n#### Create\nFirst of all, import `create` function from vanilla-milk. This function is responsible to create a model of component.\n```javascript\nimport { create } from \"vanilla-milk\"\n```\n\nFirst parameter is a callback to display HTML Element.\n```javascript\nimport { create } from \"vanilla-milk\"\n\nconst MilkComponent = create((display) => \n\tdisplay(`<h1>Hello World! Milk Component!</h1>`)\n)\n```\nWe have just create `MilkComponent` which will return `<h1>Hello World</h1>`  \n\n### Define\nNext we just have to `define` this component, so it can work like every HTML Element.  \nBut first, import `define` from `vanilla-milk`\n```javascript\nimport { define } from \"vanilla-milk\"\n```\n\nNow let's name the component `milk-element`, so it can be use in HTML. (Web Component need `-` to be declared, like `milk-component` which has `-` in it)\n```javascript\nimport { create, define } from \"vanilla-milk\"\n\nconst MilkComponent = create((display) => \n\tdisplay(`<h1>Hello World! Milk Component!</h1>`)\n)\n\ndefine(\"milk-component\", MilkComponent)\n```\nThat's it! You have just created a Milk Component!! :tada::tada:\n  \n#### Milk Component in action\nSoooo~ We have just created a web component, let's see it in action!  \nJust add `<milk-component></milk-component>` in HTML. Make sure you've link the JavaScript file which contain milk component in it. You can use quick set-up like `parcel`.\n```html\n<!-- Any HTML here -->\n<html>\n<head>\n\t<title>Hello Milk Component</title>\n    <script src=\"milk_component_here.js\"></script>\n</head>\n<body>\n\t<milk-component></milk-component>\n</body>\n</html>\n```\nAnd it should display something like this.\n    \n#### But that's not what make Vanilla Milk special...\nIn Vanilla Milk, component are reactive which mean every time `state` or `props` changed, Milk Component will know it.\n\n## State\nLike `angular`, `react` and `vue`, Vanilla Milk also has `state`.  \nState is like a variable which are responsible for storing data and display it to view.\n\nLet's say we want to create a counter and display count to view. In Vanilla Milk we do like this.\n  \nIf you're familiar with React, we have `useState`. But it's not like what you might think.\n```javascript\nimport { useState } from 'vanilla-milk'\n```\nVanilla Milk are designed to be expressive. So we separate the state, props and life-cycle to the second parameter of `create` like this.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\tlet { count } = state\n    \n\treturn display(`<h1>Count ${count}</h1>`)\n},\n{\n\tcounter: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nSo, what's happend here?\n  \nThe second parameter of `create` are responsible for handling data, so we can separate and focus on each part.\n```\n{\n\tcount: useState(0)\n}\n```\nHere we defined state name `count` with value of `0`. `useState` is a function that say, \"Hey! We want a state name 'count' with value of 0\" to Vanilla Milk or something like that. Vanilla Milk will just handle the rest of that and pass the `count` to the `second parameter` of the view callback.\n```\nconst MilkComponent = create((display, state) => {\n\tconsole.log(state) // { count: 0 }\n},\n{\n\tcount: useState(0)\n})\n```\nLastly, we display counter to the view.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\treturn display(`<h1>Count ${state.count}</h1>`)\n},\n{\n\tcount: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nNow that will display `count` to HTML, so... how do we set it in Vanilla Milk?\n  \nAs an early state of development of Vanilla Milk that's where the last parameter of `create` kick in!  \nWe add button and attach event in to it, so we can change the value of `counter`. // Hey don't make face of disappointment like that! I'll fix it in some next update, I promise! It's quite hard to create something like that ya know.\n  \nLet add a button.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n\treturn display(`\n\t\t<h1>Count ${state.count}</h1>\n    \t<button id=\"increase-count\">Increase count</button>\n\t`)\n},\n{\n\tcount: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nVanilla Milk is declarative, this is where the last parameter come in!  \nYou define any `events` you want here! It's take callback function so you're free to define everything like normal JavaScript here. Vanilla Milk called this parameters as `useEvents`.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state, _, events) => {\n\tconsole.log(events) // { increaseCount: \"increaseCount\" }\n\n\treturn display(`\n\t\t<h1>Count ${state.count}</h1>\n    \t<button id=\"increase-count\" @click=\"${events.increaseCount}\">Increase count</button>\n\t`)\n},\n{\n\tcount: useState(0)\n},\n([state, set], _) => {\n\tlet increaseCount = () => set.count(state.count + 1)\n    \n    return { increaseCount }\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\n`useEvents` take an callback which pass `[state, set]` which are used to access state and set the state. Receive `props` and second parameter. \n###### *props will be explained in next section.\n```javascript\n([state, set], props) => {\n\tlet increaseCount = () => set.count(state.count + 1)\n    \n    return { increaseCount }\n})\n```\nYou might notice something there's `@click` in `button`, Vanilla Milk use pseudo attribute and match event to the node. This pseudo attribute take an export events name in `useEvents`.\n```javascript\n<button id=\"increase-count\" @click=\"${events.increaseCount}\">\n    Increase count\n</button>\n```\nNow everytime the button that as `@click` will run the function match to exports in `useEvents`, in this case it's `increaseCount`\n```javascript\nlet increaseCount = () => set.count(state.count + 1)\n\nreturn { increaseCount }\n```\nAt here we get value of `count` from `state.count` and set it with `set.count` which came out with something like this:\n```javascript\nset.count(0 + 1) // Count is now 1\n```\nNow it should increase the value of count everytime we click it!\n\nThat's it! You've just achieve an advance concept like state of Vanilla Milk :tada::tada:\n\n## Props\nContrast to state, it's super simple. props is shorten for `properties`. A property is like a HTML attribute. For a button like:\n```html\n<button class=\"nice-button\">Hello! I'm a button</button>\n```\nclass is a props of this button and it's value is \"nice-button\".\n  \nAs Milk Component, we also can have something like that! and guess what? You can create any attribute you like effortlessly!\n  \nAll you have to do is import `useProps` from `vanilla-milk` and set it like `useState`.\n```javascript\nimport { useProps } from \"vanilla-milk\"\n```\nNow let's say that we want to have a prop name `hello`. Like `useState` we do it like this:\n```javascript\n{\n\tcount: useState(0),\n\thello: useProps()\n}\n```\nAnd access it like state\n```javascript\ncreate((display, state, props) => {\n\tconsole.log(props.hello) // null if there's no value passed\n})\n```\nSo let's define the component real quick to see how it work.\n```javascript\nimport { create, define, useProps } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state, props) => {\n\treturn display(`<h1>hello ${props.hello}</h1>`)\n},{\n\thello: useProps()\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nAnd in HTML\n```html\n<milk-component hello=\"world\"></milk-component> // hello world\n```\nThe reason we have to define `props` so that Vanilla Milk can just update and listen only to the props you used! \n  \nBut there's one special props which is always available... `children`\nChildren is any text or HTML Element between the Milk Component.\nIn HTML:\n```html\n<milk-component>Hello World</milk-component>\n```\nAnd access it:\n```javascript\nconst MilkComponent = create((display, state, props) => {\n\tconsole.log(props.children) // Hello World\n})\n```\nThat's it! Unlike `useState`, `useProps` is super to use! :tada::tada:\n\n## useEffect\nLike React, you can defined lifecycle with `useEffect`.\n  \nLet's say, that you want to `console.log()` everytime prop `hello` change. You just have to import `useEffect` from `vanilla-milk`.\n```javascript\nimport { useEffect } from \"vanilla-milk\"\n```\nAgain, add it to second paramter of `create` like `useState` and `useProps`\n```javascript\n{\n\thello: useProps(),\n\tlogHello: useEffect((state, props) => {\n\t\tconsole.log(props.hello) // Log everytime hello changed\n    }, [\"hello\"])\n}\n```\nNotice that we add array contain \"hello\" as string as the second parameter of useEffect.\nBecause we can't directly access value of hello so we just add it as string, Vanilla Milk will take care of the rest (In fact, we can add it as variable but it takes an extra effort and performance cost).\n\nYou can express name of `useEffect` as anything, It just easier to remind you lifecycle with name if there are too much lifecycle.\n\nNow we hello is changed, first callback will run. Like view callback, useEffect is paired with `(state, props)`. You can directly access it in the callback.\n\n`useEffect` is not only limited to state but props too! You can also add `useEffect` as much as you want or many listener as much as you need!\n```javascript\n// State and Props\n{\n    hello: useProps(),\n    count: useState(),\n\tlogHello: useEffect((state, props) => {\n    \tconsole.log(props)\n    }, [\"count\"])\n}\n  \n// Multiple listener\n{\n    hello: useProps(),\n    count: useProps(),\n\tlogHello: useEffect((state, props) => {\n    \tconsole.log(props)\n    }, [\"count\", \"count\"])\n}\n```\n  \n## Milk DOM In depth\nMilk DOM cover a lot of thing under the cover but the main concept is to compare and diff DOM Node aimming for lesser iteration as possible (Same idea with VDOM). Instead of constructing an object node representation of DOM for comparing between two. Vanilla Milk heavily use Native Browser API comparing between each node instead of DOM and update it directly instead.\n\nSince Milk DOM is written in template string, it's very hard for Vanilla Milk to identify which textNode should replace Node or vice-versa. In this case, you shouldn't replace existed dom with blank text (\"\") like how React, Vue, other library does (which will sometime, occured an unexpected error). Instead Vanilla Milk offter a way to replace Node with blank Node by putting any element with attribute of `__hidden__`\n```javascript\nconst MilkCard = create(\n\t(display, { isOpen }, { title, cover, children }, events) => {\n\t\treturn display(`\n\t\t\t<main id=\"card\" tabIndex=0>\n\t\t\t\t<img id=\"cover\" src=\"${cover}\" alt=\"${title}\" />\n\t\t\t\t<section id=\"body\">\n\t\t\t\t\t<header id=\"header\">\n\t\t\t\t\t\t<h1 id=\"title\">${title}</h1>\n\t\t\t\t\t\t<button id=\"toggle\" @click=\"${events.toggleCard}\">+</button>\n\t\t\t\t\t</header>\n\t\t\t\t\t${\n\t\t\t\t\t\tisOpen\n\t\t\t\t\t\t\t? `<section id=\"detail\">${children}</section>`\n\t\t\t\t\t\t\t: `<input @hidden />`\n\t\t\t\t\t}\n\t\t\t\t</section>\n\t\t\t</main>\n\t\t`)\n\t},\n\t{\n\t\ttitle: useProps(),\n\t\tcover: useProps(),\n\t\tisOpen: useState(false),\n\t\tcardStyle: useStyleSheet(\"/card.css\")\n\t},\n\t([state, set], props) => {\n\t\tlet toggleCard = () => set.isOpen(!state.isOpen)\n\n\t\treturn { toggleCard }\n\t}\n)\n\n```\n\nMilk DOM's diffing algorithm are seperated into 3 parts.\n* Diff - Diffing for the different attribute, child node, etc.\n* Hard Diff - When tagName are different, whole element node have to be replaced. Hard Diff take care of that preventing child node for being recursion.\n* Text Diff - Diffing for text different.\n  \n### Best practice\nTo prevent an unexpected update, it's recommend to contained textNode in an element where textNode is state.\n```javascript\nimport { create, useState } from \"vanilla-milk\"\n\n// Please don't\nlet notSoGood = create((display, { counter }) => {\n\treturn display(`\n\t\t<section>\n\t\t\t<h1>Counter: </h1>\n\t\t\t{counter}\n\t\t</section>\n\t`)\n})\n\n// Better~\nlet wellDone = create((display) => {\n\treturn display(`\n\t\t<section>\n\t\t\t<h1>\n\t\t\t\tCounter: {state}\n\t\t\t</h1>\n\t\t</section>\n\t`)\n})\n```\nNot only that storing textNode in an element are safer but also has better performance from prevent recursion between each node.\n  \n### Multiple node on root\nUnlike VDOM, Vanilla Milk use native DOM for diffing freeing root node from stucking with only one node on the top.\n\n```javascript\nimport { create } from \"vanilla-milk\"\n\n// This is ok\nlet multipleRootNode = create((display, { counter }) => {\n\treturn display(`\n\t\t<h1>Hello! I'm the root node!</h1>\n\t\t<h2>No way! I'm the root node too!</h2>\n\t\t<p>It's ok to use multiple root node in Vanilla Milk</p>\n\t`)\n})\n```\n\n## Encapsulation\nVanilla Milk use Shadow DOM to encapsulate logic and style. Preventing an unexpected change while working in multiple library.\n  \nTo use external stylesheet in Milk Component, you can assign stylesheet in the component instead\n```javascript\nimport { create, useStyleSheet } from \"vanilla-milk\"\n\n// Link stylesheet in component.\nlet coolCard = create((display, { counter }) => {\n\treturn display(`\n\t\t<div class=\"card\"></div>\n\t`)\n},\n{\n\tcardStyle: useStyleSheet(\"/card.css\")\n})\n\n// Or even define style tag inside\nlet coolCard = create(\n\t(display) => display(`\n\t\t<style>\n\t\t\t.card {\n\t\t\t\tdisplay: flex;\n\t\t\t\tflex-direction: column;\n\t\t\t\twidth: 300px;\n\t\t\t\tpadding: 20px 12px;\n\t\t\t\tborderRadius: 4px;\n\t\t\t\tbox-shadow: 0 4px 8px rgba(0,0,0,.25);\n\t\t\t}\n\t\t</style>\n\t\t<div class=\"card\">\n\t\t</div>\n\t`)\n)\n```\n  \nThat's pretty much it of Vanilla Milk. :tada::tada:","_id":"vanilla-milk@0.3.2-beta.4","dist":{"shasum":"552e824ad0c4af2d011546ebe00c564cf9a274c0","integrity":"sha512-u4ydSUJMh/LErdUzpdcdQOSB3EMVd9y2J4MDtrJskwhsCbZBy3oo+8OeqZMx0ARhOKPHCk1tdjz2QTFS7wcFJg==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.3.2-beta.4.tgz","fileCount":6,"unpackedSize":146650,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeE9Q/CRA9TVsSAnZWagAAR8YP/AxqS0AfYk7wN3Wf8mM2\n4TkydlaoiSjc3+3kqNzAmkwnhXfxTLQbQYy6zh3tfimabpGml2uAtKut1y9Q\nCxPmr+WjkWJaat/p1tXNbuawpiMHigSK5gj59TCq6odYHfan8SAXM6QahaWU\nQg8Il2qKdfltiN6jFCHg89+8FUf53qJVSDktlOkcZbk2iRb8YtuPQZOqmOKc\nQcUaWX/fDagsR9ewk766AGfVKE+P3Doqf2L5s0UBwv8QlSTUtNryXzlj9k9l\nlb0PayjhkEqJ0GeaHcTrK8iz+7jr/OLYusQnNYsZQT9h6rkDEid7eOLMIwXc\n8FW1BJQZe9ERJESWOC2gngZwM0/c2YIjUerTAJcdpoUTXIsOWqCOoS48fRqb\nSFhmGCHvOp85ESaPcSeC+ocnGDTKaT5mgoMDsYSW7kwXRPn48ETF4xHZ3YSO\n3wqKZkIHirxlJkX1bVyr0HhC/1YUfiWYP/awlSexi6T2yc9og5nHpjH0WWmY\nolPDYELF9JOlGMoAPV12atw0fu7zoc7icfmvutK4q8/eJjDaG4MgW+mRCDkQ\nyv/4+5xd9U2xowTl7ZkO/mWxEdv288Y8hCNINQB/pk0OH/hYIu7hmtcm4hrq\nTi0TnMgm1qD1gs/yv2hyEYNOSrIhF8PxE+HaGBlGTm6PJfTOtRUWc8eMTWun\n01OA\r\n=wGOL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHxT1bDm8uSzSqHK0wFpYYBxmnO4JDd3j1gIpwOo6JOzAiAsU5H2kx6dDfVQ9S8CKc9RxOGch39MuvoosoPc5F1a2w=="}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.3.2-beta.4_1578357822280_0.5071894441675417"},"_hasShrinkwrap":false},"0.3.3":{"name":"vanilla-milk","version":"0.3.3","description":"Simple library for building simple reactive web components.","main":"index.js","repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"},"license":"MIT","keywords":["vanilla milk","web component","vanilla milk js"],"_id":"vanilla-milk@0.3.3","dist":{"shasum":"63ffeabcb980ee4e917fcf73e4abde7f0a3a08d3","integrity":"sha512-ySve5PS8QFfG30Me2ZaMjk3PdIUEY9djWYSUfZevmgU9v2J1iH0ohMyaHiHK5ZV2HEHAJl7izzfvVzNWhJGLZA==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.3.3.tgz","fileCount":6,"unpackedSize":146979,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeFJezCRA9TVsSAnZWagAAReUP+gKpRS8x7jSGpofNLhIu\nkx2vTlqMpxtZF2DSpJzgwyAyZ0Af4Fb+3tUfwX6w11F5cac3hgNBNQEmdaE/\nq7tn9mP+Ob+ywK+AX+whj7NVnxCFBY0bILc6OcEQOckaGwKBKD1b5BcqN6dX\nJfjbYwyXGGM+ExgVLuEMv9Q5R5jdsgQ+VZxvuhuE/tE7jX8uTV1dtlfI4Qf+\nu9Bm37MoVxhFs5jjVRNeJBhMuX5xRg5WrEc+AnuA/UoXoNIULue479QQAWKz\nXay4JyuwMAwHDPeI641z3ECO0mcjbXQIp65pYSmv5wBERwD7tBa/ULcVbcXP\ncA5zvzo1YyqKaZCff6eDW8Vw2u7gosFd80n6qATylNDafhQTveRBDCJRAPqr\nBI1xy/7+CMqmeQhvOJVcKApksITLEN1PuwEHmbl5W0FLtlsCRblGCKWPwuce\nH04sPAQ07zgIi9fnoGwWROwx8gZ+CevLudc1jPDV96Y3h4ujjH/pQbOZwlVU\nAerGLP/Fpgna9brrvCIOUrw7KvquOxgQem8/MEAoSSxz0xyHkCfYZNL7Zjyg\nfN8RxJhgyfMqBWWxhX5j4zVEVznrPAB6O5wuNacXkiIuFATPwQHwmVDZ1Jmi\nNXR3nW/dz7HbfQaoicCw0+sMOAkkK7nF3Kzxjj0bXosOqXLnm0kWTx9kDQQC\nlJ6W\r\n=LAPa\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDOjavU9O0URwmFMB3mcfu40+kDJ2AHRbitUyhZlXH8wgIhAKmBqLOCDnOnL/CK6GGxAAx2aQ+sTUeFZD7JdNFr+kol"}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.3.3_1578407859018_0.41697472283418047"},"_hasShrinkwrap":false},"0.3.4":{"name":"vanilla-milk","version":"0.3.4","description":"Simple library for building simple reactive web components.","main":"index.js","repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"},"license":"MIT","keywords":["vanilla milk","web component","vanilla milk js"],"_id":"vanilla-milk@0.3.4","dist":{"shasum":"a2e6ab1c148600b38aa68e556a841b4a63ac3693","integrity":"sha512-4pR9TpQl5H+Zl3Xn3d+gqBJ6YNtAAfbFGyIT37nRY1qtwuvpCdo9RmGjk84k9Ks9Od5IbSCDDkaKnEPa+NEa7A==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.3.4.tgz","fileCount":6,"unpackedSize":146933,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeFScRCRA9TVsSAnZWagAADT8P/0tQGfj0fMpegeng7x6a\nlmIG2lqf+bjJB7uFFBzSCS6Sq0ICOJ/OSoBSBy8zphRVrqv386Lls+x6Sn3I\n2JZvKNRXA3P8ZsSKpy1nTdDwsvlmaOiVoAiz075HJEEuxW4mi3tqfONQsxbe\nnqfq2iagGAR+kuW8ERvMpP90zYN5IyHlnlt6yUNdki1djLCY1ae0bsNTo3sH\nVyHydB/ScQgDMpnl0CFyZPVxjsCcy09xiFduBL1NCyhbSEkO9Ip8/jB5Vix9\ncHDW8FS7tQsb5TCseUHwj0whkpyfcJLB72Ij374go9s6NYba3Vfdpf2VswB5\ncV75iDk1a0NvN41Jc1k6ZP0g1GXSoVobeUv6oJA9GMzx7hLENu1LbxTBAz3h\nPgnBddBFxwwSGAnVeUOOZViLpnifJW268mlV2yapnFWI9wFTtrVEsQD1KaqM\nCUnIo+p78vji1CDQS3dbC9leXXRbrrhB9Hre1wJCzvBkVhi2GK5CBGCg3x4x\nNVUpk39Y7NEEsfQ2YhkelaaRpSOQLmMCj7v38g+IwHfF5+LXJLu2BQ2BihAi\nLfSvnFnn/Ti2CorJ++roCxSNGPQyt4oW9JGd4k4CwOpVhkK4WcUFGaSmh+DG\nC0ekMdD4bFBl7kmMUZAu55AzESpe4QG1N6Yg2cz7+msvX2/oIO7ArDNJd5JX\nTkgE\r\n=f4MR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHbDzvPFXRK8Zik/lQPgibtvANqGdoP6L+afktcvoojaAiBovJ403IjffbhwX7OgTB3vE3OTXir/EK5SM9eXDboO1g=="}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.3.4_1578444561323_0.2585010281144804"},"_hasShrinkwrap":false},"0.4.0-alpha.0":{"name":"vanilla-milk","version":"0.4.0-alpha.0","description":"Simple library for building simple reactive web components.","main":"index.js","repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"},"license":"MIT","keywords":["vanilla milk","web component","vanilla milk js"],"readmeFilename":"README.md","readme":"# Vanilla Milk\nSimple library for building simple reactive web components.\n  \n## What is...\nVanilla Milk is a library which helps create to web component which can be used on anywhere! Embrace future of web-component made it future-proof. Built-in reactive state and props but also is very small and fast.\n\nVanilla Milk feature:\n* Reusable component.\n* Simple way for creating web components.\n* Milk DOM, a special implementation of DOM manipulation.\n* Reactive state and props.\n* No class, just function.\n* Life-cycle hooks.\n* Expressive Vanilla like API structure.\n* Very small (2.4kB gzipped on production).\n* Encapsulated style, ID and class name.\n* Zero dependencies.\n* TypeScript support.\n\n## Milk DOM\nVanilla Milk doesn't use Virtual DOM, instead it has its own `Milk DOM` which share the same idea with Virtual Dom, update where neccessary. Unlike VDOM, Milk DOM use a collection of Native Browser API to perform diffing instead of creating long list of object which also prevent heavy recursion.\nDrawback is diffing algorithm isn't as deep as Virtual DOM does but Milk DOM is blazing fast and has less memory consumption.\n###### Note: Milk DOM is in an very early stage of development, you might experience some bug and when that time came, you can always open the issue on this repo.\n  \n## Getting started\nGlad you're interested in! Let's get over quick start! Let us add library just for creating a component, after the component has been built, you don't have to install it anymore! Just moved the built components to your any project~\n\n### Install Vanilla Milk\nLet install this real quick with package manager of your choice.\n```bash\n// Using npm\nnpm install vanilla-milk --save\n\n// Using yarn\nyarn add vanilla-milk\n```\nWell done! Now you're ready to create a Milk Component! (Shortname for Vanilla Milk Component for the greater good.)\n  \n### Hello World! It's Milk Component!\nLet's start by building `milk-component', a traditional hello world for programmer but as web component.\n\nMilk Component are separated into 2 step:\n1) Define it with `create`\n2) Create it with `define`\n\nJust 2 step, that's all for building reactive web component.\n\n#### Create\nFirst of all, import `create` function from vanilla-milk. This function is responsible to create a model of component.\n```javascript\nimport { create } from \"vanilla-milk\"\n```\n\nFirst parameter is a callback to display HTML Element.\n```javascript\nimport { create } from \"vanilla-milk\"\n\nconst MilkComponent = create((display) => \n    display(`<h1>Hello World! Milk Component!</h1>`)\n)\n```\nWe have just create `MilkComponent` which will return `<h1>Hello World</h1>`  \n\n### Define\nNext we just have to `define` this component, so it can work like every HTML Element.  \nBut first, import `define` from `vanilla-milk`\n```javascript\nimport { define } from \"vanilla-milk\"\n```\n\nNow let's name the component `milk-element`, so it can be use in HTML. (Web Component need `-` to be declared, like `milk-component` which has `-` in it)\n```javascript\nimport { create, define } from \"vanilla-milk\"\n\nconst MilkComponent = create((display) => \n    display(`<h1>Hello World! Milk Component!</h1>`)\n)\n\ndefine(\"milk-component\", MilkComponent)\n```\nThat's it! You have just created a Milk Component!! :tada::tada:\n  \n#### Milk Component in action\nSoooo~ We have just created a web component, let's see it in action!  \nJust add `<milk-component></milk-component>` in HTML. Make sure you've link the JavaScript file which contain milk component in it. You can use quick set-up like `parcel`.\n```html\n<!-- Any HTML here -->\n<html>\n<head>\n\t<title>Hello Milk Component</title>\n    <script src=\"milk_component_here.js\"></script>\n</head>\n<body>\n\t<milk-component></milk-component>\n</body>\n</html>\n```\nAnd it should display something like this.\n    \n#### But that's not what make Vanilla Milk special...\nIn Vanilla Milk, component are reactive which mean every time `state` or `props` changed, Milk Component will know it.\n\n## State\nLike `angular`, `react` and `vue`, Vanilla Milk also has `state`.  \nState is like a variable which are responsible for storing data and display it to view.\n\nLet's say we want to create a counter and display count to view. In Vanilla Milk we do like this.\n  \nIf you're familiar with React, we have `useState`. But it's not like what you might think.\n```javascript\nimport { useState } from 'vanilla-milk'\n```\nVanilla Milk are designed to be expressive. So we separate the state, props and life-cycle to the second parameter of `create` like this.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n    let { count } = state\n    \n    return display(`<h1>Count ${count}</h1>`)\n},\n{\n    counter: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nSo, what's happend here?\n  \nThe second parameter of `create` are responsible for handling data, so we can separate and focus on each part.\n```\n{\n    count: useState(0)\n}\n```\nHere we defined state name `count` with value of `0`. `useState` is a function that say, \"Hey! We want a state name 'count' with value of 0\" to Vanilla Milk or something like that. Vanilla Milk will just handle the rest of that and pass the `count` to the `second parameter` of the view callback.\n```\nconst MilkComponent = create((display, state) => {\n    console.log(state) // { count: 0 }\n},\n{\n    count: useState(0)\n})\n```\nLastly, we display counter to the view.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n    return display(`<h1>Count ${state.count}</h1>`)\n},\n{\n    count: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nNow that will display `count` to HTML, so... how do we set it in Vanilla Milk?\n  \nAs an early state of development of Vanilla Milk that's where the last parameter of `create` kick in!  \nWe add button and attach event in to it, so we can change the value of `counter`. // Hey don't make face of disappointment like that! I'll fix it in some next update, I promise! It's quite hard to create something like that ya know.\n  \nLet add a button.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n    return display(`\n        <h1>Count ${state.count}</h1>\n        <button id=\"increase-count\">Increase count</button>\n\t`)\n},\n{\n    count: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nVanilla Milk is declarative, this is where the last parameter come in!  \nYou define any `events` you want here! It's take callback function so you're free to define everything like normal JavaScript here. Vanilla Milk called this parameters as `useEvents`.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state, _, events) => {\n    console.log(events) // { increaseCount: \"increaseCount\" }\n\n    return display(`\n        <h1>Count ${state.count}</h1>\n        <button id=\"increase-count\" @click=\"${events.increaseCount}\">Increase count</button>\n\t`)\n},\n{\n    count: useState(0)\n},\n([state, set], _) => {\n    let increaseCount = () => set.count(state.count + 1)\n    \n    return { increaseCount }\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\n`useEvents` take an callback which pass `[state, set]` which are used to access state and set the state. Receive `props` and second parameter. \n###### *props will be explained in next section.\n```javascript\n([state, set], props) => {\n    let increaseCount = () => set.count(state.count + 1)\n    \n    return { increaseCount }\n})\n```\nYou might notice something there's `@click` in `button`, Vanilla Milk use pseudo attribute and match event to the node. This pseudo attribute take an export events name in `useEvents`.\n```javascript\n<button id=\"increase-count\" @click=\"${events.increaseCount}\">\n    Increase count\n</button>\n```\nNow everytime the button that as `@click` will run the function match to exports in `useEvents`, in this case it's `increaseCount`\n```javascript\nlet increaseCount = () => set.count(state.count + 1)\n\nreturn { increaseCount }\n```\nAt here we get value of `count` from `state.count` and set it with `set.count` which came out with something like this:\n```javascript\nset.count(0 + 1) // Count is now 1\n```\nNow it should increase the value of count everytime we click it!\n\nThat's it! You've just achieve an advance concept like state of Vanilla Milk :tada::tada:\n\n## Props\nContrast to state, it's super simple. props is shorten for `properties`. A property is like a HTML attribute. For a button like:\n```html\n<button class=\"nice-button\">Hello! I'm a button</button>\n```\nclass is a props of this button and it's value is \"nice-button\".\n  \nAs Milk Component, we also can have something like that! and guess what? You can create any attribute you like effortlessly!\n  \nAll you have to do is import `useProps` from `vanilla-milk` and set it like `useState`.\n```javascript\nimport { useProps } from \"vanilla-milk\"\n```\nNow let's say that we want to have a prop name `hello`. Like `useState` we do it like this:\n```javascript\n{\n    count: useState(0),\n    hello: useProps()\n}\n```\nAnd access it like state\n```javascript\ncreate((display, state, props) => {\n    console.log(props.hello) // null if there's no value passed\n})\n```\nSo let's define the component real quick to see how it work.\n```javascript\nimport { create, define, useProps } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state, props) => {\n    return display(`<h1>hello ${props.hello}</h1>`)\n},{\n    hello: useProps()\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nAnd in HTML\n```html\n<milk-component hello=\"world\"></milk-component> // hello world\n```\nThe reason we have to define `props` so that Vanilla Milk can just update and listen only to the props you used! \n  \nBut there's one special props which is always available... `children`\nChildren is any text or HTML Element between the Milk Component.\nIn HTML:\n```html\n<milk-component>Hello World</milk-component>\n```\nAnd access it:\n```javascript\nconst MilkComponent = create((display, state, props) => {\n    console.log(props.children) // Hello World\n})\n```\nThat's it! Unlike `useState`, `useProps` is super to use! :tada::tada:\n\n## useEffect\nLike React, you can defined lifecycle with `useEffect`.\n  \nLet's say, that you want to `console.log()` everytime prop `hello` change. You just have to import `useEffect` from `vanilla-milk`.\n```javascript\nimport { useEffect } from \"vanilla-milk\"\n```\nAgain, add it to second paramter of `create` like `useState` and `useProps`\n```javascript\n{\n    hello: useProps(),\n    logHello: useEffect((state, props) => {\n        console.log(props.hello) // Log everytime hello changed\n    }, [\"hello\"])\n}\n```\nNotice that we add array contain \"hello\" as string as the second parameter of useEffect.\nBecause we can't directly access value of hello so we just add it as string, Vanilla Milk will take care of the rest (In fact, we can add it as variable but it takes an extra effort and performance cost).\n\nYou can express name of `useEffect` as anything, It just easier to remind you lifecycle with name if there are too much lifecycle.\n\nNow we hello is changed, first callback will run. Like view callback, useEffect is paired with `(state, props)`. You can directly access it in the callback.\n\n`useEffect` is not only limited to state but props too! You can also add `useEffect` as much as you want or many listener as much as you need!\n```javascript\n// State and Props\n{\n    hello: useProps(),\n    count: useState(),\n    logHello: useEffect((state, props) => {\n        console.log(props)\n    }, [\"count\"])\n}\n  \n// Multiple listener\n{\n    hello: useProps(),\n    count: useProps(),\n    logHello: useEffect((state, props) => {\n        console.log(props)\n    }, [\"count\", \"count\"])\n}\n```\n## useShareState\nIn medium to large architect JavaScript app. Shared state is very common. Mostly we add library which is responsible for share state with a common idea of store. eg: Redux.\n  \nIn Vanilla Milk, share state is built-in and it's easier than using a storage. All it need to do is to define state with `useState` and wrap it with `useShareState`.\n```javascript\nlet sharedTea = useShareState({\n    sugar: useState(1),\n    amount: useState(100)\n})\n```\nAnd then add to `data` layer like normal state. Make sure that `useShareState` isn't call in `data layer` otherwise it won't be able to share.\n```javascipt\nlet sharedTea = useShareState({\n    sugar: useState(1),\n    amount: useState(100)\n})\n\nconst DisplaySugar = create(\n    (display, _, props) =>\n        display(`<h1>${props.sugar}</h1>`),\n    {\n        sharedStateFromWithComponent: sharedTea\n    }\n)\n```\nWhen state is shared, it'll act perfectly like local state unless it will update when itself is updated on other component.\n```javascipt\nlet sharedTea = useShareState({\n    sugar: useState(1),\n    amount: useState(100)\n})\n\nconst DisplaySugar = create(\n    (display, { sugar }) =>\n        // Will update when set.sugar on other component is fired\n        display(`<h1>${sugar}</h1>`),\n    {\n        sharedStateFromWithComponent: sharedTea\n    }\n)\n\nconst UpdateSugarButton = create(\n    (display, _, props) =>\n        display(`<button @click=\"addMoreSugar\">Add more sugar</button>`),\n    {\n        /* You can defined any state name you want, even \n           if it's not the same with other component      */\n\n        sharedStateFromWithComponent: sharedTea\n    },\n    ([{ sugar }, set) => {\n    \tlet addMoreSugar = () => set.sugar(sugar + 1) // When this is clicked, displa\n        \n        return { addMoreSugar }\n    }\n)\n```\n  \n## Milk DOM In depth\nMilk DOM cover a lot of thing under the cover but the main concept is to compare and diff DOM Node aimming for lesser iteration as possible (Same idea with VDOM). Instead of constructing an object node representation of DOM for comparing between two. Vanilla Milk heavily use Native Browser API comparing between each node instead of DOM and update it directly instead.\n\nSince Milk DOM is written in template string, it's very hard for Vanilla Milk to identify which textNode should replace Node or vice-versa. In this case, you shouldn't replace existed dom with blank text (\"\") like how React, Vue, other library does (which will sometime, occured an unexpected error). Instead Vanilla Milk offter a way to replace Node with blank Node by putting any element with attribute of `__hidden__`\n```javascript\nconst MilkCard = create(\n    (display, { isOpen }, { title, cover, children }, events) => {\n        return display(`\n            <main id=\"card\" tabIndex=0>\n                <img id=\"cover\" src=\"${cover}\" alt=\"${title}\" />\n                <section id=\"body\">\n                    <header id=\"header\">\n                        <h1 id=\"title\">${title}</h1>\n                        <button id=\"toggle\" @click=\"${events.toggleCard}\">+</button>\n                    </header>\n                    ${\n                        isOpen\n                            ? `<section id=\"detail\">${children}</section>`\n                            : `<input @hidden />`\n                    }\n                </section>\n            </main>\n        `)\n    },\n    {\n        title: useProps(),\n        cover: useProps(),\n        isOpen: useState(false),\n        cardStyle: useStyleSheet(\"/card.css\")\n    },\n    ([state, set], props) => {\n        let toggleCard = () => set.isOpen(!state.isOpen)\n\n        return { toggleCard }\n    }\n)\n```\n\nMilk DOM's diffing algorithm are seperated into 3 parts.\n* Diff - Diffing for the different attribute, child node, etc.\n* Hard Diff - When tagName are different, whole element node have to be replaced. Hard Diff take care of that preventing child node for being recursion.\n* Text Diff - Diffing for text different.\n  \n### Best practice\nTo prevent an unexpected update, it's recommend to contained textNode in an element where textNode is state.\n```javascript\nimport { create, useState } from \"vanilla-milk\"\n\n// Please don't\nlet notSoGood = create((display, { counter }) => {\n    return display(`\n        <section>\n            <h1>Counter: </h1>\n            {counter}\n        </section>\n    `)\n})\n\n// Better~\nlet wellDone = create((display) => {\n    return display(`\n        <section>\n            <h1>\n                Counter: {state}\n            </h1>\n        </section>\n    `)\n})\n```\nNot only that storing textNode in an element are safer but also has better performance from prevent recursion between each node.\n  \n### Multiple node on root\nUnlike VDOM, Vanilla Milk use native DOM for diffing freeing root node from stucking with only one node on the top.\n\n```javascript\nimport { create } from \"vanilla-milk\"\n\n// This is ok\nlet multipleRootNode = create((display, { counter }) => {\n    return display(`\n        <h1>Hello! I'm the root node!</h1>\n        <h2>No way! I'm the root node too!</h2>\n        <p>It's ok to use multiple root node in Vanilla Milk</p>\n    `)\n})\n```\n\n## Encapsulation\nVanilla Milk use Shadow DOM to encapsulate logic and style. Preventing an unexpected change while working in multiple library.\n  \nTo use external stylesheet in Milk Component, you can assign stylesheet in the component instead\n```javascript\nimport { create, useStyleSheet } from \"vanilla-milk\"\n\n// Link stylesheet in component.\nlet coolCard = create((display, { counter }) => {\n    return display(`\n        <div class=\"card\"></div>\n    `)\n},\n{\n    cardStyle: useStyleSheet(\"/card.css\")\n})\n\n// Or even define style tag inside\nlet coolCard = create(\n    (display) => display(`\n        <style>\n            .card {\n                display: flex;\n                flex-direction: column;\n                width: 300px;\n                padding: 20px 12px;\n                borderRadius: 4px;\n                box-shadow: 0 4px 8px rgba(0,0,0,.25);\n            }\n        </style>\n        <div class=\"card\">\n        </div>\n    `)\n)\n```\n  \nThat's pretty much it of Vanilla Milk. :tada::tada:","_id":"vanilla-milk@0.4.0-alpha.0","dist":{"shasum":"9471a49754c98ce8d7f27ea7d4dac7d6668f95d7","integrity":"sha512-Sms51tp1qtZEHRqgZdhSwFmUxKh4j6VzT9+Lr4XvdoydOqUjJzOJlIW+CbKnu6w/wMyfmyLl3T0C/PrDk+vCnw==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.4.0-alpha.0.tgz","fileCount":6,"unpackedSize":151754,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeGf+WCRA9TVsSAnZWagAAKv4P/1p5bs9WgKeXhwp/7g7M\nevzZ0IztejbMh52dUxORjtT8f87a52BVFXmRf3hC2xtjUqNcAEsblIdfWRun\nyZjgCZ3kghMZryvzgA8X//Ah7BbRDWPxo6Vba+VzZTtK4RwrR3ZbFeBlTUbk\nCsEF17Tw9G3/KxP3NUhRkHU7G8kCwypikGL+MYp6aLiR2XfwGOh4PDeyOsGR\nsz1PBhbSTppoaFPBjac3LDY8fh5KvKw84nb5VvmGdbP4sgP36e+YS1A84go9\n22cg/2m5sQ1tGSbL9GfANIgabQ1UYLYZoRImZNHdy/mRezAqNg1SbXUDG8b/\nDIZyMOLISQrypHkqrhXllQFZGeBDzPIIoP9xarMjVeGSyVsMRGW5bJp+atlZ\nQXCQ69HIPKqwpwgw5uPfNCcVDobQaCQakSWrhfG/FZu9hkPGFmtJRf3H77NS\nB2N5T+aaLfBQvLMASb9ErJF+4OWNjEDSrhlVRlRBFdR8qjf9UOuXpXg1TFg7\n+D9rTFgqoIgEauhWMGQ7jlrTwl5RTASyhxbyGw1S3yK8FFjdWKQb40zolnlX\nnbEEzQQgUjOt9VG4cBmknV7QAvbNyZdtTAa/WmiNPWKGtld+XSUSG+co4zWK\nf1aUEnNV2HS25Ez5Fm8Lo8i7qLSqhwrowUMYxQESxgpGRUMjMpEjjRJhtMgo\nq69c\r\n=Mk/6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD62uTT0zReUoDIsNpPZ7vldf/aZsL75X3u+5huf3Q3/wIhAL2aIb9IdlcJXHJHmf4rYOEyddXD0aBCYaB/uD50GBfq"}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.4.0-alpha.0_1578762133461_0.971110453297588"},"_hasShrinkwrap":false},"0.4.0-beta.0":{"name":"vanilla-milk","version":"0.4.0-beta.0","description":"Simple library for building simple reactive web components.","main":"index.js","repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"},"license":"MIT","keywords":["vanilla milk","web component","vanilla milk js"],"_id":"vanilla-milk@0.4.0-beta.0","dist":{"shasum":"0bedaee384b580548001ca57814a9a472597af9b","integrity":"sha512-7ORoxmG8oBOAzpsMMozJQEBpdFKE32xQ3XvrlLGEy7KkAQiy2baXZ6W+UE2KH7MDipKSoPC/Lsl4yWr2G4X6ig==","tarball":"https://registry.npmjs.org/vanilla-milk/-/vanilla-milk-0.4.0-beta.0.tgz","fileCount":6,"unpackedSize":152698,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeOZT+CRA9TVsSAnZWagAAGk8P/0B5P4JMmWNuX89HTZFL\noMEicbYK9a6wtXmmFqVsEDRySvNEpNb8wUvj6SIlVUD1dL+08CVJnj/3I3oE\nFWK/8KvtoikUlPJlPxmKcCCs5LrPO1n3yXMlSDDylGuPiFujdIgkzd4/NV5f\nJ61/N2jK/eoUmhdfYWbE8PsSO6HTbImX+tudHU3cW3KRaDFgLeIFeJMUlE/F\nItQ0+1M2mjFN9+LYJncA3syJH6QB1QARLdCMbR/GMmduY1T1RVHpEwrb8JA9\nckgQEEGeNCDLteVueVoA7+EGkPWDEE8oZl+qUgDPJW+DZmLi2y1TVRlX0+o1\n92SlvY5ghReVGFpRyGrG6TCop6Qjf5gBOTle3q4UCNjmxuIUq0EYn3pfSxFp\nxPlrmjKJhFRWSdZg0Oy8b9O+ckpBTzfKAEe23tdfDjm7ZnPNuAE0GvKD0DN8\ngfK5ihYVMEkrlPUq3q8Oe4aIJ/MyTwqOXN0wmIOXEc9m5MfSantwD1m1kSpm\n1c8ismVGIxZG4elmn54CH+5rOmT/xKm5lMJL75yfZGOS2iKCdmACelwCC8el\nPoCjvS2+RaF/5dkR/OI6OBH8t87pi30MHvPxHbew49iWKCL4UhP96cgzdJnT\nE9wKiajRKRPm22gje7zesMtO9lsWMpNDmniuI17G8zYyKPAMMrdTeytIHjKu\nk4hw\r\n=bTaX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBJ27nWlIGDjrtZf6yv8WQ43EbIKABXNROTkKsLnphSHAiBKWoekj6QSuKGHlexBgguMz/NL2iczoiE1lcmaWvNxzA=="}]},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"_npmUser":{"name":"aomkirby123","email":"aomkirby123@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vanilla-milk_0.4.0-beta.0_1580831998423_0.5872514864411209"},"_hasShrinkwrap":false}},"time":{"created":"2019-12-29T15:54:12.759Z","0.0.1":"2019-12-29T15:54:12.939Z","modified":"2022-05-23T03:03:41.879Z","0.1.0":"2019-12-30T07:59:11.905Z","0.1.1":"2019-12-30T14:41:12.007Z","0.1.2-beta.0":"2020-01-01T18:25:46.696Z","0.2.0":"2020-01-02T12:37:31.094Z","0.3.0-beta.0":"2020-01-05T05:42:52.712Z","0.3.0-beta.1":"2020-01-05T05:46:38.023Z","0.3.0-beta.2":"2020-01-05T14:42:03.225Z","0.3.0-beta.3":"2020-01-05T15:14:55.753Z","0.3.0-beta.4":"2020-01-05T15:27:21.337Z","0.3.0-beta.5":"2020-01-05T15:33:45.756Z","0.3.0":"2020-01-05T15:35:38.924Z","0.3.1":"2020-01-06T00:12:40.894Z","0.3.1-beta.0":"2020-01-06T11:46:31.276Z","0.3.2-beta.0":"2020-01-06T11:51:07.121Z","0.3.2-beta.1":"2020-01-06T15:56:54.581Z","0.3.2-beta.2":"2020-01-07T00:09:47.814Z","0.3.2-beta.3":"2020-01-07T00:11:38.838Z","0.3.2-beta.4":"2020-01-07T00:43:42.883Z","0.3.2":"2020-01-07T12:53:45.051Z","0.3.3":"2020-01-07T14:37:39.232Z","0.3.4":"2020-01-08T00:49:21.439Z","0.4.0-alpha.0":"2020-01-11T17:02:13.605Z","0.4.0-beta.0":"2020-02-04T15:59:58.551Z"},"maintainers":[{"name":"aomkirby123","email":"aomkirby123@gmail.com"}],"description":"Simple library for building simple reactive web components.","license":"MIT","readme":"# Vanilla Milk\nSimple library for building simple reactive web components.\n  \n## What is...\nVanilla Milk is a library which helps create to web component which can be used on anywhere! Embrace future of web-component made it future-proof. Built-in reactive state and props but also is very small and fast.\n\nVanilla Milk feature:\n* Reusable component.\n* Simple way for creating web components.\n* Milk DOM, a special implementation of DOM manipulation.\n* Reactive state and props.\n* No class, just function.\n* Life-cycle hooks.\n* Expressive Vanilla like API structure.\n* Very small (2.4kB gzipped on production).\n* Encapsulated style, ID and class name.\n* Zero dependencies.\n* TypeScript support.\n\n## Milk DOM\nVanilla Milk doesn't use Virtual DOM, instead it has its own `Milk DOM` which share the same idea with Virtual Dom, update where neccessary. Unlike VDOM, Milk DOM use a collection of Native Browser API to perform diffing instead of creating long list of object which also prevent heavy recursion.\nDrawback is diffing algorithm isn't as deep as Virtual DOM does but Milk DOM is blazing fast and has less memory consumption.\n###### Note: Milk DOM is in an very early stage of development, you might experience some bug and when that time came, you can always open the issue on this repo.\n  \n## Getting started\nGlad you're interested in! Let's get over quick start! Let us add library just for creating a component, after the component has been built, you don't have to install it anymore! Just moved the built components to your any project~\n\n### Install Vanilla Milk\nLet install this real quick with package manager of your choice.\n```bash\n// Using npm\nnpm install vanilla-milk --save\n\n// Using yarn\nyarn add vanilla-milk\n```\nWell done! Now you're ready to create a Milk Component! (Shortname for Vanilla Milk Component for the greater good.)\n  \n### Hello World! It's Milk Component!\nLet's start by building `milk-component', a traditional hello world for programmer but as web component.\n\nMilk Component are separated into 2 step:\n1) Define it with `create`\n2) Create it with `define`\n\nJust 2 step, that's all for building reactive web component.\n\n#### Create\nFirst of all, import `create` function from vanilla-milk. This function is responsible to create a model of component.\n```javascript\nimport { create } from \"vanilla-milk\"\n```\n\nFirst parameter is a callback to display HTML Element.\n```javascript\nimport { create } from \"vanilla-milk\"\n\nconst MilkComponent = create((display) => \n    display(`<h1>Hello World! Milk Component!</h1>`)\n)\n```\nWe have just create `MilkComponent` which will return `<h1>Hello World</h1>`  \n\n### Define\nNext we just have to `define` this component, so it can work like every HTML Element.  \nBut first, import `define` from `vanilla-milk`\n```javascript\nimport { define } from \"vanilla-milk\"\n```\n\nNow let's name the component `milk-element`, so it can be use in HTML. (Web Component need `-` to be declared, like `milk-component` which has `-` in it)\n```javascript\nimport { create, define } from \"vanilla-milk\"\n\nconst MilkComponent = create((display) => \n    display(`<h1>Hello World! Milk Component!</h1>`)\n)\n\ndefine(\"milk-component\", MilkComponent)\n```\nThat's it! You have just created a Milk Component!! :tada::tada:\n  \n#### Milk Component in action\nSoooo~ We have just created a web component, let's see it in action!  \nJust add `<milk-component></milk-component>` in HTML. Make sure you've link the JavaScript file which contain milk component in it. You can use quick set-up like `parcel`.\n```html\n<!-- Any HTML here -->\n<html>\n<head>\n\t<title>Hello Milk Component</title>\n    <script src=\"milk_component_here.js\"></script>\n</head>\n<body>\n\t<milk-component></milk-component>\n</body>\n</html>\n```\nAnd it should display something like this.\n    \n#### But that's not what make Vanilla Milk special...\nIn Vanilla Milk, component are reactive which mean every time `state` or `props` changed, Milk Component will know it.\n\n## State\nLike `angular`, `react` and `vue`, Vanilla Milk also has `state`.  \nState is like a variable which are responsible for storing data and display it to view.\n\nLet's say we want to create a counter and display count to view. In Vanilla Milk we do like this.\n  \nIf you're familiar with React, we have `useState`. But it's not like what you might think.\n```javascript\nimport { useState } from 'vanilla-milk'\n```\nVanilla Milk are designed to be expressive. So we separate the state, props and life-cycle to the second parameter of `create` like this.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n    let { count } = state\n    \n    return display(`<h1>Count ${count}</h1>`)\n},\n{\n    counter: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nSo, what's happend here?\n  \nThe second parameter of `create` are responsible for handling data, so we can separate and focus on each part.\n```\n{\n    count: useState(0)\n}\n```\nHere we defined state name `count` with value of `0`. `useState` is a function that say, \"Hey! We want a state name 'count' with value of 0\" to Vanilla Milk or something like that. Vanilla Milk will just handle the rest of that and pass the `count` to the `second parameter` of the view callback.\n```\nconst MilkComponent = create((display, state) => {\n    console.log(state) // { count: 0 }\n},\n{\n    count: useState(0)\n})\n```\nLastly, we display counter to the view.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n    return display(`<h1>Count ${state.count}</h1>`)\n},\n{\n    count: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nNow that will display `count` to HTML, so... how do we set it in Vanilla Milk?\n  \nAs an early state of development of Vanilla Milk that's where the last parameter of `create` kick in!  \nWe add button and attach event in to it, so we can change the value of `counter`. // Hey don't make face of disappointment like that! I'll fix it in some next update, I promise! It's quite hard to create something like that ya know.\n  \nLet add a button.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state) => {\n    return display(`\n        <h1>Count ${state.count}</h1>\n        <button id=\"increase-count\">Increase count</button>\n\t`)\n},\n{\n    count: useState(0)\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nVanilla Milk is declarative, this is where the last parameter come in!  \nYou define any `events` you want here! It's take callback function so you're free to define everything like normal JavaScript here. Vanilla Milk called this parameters as `useEvents`.\n```javascript\nimport { create, define, useState } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state, _, events) => {\n    console.log(events) // { increaseCount: \"increaseCount\" }\n\n    return display(`\n        <h1>Count ${state.count}</h1>\n        <button id=\"increase-count\" @click=\"${events.increaseCount}\">Increase count</button>\n\t`)\n},\n{\n    count: useState(0)\n},\n([state, set], _) => {\n    let increaseCount = () => set.count(state.count + 1)\n    \n    return { increaseCount }\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\n`useEvents` take an callback which pass `[state, set]` which are used to access state and set the state. Receive `props` and second parameter. \n###### *props will be explained in next section.\n```javascript\n([state, set], props) => {\n    let increaseCount = () => set.count(state.count + 1)\n    \n    return { increaseCount }\n})\n```\nYou might notice something there's `@click` in `button`, Vanilla Milk use pseudo attribute and match event to the node. This pseudo attribute take an export events name in `useEvents`.\n```javascript\n<button id=\"increase-count\" @click=\"${events.increaseCount}\">\n    Increase count\n</button>\n```\nNow everytime the button that as `@click` will run the function match to exports in `useEvents`, in this case it's `increaseCount`\n```javascript\nlet increaseCount = () => set.count(state.count + 1)\n\nreturn { increaseCount }\n```\nAt here we get value of `count` from `state.count` and set it with `set.count` which came out with something like this:\n```javascript\nset.count(0 + 1) // Count is now 1\n```\nNow it should increase the value of count everytime we click it!\n\nThat's it! You've just achieve an advance concept like state of Vanilla Milk :tada::tada:\n\n## Props\nContrast to state, it's super simple. props is shorten for `properties`. A property is like a HTML attribute. For a button like:\n```html\n<button class=\"nice-button\">Hello! I'm a button</button>\n```\nclass is a props of this button and it's value is \"nice-button\".\n  \nAs Milk Component, we also can have something like that! and guess what? You can create any attribute you like effortlessly!\n  \nAll you have to do is import `useProps` from `vanilla-milk` and set it like `useState`.\n```javascript\nimport { useProps } from \"vanilla-milk\"\n```\nNow let's say that we want to have a prop name `hello`. Like `useState` we do it like this:\n```javascript\n{\n    count: useState(0),\n    hello: useProps()\n}\n```\nAnd access it like state\n```javascript\ncreate((display, state, props) => {\n    console.log(props.hello) // null if there's no value passed\n})\n```\nSo let's define the component real quick to see how it work.\n```javascript\nimport { create, define, useProps } from \"vanilla-milk\"\n\nconst MilkComponent = create((display, state, props) => {\n    return display(`<h1>hello ${props.hello}</h1>`)\n},{\n    hello: useProps()\n})\n\ndefine(\"milk-component\", MilkComponent)\n```\nAnd in HTML\n```html\n<milk-component hello=\"world\"></milk-component> // hello world\n```\nThe reason we have to define `props` so that Vanilla Milk can just update and listen only to the props you used! \n  \nBut there's one special props which is always available... `children`\nChildren is any text or HTML Element between the Milk Component.\nIn HTML:\n```html\n<milk-component>Hello World</milk-component>\n```\nAnd access it:\n```javascript\nconst MilkComponent = create((display, state, props) => {\n    console.log(props.children) // Hello World\n})\n```\nThat's it! Unlike `useState`, `useProps` is super to use! :tada::tada:\n\n## useEffect\nLike React, you can defined lifecycle with `useEffect`.\n  \nLet's say, that you want to `console.log()` everytime prop `hello` change. You just have to import `useEffect` from `vanilla-milk`.\n```javascript\nimport { useEffect } from \"vanilla-milk\"\n```\nAgain, add it to second paramter of `create` like `useState` and `useProps`\n```javascript\n{\n    hello: useProps(),\n    logHello: useEffect((state, props) => {\n        console.log(props.hello) // Log everytime hello changed\n    }, [\"hello\"])\n}\n```\nNotice that we add array contain \"hello\" as string as the second parameter of useEffect.\nBecause we can't directly access value of hello so we just add it as string, Vanilla Milk will take care of the rest (In fact, we can add it as variable but it takes an extra effort and performance cost).\n\nYou can express name of `useEffect` as anything, It just easier to remind you lifecycle with name if there are too much lifecycle.\n\nNow we hello is changed, first callback will run. Like view callback, useEffect is paired with `(state, props)`. You can directly access it in the callback.\n\n`useEffect` is not only limited to state but props too! You can also add `useEffect` as much as you want or many listener as much as you need!\n```javascript\n// State and Props\n{\n    hello: useProps(),\n    count: useState(),\n    logHello: useEffect((state, props) => {\n        console.log(props)\n    }, [\"count\"])\n}\n  \n// Multiple listener\n{\n    hello: useProps(),\n    count: useProps(),\n    logHello: useEffect((state, props) => {\n        console.log(props)\n    }, [\"count\", \"count\"])\n}\n```\n## useShareState\nIn medium to large architect JavaScript app. Shared state is very common. Mostly we add library which is responsible for share state with a common idea of store. eg: Redux.\n  \nIn Vanilla Milk, share state is built-in and it's easier than using a storage. All it need to do is to define state with `useState` and wrap it with `useShareState`.\n```javascript\nlet sharedTea = useShareState({\n    sugar: useState(1),\n    amount: useState(100)\n})\n```\nAnd then add to `data` layer like normal state. Make sure that `useShareState` isn't call in `data layer` otherwise it won't be able to share.\n```javascipt\nlet sharedTea = useShareState({\n    sugar: useState(1),\n    amount: useState(100)\n})\n\nconst DisplaySugar = create(\n    (display, _, props) =>\n        display(`<h1>${props.sugar}</h1>`),\n    {\n        sharedStateFromWithComponent: sharedTea\n    }\n)\n```\nWhen state is shared, it'll act perfectly like local state unless it will update when itself is updated on other component.\n```javascipt\nlet sharedTea = useShareState({\n    sugar: useState(1),\n    amount: useState(100)\n})\n\nconst DisplaySugar = create(\n    (display, { sugar }) =>\n        // Will update when set.sugar on other component is fired\n        display(`<h1>${sugar}</h1>`),\n    {\n        sharedStateFromWithComponent: sharedTea\n    }\n)\n\nconst UpdateSugarButton = create(\n    (display, _, props) =>\n        display(`<button @click=\"addMoreSugar\">Add more sugar</button>`),\n    {\n        /* You can defined any state name you want, even \n           if it's not the same with other component      */\n\n        sharedStateFromWithComponent: sharedTea\n    },\n    ([{ sugar }, set) => {\n    \tlet addMoreSugar = () => set.sugar(sugar + 1) // When this is clicked, displa\n        \n        return { addMoreSugar }\n    }\n)\n```\n  \n## Milk DOM In depth\nMilk DOM cover a lot of thing under the cover but the main concept is to compare and diff DOM Node aimming for lesser iteration as possible (Same idea with VDOM). Instead of constructing an object node representation of DOM for comparing between two. Vanilla Milk heavily use Native Browser API comparing between each node instead of DOM and update it directly instead.\n\nSince Milk DOM is written in template string, it's very hard for Vanilla Milk to identify which textNode should replace Node or vice-versa. In this case, you shouldn't replace existed dom with blank text (\"\") like how React, Vue, other library does (which will sometime, occured an unexpected error). Instead Vanilla Milk offter a way to replace Node with blank Node by putting any element with attribute of `__hidden__`\n```javascript\nconst MilkCard = create(\n    (display, { isOpen }, { title, cover, children }, events) => {\n        return display(`\n            <main id=\"card\" tabIndex=0>\n                <img id=\"cover\" src=\"${cover}\" alt=\"${title}\" />\n                <section id=\"body\">\n                    <header id=\"header\">\n                        <h1 id=\"title\">${title}</h1>\n                        <button id=\"toggle\" @click=\"${events.toggleCard}\">+</button>\n                    </header>\n                    ${\n                        isOpen\n                            ? `<section id=\"detail\">${children}</section>`\n                            : `<input @hidden />`\n                    }\n                </section>\n            </main>\n        `)\n    },\n    {\n        title: useProps(),\n        cover: useProps(),\n        isOpen: useState(false),\n        cardStyle: useStyleSheet(\"/card.css\")\n    },\n    ([state, set], props) => {\n        let toggleCard = () => set.isOpen(!state.isOpen)\n\n        return { toggleCard }\n    }\n)\n```\n\nMilk DOM's diffing algorithm are seperated into 3 parts.\n* Diff - Diffing for the different attribute, child node, etc.\n* Hard Diff - When tagName are different, whole element node have to be replaced. Hard Diff take care of that preventing child node for being recursion.\n* Text Diff - Diffing for text different.\n  \n### Best practice\nTo prevent an unexpected update, it's recommend to contained textNode in an element where textNode is state.\n```javascript\nimport { create, useState } from \"vanilla-milk\"\n\n// Please don't\nlet notSoGood = create((display, { counter }) => {\n    return display(`\n        <section>\n            <h1>Counter: </h1>\n            {counter}\n        </section>\n    `)\n})\n\n// Better~\nlet wellDone = create((display) => {\n    return display(`\n        <section>\n            <h1>\n                Counter: {state}\n            </h1>\n        </section>\n    `)\n})\n```\nNot only that storing textNode in an element are safer but also has better performance from prevent recursion between each node.\n  \n### Multiple node on root\nUnlike VDOM, Vanilla Milk use native DOM for diffing freeing root node from stucking with only one node on the top.\n\n```javascript\nimport { create } from \"vanilla-milk\"\n\n// This is ok\nlet multipleRootNode = create((display, { counter }) => {\n    return display(`\n        <h1>Hello! I'm the root node!</h1>\n        <h2>No way! I'm the root node too!</h2>\n        <p>It's ok to use multiple root node in Vanilla Milk</p>\n    `)\n})\n```\n\n## Encapsulation\nVanilla Milk use Shadow DOM to encapsulate logic and style. Preventing an unexpected change while working in multiple library.\n  \nTo use external stylesheet in Milk Component, you can assign stylesheet in the component instead\n```javascript\nimport { create, useStyleSheet } from \"vanilla-milk\"\n\n// Link stylesheet in component.\nlet coolCard = create((display, { counter }) => {\n    return display(`\n        <div class=\"card\"></div>\n    `)\n},\n{\n    cardStyle: useStyleSheet(\"/card.css\")\n})\n\n// Or even define style tag inside\nlet coolCard = create(\n    (display) => display(`\n        <style>\n            .card {\n                display: flex;\n                flex-direction: column;\n                width: 300px;\n                padding: 20px 12px;\n                borderRadius: 4px;\n                box-shadow: 0 4px 8px rgba(0,0,0,.25);\n            }\n        </style>\n        <div class=\"card\">\n        </div>\n    `)\n)\n```\n  \nThat's pretty much it of Vanilla Milk. :tada::tada:","readmeFilename":"README.md","keywords":["vanilla milk","web component","vanilla milk js"],"repository":{"type":"git","url":"https://github.com/SaltyAom/vanilla-milk"},"author":{"name":"SaltyAom"}}