neko-vue 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,616 @@
1
+ import { r as DEFAULT_NEKO_BEHAVIOR_CYCLE } from "./types-Ctrldouo.mjs";
2
+ //#region src/runtime/nekoSpritesData.ts
3
+ /**
4
+ * Embedded sprite data (base64 PNG data URLs). Third-party runtime licensing: see repo `LICENSE`.
5
+ */
6
+ const NEKO_SPRITES = [
7
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABIklEQVR4nO1WSQ7EMAiDUf//ZeYwoguYLdVIPdSnqklsB0gI0QsMeQJntKAiQuPLG7ILRUQkIUTjqfinMMCI4KcBzUUcpYFsV0oQCTgEBi9TdFwNMB27bakYka455Vc9l4LISCYAB6xBK6zYAtI0b0akg5CvKkLMxpgv+p9hIx/COUsfTmv7s6CF01pKQZT7QU3siIoQ4pxjFWPmy/fUzCT87YvoZKbkn6SAu1XeFW9PMtjDcI6IMWd5BfwjorUidLdZMSZZb1g6BQTqYdghbxkISaMGldXEtAZaJwEczVu9oN2ikZEKlQERkfSBkTWmam1l4BJudNtlhsDa+6dg+CRrIe0FaDdTVBGLIiAqnIkreSZiOBxZtHKyZfh0L+a/eA6+YR662bT+YjsAAAAASUVORK5CYII=",
8
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA40lEQVR4nO1XyxLDIAiUTv7/l+mhsfUBsogZM233ZkZ2F2SIUpoHN2uaIUGDWrHEXH8iEqlMfq9rboU7wpcRmPeBCpfiUrb527mHk1C1iIGu5Kv2wgauAnJW5rmr5EA/QAYERyNBl8b2CiA9QG1m1hoVhzacqEogVeTqQcSasEj6MRM2oCqCo9jUGUVVWRORqwLC1BS1hk04I57jmtGsYvskNA14s88oqxAyMDuE0NiRgW4AzcAaSPfvgZ83EOqDVfeBlDb+C0Qj74V+SYV5D6eBknjJw+T2Tfj9BqKAX0B/aHgCdIBeOO78F8UAAAAASUVORK5CYII=",
9
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABDklEQVR4nO1Wyw4DIQiEpv//y/TQuEVXmBG3ySbtnFQQRuWhSh02zLViBG0anXwE1otUU1Oh8JE5907a2MxOzsf1yb7wIBmBzpiqduMRbc3MujECJDASuVqXJvAtQAL+6huiGBjnIDBFROQJNeT85tEVMw5LBNg3XUxNESGzYDSE5m2NIQ4L0YzAzPCMhNsb+qGfAJ3Iy9jT0wQ8iZnD5jSSXUIAGV5x6oGCUCup5TaLgDijK6GqUmnF6h36hM67nSWRD7Ji/wYiB60FRynIABGwanA5EqmB+3fDP4HbEph9WCtYKsUe7CcFYbcUqySF5tJSDAyXe8YygeRUJRJLBIgr3eqeGUxASd3U/2G8AFt7mTLOfRenAAAAAElFTkSuQmCC",
10
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABF0lEQVR4nO2W3Q6DMAiFYdn7vzK70E5KDpTS6s1GYqJt5XzlR8tUM1H3XPSx9LKIHAzMKRfuomUABKHn1DzUehUBoKCIkIh8gZhZwwl6970DAAExM4EoCR2RaBO8JQIRhH5utycEE21KQQQBrKuFbQCO2NBmAERd2fYb2sjLlTiwQ1tooZDTilEXyMh5NezavAgMxdMCV6qgFhrcLR6m+dY2zJgF2Lb7CsDj4hagZOaH040/AmD/gJbjdoBOrfB17ABWP6+VGrqlDTP9DwGqXbASuQbQKWuHXpXbta0QZ3avAciecpuzKCpaXA9nxRsAOmIzcAzFveesMQBonqC6dy4wPqcAtFj6gIJgZvM/vTiC2eTzbz9oHxxQekFCimcpAAAAAElFTkSuQmCC",
11
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABKUlEQVR4nOWX3Q7CMAiFD2bv/8p4sdGxFljpT7zwJMaoG+cDCpnAv4sWxOAZj1kABgBmBtEZivnJc33v+mQAmkxrs8q0XBNBpAAsQy9zB6jx+yQASGdWkYGIysu7H2cVH6RHAiCUVCAAEIiHMhW44sddi1qBuwKlElmAtBRwmRgNmQVgPXISsPNGs02ZM2BOgScPsp4Iq6HaRX5vzImoO3vPHHBaoMrFlrlcIwHr917z5sMd++5VNsvAPLUJl0BEG1BkHcL5lBFnreWeAb3j35bPqDnwrEBZFBbQDnN9YWrGV5kDiU2YbcNSgFXjOASw0xw4D6G5ZrMa6b8AvAXalz6qFoxmMXofMPBI5rRneEQKQE8WM5l6+uwK3KvjV8ai7Q+lq9T8oVilL9sKg2SESmbvAAAAAElFTkSuQmCC",
12
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABGElEQVR4nO2W3Q6DMAiFwfj+r8xupBLKb+vijSfZkilwPmmlA/j0snAhhzbzlwEIAIDo9kcc6csglcTJeCqyAZIlUGTsgLQgjk5wpgu2TpwAtJ6+AUHyvgewZF7QVNcC2DY3ukBeXQ0wgsTOdlWIGcaq7kiUABNhZkBEZgwiAptm3WQAMgbM8nDpLOG0B7rmXheieFBvgV53vGOffRMYVEIc6ubfzD0dhvl1qdZW3nD6Gn8qAAj2mpchLCC5rKr1UrR8GMmiVheqsCkAm0hTQbdlDgB4dhP1vKh0yDMfX77X/eRWF4Li4yfYJ+MISjtgbcTIWAwmTgyXOeyAiqFo6nmHTab2n1Ijz5ukjwNICDSurdT79Ol9/QD98LQSLfZm6wAAAABJRU5ErkJggg==",
13
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABBklEQVR4nO1V0Q6EMAiDi///y9yLLHUC66Ymd4lNTNQArQWcyIsfgMH1NM8JHxERMxMzS4OeIm8C2OBV8v3jUgGqqh55txMluQsQFOFCbhAxJEcBd4qwgvz0UqMgTAZRUWyZG2Gv12pFQ9hXRDeqdS2Zcc4wdhsJQCFQzB80i2HRO0ANTrAtVB4jYAozg4oCMY9uAVMYgRtVxV0WkIFtyaUWrAJXEX1aHiSS8PDKb6ZboKq0vcxPbJN9Gsk/2NKul3WlsD44G+YJBi4cBGSrwwrJXKpENAGYXAzN0AbPj4T2B1ET0CdHSglEdTI3QkvCA2YRp7YGR/zyl9IinK97fpr3xYs/wxfuy7Lj/kO2hgAAAABJRU5ErkJggg==",
14
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABHElEQVR4nO2WwRLDIAhEof//z9tLSJUAATTTQ7uHzKSi+6JIIfrry+JCLDat4060DGQcgO3PPHmXQUKDY/Ezhj7BU4y8q/gSQGig40bDFfNoAgyICc4wfw6gCNI+gluA1IJFiFfLJdABLvSg+PruB5hZXO8T7DEAZT7tyDjmAbAqMGmNSalAAECDhTtQgmDmi7kBcdHdEaQgxDh7c8abkskBlq9bkQeXTUKmhbyIVL0FJkS3aHUATMkRabi7dyJCB+CyC5KAACq5AiLi5R2wYLJTz0dTZl+Qci5ew2AdFhIzBwzTa14sAIjc5kXgjLF+B5OBsEAERvcLu/4NvSLFYiaAql94tB+YQLz82AnQKtX7i/vcgun14fz+w3oDTA6XRee9YIQAAAAASUVORK5CYII=",
15
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABDklEQVR4nO2WSxLDIAxDUaf3v7K7aEKJI/8I7abRMjHWsw0Mrf27kIiRYvwSgG4q8vEHDuFLYFgSGU3pIlDvKaCwA6cfBtwGVYaIFtBRmMkmILxgyRpfgXBHUDVXEMxD9LeHleSqOVlPN7cJ4CWPlDUvA4iICwGgZF4G8CCYuYiEoywDMBmVp2QBIDvvq1rSASZdgDodvV1fA8jqWV2g571X5px/SzIFcMpiGLIToYTWfjgCa1N7AKeTYLU/o9mbMH0coxtS7ZUenHoT6qr321BXFcCivTfeISizCQEgfKYNtCzBCHHQ1Cmwqnc6Yramct/2Loxmuu3qe5i/BLAbkFm7r55VAGPymbW3blG9AHEphjo0CJF9AAAAAElFTkSuQmCC",
16
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA80lEQVR4nO2WwRLDIAhEoZP//2V6qHZMdHGRNL24M7kosi+IjiI5WfmW9cqYm5mYWQV5HOAWbYC/AxzBeK/Z2jllE9KBUrqeSqpK52a3gDYvwSLk0WQAQuZRiBnAknkEInwKyv7S8zOIEICqiplBiNl8FACWf2RSzVG8gCrQFfAMGECk5ZuwNYnALQF4BuhP2SpEr+LOJCtUgXxmMi8C+FzmgePkqcnTJYQVqM+tEYR3D4zGvKeb24Q/qEAnCFAXZRutrkcQXg98V1y3ooXyxi/wp5zt4EynLExFBn8LfUIvom4AVCKSP9Nlo1Lc07VbW0/qDae6gB08t42YAAAAAElFTkSuQmCC",
17
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA+0lEQVR4nO1Wyw7EIAiEzf7/L7MXadTKY6gemuwkPRSFGVFBojykfZHNs9/wyZKLXPGktzV7TyZtcLY/EqCMW+fBAk4gI6BPf5RaZG5aQBaCpF7xLTK5/whecQb+ApiZS8Gbn+sMZyASg4qF6gAzk4iYJPP4sTqwEqHkKNICEAIvS2UBHkl19UTBCVUuJbw5d6sMxk2eUin2SFFYW5B+0QBYxrQyoCnbJULI2IboEC6dvDqAxMkIOI5UL3jI4fpng7tXsXoFiYAtsKobImoFqA7MInqSqChtEdAHZ+ZbRiqFCTlgQ1s2fDNzBrziGg7Y/SJCkekRJ/rIOfwAzH6TFVfg/LAAAAAASUVORK5CYII=",
18
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABA0lEQVR4nO2XzRKDMAiEwfH9X5kebDQSfhOcHurepDPuR8DVAvy78KH7UtSjEuA0Jbr8EW8Wg98KAA0FGkp3swPGJoqaa2as4+Fnt7BiroCU7kDIPAPCiyTUxeWqgth44WtCQs2bryoLfADwIDxlIUUAC8IyQMT0mFSAZshvqEHMmLsAFtjsPpQAZCUloARA2rZXdesB/EQbHJse3h5EPE+kP5nZvdjhmo2aeP31bBpqEkfw5MxDAJkuvTFYTwAHwH62XuIl4NKvY7d9fkItBXkaRgB2B2p4/1d2D+DnAHJDac4r0RwJohuEtScsSUNEGWzza6kBRL8FZwA8hf+MvHrV6wMLunpMS0n3sAAAAABJRU5ErkJggg==",
19
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABHUlEQVR4nO2WyxbDIAhEh578/y/TRWpKEFCRnm4yS19zeWgCPPqzaHM/756dBbiMmW0GIpLnW4sIAI6MeTP9mGjTm4Fcr9YyAEpnQEIoILLWeYBbJQggIOcdOAAFJWBmMLNrPNJqBsx6Thk5GXhFZrh3b855oAagzc7BM9prLhv9DEBnJsd/YdwBCIgGAj2n7/2svPp3ABLCirpBrIBE5npiqcPl3c+aA7l3YCiRoWGqygFmopaK3oFQzgdmybwB3E4afOGuJszeCK0DJ/FU90WNl4ke+JZgaqM2r8hCyTXMRg+oJmwRRZG1+leYWxu7j46GmfnJWFH3DnhvvlP/7SaQJbD+dMkyqTLXAGV1TQPMqBrObMJgvNT8EQC8AQ4mj0+E62kZAAAAAElFTkSuQmCC",
20
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABHElEQVR4nO2WwRLDIAhE2U7//5fppVjUFVHTaQ/ZmVwSw74gEEVu/Vi4KI7uxjwFUBER1Y8/UEKmYu8CdMZd4CTIDoBGxgOQoc/jm+YZeQCVupguMX+/M3yxysBs8a6iuN0WuMVa3z7jGkF4AFjlquoIpJOr9ukaBhEWoYGoKjUCELYiA2wh0l1wuAXwIB6i6oLV/l6EAsuiARTzzJ6uqEk52npYHUSXQogkagBAudqg2WyRcVwgntK0BduKkwIM/gUwAGqQaS+fhV1II9uadC2EiWRx+jekLWJBRs/M3A+sVbWRWQT4+8yE1YufE9GZoO0CkKu8bF/MUj4DG2l16kwHlquJUl+R19GRjKR2+XR8dCglMcKvvXXrL/UCkH+5C6s6Dz0AAAAASUVORK5CYII=",
21
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABAklEQVR4nO2V2xKDMAhE2U7//5fpi1iCXBJL60zHfdKY5CwkINGti4VgnJNvHWJ5eMxM6oYzMzFzbmCb0G2CBSzKMtBtYoADICJCaqDRhAsn8jNwgCkTZ4yE8OHBm+zJbpCBtw3TtU8PDoAKI1GZ7ouqQDwDU2JmieQAnoVqlZcwMkHvaIe6Xlg3GBjOfiGS8s5UCo/AptmCPgWXBroAleQI4Fysn+jQB4aXL2VB94Mq7CVDE/1j3cBqFuQoJztqauB0c9GAbA8AYRW48Cq6qHSzknb7uQeQ8y2qZepS673Kv6GO2sDP1C3brMD7aMHqvaNZCMTdUIcPM3ZNp7p16+/1AoBksuBmmrTtAAAAAElFTkSuQmCC",
22
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABCElEQVR4nO2XwRLDIAhEodP//2V6aDa1gBEUc+h0T5mUuk8UJUzrkuaZs39+Jgb3A+Qdwpz2HgIIBoe0if59Ro+eOQxhyswkIqdphTnRJwMYjfHcGsB8hwCA3N5qTmSXwOykneYeQEiVUKMyDKmpjvSZ0AsyJXhl7sWqku3CLANEdMC4XldpMhWxAyKyTmXZ8CCmqqBStwIcmfxK5+0Z0BAhAO+qbS+qFUUOovOCas2rNmZ6CSpmvQSwOnM9gSgAV888C2A0C6QzmAFg7PxII6qrxImVLADRcYxGIUTE9JV4D5UcRCMIhDkQMt2QRPoAB8yeKRPew++FwLhnFz4F0Hm/p07/+nm9AC/+b1UxIU8OAAAAAElFTkSuQmCC",
23
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABJ0lEQVR4nOWW2xLDIAhEl0z//5fpQ6NFJCAa04cy0+klsnsELwX+PWhgDN+gMZ3MzK0/EZUH9fMKhJfIygQaRkMltMNB7BlKU2vM+WwI4GUZn8mdsq6GNfOMuQUQJnpVmYkCoFVNkMg8O3sAOKS4MGAhuDUqgFxUo2WW44iofE/1qACQhJDiRJSqRBZCK4fbzxT5zr75TejLh43ngTa6Slhm+t0CFpVgr63hSbgaEtDaJeFdcJJsMQf6FnQan9zbtmM3kwiggmQh9OyvqjgKkIaIFmYVTQAInXsWJwDKVCArPhRbAK6u6scAMhCz+2toHWgA67jeVgHpA+c8mQWYPZy6PP2XLCvW9SG7RVdbQPo1UJlmzBNrwIVYacEyBPC7CmyP5sLx4g2TyYdbcQVdwQAAAABJRU5ErkJggg==",
24
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABH0lEQVR4nOVX0RLCIAwrnv//y/EFbgVaGjp2emdedFLSUCCrIhzgfI7j7fs47uLFBpIAAAEwinLxjgiTYzQKGTclq6u8iIpLtcxBCwAgpZQp8USoYqqoZQ76DBjE03hVuqpGSgAaMYsdEadvwTYYmdhZfUdOnIFIgJnZE5S5CZSAJysQnYHSiPTqxpVaz0xyKkCUB6gfZqJh/KgAL+mS+BJ0xgm7B/4QHqlAzZmqQMhPOWHmFrCv5EhA2oRYEV+34p8UsNXTbcDkHQXoPYfI0t9DqLlur2j2hPrgNVvNGlHYQdn5n9gB2xu8+l77MFSjC3JatMWcfauUfs90POA3n96cCdH/Ao8g2ib65GZ8AEaJ01fllhHdTX4HT5nVH+IDSk+VHrQ/yTUAAAAASUVORK5CYII=",
25
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABHUlEQVR4nOVWWw7DMAiDqfe/MvvoQ4xAMHlok2ZpmloS7AIhEGGQ66efrd37T/FCyEWERKTkGMUxsTcTc9t5iQDmx88ZChFrt+HvEj/7gDVykzFzQ9wRCglAaqAhVyQNcbVeIAHIl48CjsAulGqg7PxMS5cjE+AyR4K82sh4UgEzuV8RASIVheg4es+of7gGdHi9qFg78vWwgIi06xiMAtStyBRjoQiXRODiHIpA6h++jqtA23EmYOoYIiK+3op/UoCd/1bB9WsF6JwLUbe/p9BTVDQnuCOZbasj84AeULrrfP49w4fXG6L4NheQckDWFr13bPVWSZ850+vFCGBgT4PxCjOpQluvxUwfYOeKLhfPbCPimWO6Erua1x/gDfHvngq4OJEYAAAAAElFTkSuQmCC",
26
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA/ElEQVR4nO2WUQ/DIAiEj2X//y+zF2ksgmCL3UsvWbJM4nfisRbYL24fU5/dcGaXvd1ACAeA7x/hDABUDW70YYHoQBG6TFQaSLW8MwKgLgMpeCvcYiCUPvnjBrSkE48b0J3YNYYuXGfgioEhbcxsbi5QqTFNrYKzaY8kxrIG0mOWBTc2ZwxM4VGLDbDAz1+uwDXAvWcHDszHcKntEsSJSMMjA8tKmBjkjWFJ6FTg0gZuk2d3HhkoG7cILOozcBueabln4AQnojBMuuYKXIoHuLdmmUjsnypg4zfoNe9hYx2gG8mpCbkCgvNH0a9ZJ76dm8X6VVr1W/erV/X6AU6CeC0t3vKrAAAAAElFTkSuQmCC",
27
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABCElEQVR4nO2WzRKDMAiE2Y7v/8r0kqSISVzS0F5kxoPK8G34U5F803J17ZUNVx2y0wXcwjMFUHARkWM3uNBpf+yEz8BAQ1nmNgF0youQytXsKfDgWp6m9mcCRvYXATYLqQIA+NRffRbiXiKpqgAYQ5wI04ihKYjO+NCsAHYR0WPWAdkgfgypElAL5k7g6iIKLRjG12cF8mkqLyacdlaE9T8KSQBoR0TIRtPgT21ftT3gVuRS012imz1gOTY2PIxtqhnUP3L3p5K3r9KOEzsBVDlrCTCpUxq853hKQ2T+V+CMM/uXsxqf24RGTVeEb2Kzcm8ZzOcY9eqd+NvmjXZelLbzp/exx3LsDfOJkxZk2B+5AAAAAElFTkSuQmCC",
28
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA+UlEQVR4nO2VSw6AIAxEKfH+V64bwfIpTPm5cRKNgdB50FKd08XPs1W+NcnMAeQbgBMQXYDdEB4NLCCWgtATkKSXMKwvIgprlwNwy3gHhKyBaP4EPyKoCE8AwEe/CyCRTMXudMgiLGpAOxUicsyswZmIqwAzElAQSPUa5jsbAUOv6VAjEgbTDSsAvO7AbkMNIOpBmHNvMe9AsBysRsyNRswVgFhrXoxUDVf0gex3npz49XpRGC2OamEzKtJtiQzdDlQhLZafEYmFS8zjy6jkJAz9IBkqPhBTdXKiGSEASXuWZtq1zHbc9LhakwCZZg6ndkkKJuL++vW9bhYolBau0DkQAAAAAElFTkSuQmCC",
29
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABA0lEQVR4nO2WSw7DIAxEPVHuf2V30TgyCP8SoJuOVKkthHkG24HIFl+fpTq8QWYWkN8A7IA4KLHVKyHQLXz/vkzbyYCetwRgaGyATIFociBjruZNOZJhEqqtXq6DKB/5MgDRzshFp3yRXdgNga+3XXLWGDNbsKUI3Lp/omqvEIBVICFEP+F2j0C8I6pAjAZDCMmBjCKIUSOC90DFnCjumuHr+I15Rh4AAEzpC94unKM/NQQR8cTmJBXXGFQefn0EfVKWcsDpfqU1SB1HBQCjFpzJk36OhsiGk7kzmuZkdFoAKQDWUfcLBHdHMW/W02NRFURklrkX2KMqqKb+/pvNX3891QdsP4ApjDDinQAAAABJRU5ErkJggg==",
30
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABBElEQVR4nN2X2wrDQAhEx9L//+XpQ7PB7FVdE2gHCoVtnIOuxgJ/JB4fl15Z5iRBsoA8CsDDOKRdgIu5iACAPAmwZQ4A74DXLN/6zATjJTbX25oRTwlcl83aEVaA0E23QFgAttpsBbECaMyP2g61OvcCNMFJDk1W516AYdp6JsXcG68HQKjZXowMBl3A8py6C5cgNYB+qZzBrCaj3+nv9aWsizVNey1dhtV5RwK0o3j0RBfMWJIpRdrLKKrfBJjNgUcAMnUbgDUbVgAZtdyqFbMAGrOZqWdqelcyEZEzckYmIjsh8B0u7GRE4PxfEAXQhkWhreWWLsjaBzYZ8rdi/5j7BX0ADfCTHKrbEI8AAAAASUVORK5CYII=",
31
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABCklEQVR4nNWX4Q7DIAiEYdn7vzL7MW3QgnLIlvSSJUus3KcopUQPlrTfkV5ZcxEhEekgaTFq3NzHIMyZWCmAC6QKIpsCbobHeoPP7/Ktx0OEyDJu274MHExJNAWQeZtAFLghEQDYHIHYAaTNoxDwLdidfvR2QADMTCLimuzGUQB32yyTbo7GswCEVK3vRgEDE7DPU2dhCDID6JfMFSxq4j2n/8+Hck7Wcttn6TTsxg0x0b0UezNMsGBKlhTZl1GZngmwqgN/AahUGKCqAUkDaOnT713F6n7ArfGJ+z8IaslmCG8n6LvyUJFAe8LBwFhp2PgUQBt2pToXuB+oVhSAsx8eVQAZ/aZwVOsDqwuPItm/Ur4AAAAASUVORK5CYII=",
32
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABCklEQVR4nO2WSw7DMAhEcdX7X9ldJFQO5jfYirLISFmkJcOTwcZEr3D189miT4mg920gJQCGGEDuBxhBViAsgE7AEq+UpNmeh1drl5DGSfj/yfCIt3xxAMXcTF6B8IJUCC2ZAxtCbGlCUSZIywAMwUJhIIDI3CpHFaDJhNpyj+9ocqK4SVKNKEGS3ukg9UyQdVf6YBvABcI0KkIgLTsRJLo/9P8CANKsAjSpeg70lb0/ClkBNfn5QxkARU81I+KdKUFqzhuTMvw2KsF4BqhGzoiW38LbZFpuLVn2/LfOBWgXrDQbW5Aoi1uC7A2IY71blPThsphXMivxmAiZhNawcgGS+l9UgfhXz9EPsSqlDRy22m8AAAAASUVORK5CYII=",
33
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABCUlEQVR4nO2W0a7EIAhEnZv9/1/2vpRdtB0YXLtPnaRJExEPKGhrjx5p6se3XX8yQe+3gMgABrEbpARAQH4P4EHal9mA9xeNHYtxR4DNMUNw64+GDFhqp8ik6PyWVLbn5f4B4B1pFvEuLZ2BI923ACBzDqCSndTwKgMUorK4WqrLZQhA2ooMgnkYJsxRs0wYUDB2Wo8CVKvAoKoQdAssxeZQPfll8MgXc8ii9JBqBpSwTp6iKKNKKW2Bn+e+NMX+HChSAG57DSkAPWsoarTMLgIYStH+lVYdDVcAroiW7FgTam28jk+KmoqiKRtXTsAAaA+4WmAuvawfOLsu3QWJ/DOsqn0Pi0er+gdkMKQLf5051AAAAABJRU5ErkJggg==",
34
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA9klEQVR4nO2VzRLDIAiEs528/yvTS5NRyvKjTHsJx6jwueDmOJ54Yi2kK9FrpbiItEEwgDB5F4QFkL5hBwRtAUl+wbVBuDPwCyXCIRySf92+A+LMbPIK74alAAAsJVtRYcUH7lgFHSPVAla4ozVlAAC08AesJAvbPFUICt7rQUvMRaqAJ2/UAus7ALEg0gpo6dltE+DTQU8zYQnH4pVBrAJMINMH1XOtTGVIqw/ZtGOtCIOwADLP8MpEYXf8IHJCERHXYnfd0AOY5E6+dbrOTKr0L8hKXWmJOwO7nm+ooROBAVAPsAp4JhUYk6ScMAgU9+uzT/w33t2WoP+qWuSTAAAAAElFTkSuQmCC",
35
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA70lEQVR4nO1Wyw7DMAgr0/7/l73LmAglBJNKU6X6VDUBm0dCjuPBDYHN9QEvlhxARrJa3xagLBGJklNgBJQJmCy0MhCQtKJnBGQE4UI1C++igJi5GbVFqwQiQv2/XMCVuKeAWe07PUE1oa2xkonI8M2KYbqGOutfMUv/TAmk2uVV8vImh18abEacuLLfzkWkzqN60AF1j+GpH9gxvCNg2owdEd0HSbaBElERAMYha7sSAABpVMnRXNquBAzpjm67TFBgG4qgeoB8kpWQ3gNRNCxcxrwjmQlAhVid24F0chQMLWOPWUGZkIXc720f/BcfQ6ib3RoDepoAAAAASUVORK5CYII=",
36
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABBElEQVR4nO2W0Q7DIAhFYdmH98/ZEwkiIhebLE16X5bVyj0iRYlePVByOD7og5qLSGayGz8GUJfIRM0hIQBlAyQLrQwEJq3VIwCZQThQzcK3CEBERMw8GHgoP14RBGCDMjOJyPSLCq4BXaWaejj7rKJyBqyx/r/MmD73YLcBIOlFstH+DO8SsmEyFaEJsvgitvGxigkg6MC8A0BkmksEg8aF+oALHlUlvKBuEU6tGT2GTwCW50IHonshyV6AICoAggRE5+4AxJx6YaCk223n7gCGdFfba9QbMgioBsArWUlpH1h1OkQuYz4QrwCkYqzBs8uI3bqgZctqQ5ElM/i+n/vqv/oBKoa/WI/BrT0AAAAASUVORK5CYII=",
37
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA1ElEQVR4nO1USQ7EIAxzRvP/L6eXgUlTstDCpYqlqmyJTTAAhUKhUCjsB3uTn93kzOyKWCHASt7IXTwVYO0wRQ4A3wXkvR+tB0B6cLYC3D5J3tr6fwo0vJAV0Emt0jIziC4bPM2NRIwjLvH/GJFoGkJgb+y+hiEiAWk3T6In9QQsJW/l1zmnj0CajYhM40lizzdP3oGeVIqYMCwDcOW7R2Alj8blHwDdvgXWvddVkUcwWh+9A6ERIw9oQaofRP9yeIkjQZJw4JmUgLQoqSOx7i73y3AA4giQ7eL+8PYAAAAASUVORK5CYII=",
38
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAA10lEQVR4nO2UUQ7EIAhEYbP3vzL7wxo6IqKpadIwSWNKlXmClahUKpVKpbMSfYb6nDQXCb1vARg5zJ1vABAYrx919zoOgb6bpi05M4cGsJYxmK2AkPYUdnYZMYawHmhH5JljQmbuTLQSrrldo/Oa7wwgZZ7VH9L6nvwNU3oKoJUwAkhdJBmZ0nftW66AOUjEzO2JzKONrN4DHYw18mKBuRARb50BWwUbw7gHg1Dbh9CDsKbYptH85XugSxD03wOC98lqzRElngFZQ4TJAqShLEdi3q73y/QDzYaO9US4bAEAAAAASUVORK5CYII="
39
+ ];
40
+ //#endregion
41
+ //#region src/runtime/nekojsRuntime.ts
42
+ /**
43
+ * Typed pet runtime. Inspired by [nekojs](https://github.com/louisabraham/nekojs); licensing in
44
+ * repo `LICENSE`. Sprite data in `./nekoSpritesData.ts`.
45
+ */
46
+ const BEHAVIOR_MODE_MIN = 0;
47
+ const BEHAVIOR_MODE_MAX = 6;
48
+ function normalizeBehaviorCycle(raw) {
49
+ const fallback = () => [...DEFAULT_NEKO_BEHAVIOR_CYCLE];
50
+ if (!raw?.length) return fallback();
51
+ const out = [];
52
+ for (const m of raw) if (typeof m === "number" && Number.isInteger(m) && m >= BEHAVIOR_MODE_MIN && m <= BEHAVIOR_MODE_MAX) out.push(m);
53
+ return out.length > 0 ? out : fallback();
54
+ }
55
+ const NekoState = {
56
+ STOP: 0,
57
+ WASH: 1,
58
+ SCRATCH: 2,
59
+ YAWN: 3,
60
+ SLEEP: 4,
61
+ AWAKE: 5,
62
+ U_MOVE: 6,
63
+ D_MOVE: 7,
64
+ L_MOVE: 8,
65
+ R_MOVE: 9,
66
+ UL_MOVE: 10,
67
+ UR_MOVE: 11,
68
+ DL_MOVE: 12,
69
+ DR_MOVE: 13,
70
+ U_CLAW: 14,
71
+ D_CLAW: 15,
72
+ L_CLAW: 16,
73
+ R_CLAW: 17
74
+ };
75
+ const NekoJsBehaviorMode = {
76
+ CHASE_MOUSE: 0,
77
+ RUN_AWAY_FROM_MOUSE: 1,
78
+ RUN_AROUND_RANDOMLY: 2,
79
+ PACE_AROUND_SCREEN: 3,
80
+ RUN_AROUND: 4,
81
+ STAY_STILL: 5,
82
+ RETURN_HOME_AND_STAY: 6
83
+ };
84
+ const BEHAVIOR_DEBUG_NAMES = {
85
+ [NekoJsBehaviorMode.CHASE_MOUSE]: "Chase Mouse",
86
+ [NekoJsBehaviorMode.RUN_AWAY_FROM_MOUSE]: "Run Away From Mouse",
87
+ [NekoJsBehaviorMode.RUN_AROUND_RANDOMLY]: "Run Around Randomly",
88
+ [NekoJsBehaviorMode.PACE_AROUND_SCREEN]: "Pace Around Screen",
89
+ [NekoJsBehaviorMode.RUN_AROUND]: "Run Around",
90
+ [NekoJsBehaviorMode.STAY_STILL]: "Stay Still",
91
+ [NekoJsBehaviorMode.RETURN_HOME_AND_STAY]: "Return Home And Stay"
92
+ };
93
+ const STOP_TIME = 4;
94
+ const WASH_TIME = 10;
95
+ const SCRATCH_TIME = 4;
96
+ const YAWN_TIME = 3;
97
+ const AWAKE_TIME = 3;
98
+ const CLAW_TIME = 10;
99
+ /** Sprite edge length in CSS pixels. */
100
+ const SPRITE_SIZE = 32;
101
+ /**
102
+ * Viewport-fixed sprite pet: chase behaviors, `start` / `stop` / `destroy` lifecycle.
103
+ *
104
+ * Document-level listeners use `AbortController` so {@link Neko.destroy} removes handlers cleanly.
105
+ */
106
+ var Neko = class {
107
+ /** @internal Consolidates `document` / `window` / element listeners for teardown. */
108
+ listenersAbort = new AbortController();
109
+ fps;
110
+ speed;
111
+ behaviorMode;
112
+ idleThreshold;
113
+ state;
114
+ tickCount;
115
+ stateCount;
116
+ x;
117
+ y;
118
+ logicX;
119
+ logicY;
120
+ prevLogicX;
121
+ prevLogicY;
122
+ targetX;
123
+ targetY;
124
+ oldTargetX;
125
+ oldTargetY;
126
+ moveDX;
127
+ moveDY;
128
+ boundsWidth;
129
+ boundsHeight;
130
+ mouseX = null;
131
+ mouseY = null;
132
+ hasMouseMoved;
133
+ element;
134
+ spriteImages = [];
135
+ allowBehaviorChange;
136
+ animationTable;
137
+ cornerIndex;
138
+ ballX;
139
+ ballY;
140
+ ballVX;
141
+ ballVY;
142
+ running;
143
+ intervalId = null;
144
+ tickAccumulator = 0;
145
+ actionCount = 0;
146
+ lastMoveDX = 0;
147
+ lastMoveDY = 0;
148
+ /** Minimum distance (px) from movement anchor to pointer in chase mode; 0 = legacy snap-to-cursor. */
149
+ cursorStandoffPx;
150
+ /** Modes visited in order on each pet mousedown when behavior change is allowed. */
151
+ behaviorCycle;
152
+ /** Spawn / home top-left from `createNeko`; used by return-home behavior (mode 6). */
153
+ homeX;
154
+ homeY;
155
+ /**
156
+ * @param options - Initial behavior and layout; see {@link NekoOptions}. Empty object uses defaults.
157
+ */
158
+ constructor(options = {}) {
159
+ this.fps = options.fps || 120;
160
+ this.speed = options.speed || 24;
161
+ this.behaviorMode = options.behaviorMode || NekoJsBehaviorMode.CHASE_MOUSE;
162
+ this.idleThreshold = options.idleThreshold || 6;
163
+ const standoff = options.cursorStandoffPx;
164
+ this.cursorStandoffPx = typeof standoff === "number" && Number.isFinite(standoff) && standoff > 0 ? standoff : 0;
165
+ this.state = NekoState.STOP;
166
+ this.tickCount = 0;
167
+ this.stateCount = 0;
168
+ this.x = options.startX || 0;
169
+ this.y = options.startY || 0;
170
+ this.homeX = this.x;
171
+ this.homeY = this.y;
172
+ this.logicX = this.x;
173
+ this.logicY = this.y;
174
+ this.prevLogicX = this.x;
175
+ this.prevLogicY = this.y;
176
+ this.targetX = this.x;
177
+ this.targetY = this.y;
178
+ this.oldTargetX = this.x;
179
+ this.oldTargetY = this.y;
180
+ this.moveDX = 0;
181
+ this.moveDY = 0;
182
+ this.boundsWidth = document.documentElement.clientWidth - SPRITE_SIZE;
183
+ this.boundsHeight = window.innerHeight - SPRITE_SIZE;
184
+ this.mouseX = null;
185
+ this.mouseY = null;
186
+ this.hasMouseMoved = false;
187
+ this.spriteImages = [];
188
+ this.allowBehaviorChange = options.allowBehaviorChange !== false;
189
+ this.behaviorCycle = normalizeBehaviorCycle(options.behaviorCycle);
190
+ this.animationTable = [
191
+ [28, 28],
192
+ [25, 28],
193
+ [26, 27],
194
+ [29, 29],
195
+ [30, 31],
196
+ [0, 0],
197
+ [1, 2],
198
+ [9, 10],
199
+ [13, 14],
200
+ [5, 6],
201
+ [15, 16],
202
+ [3, 4],
203
+ [11, 12],
204
+ [7, 8],
205
+ [17, 18],
206
+ [23, 24],
207
+ [21, 22],
208
+ [19, 20]
209
+ ];
210
+ this.cornerIndex = 0;
211
+ this.ballX = 0;
212
+ this.ballY = 0;
213
+ this.ballVX = 0;
214
+ this.ballVY = 0;
215
+ this.init();
216
+ }
217
+ init() {
218
+ this.element = document.createElement("div");
219
+ this.element.className = "neko";
220
+ this.element.style.cssText = `
221
+ position: fixed;
222
+ width: ${SPRITE_SIZE}px;
223
+ height: ${SPRITE_SIZE}px;
224
+ image-rendering: pixelated;
225
+ pointer-events: ${this.allowBehaviorChange ? "auto" : "none"};
226
+ cursor: ${this.allowBehaviorChange ? "pointer" : "default"};
227
+ z-index: 999999;
228
+ left: ${this.x}px;
229
+ top: ${this.y}px;
230
+ margin: 0;
231
+ padding: 0;
232
+ border: none;
233
+ background: transparent;
234
+ overflow: visible;
235
+ box-sizing: border-box;
236
+ user-select: none;
237
+ -webkit-user-select: none;
238
+ `;
239
+ const img = document.createElement("img");
240
+ img.style.cssText = `
241
+ width: 100%;
242
+ height: 100%;
243
+ background: transparent;
244
+ border: none;
245
+ margin: 0;
246
+ padding: 0;
247
+ max-width: none;
248
+ max-height: none;
249
+ display: block;
250
+ box-sizing: border-box;
251
+ user-select: none;
252
+ -webkit-user-select: none;
253
+ -webkit-user-drag: none;
254
+ pointer-events: none;
255
+ `;
256
+ this.element.appendChild(img);
257
+ document.body.appendChild(this.element);
258
+ const signal = this.listenersAbort.signal;
259
+ if (this.allowBehaviorChange) this.element.addEventListener("mousedown", (e) => {
260
+ e.stopPropagation();
261
+ e.preventDefault();
262
+ this.setState(NekoState.AWAKE);
263
+ this.cycleBehavior();
264
+ }, { signal });
265
+ document.addEventListener("mousemove", (e) => {
266
+ this.mouseX = e.clientX;
267
+ this.mouseY = e.clientY;
268
+ this.hasMouseMoved = true;
269
+ }, { signal });
270
+ window.addEventListener("resize", () => {
271
+ this.boundsWidth = document.documentElement.clientWidth - SPRITE_SIZE;
272
+ this.boundsHeight = window.innerHeight - SPRITE_SIZE;
273
+ }, { signal });
274
+ this.targetX = this.x + SPRITE_SIZE / 2;
275
+ this.targetY = this.y + SPRITE_SIZE - 1;
276
+ this.oldTargetX = this.targetX;
277
+ this.oldTargetY = this.targetY;
278
+ this.updatePosition();
279
+ this.running = false;
280
+ this.intervalId = null;
281
+ }
282
+ /** Starts the render / logic interval (runs at `fps`). */
283
+ start() {
284
+ if (this.running) return;
285
+ this.running = true;
286
+ const interval = 1e3 / this.fps;
287
+ this.intervalId = setInterval(() => {
288
+ this.update();
289
+ }, interval);
290
+ }
291
+ /** Stops the interval; does not remove the DOM node or reset position. */
292
+ stop() {
293
+ this.running = false;
294
+ if (this.intervalId) {
295
+ clearInterval(this.intervalId);
296
+ this.intervalId = null;
297
+ }
298
+ }
299
+ /** Assigns PNG data URLs for animation frames (see bundled {@link NEKO_SPRITES}). */
300
+ setSprites(sprites) {
301
+ this.spriteImages = [...sprites];
302
+ this.updateSprite();
303
+ }
304
+ updateSprite() {
305
+ if (this.spriteImages.length === 0) return;
306
+ let frameIndex;
307
+ if (this.state === NekoState.SLEEP) frameIndex = this.animationTable[this.state][this.tickCount >> 2 & 1];
308
+ else frameIndex = this.animationTable[this.state][this.tickCount & 1];
309
+ const img = this.element.querySelector("img");
310
+ if (img && this.spriteImages[frameIndex]) img.src = this.spriteImages[frameIndex];
311
+ }
312
+ updatePosition() {
313
+ this.element.style.left = Math.round(this.x) + "px";
314
+ this.element.style.top = Math.round(this.y) + "px";
315
+ }
316
+ update() {
317
+ this.tickAccumulator += 5 / this.fps;
318
+ while (this.tickAccumulator >= 1) {
319
+ this.tickAccumulator -= 1;
320
+ this.prevLogicX = this.logicX;
321
+ this.prevLogicY = this.logicY;
322
+ this.processOriginalTick();
323
+ }
324
+ const t = this.tickAccumulator;
325
+ this.x = this.prevLogicX + (this.logicX - this.prevLogicX) * t;
326
+ this.y = this.prevLogicY + (this.logicY - this.prevLogicY) * t;
327
+ this.updatePosition();
328
+ }
329
+ processOriginalTick() {
330
+ this.tickCount++;
331
+ if (this.tickCount >= 9999) this.tickCount = 0;
332
+ if (this.tickCount % 2 === 0) this.stateCount++;
333
+ switch (this.behaviorMode) {
334
+ case NekoJsBehaviorMode.CHASE_MOUSE:
335
+ this.chaseMouse();
336
+ break;
337
+ case NekoJsBehaviorMode.RUN_AWAY_FROM_MOUSE:
338
+ this.runAwayFromMouse();
339
+ break;
340
+ case NekoJsBehaviorMode.RUN_AROUND_RANDOMLY:
341
+ this.runRandomly();
342
+ break;
343
+ case NekoJsBehaviorMode.PACE_AROUND_SCREEN:
344
+ this.paceAroundScreen();
345
+ break;
346
+ case NekoJsBehaviorMode.RUN_AROUND:
347
+ this.runAround();
348
+ break;
349
+ case NekoJsBehaviorMode.STAY_STILL:
350
+ this.stayStillBehavior();
351
+ break;
352
+ case NekoJsBehaviorMode.RETURN_HOME_AND_STAY:
353
+ this.returnHomeAndStayBehavior();
354
+ break;
355
+ }
356
+ this.updateSprite();
357
+ }
358
+ chaseMouse() {
359
+ if (!this.hasMouseMoved) {
360
+ this.runTowards(this.logicX + SPRITE_SIZE / 2, this.logicY + SPRITE_SIZE - 1);
361
+ return;
362
+ }
363
+ const mx = this.mouseX;
364
+ const my = this.mouseY;
365
+ if (mx === null || my === null) return;
366
+ const footX = this.logicX + SPRITE_SIZE / 2;
367
+ const footY = this.logicY + SPRITE_SIZE - 1;
368
+ const standoff = this.cursorStandoffPx;
369
+ if (standoff <= 0) {
370
+ this.runTowards(mx, my);
371
+ return;
372
+ }
373
+ const vx = mx - footX;
374
+ const vy = my - footY;
375
+ const d = Math.sqrt(vx * vx + vy * vy);
376
+ if (d <= standoff || d === 0) {
377
+ this.runTowards(footX, footY);
378
+ return;
379
+ }
380
+ const sx = mx - vx / d * standoff;
381
+ const sy = my - vy / d * standoff;
382
+ this.runTowards(sx, sy);
383
+ }
384
+ runAwayFromMouse() {
385
+ if (!this.hasMouseMoved) {
386
+ this.runTowards(this.logicX + SPRITE_SIZE / 2, this.logicY + SPRITE_SIZE - 1);
387
+ return;
388
+ }
389
+ const mx = this.mouseX;
390
+ const my = this.mouseY;
391
+ if (mx === null || my === null) return;
392
+ const dwLimit = this.idleThreshold * 16;
393
+ const xdiff = this.logicX + SPRITE_SIZE / 2 - mx;
394
+ const ydiff = this.logicY + SPRITE_SIZE / 2 - my;
395
+ if (Math.abs(xdiff) < dwLimit && Math.abs(ydiff) < dwLimit) {
396
+ const dLength = Math.sqrt(xdiff * xdiff + ydiff * ydiff);
397
+ let targetX, targetY;
398
+ if (dLength !== 0) {
399
+ targetX = this.logicX + xdiff / dLength * dwLimit;
400
+ targetY = this.logicY + ydiff / dLength * dwLimit;
401
+ } else targetX = targetY = 32;
402
+ this.runTowards(targetX, targetY);
403
+ if (this.state === NekoState.AWAKE) this.calcDirection(targetX - this.logicX, targetY - this.logicY);
404
+ } else this.runTowards(this.targetX, this.targetY);
405
+ }
406
+ runRandomly() {
407
+ if (this.state === NekoState.SLEEP) this.actionCount = (this.actionCount || 0) + 1;
408
+ if ((this.actionCount || 0) > this.idleThreshold * 10) {
409
+ this.actionCount = 0;
410
+ this.targetX = Math.random() * this.boundsWidth;
411
+ this.targetY = Math.random() * this.boundsHeight;
412
+ this.runTowards(this.targetX, this.targetY);
413
+ } else this.runTowards(this.targetX, this.targetY);
414
+ }
415
+ paceAroundScreen() {
416
+ if (this.lastMoveDX === 0 && this.lastMoveDY === 0) this.cornerIndex = ((this.cornerIndex || 0) + 1) % 4;
417
+ const target = [
418
+ [SPRITE_SIZE + SPRITE_SIZE / 2, SPRITE_SIZE + SPRITE_SIZE - 1],
419
+ [SPRITE_SIZE + SPRITE_SIZE / 2, this.boundsHeight - SPRITE_SIZE + SPRITE_SIZE - 1],
420
+ [this.boundsWidth - SPRITE_SIZE + SPRITE_SIZE / 2, this.boundsHeight - SPRITE_SIZE + SPRITE_SIZE - 1],
421
+ [this.boundsWidth - SPRITE_SIZE + SPRITE_SIZE / 2, SPRITE_SIZE + SPRITE_SIZE - 1]
422
+ ][this.cornerIndex || 0];
423
+ this.runTowards(target[0], target[1]);
424
+ }
425
+ runAround() {
426
+ const dwBoundingBox = this.speed * 8;
427
+ if (this.ballX === 0 && this.ballY === 0) {
428
+ this.ballX = Math.random() * (this.boundsWidth - dwBoundingBox);
429
+ this.ballY = Math.random() * (this.boundsHeight - dwBoundingBox);
430
+ this.ballVX = (Math.random() < .5 ? 1 : -1) * (this.speed / 2) + 1;
431
+ this.ballVY = (Math.random() < .5 ? 1 : -1) * (this.speed / 2) + 1;
432
+ }
433
+ this.ballX += this.ballVX;
434
+ this.ballY += this.ballVY;
435
+ if (this.ballX < dwBoundingBox) if (this.ballX > 0) this.ballVX++;
436
+ else this.ballVX = -this.ballVX;
437
+ else if (this.ballX > this.boundsWidth - dwBoundingBox) if (this.ballX < this.boundsWidth) this.ballVX--;
438
+ else this.ballVX = -this.ballVX;
439
+ if (this.ballY < dwBoundingBox) if (this.ballY > 0) this.ballVY++;
440
+ else this.ballVY = -this.ballVY;
441
+ else if (this.ballY > this.boundsHeight - dwBoundingBox) if (this.ballY < this.boundsHeight) this.ballVY--;
442
+ else this.ballVY = -this.ballVY;
443
+ this.runTowards(this.ballX, this.ballY);
444
+ }
445
+ /** Idle in place at the current logic position (same target pattern as “wait for mouse”). */
446
+ stayStillBehavior() {
447
+ this.runTowards(this.logicX + SPRITE_SIZE / 2, this.logicY + SPRITE_SIZE - 1);
448
+ }
449
+ /** Move toward spawn, then idle there. */
450
+ returnHomeAndStayBehavior() {
451
+ const targetX = this.homeX + SPRITE_SIZE / 2;
452
+ const targetY = this.homeY + SPRITE_SIZE - 1;
453
+ const dx = targetX - this.logicX - SPRITE_SIZE / 2;
454
+ const dy = targetY - this.logicY - SPRITE_SIZE + 1;
455
+ if (Math.sqrt(dx * dx + dy * dy) <= this.speed) {
456
+ this.logicX = this.homeX;
457
+ this.logicY = this.homeY;
458
+ this.prevLogicX = this.homeX;
459
+ this.prevLogicY = this.homeY;
460
+ }
461
+ this.runTowards(targetX, targetY);
462
+ }
463
+ setState(newState) {
464
+ this.tickCount = 0;
465
+ this.stateCount = 0;
466
+ this.state = newState;
467
+ }
468
+ runTowards(targetX, targetY) {
469
+ this.oldTargetX = this.targetX;
470
+ this.oldTargetY = this.targetY;
471
+ this.targetX = targetX;
472
+ this.targetY = targetY;
473
+ const dx = targetX - this.logicX - SPRITE_SIZE / 2;
474
+ const dy = targetY - this.logicY - SPRITE_SIZE + 1;
475
+ const distance = Math.sqrt(dx * dx + dy * dy);
476
+ if (distance !== 0) if (distance <= this.speed) {
477
+ this.moveDX = Math.trunc(dx);
478
+ this.moveDY = Math.trunc(dy);
479
+ } else {
480
+ this.moveDX = Math.trunc(this.speed * dx / distance);
481
+ this.moveDY = Math.trunc(this.speed * dy / distance);
482
+ }
483
+ else {
484
+ this.moveDX = 0;
485
+ this.moveDY = 0;
486
+ }
487
+ this.lastMoveDX = this.moveDX;
488
+ this.lastMoveDY = this.moveDY;
489
+ const moveStart = !(this.oldTargetX >= this.targetX - this.idleThreshold && this.oldTargetX <= this.targetX + this.idleThreshold && this.oldTargetY >= this.targetY - this.idleThreshold && this.oldTargetY <= this.targetY + this.idleThreshold);
490
+ switch (this.state) {
491
+ case NekoState.STOP:
492
+ if (moveStart) this.setState(NekoState.AWAKE);
493
+ else if (this.stateCount >= STOP_TIME) if (this.moveDX < 0 && this.logicX <= 0) this.setState(NekoState.L_CLAW);
494
+ else if (this.moveDX > 0 && this.logicX >= this.boundsWidth) this.setState(NekoState.R_CLAW);
495
+ else if (this.moveDY < 0 && this.logicY <= 0) this.setState(NekoState.U_CLAW);
496
+ else if (this.moveDY > 0 && this.logicY >= this.boundsHeight) this.setState(NekoState.D_CLAW);
497
+ else this.setState(NekoState.WASH);
498
+ break;
499
+ case NekoState.WASH:
500
+ if (moveStart) this.setState(NekoState.AWAKE);
501
+ else if (this.stateCount >= WASH_TIME) this.setState(NekoState.SCRATCH);
502
+ break;
503
+ case NekoState.SCRATCH:
504
+ if (moveStart) this.setState(NekoState.AWAKE);
505
+ else if (this.stateCount >= SCRATCH_TIME) this.setState(NekoState.YAWN);
506
+ break;
507
+ case NekoState.YAWN:
508
+ if (moveStart) this.setState(NekoState.AWAKE);
509
+ else if (this.stateCount >= YAWN_TIME) this.setState(NekoState.SLEEP);
510
+ break;
511
+ case NekoState.SLEEP:
512
+ if (moveStart) this.setState(NekoState.AWAKE);
513
+ break;
514
+ case NekoState.AWAKE:
515
+ if (this.stateCount >= AWAKE_TIME + Math.floor(Math.random() * 20)) this.calcDirection(this.moveDX, this.moveDY);
516
+ break;
517
+ case NekoState.U_MOVE:
518
+ case NekoState.D_MOVE:
519
+ case NekoState.L_MOVE:
520
+ case NekoState.R_MOVE:
521
+ case NekoState.UL_MOVE:
522
+ case NekoState.UR_MOVE:
523
+ case NekoState.DL_MOVE:
524
+ case NekoState.DR_MOVE:
525
+ let newX = this.logicX + this.moveDX;
526
+ let newY = this.logicY + this.moveDY;
527
+ const wasOutside = newX <= 0 || newX >= this.boundsWidth || newY <= 0 || newY >= this.boundsHeight;
528
+ this.calcDirection(this.moveDX, this.moveDY);
529
+ newX = Math.max(0, Math.min(this.boundsWidth, newX));
530
+ newY = Math.max(0, Math.min(this.boundsHeight, newY));
531
+ const notMoved = newX === this.logicX && newY === this.logicY;
532
+ if (wasOutside && notMoved) this.setState(NekoState.STOP);
533
+ else {
534
+ this.logicX = newX;
535
+ this.logicY = newY;
536
+ }
537
+ break;
538
+ case NekoState.U_CLAW:
539
+ case NekoState.D_CLAW:
540
+ case NekoState.L_CLAW:
541
+ case NekoState.R_CLAW:
542
+ if (moveStart) this.setState(NekoState.AWAKE);
543
+ else if (this.stateCount >= CLAW_TIME) this.setState(NekoState.SCRATCH);
544
+ break;
545
+ default:
546
+ this.setState(NekoState.STOP);
547
+ break;
548
+ }
549
+ }
550
+ calcDirection(dx, dy) {
551
+ let newState;
552
+ if (dx === 0 && dy === 0) newState = NekoState.STOP;
553
+ else {
554
+ const largeX = dx;
555
+ const largeY = -dy;
556
+ const sinTheta = largeY / Math.sqrt(largeX * largeX + largeY * largeY);
557
+ const sinPiPer8 = .3826834323651;
558
+ const sinPiPer8Times3 = .9238795325113;
559
+ if (dx > 0) if (sinTheta > sinPiPer8Times3) newState = NekoState.U_MOVE;
560
+ else if (sinTheta > sinPiPer8) newState = NekoState.UR_MOVE;
561
+ else if (sinTheta > -sinPiPer8) newState = NekoState.R_MOVE;
562
+ else if (sinTheta > -sinPiPer8Times3) newState = NekoState.DR_MOVE;
563
+ else newState = NekoState.D_MOVE;
564
+ else if (sinTheta > sinPiPer8Times3) newState = NekoState.U_MOVE;
565
+ else if (sinTheta > sinPiPer8) newState = NekoState.UL_MOVE;
566
+ else if (sinTheta > -sinPiPer8) newState = NekoState.L_MOVE;
567
+ else if (sinTheta > -sinPiPer8Times3) newState = NekoState.DL_MOVE;
568
+ else newState = NekoState.D_MOVE;
569
+ }
570
+ if (this.state !== newState) this.setState(newState);
571
+ }
572
+ /** @returns True when the sprite is in a stationary / idle animation state. */
573
+ isIdle() {
574
+ return this.state === NekoState.STOP || this.state === NekoState.WASH || this.state === NekoState.SCRATCH || this.state === NekoState.YAWN || this.state === NekoState.SLEEP || this.state === NekoState.AWAKE;
575
+ }
576
+ cycleBehavior() {
577
+ const behaviors = this.behaviorCycle;
578
+ const nextIndex = (behaviors.indexOf(this.behaviorMode) + 1) % behaviors.length;
579
+ this.behaviorMode = behaviors[nextIndex];
580
+ if (this.state === NekoState.SLEEP) this.setState(NekoState.AWAKE);
581
+ const nextMode = behaviors[nextIndex];
582
+ console.log(`Neko behavior: ${BEHAVIOR_DEBUG_NAMES[nextMode] ?? nextMode}`);
583
+ }
584
+ /**
585
+ * Stops the animation loop, removes listeners, and drops the pet node from the document.
586
+ * Safe to call more than once.
587
+ */
588
+ destroy() {
589
+ this.stop();
590
+ this.listenersAbort.abort();
591
+ if (this.element?.parentNode) this.element.parentNode.removeChild(this.element);
592
+ }
593
+ };
594
+ /**
595
+ * Creates a pet, wires bundled sprites, and calls {@link Neko.start}.
596
+ *
597
+ * @param options - Passed to {@link Neko}; see {@link NekoOptions}. Omit for defaults.
598
+ * @returns The running instance (`start` already called).
599
+ */
600
+ function createNeko(options) {
601
+ const neko = new Neko(options ?? {});
602
+ neko.setSprites(NEKO_SPRITES);
603
+ neko.start();
604
+ return neko;
605
+ }
606
+ function installNekoGlobals() {
607
+ if (typeof globalThis === "undefined" || typeof document === "undefined") return;
608
+ const w = globalThis;
609
+ w.Neko = Neko;
610
+ w.NekoState = NekoState;
611
+ w.BehaviorMode = NekoJsBehaviorMode;
612
+ w.createNeko = createNeko;
613
+ }
614
+ installNekoGlobals();
615
+ //#endregion
616
+ export {};
@@ -0,0 +1,2 @@
1
+ import { i as resolveStartPosition, n as NekoStartCorner, r as cornerToStartXY, t as NekoPlacementInput } from "./nekoPlacement-fXmlU6ys.mjs";
2
+ export { type NekoPlacementInput, type NekoStartCorner, cornerToStartXY, resolveStartPosition };
@@ -0,0 +1,2 @@
1
+ import { n as resolveStartPosition, t as cornerToStartXY } from "./nekoPlacement-DUdnhZoX.mjs";
2
+ export { cornerToStartXY, resolveStartPosition };
@@ -0,0 +1,2 @@
1
+ import { t as loadNekoRuntime } from "./loadNekoRuntime-DLd1lr8Y.mjs";
2
+ export { loadNekoRuntime };
@@ -0,0 +1,2 @@
1
+ import { t as loadNekoRuntime } from "./loadNekoRuntime-CskWI70T.mjs";
2
+ export { loadNekoRuntime };