{"_id":"swingset","_rev":"70-e6450350a0a0a0ed1885f394c3065981","name":"swingset","dist-tags":{"latest":"0.17.0","canary":"0.18.0-canary-20230629193328"},"versions":{"0.3.0":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.3.0","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.1","gray-matter":"^4.0.2","loader-utils":"^2.0.0","next-mdx-remote":"1.0.0","query-string":"^5.1.1","react-live":"^2.2.2","require-from-string":"^2.0.2"},"devDependencies":{"jest":"^26.6.1","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":"9.x","react":"16.x","react-dom":"16.x","webpack":"4.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd example && npm start","test":"jest","release:major":"release major && npm publish","release:minor":"release minor && npm publish","release:patch":"release patch && npm publish"},"gitHead":"54c4e9816a63e0ec9f3c2987ff7f66c5a968693e","_id":"swingset@0.3.0","_nodeVersion":"12.13.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-hiyX4rNFRv8Ld42Vl0lcl3VHpzX8lkQ1j6HfkgbR1dacwxhur85Na09EJOvUNLDOIefK9RaACdNKif8yEDGufg==","shasum":"23bcdb063670639fd9acf3331073835cb4d4fbd9","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.3.0.tgz","fileCount":25,"unpackedSize":87793,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJflzuUCRA9TVsSAnZWagAAhZkQAIWgQ8pLkuzQvgDRiEX4\nu2GHwcpbUL0f+Z7sHEkRGYK6exQ1RlAb/+FTUeLuGN+IlwhDZatP1B0etdgl\neV/w6a/UQNxbK04eiZ/DL6UMe7WCVbmimpTRD3YcwLZ5kSx/QlNzlhZT25eI\nY2hA38i5z0QVY+Uggc7tHSnGYUPQgQXu4QuEyXAltNgeV7oG6zuAsCBNKxvB\nKaKi2pZPatmcOGsgZZHapYWyH5UWXRW3mlC/NYfVvBaZJxRBJKE47cZpIJFe\nM66QekFMVwRdLt7VIFPf0k+bPZuPTrhudp5tGa0sxSuZEyUYi7fAsIAgWFVo\n8o2CHJT7apMZ20CSkvJM8nTZnnKHi+KcNrQxKRnfXlNt/6HelMKUs94AosiS\nvG/qscenHFm2xMnBPJelJ3F9gTIzdpHxo9Cw7oVVVPIzL+2W1ILiA1dVbzRu\ntFzdTgOScAnQYAN73CC+0Bl/FQps89gSyx8+7G2nnzGUAuPOb6ANvXb5LXCU\nl+JE0bpheJCt4acKVDIlclCM4iBE2zoN28RPgh+P9aXjnO6dJxTrAu3Kmelk\nTp0lpQsgkFaehaXU5SIkUoDj0P9N58eHj6rFGA+IL3t/WLeW3sx02otgLGxp\nx2hKuoQ4fQmmwsKZHIi7VJcTccv8kbzSgjo34tffqayPiLf6k5UjXFKrXcWE\n8ZLX\r\n=C34p\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDDOfZjakxc8wRBM68uFbOXTCRPnQwLM3zvZROEjsZgNAiB+CY5SsLOtqH6AMiqIMyIF+pofQgmXxbKSyRqeIfnwtA=="}]},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"}],"_npmUser":{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.3.0_1603746708057_0.851933626061637"},"_hasShrinkwrap":false},"0.4.0":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.4.0","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.1","gray-matter":"^4.0.2","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"1.0.0","query-string":"^5.1.1","react-live":"^2.2.2","require-from-string":"^2.0.2"},"devDependencies":{"jest":"^26.6.1","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":"9.x","react":"16.x","react-dom":"16.x","webpack":"4.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd example && npm start","test":"jest","release:major":"release major && npm publish","release:minor":"release minor && npm publish","release:patch":"release patch && npm publish"},"gitHead":"cce4e1942cd76159e3dbe277e7d674ba8c136003","_id":"swingset@0.4.0","_nodeVersion":"12.13.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-+HKSmyAriRJUiGkgob92hyKBET9TpyAopKuN3547kQZstfYUo3sYr3gXvUaef9/EDk5ELt+QyumAlbHPDeMOJA==","shasum":"922e8abc3c6099fc01eeb85772fe987ab41e2275","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.4.0.tgz","fileCount":25,"unpackedSize":88342,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfoHhPCRA9TVsSAnZWagAAPAUP+gLDLcNFTDtp8MOrpv3T\nxvPC6R17hjANsmxePp0aQpeU4JBPg+3OorA5wsG613N5AKOvgz0JGkuIFci7\nP/ufs7jLaI6NGkGej5UILW93hVWMQyHnBeY94sLAv/h+1OVzlmAbaUKIwNue\nlRBf/6q7z3pxCP15FhaIfSaMq97TRqnaw9fN9ktb4j1uKBUW8gErMwHpdax4\nhtYrxvikPQCIJyI6cD1LcwWF2GSGJj/5TLhMduP34y5b3m9enneeLT+E+2K2\nJ6gTZAfWeXqZgAQylIc/a8k1p6rWJ8W3vHDwEsCJS7qiqvgiop21xJuk0pf4\nHASJAps67DBGgxicFadAaai0Wskh+e8e4Hgu3dep7SjY2xzXGPsEaMrH1A1o\n9IISTQ6Z+7bbsyWexncLshTEnsVke3VjXZ/Nb//aYquuzHSQKfrerioJ5IXh\n9WIOATSMI/Q99IYeHczcN2ESTaXfX2nMzxJGbiCvRhTMSDfO+ih4PBC51FNT\nKuZFjHiPHtReouOYXfHNE6KDvFgrxCftT76v04FZrfk7vv54FGtf3IqJy1ry\n1uyovqM0riI2eR3J/iAinzrwNeyZo1iFc5CzlaxHdtbT786sNCufx6K4/Jtg\nbkaV+GmUDgDdqNwu8GO7QThxk7eEHfBji9wj5X9YqFeYsVQNnSv5zP/qsOZn\nMC6P\r\n=dayx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAvU5hnAsMxejBZeuZI83siFDX1qMaeKxk+5d8qt9QKXAiAiDzXoyi5f6gvBJMveOrZ6R8otRhi5D1+8dBwK5JPeXQ=="}]},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"}],"_npmUser":{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.4.0_1604352078929_0.206988185345095"},"_hasShrinkwrap":false},"0.4.1":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.4.1","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.1","gray-matter":"^4.0.2","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"1.0.0","query-string":"^5.1.1","react-live":"^2.2.2","require-from-string":"^2.0.2"},"devDependencies":{"jest":"^26.6.1","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":"9.x","react":"16.x","react-dom":"16.x","webpack":"4.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd example && npm start","test":"jest","release:major":"release major && npm publish","release:minor":"release minor && npm publish","release:patch":"release patch && npm publish"},"gitHead":"00c275f2cd778c0ba5004c0fbb6333ab138f0e81","_id":"swingset@0.4.1","_nodeVersion":"12.13.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-5zDTvyWLefs8v0RaKexMVTw8a3R7/DJIxa4apujfWzzMoVjcQvY87k73/AGbhVhJJHg1hitABiJZENekUEohZQ==","shasum":"2dfea1fb88e78fd97a90ce582768cdcbf4a96831","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.4.1.tgz","fileCount":27,"unpackedSize":95356,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfpD5OCRA9TVsSAnZWagAAPSYP/jUO1FHhYQw/in92BJhd\nu5TTVbggs+WJMIVOeEIDYq8FOJQY46SVpjjBvvbZYRe+VvT0VblwCV9SZ6xd\nMXPCxOd5pPg9uNLL7SWaEu5qAjjqHNrvBEeBYBgZ8EppJWPdU6G/buflGoeh\nsdIvF9Euy/zdOzmxeMCgjEpLriJ16tRRxWCSFd1ErEHeBX5kOV907s9aVOkM\nGgevDrghj2QHc1z7kAZvrsBlYpecDdL+IWUQygkSmi0T9SpVqfvBlXSyGx04\nwmNveGsf1bikHfKJsJBR8jWTDJk77BF8W9AVXk/AuRXe7ep74pHZL/Cy+zKP\nMZO6XP27p7fGa7wB8JrfMU3ChY1B9i40MBPbFKzhi2dHKSyOjycY70Vs0XbD\nX1A8M8Httiwmy5NrFr5+pMfH2urorSoNVZIzRftIHJBn4wT/M+07ChI0b5h6\ndb+u9O9AwT2Mc9lyDsmFLWZKJ/J6NMBfMIIs+rvkY1g42aVx8cgugTFUu5c5\nBQbVjUAuiGKkal8ucopFZaHVgfmaTnz8uorQcGnW2tH0wyzz5nROM1V3CWbS\nRam/adK/E21+xvwYzgENnbAcInnVebYKw46urBhjCXeZQhimtJuaSPSdPqEi\nKOp+cMc4qcIxtqtX2l8kLoVKXuwQS9SLnCpRFwIwJ7Y1SHTlLArtMDuaD3X/\neGae\r\n=U4PP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCYPj9xusGZrQg5X7HfCB9iEelk3iFXltKbDpBxxeMpWwIgcM+0qoesQOD6F9pSewJ4MyWxahDWHzVPLV06CBNpNdI="}]},"_npmUser":{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.4.1_1604599374009_0.6161764100777511"},"_hasShrinkwrap":false},"0.4.2":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.4.2","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.1","gray-matter":"^4.0.2","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"1.0.0","query-string":"^5.1.1","react-live":"^2.2.2","require-from-string":"^2.0.2"},"devDependencies":{"jest":"^26.6.1","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":"9.x","react":"16.x","react-dom":"16.x","webpack":"4.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd example && npm start","test":"jest","release:major":"release major && npm publish","release:minor":"release minor && npm publish","release:patch":"release patch && npm publish"},"gitHead":"7690136b6c81d056897e58a8d98ecba9c8bb3c06","_id":"swingset@0.4.2","_nodeVersion":"12.13.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-9wAsmkLw+DXb79Zh3teE4JBUGGJ6yciqGzPoJv54q5jORQq0bta6SrQ3NbzPl2wLDLBFsz4Ycz9vKINWVyad4g==","shasum":"cd17ae31e3949cbe2c8c4744c628f975afbd1d70","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.4.2.tgz","fileCount":27,"unpackedSize":97384,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfqYROCRA9TVsSAnZWagAAXqoP/1L3y60lxvWgILdHL4fu\nE98cjEGW/YlegEFfkzQE/ZfTtcwz5iiP1bF1dxboyP72kDQcys/bu/91+Yua\nDgCrmGQwVqyq59eVV7AKGs/CT8sGpxL/amhWF9JKJzoVN4HitaJuoCES1sJ5\ndfyRC4jT7fAKHG582KpWWjYj/bYCMaFqhKm1PwzpgGXrgEaiHPg/l518LKyf\nYpCxgYxVBjpTNFR8VlPwck1Wyk4SXjoEP1MijLxaylbPSKchW+BH/oS6kWJu\nx8sykOM8HD8Q37EilrLgVBC8rtguHmhmDtLpIlDggWZKIYqVkA4baZvDdZIm\n6mlRBZPV0URLvSlDuf1IU8lty/5SGwfX7SJOkVMs2iIWxC0UGLBDPxFGhotx\npLqsdzm7GVDh9+h7Wj2BKRkYTVmh1hJ++xK/GGMzBcADvaM2xVkQZqWllkCv\n53sS2TLTdTPqR4ayerh6Kz59ut6PeZKzqkJ1m9fPmpyxiik3iVluL2X3wC64\n62DiaUQh01226uKYZ9D9FxfiJIGrqQ9rz87qyii9nZj3QYV5wEXOKuR/oi1D\nw1a2qPDcG1Or/BmNpCyC+dDpW1W1o3tP0nUw/eDMDQoYs/uo98ZGp10Bfubo\nu6stijVFpXHBKzKBbH8YOtXODNEJCF1WPY6ja0ux8AbXLYW8cgoOdcTgL0f5\n3vmu\r\n=g3Ue\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCiuHwy+JrR2vUZw6SxQUnlElPCW4F9HuLspx9qZHHG9wIhAP4B4hvnjnJ5YF830lopmtdX1CbQBvftyXnpwQwKjCC6"}]},"_npmUser":{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.4.2_1604944973666_0.7433645299268037"},"_hasShrinkwrap":false},"0.5.0":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.5.0","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.1","gray-matter":"^4.0.2","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"1.0.0","query-string":"^5.1.1","react-live":"^2.2.2","require-from-string":"^2.0.2"},"devDependencies":{"jest":"^26.6.1","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":"9.x","react":"16.x","react-dom":"16.x","webpack":"4.x","next-transpile-modules":"^4.1.0"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd example && [ ! -d 'node_modules' ] && npm i || npm start","test":"jest","release:major":"release major && npm publish","release:minor":"release minor && npm publish","release:patch":"release patch && npm publish"},"gitHead":"fe3a1a8412bbf168fb839b4a2bdc9127021e6c05","_id":"swingset@0.5.0","_nodeVersion":"14.15.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-dKtdRw2z65Gp4lbGiriPxQGYjKCwH+warExt5kvbXKoxWo097D038UKON3egLNo6cHH8P6tFJ3WsvO6H8wn/7w==","shasum":"62487a9663db8074d7c4a46977312e9642abd0f6","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.5.0.tgz","fileCount":28,"unpackedSize":98035,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgCwUqCRA9TVsSAnZWagAAcqwQAKMp37xqh0W0+o4ehjt9\nSxJ9Ij2kJZLg4J3WRy/pscUFEtmX+/yBf56X0bwmvN7+yxDa32GPtvnrsj+v\nizyoySr5w4wHRsQLmkVUgx5yvLpnj1OQIBOXeB8AXLtVJKvQKd62C4dS4iGx\nvVVxuSgWBNCsoZfKURjU5PTo8SDkzX7TuZ+rP3UZcPcAVbX7dDm8jwoEVrTK\nuLpPJNM/CO4Bbp36LA9+O+hVKVxxPD4KQTE9po+Cd2B/wJMa/3IVowB4reIE\nDvETUUerMqIjLx4rcgSMf0TX2J1VnzKmLiSt7vrXiD45jl4lCMlm/fdtW9IC\nGGh+wawp4qdbf7Hbxcbpjz4pjIX2/f0YLztW21QbhJolbhVdEbi5AN3wk43y\nA3AErvXnt1E3LwazSmYVSLTTzzMrgcqbNzUMIpucn9Jm5OwKffVjy5TA1hFP\nR26JzuSd4Oabjc3tf+AkibBxBLJe286hfhLKHTJX/yiX1q2OjIStRrKDevya\nT/kaaJT1czgISTEAEogIzp8fw5qhgaB5caGSWfDzXSx7xIZ4XYIWcAIonD5j\nttxsq1STAi5bAi25Z5aaVL4qAuT9vbiIY8mWEThHg1Jjrk42r7pThegfAaTp\nF/eCOZzcmzUiqc7FDlA/8H2/bwvGjy0VgxaYQz9f93PRfJ1nyxyYDYUuoMHs\necyh\r\n=GJ/V\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCC2bso+DO0S9B1yP0vG3MHr/h1dnU8uupHPEiA4S24XwIgfG4dhSx5jbhl0xG2QFvB457r2/fXi2OmBDzGPuW+Hr4="}]},"_npmUser":{"name":"zchsh","email":"zach.shilton@gmail.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},{"name":"zchsh","email":"zach.shilton@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.5.0_1611334954186_0.9826563289402022"},"_hasShrinkwrap":false},"0.5.0-canary.0":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.5.0-canary.0","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.1","gray-matter":"^4.0.2","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"1.0.0","query-string":"^5.1.1","react-live":"^2.2.2","require-from-string":"^2.0.2"},"devDependencies":{"jest":"^26.6.1","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":"9.x","react":"16.x","react-dom":"16.x","webpack":"4.x","next-transpile-modules":"^4.1.0"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd example && [ ! -d 'node_modules' ] && npm i || npm start","test":"jest","release:major":"release major && npm publish","release:minor":"release minor && npm publish","release:patch":"release patch && npm publish","release:pre":"release pre canary && npm publish --tag=canary"},"readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n```jsx\nimport createPage from 'swingset/page'\nimport createStaticProps from 'swingset/getStaticProps'\n\nexport default createPage()\nexport const getStaticProps = createStaticProps()\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.jsx\n│   └── components.jsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.jsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\n---\n\nHi there, welcome to the button docs!\n```\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n2. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n3. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n4. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n5. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport createStaticProps from 'swingset/getStaticProps'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Anything that can fit into the `src` of an image tag. Default is the swingset logo.\n  customLogo: '/img/my-company-logo.svg',\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.jsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n","readmeFilename":"README.md","gitHead":"a99e8c5a0e39f965475c7dd17adbb2355b9aa8d8","_id":"swingset@0.5.0-canary.0","_nodeVersion":"14.15.4","_npmVersion":"6.14.10","dist":{"integrity":"sha512-m981Vmlm73OB4IE2mKbwQoQeRLK7n36DyiwbYhnNRlNL41CXae/Iho+fzV8SXL+rZ2UUDPKO8FKc+t8SzNUZpA==","shasum":"20ce975fdab9b54e3e5eaa82a4030c166f9cd8ed","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.5.0-canary.0.tgz","fileCount":28,"unpackedSize":98103,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgCzQ4CRA9TVsSAnZWagAA8pEP/iYDQGc8Q5xX9wmWiM0Y\n67R+c7OHbv1AtdGtCieKfHutP9YrPJoawxqbXUtkn/Nf5EQDkzNYxkpi7liY\nhtkZrUmxT4hM8hQqa1WxPd53CB1sX0jXp5EpilM+L6MCN0JwkEozubtEwDZa\nIqtp7v9wXOkH9W+sh52frCNEU9sni8QT0wwMftX2KLcnIvd9knCEd8LjK6LU\n12QTZMSZyVzlxOcMxcIkKtaEu6Ds2o+9uyd0fpdA4uAT52MYASviMANlrxrp\n+LO+SgwQdnLuxDWfKArsoJzV79eaYoLLxvINigKz2eHPvInDal9llDYzefQT\nElHjQ0L9EZR+s5tZ1zRztXxvXU0pd7jsOhlcGFOggdLWLMlzo3mk+9ose79G\nG8gxVLCYC0GkgKvR/9iXdGcs8a+qXUR30JyrnxdjhC9E51KZfvC0ha+U4pSg\nbwA3gywgB1e+3OiqrjVngE0pShsdP5tBgW/BpdEZ0K0lbv1hbkkiHCKpMZuY\nS4rZ2JUxBTAVN8shxF3eVg4jvVYx+uGJrTBjTxiPfgYEpj63Od5xzZ3eKUnW\nSL2386VyNgUKfKLVjq99A7x1/sujLZKiVyjza5qj6Bd2+FaxKFu3xbQnbMWG\nXpWeOZYLRK5QqRgyC/iuWXK93EwUc+Z4NfC2hAAb/9tPmGsMWcIXTIcbVf/P\nwd31\r\n=8/qG\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD9N35IO+BfrXSJMCa5P9e5FEA5k1wGvkAb5mccem8rpgIgVBWJ8s91eRqqdPIBXhHpbFCh3KsVjVqlYXdk4LiV69o="}]},"_npmUser":{"name":"zchsh","email":"zach.shilton@gmail.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},{"name":"zchsh","email":"zach.shilton@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.5.0-canary.0_1611347000404_0.3955706464023716"},"_hasShrinkwrap":false},"0.5.1":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.5.1","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.1","gray-matter":"^4.0.2","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"1.0.0","query-string":"^5.1.1","react-live":"^2.2.2","require-from-string":"^2.0.2"},"devDependencies":{"jest":"^26.6.1","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":"9.x","react":"16.x","react-dom":"16.x","webpack":"4.x","next-transpile-modules":"^4.1.0"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd example && [ ! -d 'node_modules' ] && npm i || npm start","test":"jest","release:major":"release major && npm publish","release:minor":"release minor && npm publish","release:patch":"release patch && npm publish","release:pre":"release pre canary && npm publish --tag=canary"},"gitHead":"3a407c21f6ce892124e4d2b37bfae445ed8a3f95","_id":"swingset@0.5.1","_nodeVersion":"14.15.4","_npmVersion":"6.14.10","dist":{"integrity":"sha512-g1V6DmfHHLyTEgofXLKZENCsOGDkan21J9DRBenpEtfWwybsfqs5numqxlnr9rrI6O7YDG8SznBNx4sgtEGoGQ==","shasum":"8bc1a426578cc5ed482067dcf8716ef79283a8d7","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.5.1.tgz","fileCount":28,"unpackedSize":98094,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgDuQoCRA9TVsSAnZWagAAIbQQAJ9mSRD4muogR1Qw4nBa\nUHmCaUNker8xu0AYvSgO2LwmSsauGBpKefg+cpcQYUqmUpEg82E+ppiYfiVp\nC/jAWNJAcVif5U60rvJUNncqXexr78QznAl+p13Piu/LZ56gEUXAJlaS+ijn\nd/uV21xFg4M5dZTuyAUqE6cGAi39QLo17GTCerF4pkSbcQuoFKui/ab6cies\nLo1cGlzom/CxHnaSXx7p2NnpfAIOOTDt8bSn7ZWVXIe69WSJsE/dAuoMGOhl\n/QvWmtG1WV0VB1es7Bn+AtpPYwnMKVkpyqZdSwBLZGE+KswiQg8PxCmtWWJn\nke0S7SyL8YdXsDflud3DNYinwNbjBPnsuC8ZfOB91SWBdiDRSWKv8Yx+6F/y\njH+YMnFM+2nSYqDg0fdcuejdsUDuHCKiXrK3hkNEHLr0Lv4u8g+WRba1Vnm/\nxALxiyp4M4FT92HJnfjbyVN5/fDGnQjNe5lcQztxqCQocsLSzS4B6Cd5Gbgv\ndmfii083k0ufbXf1Lrq2bHRqoMumd/vLokHUvMpgxcEKTHqHaKA+GW237+Wi\nTbiuZbiGV8++LCR45e8jEQJlIjmJ44IxpGRXRlUIT27KiGH4r9JQ7oCEjsyr\nBKdwe1aEbvfTKE2tmnLpIImBfQvwO69ZsvyaFe81jiq51pwyboEzwtFBfMPq\nn9Y/\r\n=pXhT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD5bbm2k3BIdgKUuhAftpTJAFILR9W5XkE6dnrRmRCN9AIgOPqU2Y/wr2caJ+gqalbYOB0TIJdyTj9sntafx1xmGQI="}]},"_npmUser":{"name":"zchsh","email":"zach.shilton@gmail.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},{"name":"zchsh","email":"zach.shilton@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.5.1_1611588647659_0.6446260412685048"},"_hasShrinkwrap":false},"0.6.0":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.6.0","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.1","gray-matter":"^4.0.2","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"1.0.0","query-string":"^5.1.1","react-live":"^2.2.2","require-from-string":"^2.0.2"},"devDependencies":{"jest":"^26.6.1","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":"9.x","react":"16.x","react-dom":"16.x","webpack":"4.x","next-transpile-modules":"^4.1.0"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd example && [ ! -d 'node_modules' ] && npm i || npm start","test":"jest","release:major":"release major && npm publish","release:minor":"release minor && npm publish","release:patch":"release patch && npm publish","release:pre":"release pre canary && npm publish --tag=canary"},"gitHead":"ac2309b8d8ccf0c969d5cde2c3eea25347d861ee","_id":"swingset@0.6.0","_nodeVersion":"14.15.3","_npmVersion":"6.14.11","dist":{"integrity":"sha512-7Wj7/fY7FC9TCeHX+csCgDgYRLQMSDdHzEVtNFAOvN0RzIrZG411SV50iD39FtKs6xZezdS227mnUd8CrK4d9w==","shasum":"dba5b01e5081683c6e1d7558c3636ed24b8def7b","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.6.0.tgz","fileCount":28,"unpackedSize":100323,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgRkDnCRA9TVsSAnZWagAAFkAP+wSv3VCx9FaesGJ6gyqc\n7Ee7Z+73zsJ4PJsLzWs8xkhtbfyLcrclXgYB6ipEBgRep+ES20zEcSqhjx4H\n4876BImcjnhdPmzvV8M73yNjJxwVzN0JV15FZ9EOj6m2TEcioyoeJfFBhPLO\nDrtg16NNEB8w7d7iBjCbws5bw4E0yvqusw4svBVpvHXr9bsWJ/s3CimviXO6\ndPW5irQyTemJmnbsHeHhCxXGLBKwlwcdTApw6jVbjh9sxT3EVXOpLwk7HYjR\nMiKynSvKXBW/FHs0eWhlqUa78Xj7jA+pMj+dqgCBPL22G6ZgkzefpxAxj54w\nqTWogzHYkIGIf3DGKbZ1p51FMfH1vzKf91elxLFRJHuEpQ6VsavuPfcZKKs3\nNYfh/D8oGgkoG6Vh+DiH/6Ybwp3S55jLx9dm9cR7JuOqsTlTXfmnuj5X44mi\n5LOR2z46u4IDMdyBZu4VENpKO4c8hDbm/a4Is58Mg0MEpsRE/MDuthQAkrLN\nHnqL0IhRjY6akkyUAYU1qAKHWmMTeD9lv05LrRleC9Uw9Chi92hWnrEj7b7G\nf7U72sJTHhemWO/+pzxRC8VmjImwSDocJa2TtPh2vJZmwNSj18Dq5+T9VbKP\nWBQub5PMkKQwQjZotKdVqWdORTvzy3wXlhSqwIob5QYuDPRS1Z1PD38UeZaq\n+lO5\r\n=iIfe\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHw77pBDpwe+/AOqmG2AM7WC/Cj4KwElaNv7EEiGoJ0GAiAnaXxuziPnDYfQGJKHYIgvFRIGrls4Xdc+oWU3FcFTQw=="}]},"_npmUser":{"name":"bkalow","email":"bkalow@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},{"name":"zchsh","email":"zach.shilton@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.6.0_1615216871339_0.10688745515669829"},"_hasShrinkwrap":false},"0.6.1":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.6.1","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.1","gray-matter":"^4.0.2","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"1.0.0","query-string":"^5.1.1","react-live":"^2.2.2","require-from-string":"^2.0.2"},"devDependencies":{"jest":"^26.6.1","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":"9.x","react":"16.x","react-dom":"16.x","webpack":"4.x","next-transpile-modules":"^4.1.0"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd example && [ ! -d 'node_modules' ] && npm i || npm start","test":"jest","release:major":"release major && npm publish","release:minor":"release minor && npm publish","release:patch":"release patch && npm publish","release:pre":"release pre canary && npm publish --tag=canary"},"gitHead":"5bb231ca8b80dd9ca921d8c0c590c90351b981f0","_id":"swingset@0.6.1","_nodeVersion":"14.15.3","_npmVersion":"6.14.11","dist":{"integrity":"sha512-D1YrwpIbhthcRAR+kSkSHc4eoRgnvH96BC/GwLzrHvMoqkW0J8ECUTsecUOucKr0iKvK0hJ17Ib/ZACXPNO2Vw==","shasum":"675aad8866dc51f4a0f95cb7847c54a098812156","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.6.1.tgz","fileCount":28,"unpackedSize":100309,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgRlQYCRA9TVsSAnZWagAAv2UP/AyTMjT8SI4FBs44vxYd\nu+dplYHETcaetw0PIi8oHUbdVkxDy7270VZuB/q9I7wsx1Zk4NdtBHrFb1cd\nu7+kXareP7k0AKdzhZhVaEn2DU6uI4FRetTSPR3eBKLK0q8KyM9+SCa8dq/C\n3iSj2Oz0hbZzGx3CdpMDasov92C7pw+yAL/oe0OvjQICZfcdRTRwyI3I7+EM\nSiOtSUO8wjMdAywZ+Fgj2GR5CMPOgO/eKF/dfPhqikPy0sB2evR7b0cxPY+O\n7E1P1igiCCzlhnHGz7Tiz8izG6oTB4kFi9xdOI2j25EOKuWrHjW0YoWspAp5\nfo5k8NHvEOPDMUeACNsDZTQ0LjM0R9I2MmVodehA2Fws4sxrS2l1+cb51PbU\nc3dOKwHjcD+f6nwsy5AI3U0JKaqvqWzq65YtZ7o/IF2kT3iBwt0QxlFwZvF7\nqLVCs4saLUM0Q0ncUcGG2kd0tP4C9GpofjmQSzoQ4RpPZK9FtUVjWz/vWs+i\n2+nz5poQ/5psiS1ML13gba38itjQRTaT0PZyFM/qap3MfqYan4qH26QlNWrT\nCsps3ZWqDpE3cxZlGh2SF7JnrDwGhD4AXGULqxUjVc5ipw52eklK46kKjjs8\nRVcGbyRW4+69qSXBym8FkxqW79BN/oZY3k5x8DVf9ov2qeWQJKvQ5X66Bw+o\n7U4F\r\n=2xZu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDOsO2ItanT64wZJf02hw8risWRmnJAc4OdRahyuSedhAiEA+g82b6NtsKEabrx4hSvHAyn8ZIm8uITV1hv0+F2xfMI="}]},"_npmUser":{"name":"bkalow","email":"bkalow@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},{"name":"zchsh","email":"zach.shilton@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.6.1_1615221782959_0.3224514286124751"},"_hasShrinkwrap":false},"0.7.0":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.7.0","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.1","gray-matter":"^4.0.2","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"1.0.0","query-string":"^5.1.1","react-live":"^2.2.2","require-from-string":"^2.0.2"},"devDependencies":{"jest":"^26.6.1","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":"9.x","react":"16.x","react-dom":"16.x","webpack":"4.x","next-transpile-modules":"^4.1.0"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd example && [ ! -d 'node_modules' ] && npm i || npm start","test":"jest","release:major":"release major && npm publish","release:minor":"release minor && npm publish","release:patch":"release patch && npm publish","release:pre":"release pre canary && npm publish --tag=canary"},"gitHead":"1d8b1cfd4fd1f93e4dcf23ab034820fee6617936","_id":"swingset@0.7.0","_nodeVersion":"14.16.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-14om7B4lm+O4OlqRFxd+E0ED0S4t1QUCzFP8BiBMTey3CPwfKq6JfrwDnrTjf343fgM+QpMc/pqKW1IehqRBzw==","shasum":"6af418bf319d92ba51fd6d8cbe00e72fe7738c06","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.7.0.tgz","fileCount":55,"unpackedSize":1247182,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgZjIqCRA9TVsSAnZWagAAKaIP/0MuEH59mTh1EtcANmPD\ngHTx1S1xl+NmolhQ8YwoihStV/TFqjavourSfppgXXX+p0IYnQbAeAqqRE5m\nHUbROtJDcF6xxKLFoyErBolPYF2bzqRQxDM+yfsTbw+YPq4dkMzdr++1++D4\niSIYIzudZUqNHeWH3x1Sf82n7PZKNXEfyyKbFSLGyFxkQTV2wAvez/iLZKCR\nROF5YTaD0Q6L8f9CF4VhOBnrMUczRT0Cdq13MJycN0m0fxzBzMCwjA3E1htP\n1Jb3OsWxgWG9AoXfut1pDQF779iPAaI5Yuyl1V5hHJPgMmo0b7zrZ6/xERXI\n9IBGNskM4I6xsG3HwLpM6oXIJK/ZJ7Z2IUnG+lhV2sUi+bDbfBVCJs5JcUCK\nWgJKagxbHqphEQm3VHdKnBoSiI9qHhzdrpl8OQhgyea7UxD/wpl2GNDZza4h\nOohdnY4HaksHnHfK5emz7JmJdpShab/Zge+isWS8bhx1C+QpWI6ex3uWuF+E\nR2yY/at6qhxHgaaayc79Bc4LD2oWfEFMhdWwdt677n9oqsbi+5QLs1i57QNp\nXhakcJtW9rw83IYtsPsHmgYexMqvtXQ5Ek2FmUJ6oMSyEZ8SLwRoF6Pum66o\naIm9fYhdcXjKJ2SUA3WuXXpsscUxk4hw1UGR+5MjXBlyoyYdytia66rg+w1O\nU+QU\r\n=I1oU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH+piUPRqnvsQRLV3aEOK95FpE2/uidV/zZUqRvZy+8aAiBUDcozSBxa1/xXJdpLaKwuf9W5jKNKYzvjxEvciv0vQA=="}]},"_npmUser":{"name":"wkentdag","email":"hi@wtkd.info"},"directories":{},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"zach.shilton@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.7.0_1617310250231_0.3556849433618372"},"_hasShrinkwrap":false},"0.7.2":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.7.2","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.1","gray-matter":"^4.0.2","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"1.0.0","query-string":"^5.1.1","react-live":"^2.2.2","require-from-string":"^2.0.2"},"devDependencies":{"jest":"^26.6.1","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=9.x","next-transpile-modules":"^4.1.0","react":"16.x","react-dom":"16.x","webpack":"4.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","test":"jest","release:major":"release major && npm publish","release:minor":"release minor && npm publish","release:patch":"release patch && npm publish","release:pre":"release pre canary && npm publish --tag=canary"},"gitHead":"2ba18dda0495134d581d7a902d37851055238ea4","_id":"swingset@0.7.2","_nodeVersion":"14.15.4","_npmVersion":"7.9.0","dist":{"integrity":"sha512-b90tLlqUNpXLqhRJLlI9gqisi+EHziLU0BAgpQ1WUnVd5NV7E1YxZNShFd39ztx3o6gkahj2iZO7fyd0h8i56g==","shasum":"46bf2ebffedc6a62cb59fde3882576307e71db5e","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.7.2.tgz","fileCount":16660,"unpackedSize":122413187,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJggfFCCRA9TVsSAnZWagAArHoP/RQozMg3GZy4G3IROmsc\nbD8wUy/tvUhHw92cFlaOUntWqDeN6abTl5MHQ5bPYAtRhHD2d4hLzrKk9iZN\nDINf9lsQs5YDGWojVRu/NIgihrzioXSTLjEWmDxYH4uTQHkGrpi9uF2SHBY4\npc1Q16PWm0xMLQQMS+zOxzpwSD3vdd/RcnYLt/B+TEN86jcS53WOzX/n27nw\nQ1ua15uUmKpEWXFzrnI65VNC0NhEdjglwN39+DEQRTs7Sz3WSgOfXiL8T+fk\n2u4mxpzYGLpLecXDiaUzmibXNCeUAwzYpRYEMXtyU2AvkNNS98Bt68+HT7We\n+zPrusMVJQ+bHyl6gS1im5o7W0WZedzB669mv3I6XdgbJ7zcJKpw0Cjqausi\nDS+2z4Dq1f8iIBh+B+QVdD40xzRK4hl47KsgaMLV5aUzOm+qnqJID28SJNQ5\nEdh4T6JOQgK+NwO9O/uIKeAwbWOL6R0uKDd3KGpHPHorLiu0CZXMWefio7Rz\nz7Yrlu7EnJ1i4cGub2xq2yA7OE4gZ77jPUxckeRVCfLRlxODaLblqTOVTDLR\nG3vMXs43HvNgV8e5WuVIyEWNoYK2A1IlwblJQMb5XxpGvoFeYh/+yfOpbSzv\ndCWZyR8Su+DL0UnHF4LJEmTKJhIiWQQNsN3VfuUc+crvepMJsdAKFk3B56ZA\n8iIQ\r\n=aLjT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC8B5gpcEIxoCTrxIQFAXveJTzLswlFT0dnZ9RDOQ/jPAiEA8C6cya5Qh5q3YBClfbYoyQi3pl9pmzrFZY8WguMQV4Q="}]},"_npmUser":{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"zach.shilton@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.7.2_1619128641193_0.9018609042554637"},"_hasShrinkwrap":false},"0.7.3":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.7.3","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.1","gray-matter":"^4.0.2","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"1.0.0","query-string":"^5.1.1","react-live":"^2.2.2","require-from-string":"^2.0.2"},"devDependencies":{"jest":"^26.6.1","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=9.x","next-transpile-modules":"^4.1.0","react":">=16.x","react-dom":">=16.x","webpack":">=4.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","test":"jest"},"gitHead":"c6763594f2257f786d342a3968b0273429475d50","_id":"swingset@0.7.3","_nodeVersion":"14.15.4","_npmVersion":"7.9.0","dist":{"integrity":"sha512-ZYaF41/zVAvfBUuX/xBuo785Ynb86m6Ya1HZFwfrWgVu0ATyxgTUjJ3crAQELi7MPrPWmdVh8wIr7uBUPtIXmg==","shasum":"f32c20cda5cdad6c05dc9dccd230a6d90bade63d","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.7.3.tgz","fileCount":16660,"unpackedSize":122413199,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJggfMPCRA9TVsSAnZWagAAdH4P/3QJeTMdpbR1+Fv75zJb\nsqCFjfKGyQZ95FFT5xx2z7bHWW4W171CTP+VrkTjcwdZPHIVwkarp93LSwjD\nN8Fnwl+12YuRRdnveLlp3Wt5WRB5UIhHGCpxqJpmjmhPKIE2LQ3qUK4XKzpt\nazxmChTqCrKcC4rXSB+dInDWEWqC7RAjYc9LMsP5IijXiZ7rgCTcUbcx1YkL\njG+c4xNdH1qecKt/Dy7SIb3RYRwSfts8rGnh7GqwGK21NtEMgKwBlFn3sCdO\n2RpvsWMoa1rUJOVHOAJHcWhLh0MscNnEApXHKgcYx3107HV70/dd/F5ft9dM\nWocc1nyCVfp1TpAGDSbM5XhQcTM3URloGUYHS96fMk4atHILMYm4Xcy0zKjN\nJAeg2yQUf0IUT/WjcTXz7BOWs/s2rm8XT6Vrzsn25tltPtPTqjLlluLaseHn\nPCqQh92hWLMS71NXPBUB1AalO/w7/JhfssTmAFT9qxhB5lMD8nO4WZdOiG9Y\n0wtNafdsWb+4Z4jxrPuE8LBAaZMCn7hC4qvDyDbuOROmOMxbl3Mdr6JZYm7g\nWscL819ziQi51BJT4Ya3Ompjj47gIB27hU0CdvvpziV6G2fPJgsE7PgbJEiy\n03JXA5MC8f0dW1Dj1SPJo2GA4ghHTUQE1QJvNglVtMJWZG1v8i/OKwF3Ijir\nRoao\r\n=L7Gm\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFlr+wyae/S5rmA3lunxMopN3ebsCwFi7KZIaK/7zIPBAiEAxQFYZoKWiGebMgqLQSM+OwwMCKD+7GxgafgpKmD+ohI="}]},"_npmUser":{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"zach.shilton@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.7.3_1619129102920_0.39890194695192727"},"_hasShrinkwrap":false},"0.7.3-canary.0":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.7.3-canary.0","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.1","gray-matter":"^4.0.2","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"3.0.1","query-string":"^5.1.1","react-live":"^2.2.2","require-from-string":"^2.0.2"},"devDependencies":{"jest":"^26.6.1","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=9.x","next-transpile-modules":"^4.1.0","react":">=16.x","react-dom":">=16.x","webpack":">=4.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","test":"jest"},"readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport createStaticProps from 'swingset/getStaticProps'\n\nexport default createPage()\nexport const getStaticProps = createStaticProps({ /* mdxOptions = {} */})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.jsx\n│   └── components.jsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.jsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components you list in the `peerComponents` frontmatter key. \n    1. In the example above, `<ArrowIcon />` is added to scope. \n    1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport createStaticProps from 'swingset/getStaticProps'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.jsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n","readmeFilename":"README.md","gitHead":"afe115fe17a0fdedc78a6b060651e15edb7c3e50","_id":"swingset@0.7.3-canary.0","_nodeVersion":"14.15.3","_npmVersion":"6.14.13","dist":{"integrity":"sha512-qnd8cDJl93JxrQxaIKJ11ubxtSl9ZJAQtVGfPLYKxd1rd91Gh9zO+qSrBG0cgtjHjtdfFfqSoQH/XATjzY2QVw==","shasum":"93eb6837141cc8dfb2967c9e41d9437e9ae4de1e","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.7.3-canary.0.tgz","fileCount":55,"unpackedSize":1247216,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgkZpyCRA9TVsSAnZWagAA3o8P/1KzEnBoLXcHCFfriW4n\n4yZvcf9tdXbCsZtC2RJRkR+JRc8IXa1rLnfXESTpisC0AwZeQAZxP++2XsyF\nZJnUkYHBHNKGY81Z5hPlW6IYAuXa0CmVSPvKvD55w8iBKulVGTrHf26xci2o\nG9ZWtQzD+mrcGm8AYEfFyJashbdvLCFYjxEtv4RKi4np3oiOHq/tu4odOvvB\nW1M2782YZjf63GYH88xydwZSmoip5W7IT4BBRNnMqdd4sDawsys04UYG30ib\nDPLKWnnX9yVoem9gbW8dAX99pQ/r4aPutjMsU2nWdoCALcoZ/2hxAtoW7a8f\nokuqk0BqMxIUEjSpS9swzuppwjNILVvNpOk9DB1NKkjJDO9t2R7TwEwjuUe4\nIZKU4KDuibAdDVgn798KST14OJnG2aZ73uQel1qqAfOF3wDatmjBdBy7XGCS\nH5PGvA+h+c3NASBzUJX4KgGuRnh0utqNPZQYSAO41BzSt2nIkHJsq9FnVcwq\ndgGMDU6aTdGXztiWBw5pCFxnj84ZAR9Y/S1dAup6MZZ3MHwM89RTocPYrRjz\nhwTKg2Z9DDlrTeIiu8INyLqvW/pp/drmzRXCTxe4QN2QBTuaF+Wvyr7ZKtBc\n0hG99eMn8RWVjiRFP61xNV9ie0F9YuVomODgBJfsljbLrGuJQrtSFur1ffo9\n8FGF\r\n=j7+2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDuZ7Kb7h3w2psN6zQm4k0owGW4KKi+fq0sDMgEBpo0VwIhAP09G5L6tlnYaEeRSpIkXsY6CtjGtIifHxCj5D+LbkaB"}]},"_npmUser":{"name":"bkalow","email":"bkalow@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"zach.shilton@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.7.3-canary.0_1620154994121_0.9510252063967699"},"_hasShrinkwrap":false},"0.8.0":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.8.0","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.1","gray-matter":"^4.0.2","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"3.0.1","query-string":"^5.1.1","react-live":"^2.2.2","require-from-string":"^2.0.2"},"devDependencies":{"jest":"^26.6.1","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=9.x","next-transpile-modules":"^4.1.0","react":">=16.x","react-dom":">=16.x","webpack":">=4.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","test":"jest"},"gitHead":"aa0ce5ea625af3952e6c0c0aebf6a2d1f877d76d","_id":"swingset@0.8.0","_nodeVersion":"14.15.3","_npmVersion":"6.14.13","dist":{"integrity":"sha512-a1zRSdZWshqdKAO6TsKjF8h2OTLyS6cqGuOq4NAPrH50AdmQenb+xufCJ/+TO1kD3dJAEpPJIaiyn7OEPdKHmA==","shasum":"2bbe9f9273f521b0c54d425b94acad6290678632","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.8.0.tgz","fileCount":55,"unpackedSize":1247207,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgkdLlCRA9TVsSAnZWagAAu0MP/R9m1W0/wfFtlX0TrXFu\nn6AXvn0m++iry0DZdc9y7ZzZe7BTZdNJCbBgsQqGA06LXeMrgd1asd+/HIAA\n3+WF5+kWOkYWG/DHX2oSnk5+piBuNWchriQTi9f4ankYVLw54YapBdS2HVKG\nJEuelvFvakzuB7VszkeFo+gEzA/x9LgQLIJVFU+1e+TP/kcucjUIKbWIuvZs\nICHsSD5pXcCqW70CxjSZEaVB3nqsXPY+HqgljzMfNohRodn/CDLCNXbAVQFt\nqeMNvd+ZCwgQtSm2Pr//5uh0GVA6w+KcJuOXCXDtKvIQE46PXDHPgA7zLdUP\n8pMosP3g6pcLzASmrGgCeXOghhIDCVB3NR7O8ZYOLjIePlMUfe14xANXIAB/\nBJCqLsP2tAH8r0LfkR/6q/cg5L0OU7o6Q28nRkxLnlShLyapBn0F7tsU4QPQ\nAZlVvKonfzl2KM05RfQrPamS2bPo3WXPkzm4RCsrvvpze53Y4ID194n7oJNN\nnRa8h69PZrTyDtkEJMS+QaaY4yUCnRlCfqYsTKd/YWlNkF4OEr4IKcjPFgEr\n4JFaaUcA1G4HDUJLs0/l/qBxfcA3+refz8xq1xIDLHHetTb4omg59b98doHk\nfK4LETwdwxLaCt7V44KXWIGnkWioU3GlOJ7pQsyISfJrH1nIutvWI/co8Z0m\nIkdi\r\n=82Tn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHS92l3NTHbuP8/x2MTgofFQEsJn3MH0HLo9QQgom1x+AiAoxH9lu9IAgpmo7YCNdQpystmrStfS/xTX8fXh1JvFQw=="}]},"_npmUser":{"name":"bkalow","email":"bkalow@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"zach.shilton@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.8.0_1620169445334_0.03216025543347367"},"_hasShrinkwrap":false},"0.9.0":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.9.0","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"3.0.2","query-string":"^5.1.1","react-live":"^2.2.3","require-from-string":"^2.0.2","slugify":"^1.5.3"},"devDependencies":{"jest":"^26.6.1","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=9.x","next-transpile-modules":"^4.1.0","react":">=16.x","react-dom":">=16.x","webpack":">=4.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","test":"jest","start":"node server.js"},"gitHead":"e9f73227289013f257148dc9596da7bfc41697d8","_id":"swingset@0.9.0","_nodeVersion":"14.15.3","_npmVersion":"6.14.13","dist":{"integrity":"sha512-FepDH72EewU5Ezc+yEv6dULsTAbdWPoO58ewOQuWe+QqkocfKMoIcnM9lezDBH+/KA2ee83nmHBglaTbxDO1+Q==","shasum":"5760d36136e6cf9814fc45bb77eb45f3464324b6","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.9.0.tgz","fileCount":33,"unpackedSize":107909,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJguoHDCRA9TVsSAnZWagAARoYP/331P9AZ0/w1W6nOR+iP\n8JwqC7cOiBV7MNcxXSQgKRrbZ4oN4CO9v29APstsg8CZmWLD+XFtlKWTBktS\nDRfDERQS95cfrplMy7zdTXg8kCjxnzbCrRdr6MPFF+68Fv45M4favgjK5dpW\nqZMiIeqhQMQxOG3dxdSYeOojD+2pcNdNc05iURRWuJO+YsyAMKNbf1eY4G1D\n1j4SQLx2KIexPnP7GwZzr291J/KAZQZ2dtsLDzRwOebKL+0PHalryYqdLqNo\nFR6W5YNy39MpX4CBI9W2ZsiVWF0FmHFLYH8AyLpkRU0zRT+g21lgqBnVeavQ\nbM7O0V195WKhdCBlgUX8f9aZD4GBVDS2otfQnyg2wYWh1Zk6UP1p7cmv29gy\nV72GzjvUCfvBzn7X22TVXFYD1msNJH9tfoAo7v+Yg7W8WRuyUe4jcnRPE5MT\ng1f4fpCi760IWIHwQHY096b62k9SDiGenPllmA0kLlOeslnD+x50hQLMV3XX\nmWYQd+JJcCtXzE06zkjycAlkYvzTdJr5ElGPQnHhZRt2vVov4UCQF7pYLMZQ\nH9BawuPjo/I+ic0VM7adpkKjcz9yNWsocIEy/5YZXAspl0rMTUSkqQTQ1B+U\nc6fAPPiLMcvQS5v9JXFSOLusR9PCYnpIaPqO+6SCM8w9AYDcXJAcUKYP/wCV\nLiX4\r\n=Mkjz\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCttOCSt7fca51tHxKfcf0KiBxNNN4v3X76g5pBh9gBzQIgY8cWYoUa4L5r6HivimvKy0I2xeU9f/H7c3D0bkxSlQw="}]},"_npmUser":{"name":"bkalow","email":"bkalow@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"zach.shilton@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.9.0_1622835651309_0.6923752559019019"},"_hasShrinkwrap":false},"0.10.0":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.10.0","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"3.0.2","query-string":"^5.1.1","react-live":"^2.2.3","require-from-string":"^2.0.2","slugify":"^1.5.3"},"devDependencies":{"jest":"^26.6.1","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=9.x","next-transpile-modules":"^4.1.0","react":">=16.x","react-dom":">=16.x","webpack":">=4.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","test":"jest","start":"node server.js"},"gitHead":"63d39f74e4d8a7fd9f2b41b5a8d9f33710739369","_id":"swingset@0.10.0","_nodeVersion":"14.15.3","_npmVersion":"6.14.13","dist":{"integrity":"sha512-RJW9Z7LJ6Lgb1mFU98WjRQdnsxPA0Er+QnBahKE+kuYiQ7XhRLlppw7uBsUGwptehx5EBlo7JCPeKIUzqWjzcg==","shasum":"98bab85a2ca6fa2bb8e33d8463480d6174aa5ed4","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.10.0.tgz","fileCount":35,"unpackedSize":112816,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgyhfcCRA9TVsSAnZWagAAf9kP/jMkbPp5tPlIGvOKNQBY\n9k5J/wEBoFuPRSWoc176pQCrDEUH0rwvDQYBmW9IUbWfX3hnTU7NrrDz0j7r\nQXN0ysD07sLDaQJpakpvqQr96Wl7RL8WY0jwmCKiBQMIjdcjIUT2Z/T59Vhd\ndMG3DBUjwaLoFHuD4DXhtmuKETc+sRmlNR4bSqbpPRjf1nNXQ1MlUG/M1QYy\nFvQwe6YC9MKNn9JjNmwUAomdjd4VUaqjvKz50yg3Vc8AOoZfbqTRAlilU2la\nmhz1+r46d7XHYcfFi6Nu3lClqOQziXjKJ4D22NNw99bIhDm6x4ASSXeIZBQ1\n3Armw6bUxqAw/ReLz/M8UuzVa1puycdZzbcKQKDOm9Bf5822rbY6BGmRz6OY\nWaVglzTZMYmcvnukFEm3COL0UHlx7t5liggwl5cGzvfKMNS/pvMoUhqbWSLh\nfDRdzfLYmHSwG+jkVbZJAOVKEjo5GqEuLhYrbarGKeXCivLWUZJf834sbCay\nZX5pJONLyNXTxH+Hi19qGbmmQH9MUhnyDvyS1iJTdVRlwDZOGNosbahm3p/T\nbapnPA6Tu1uoXnOI1pz+XY/PiLlJfEtrIpOeZNGLfXXxYe5xwslZRETqk4xc\no5w6RDYJ+VLcskQf+TkWSpS3HN447MvsHSpy8tfgt5WT+fcnkU04oyfuAyjV\nEeyW\r\n=zuFE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEPxtGGZ64v33h5US+S19gFH7dVT+mPfihAl82zjcjFWAiEAtOyLIU179y/dW+mGyAwdqMnco/FSL1crKl9m6/qChTo="}]},"_npmUser":{"name":"bkalow","email":"bkalow@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"zach.shilton@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.10.0_1623857115425_0.3258426424941636"},"_hasShrinkwrap":false},"0.10.1":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.10.1","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"3.0.4","query-string":"^5.1.1","react-live":"^2.3.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"jest":"^27.0.6","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=9.x","next-transpile-modules":"^4.1.0","react":">=16.x","react-dom":">=16.x","webpack":">=4.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","test":"jest","start":"node server.js"},"gitHead":"97bb4e12c7de27b59c9f036b4b3bdb759d41be7e","_id":"swingset@0.10.1","_nodeVersion":"14.15.4","_npmVersion":"7.20.5","dist":{"integrity":"sha512-YwSCCSW1RHFO6xkGe+qCCyebPuUAGO2sjXcaVYnOC87WR7SzQWKgQEkl+OO+mMS/ask8pTeJTm0+3dXnMW5RdA==","shasum":"d5602be5a2e650054b3a326a942db7b8cff73a50","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.10.1.tgz","fileCount":35,"unpackedSize":112816,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhEbhkCRA9TVsSAnZWagAAKa8QAJKb6PFvDtkNuE1RtJUt\nYEE/k0y1CW17NfF8tZk32xjuss9rWiJDLZWgnAom5phAhWTaD/mm3LiqIDHx\nfWke6X1T45oRryqwnlnenBYPJVz7N3a4ddFq27+SXonW6lQUPMZeFOkOI3Jj\nVKLVXdcH3TqH/uV73y+1P3lf39VghCvlbbsoAL7umsyXXRIiyD2xfno9Py7n\nGwC7j+dDVFivztA+Wn3UwSnsWEbCHohhiZ4pKfLoQZhsapPKW145Q6NTTUQi\nbFNcmfy0nyvruf3I5V2b+puaz37StbNtIxgPNyqu2a0K5R9c90mduK/7aNEP\nFzufENkHmgg32i12y9pBM+eSzpIZryAbF9HrIryrEscnyRxkBOMPdhp9vLsv\nu1MmHx0kxJeTlLY+O+zl43tciJHBkgeh1p2E2aySvtjUTta3snwD+6NUAN2d\nxZXVMqoEMsNoPOXXmMQuvw2FtSyRbe7Twjkqjyxd2jJuwi5TIWSAq5Lu/QF/\nq5UUJDouH24jmksbvq4E/CIOggzc/HRK/Y7eI1x1FY+CMDeX/+5v+xULQ6qU\nCHkGM/4AZc1GEDlSi9rnHkd64NpM6EYrzE32feOHVtoLzibMV2yoYYyahMRg\ni83H+CWytINNKpgZYOE2lTJhC6fz8w0NqBTy1kV+v0e3lGMI45wk74eI8O+W\nw1lL\r\n=UIGH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID1ViTTXjvReBoNssKOjsYCK2hrFSSug+KNcZm5jY3fZAiEAouICVHNkT8UzcGtGFdlL/bzeiCfm0eEOEjGnOxVdo88="}]},"_npmUser":{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.10.1_1628551268695_0.6070831034206827"},"_hasShrinkwrap":false},"0.10.2":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.10.2","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"3.0.4","query-string":"^5.1.1","react-live":"^2.3.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"jest":"^27.0.6","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=9.x","next-transpile-modules":"^4.1.0","react":">=16.x","react-dom":">=16.x","webpack":">=4.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","test":"jest","start":"node server.js"},"gitHead":"5fbae60a2d13283e5850fae0333bfa6f9f057231","_id":"swingset@0.10.2","_nodeVersion":"14.17.6","_npmVersion":"7.24.1","dist":{"integrity":"sha512-188hgN1PjY5kUj4CeglYX1NcTZdlapvv6HOPg3sC58eBH94umsd5ONUB1GXm+hDeUouFsTA2rwNd8wqsDQ2CTw==","shasum":"6b4a5fb6b901b6aac6199d92202fcb59b0fe1e06","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.10.2.tgz","fileCount":35,"unpackedSize":112846,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh28nvCRA9TVsSAnZWagAARLEP/0qY4ppyGnCj+co1KhHl\nF59dlm02D7fi5Uxhxcd6QRk33EVfO+LQNhOa6QwAYIXNggHRTEX4HD4OyLL0\nRREIOZfnkMAYymOSk7YaD+v5d/GIP7pxcJwlGjJtcGnaVMyg9xaQtmbUuJBx\nLPzV9yY0/jKR3y/o7zlgtnHLsS6+kufPudbNTHfXdtYIfYmHiTo1iDI1F2Jc\nJLjU0PsgPRu9z63EgCL0FY7c9AgbCf+a2qBk3Cm0sSjcMp0ZQ3d8DliPkurW\nhDMK5H5IcZiibD5PnH49O9PV7qx1AmiIQ3znb24C+G0WpB0npXklXYewZk+t\nyCxtDFnswyEcHMl7lPpjQbb+5MhnHTSymi4R047PUvgJLqkcrL6wKBgMdiBE\nD0zqe2NW0lM4gk6EAGPlTffjtYTc5tnBjDAu3V51QpMqX9/kwJe/6OuQhjOJ\nuAzSiLAZXdSnCVvRqby8RlMTk/GNm6YAevHfcc6UVD3sr37XrEhPL3Q9NSQc\nOr4zP7UzrdA8AFSKOtmMZ8RMgSRHioctjWY4pUgz33g4Px7qETrlrn7a6mp3\nbXL425Gwa9ra+YjpLgTJQUBubQZpVVjH0ps49kXPDXkW5IlOK5PHCDgqzBIW\nNdY5rmXIv26l8d5zLaN+I3TgnNqJ8o7XlJgndNNSQm0ISd7J6NY2wi5Hnquf\nNbEw\r\n=cS42\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBwgrYxA9jn3hJ1Awx9w2c67LXMzTy7mpzvzawKUx3/GAiEAkhw6j0jifeBIXZwVq5SfPkgh06RYv43Oq56/9HQyeJ0="}]},"_npmUser":{"name":"bkalow","email":"bkalow@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.10.2_1633029757732_0.16034177176429032"},"_hasShrinkwrap":false},"0.11.0":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.11.0","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"3.0.4","query-string":"^5.1.1","react-live":"^2.3.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"jest":"^27.0.6","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=9.x","next-transpile-modules":"^4.1.0","react":">=16.x","react-dom":">=16.x","webpack":">=4.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","test":"jest","start":"node server.js"},"gitHead":"169750746870bf87bdd3c2a98e472048e1e429c6","_id":"swingset@0.11.0","_nodeVersion":"14.18.1","_npmVersion":"8.0.0","dist":{"integrity":"sha512-tq663PF48Sqx87A2KXpzDoa/TQxQw7apdDQXf2FjdBwkOTix5c2ixXMKSKUvxtZuMETrx2c3a9HIL849mqK1hw==","shasum":"38d321733d771de40c881ea504996d6eb5e747a1","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.11.0.tgz","fileCount":35,"unpackedSize":113029,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh4GdGCRA9TVsSAnZWagAASgwP/36P3MetFPqwn3krS7tA\nqYsUDiNReRp39bc4omG5AjP86/l3nU5L6u52ERX9pVvHc1g4E6dZssG9Hr6m\nYVoXM0E6QHXJPHe6FhBq3xCFEeAwFmqfZVBif6GcKAG+7Odr6Y4hEL4hhE1Z\nhagEqoD3Y7Dz2ec19HvjXgDADwK3J+EGEQuP12CBQ1PHBmreCFsfN+H7EFng\nuzvQL5jSq8WIq2Pwj2s7PeL20bYMWrFHeWvS7qqJccpksJv7t2YF3+6Etq5+\n4KrzzjhJr5vaL2TnUFRxPZZgFnyEmL7WfhBPmgZ/HmSLw1m7BGRKkYUITN/v\nCobIOCz8+mvFjTtUP7tgAz2EBGHf+SNPVRUpEWy9pafCLzjkdW5nYsVZKKou\nijBMFAuE1k/a2PNOX7XesVuubLcf3JeDdkKt2Je/DGeVaqqgCDBcG9UMNXqS\n7iCy6CayDLWSoH0iOwTQ8kmvnK1P3nKZh/kBgyEPqhSysBWjPpYQMexqhSFE\nBLFiQ6xJQMRu9sUDiN0bz3ystzBWLFCXz6PZZS9Ta/DeP4p2Sv9C/WF1x6SI\nYnmUz2fEVIGkkTkloVvw+dyNoAC3IhXdKdLfI+DLpRLXXn7nVZXWoFhBvPk7\nzcRS1joyclIs2OEinvvtc01XIwWSfBktg8byDPvnoBbo7KsbK7IT15RmV8Em\nvJqF\r\n=6k43\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCwt0vs2coI+uX9L5iW6HncAU25cP6H/f8eJsbW4YWxGQIge86UG/8aFnCHApheapBHO68cE/770xm9WWvz6eqRx4s="}]},"_npmUser":{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"bel37glbc@relay.firefox.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.11.0_1642096453841_0.2957440875073931"},"_hasShrinkwrap":false},"0.12.0":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.12.0","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.0.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"jest":"^27.0.6","release":"^6.3.0"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"react":">=16.x <=17.x","react-dom":">=16.x <=17.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","test":"jest","start":"node server.js"},"gitHead":"54999acacabea8161d5aedfc822a5c489d442ba1","_id":"swingset@0.12.0","_nodeVersion":"14.17.3","_npmVersion":"7.21.0","dist":{"integrity":"sha512-qr6Me+0Isb0rQMfLlAKhelOlk1kXzHzJqmloza7RbzMfdfRzGyErSc0eKWoRWhtGL33xQWzRfwFifU5+hCKiqA==","shasum":"1622ad6bdd3fd96952c71c5fbe92d8187cc82b86","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.12.0.tgz","fileCount":1088,"unpackedSize":3286072,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiOJooACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrE+Q//Tuy/9aAOpAtIZIsttq/GH370XODaOQ/wzcs6ujvetQYuwqGk\r\nFxuihhng2aXZRN5IwmYEF0P585zYyAY4/A7wV5iAveb5IqQYqov3pB8FIiKZ\r\nOfFKQGlcv7ekzGtp1C4e1UUwcPUVoyaRLjHadMjqVSH20Hl+4DB5rvFRz6zp\r\nsYBohGKi5rc7DHH9EsVTXey3Ket9aXR7wKNAdoCVlIvoqo90ojCqYfaHpqn7\r\nq5M08r3SIul+kgQstfonbkpjIIf1upcqu3rB4736VuFBKS7l8uGYMSnbDZW1\r\nbrjt1l2Q2koqbrsDVq0eGw7UVrcMUqYb8ixGdeKZHo6n/KHS0NMDujzaceWC\r\nNHEwSMelVFlGLzJ+pa2YN1Z5xt3qXuEWDV9980pFkR4UM5kEMUUZAaMaavcn\r\nAWKPgtT1adoe/z1VSDjCh9xMCh2FKR6j6GvXNJL83kn/iqQDryUTfk7bb941\r\nG+TgE+ED6Me52SQ7uazJ49oowqpCQtegA+8toJWLdjXV2x53pQ2/U923PEuI\r\nF5p7Fzp3SlkrjazhGWHX2nRCtyvB7T7tu2CM+yCZS1mSET2Bz7/FfM54f1Ot\r\nsJUvSQWD+RRaQ3/ahpxF3ioNBwrKVRCc6uxr75ChNBX82rBji84zuTLQqw40\r\nwTJM/MHGRnqsbvaGJD32tst5txMYho+hE54=\r\n=I+P2\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD4QlbxMOTByfRi4Y72uufEsmsVsZDxS2uIemNr4XVogwIhAJ3hvJq17GYAhYpCvy+rVNcJQmoON0q/nHtQWeXSM3sg"}]},"_npmUser":{"name":"zacktanner","email":"zacktanner@gmail.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.12.0_1647876648264_0.6062305396290102"},"_hasShrinkwrap":false},"0.13.0":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.13.0","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.0.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@types/query-string":"^5.1.0","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^12.1.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"react":">=16.x <=17.x","react-dom":">=16.x <=17.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","test":"jest"},"gitHead":"43c982ad58291e228cf4bececf2dc657881cdc86","_id":"swingset@0.13.0","_nodeVersion":"14.17.3","_npmVersion":"7.21.0","dist":{"integrity":"sha512-VeCNHMnI4csXsPYuYOOlTudmOYIQL5vUq+coT1B9B57Ej+WrnVIbLXFma5y+VYFNxo681kt+QLJVGvVEIY5G8Q==","shasum":"77f68c73a8208a6c721d4bf6907683f9ec0a6b4b","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.13.0.tgz","fileCount":38,"unpackedSize":118960,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC5CJlKi8q4bZT5OPXxjZtlKSpjkmamY4RYX0RbPqfzcQIhANJSTkr2A8hrrv77vu0lK87USGH35PmwRYWvgUYlJ4Rw"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJido6JACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrJpQ//Zv55xdQtDwKsYWv3Z25VOLq50SBHj8/ThqJNTRiwge9W78VK\r\nGzo3d7VDJDHFj4OOfEd36TGvlAYFE5tRXhvzEpOJkUmTN0BqiBPO8IcQK0PC\r\nAZESofirkQFD2MCCCEF0UQsAGzIU+h5AAOe54vbueYLvsDnHi76c/mwPBzg7\r\n0p17NY7dm7JHD7R8Q9/s+vHZTD4ghhX7BBIX/ahpTXhuMFZIRSYgvMglfq2k\r\nsDImRX9tnyl+TrU1ZY3uER65pkLeqEuk5wyBk7x+q4sRBth70APS9hh9ZkoV\r\nX8ZgM34ja3xxPxHpWtxpEfdTw2dyuu+lLm3vg9pu0Ko5lYZoepHC8+qhkbum\r\nvuQV31gBReMz4R7qUk8E6+IsmHTxc3sE26PVJDx/z4U4QhZ4ZSzTN+LFt1Bj\r\nhOU01ov+K7eHJhYBj0kqQO3Z3cLteKpJZZq6AhzLPSfDgE3T7JzpqOvNzDF8\r\nPFHM5brSGyeBuUmvcdpoPuWZgFGwGu+siykIbtxXC7PoXiLhIHQW2/62RfP/\r\n82TqZxq5gZnwiSp57CULYjAqb95KELSK+cPV2A8TehKJT2L66cD2Xb4i5OZU\r\nKX1oAxVRFroowXfw2XhtEC3ltTtl+yxvmVVobjGaaHL6VwASauR9XN5W53yW\r\nZJzdY3JLNotZQegPwe2AEHWgZm/+P51KuKI=\r\n=iQXC\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"zacktanner","email":"zacktanner@gmail.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.13.0_1651936905340_0.8092443346843685"},"_hasShrinkwrap":false},"0.14.0":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.14.0","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.0.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@types/query-string":"^5.1.0","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^12.1.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"react":">=16.x <=17.x","react-dom":">=16.x <=17.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","test":"jest"},"gitHead":"51ad72d3ce8d6879f08c80ff836fbc18b9884288","_id":"swingset@0.14.0","_nodeVersion":"14.17.3","_npmVersion":"7.21.0","dist":{"integrity":"sha512-Re7hfr1KFuWwkkU9TWQzlLhYLceMPIDR3McCGq0oGGT0dQn7yIRBmvYfb4pc3uYCOkrsBmVWLHZ1jB/j5p96UQ==","shasum":"ae852fd18be88a1a178cc915036428189e2e8336","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.14.0.tgz","fileCount":39,"unpackedSize":120884,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHxa8hYJMY6TWqhaoVGtV0OPGiTQ1ZvYNH0Y6lIwB6K/AiEAygsA471FBG1s+vQJNWXD+MBTaqbiICjq4QJu7s8OXhc="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJin7KuACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo4Pg//dba9FCiJks2iXN9zUQjzM3EnO6qMT4pqIy8JU+FCm63aiKNe\r\nlWXvrpkaiAaF9NRqaZswRbrpRGncHhH1yrE4bRIhMJdXVsatWXQ5NIuO4c/T\r\nQL25sSOEokVai+oTo5HJ4/Cs4cRg+TlWh3UCIDYxQSMpZNZtWE+Fl95IL5+f\r\nsWAO6nVJ8hB8Pfrivgk0hi5Efhw4iMbT7pyNH2xbo6ouVFvCjT/NDt22SjAS\r\nDQJJ55BEIQtofYccob1tHpP+YG7DtHaqcF3YY+o/j1rsxpb4ut4v+pQ6UdQZ\r\nxF8b0ni5i+klLHEOOfducSt7hCziKjcq1euIvR7vraq+2hoZ3LFQDDa5Wk0D\r\nlJ5ffUyXfMF9y8kLTA6wP+ANRXKZK1wxDpuE/Cf+DVcsyyaGcSG7TA6vBuDu\r\nOHbteofVBNuBML1zCIq7Z1Wx4bM6CXl7Hfe4Aj5meUC0ARcOFOpuiacvUWZv\r\nfkIctvqCeu23cPTeSZb4+UBU6O8bCJv4oqXDHJwRJFziH74vjnAYES7xVxVC\r\nGX5O/vcxd9bbPxe16t3nUWcy0idkOI2OMDeh4jsNPGw/zzqAm0hqBWnYWI9W\r\n7IwIhKhOteTxzO2vWiru8TElQB1roptmrpRDzKLEexzjwyhhXNVrm7p9dGHE\r\n0mf/12eu6GAYIPh15AgyUy32XgFQMqkRQP0=\r\n=0XAA\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"zacktanner","email":"zacktanner@gmail.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.14.0_1654633134080_0.4807256687461927"},"_hasShrinkwrap":false},"0.14.1":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.14.1","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.0.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@types/query-string":"^5.1.0","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^12.1.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"react":">=16.x <=17.x","react-dom":">=16.x <=17.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","test":"jest"},"gitHead":"29f6d2ff9320d26992857bc7c6c53492de8665b5","_id":"swingset@0.14.1","_nodeVersion":"14.17.6","_npmVersion":"8.6.0","dist":{"integrity":"sha512-lQYKkwF7ECQTibGiauOhUKXnYMWz5Yewki8zeKwRYUWt6yHdlL8CpKuUYdmSVGq2pU+jEkdmbH247NaDmCWQmw==","shasum":"683bd11f0c18bbd25f0e4ff85c49190a5b7e8cbc","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.14.1.tgz","fileCount":37,"unpackedSize":120584,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCu4ohgH8E7a8crx/P7yD/1/QtJ4d94lx5Ooe5HTq51RQIgPxONzH3PaBcog6lJ42edlJ8WW91H9g7y9Rj7SsX63jE="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJitLUsACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmos9w/8CWlgf+6YJ3gdDlXfL4OQQAsNiqebkOihMnn4vs72VvpPTaqi\r\n/GAvxf4bJxyfEe1SOyBy/9kW+3/JHa5pBzuj7jZbYz6tsL9tZXHNV+8mgSze\r\nFe/BYVGspuJKjjklDOdLN1siZ2lgWLcR7QKJ9ZsGofFgpCT7CpjTZxafeiTf\r\nIjCs47sC2OIu3gVxK/QUEpInw6qMZNCv/Y3TPZjb7SLzidH/FoJHaoBx3bxI\r\nmDe0xnQFZViX+/LuTgZtK4P64qkvmZuqZlm3hH3LtBz7mi0Qr5Rx9O4ledAG\r\n/VMUoPqlYNAPkziQ9CndYEynJksAaunt7G6vBgez2ZkHx3Ce3v0yf+V3uH31\r\nWUV8l3kFhUEFGqb4cbw7IQuKn/4a3WcXr3TREAPC32sV+sPTGydwJNwyG0pJ\r\nvCXHzq1z5aVpsnOzEXrB/BQ+DqmrJH3HNYUxzWRzxSZ1sr7anCHF5ZWihRge\r\no96XdXqf0Zl4/pvhUmiiIa+OhzWcdnrC3MdItDgrBfrOduvaE5gXS3EDBLox\r\ntIPinzpRLPewI/+ALHmIL58lXU5r7JZ4JdFeN8NXmjxoXbXrtrGSr5WGdqXv\r\nVbWjYkobhN1kSg3AzVLnvhTvx+nSLkClXW6NM8Nl8KRhuDzNVcUKnpyjEEPr\r\nxq1+zWRW4x74MvFtX7lfCL+x/6zh/56tic0=\r\n=E6pp\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"bkalow","email":"bkalow@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.14.1_1656010028546_0.23548166529911518"},"_hasShrinkwrap":false},"0.15.0-canary-20221115193513":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.15.0-canary-20221115193513","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.0.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/query-string":"^5.1.0","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^12.1.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"react":">=16.x <=17.x","react-dom":">=16.x <=17.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"f03032a5fcab1f1cfd02cd81de1dadb328393100","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.15.0-canary-20221115193513","_nodeVersion":"16.18.0","_npmVersion":"8.19.2","dist":{"integrity":"sha512-Cp6OFAoYC0Fopqx8HYgAN/Hrh4GorS4k8Gi0Szjr1WAbM8ANFRJsFKDY32CHaSxxLq7B5TpK3fVhIoT+mow0fg==","shasum":"0c4686be767ea26674f8f868d0ca953c863d2d73","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.15.0-canary-20221115193513.tgz","fileCount":41,"unpackedSize":138778,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD2FUVeSmYox1yUbbAi3nVB/Za4Uni5SwsqsdSkTOn6tgIgeSbo6pRLjKWs7ZW9xap5ACARwgpuO0jH9QXAGc+4ZqQ="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjc+n4ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrYAA//QQ6oahMl6WBwH7XEkCHptLcUz+sfAJXkjaxvjmbzPwoAXmcp\r\neQTKrCHjQ5LmQEkh6d/cX/LdIGbOLJh7dBP4dgEqPfi/i7FtC2Q9hwHqxesr\r\nkHF1gbNjfzRkxspcMI9SanKmhrNaYtSCH6VfcoRuKGpqfWY5rLlNzPDxj9rn\r\n7ACit/YHWZ7lNFlTfSfdMwuKWWz1R/DHjRrdq/Zj5Vl1Ym6wLLCROeXIyst6\r\nV3BHLbi92AXea1Moya7QcC97etQp7USm5lRQ1VQq7tpp4yBXwpNev2HOz9PR\r\n5bXxSfQ2dUpBjg+By7gLSpw2BIgfD5U08gOS35zqm2EuDnyD0uGSryCFUSOs\r\n60bL+KSGUY6LH7BYYIXs9rLDXxhNx+2AvoxrQ3b2UFwIoxRuDDiShxAfLQkr\r\ngc+V+WTqK1Yq4kq9+CGV4L5zhXv71uiMroGpAZtQrpKHHPlASpL9I+MV6UHv\r\nVkwpCAEnM5BPZX3hmLGZGHzCNxZle97mozanbeHxJy7XEMMzDfmvKPENnMLF\r\ndExIvCt6RygtN2QBsoeW2oGE8zWC/mKIZqcWTOVrWMIaS3zZZvWg+q1v3dGB\r\nSVB+QusTbsCNoBEj6yOi78AZEXjZV1mm8mynGlgZUi7Puqw6nJrPbD/hWYlf\r\n+Jz43xFFj6RQwaT9rWWdJqJjorcrZhJ2mAw=\r\n=NCsB\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.15.0-canary-20221115193513_1668540920117_0.9921614550252276"},"_hasShrinkwrap":false},"0.15.0-canary-20221208035901":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.15.0-canary-20221208035901","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.0.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/query-string":"^5.1.0","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^12.1.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"react":">=16.x <=17.x","react-dom":">=16.x <=17.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"78bcb9dd098f1b96d6598e13bf42187c7dd8b472","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.15.0-canary-20221208035901","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-Bz6CVFmXu+RtHA2NogSvxBzyLk5TpIw8a8lC0rYpWCwR4ozhktEObOgESKu4ixW5N0vK5iTs+efYTc98rtiXZw==","shasum":"8fb0e75ed27d2f07b228b8f98277f88bc0ec5b9c","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.15.0-canary-20221208035901.tgz","fileCount":41,"unpackedSize":139910,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCAzvzrLrJZphaYt4pjhbIB/azUzhYttyp1z4UBh6YzJQIgZPCp9XDxS19CqhWTZlY+DtgSVHPcYMqFiS/VlLyQZrI="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjkWEKACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqMRw//Xsa7Izj5S0Jmys61hZUWOmw+PX9raV9jNtucZ6jPNmiplIaR\r\nL75qSuGNkc5C0qHsZyl4FvzqQDZJw02dUFwP2Qe+RUtbsplkG5OrtFV4N2Ii\r\n3Axol0AIkX7qdWcymubCjOTGp8IUccIniQCPEFX1cjEvs2D8F902b9PGL1zD\r\n00wZpPkEnXBbzm04Nmf1qvHjqCbYarqG3gahz9yANs2nBE2vBKd3bglYznWW\r\nk56XHdk3cWpPvNAsj5bUSfDf6W5VmHveC0d+IwmLRDitIW9fS9B9F5WbUpTo\r\nEcpXIH2trol/LNLsRhwsZsQJGROF1paiH69Tijo4U0P+tQM5g/eyp1ocoZO1\r\nH6VrCZ1S2p74V5Llj5ruvLIBb4bQ+Je/g0Ghn6HdY6YGeLK3TDfw0MCC06a/\r\nd777QvbIwL2AVsus/P221Fw7tEE48HKbvcA63nZ19ccewWQ8KK0w4bZSga4V\r\nSVukfK87DqhguXaZrn76SXNZQO4ho1xsr5wWC846AnMyCip7BGEbi5I9dyDD\r\nbivWRQ+gtvpcB88/i/5QVsPAl4v0xE8TjhtbME1UEAYiisPUrFriq5Cu8M1g\r\nOky4xD+8IOUL/jH4xJnj/bXQNMGHjo5UHJx1CB3mi7eL+PYH/O6xgZME2Fil\r\n7GCAVsTJocuIyYzBu5VtyqSR1MUkw0ztbuM=\r\n=eIZf\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.15.0-canary-20221208035901_1670471946445_0.29112725702335607"},"_hasShrinkwrap":false},"0.15.0-canary-20221208040638":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.15.0-canary-20221208040638","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.0.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/query-string":"^5.1.0","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^12.1.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"react":">=16.x <=17.x","react-dom":">=16.x <=17.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"6b1874d3459c8b73fba8e0be6653a53689f5ebc3","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.15.0-canary-20221208040638","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-k/FSedz0DsfZA32mMbgZEPVNC5y/c3hY1v9U9v1VfjtbrGe5AifFUmUKPTxCzlVkZcGf0y7d6aF5tYUvj/v70g==","shasum":"66d181e59d7872dad32935ee28b460fb0b4bd31b","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.15.0-canary-20221208040638.tgz","fileCount":41,"unpackedSize":139960,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFGE+2dC72rjOJiiahPEfdbHWltE3Iy8uIa6cBedsR7mAiEA/3JrnEXMzLG4fPCKpRiDASZCAzm9GadWbnH00BQLB6g="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjkWLUACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqC3xAAgDj0CdlPtFH/Sd+66TU792XiVsZkdVi6KX+O4rvyl+qWns26\r\nQ6NDgosfhYiNd8EPOdcxHPis0G1u4W68s5HqXbxyDr/ps3z7ahnAgM6Osm6l\r\n/2NXjObRlQWRXkGr7cewm1az1IUi1YdFc/MBovjnDgC01D4RQxTPGcb6DggN\r\nIFXCcqCarXuS91GTzASkM3nm+MWb4NAgkmDCE5R/gLci9lfdj6gN8nBbJxlR\r\n7N0H3YhxBm0tgfYa4YVDV++zXv7JysJtuyZNH8wnCzP9yOLLNs6KuseHhd39\r\n9uX8Ky0Ow9E6cZV6r4wHHmpZteAJ8yYvVIcdspuRV/KLlBZ5z6bvVIr7ieOV\r\nsbHQPcnlUbAEHDf8vBSoFUPaXTn5ztqR9o7ysotY28XUka4HKlHpF01TKKEc\r\nInG0DCTM99F8y/B+q/gUOZ9Ql70QZLAs2SEnuk1qf8bzfHtfwbcx0mXbmnjI\r\nzGgXqfP9Ax98U2O/fRKObr/nMPrhqzMGHdEPATAYI6nTXTZq7v/TRA/Ta+nm\r\n/EtDJddGMaBCviK1rUAIYrFKkySOIY4mqiGteidtNuS+wVfYqdgynNHdFafw\r\neUdjESppDabKhTyDYsYDajJVY790E0j9F6i/d3GCyHDiSIQD9TJKZ637AhrI\r\nH4ByHDQzHeTZdOFpOn8UWa0Uu+bSCxsjRME=\r\n=JZKQ\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.15.0-canary-20221208040638_1670472404275_0.04693857296772874"},"_hasShrinkwrap":false},"0.15.0-canary-20221208041053":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.15.0-canary-20221208041053","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.0.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/query-string":"^5.1.0","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^12.1.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"react":">=16.x <=17.x","react-dom":">=16.x <=17.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"3baa6d9b2b5b002ed286ba3a45c424b75ba4e00e","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.15.0-canary-20221208041053","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-yQbWvuP9FHbb3h3OBw+YUifBqYs5R/QW4A9EhQDsqIJk8RomzmTAr77dAvzJLIXm6CHlFHJZwipHz+/fU59cqQ==","shasum":"ceea492f0a0d674b397358e8d8b951b3c494a5cc","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.15.0-canary-20221208041053.tgz","fileCount":41,"unpackedSize":139945,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDA3QrHVEMHQq1XgdW2/hO1jHhIzeocUt7B/vgI4nz/EAiA80Qa5Bh1BuWHHIpI1TyZv08W7pUF4tMJRMKiXE8RiXw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjkWPRACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrjmA//fhqnC9mX2ClGDPLYBF5YWsTovBFrpGH5U97WC4bGufn4sdpj\r\n5R02bjU8h8zEqvsqJNoRJH03YkHZKyjlTW8TLlde0NU7HMMbabYGK2tnFhOE\r\ngENswILbiPv0Q4XA3KMkCKBKYqyCBvcOYk8GX0WqfBWVDMNf+uB/YGnomrbd\r\nzyolBRE6A9fI8KFlfRBnRh65Q5sdkiqrEpTA49AbSSI54mOAu3NUsFB6M1SL\r\n0JkvFnCMD+OIcJ+TNQHZrG7W72oW5L6qj4UEzq/7Vi14NJYX6LyDzyZfMh4+\r\nz3uJu7cM39ooBErkB5iYl2762iIPrBkbxJHoqqnAxqf5/rdDgtHhZFNzMjdP\r\nI0gwXGX0h9hyrAt6fpteVOo3ZKsw6IPVo5g+bCqYRlEpAWQIy6H/l2M+UaZF\r\nubiER/b8x2Rn75gtZ2DAItVik3DNHUsE2EK44CQQxepI9IH/HZ1fzLA332G8\r\n/jcZKZtJ/J5Z5A6JMw3gAH8QnaJawAzFvBaXML0HsdbDLvhZ3kAxxHrAQExm\r\nezwqkcwQzSfaRUBswSODaPj/f8BYizQfXtPzzHoUFTWosY32ELitJRT3pMuG\r\ne/8bcJqXGPQH8SE3A6stlGypSEgvcwKW178RzWmxq3KTIYNvrYtnrjeXcypJ\r\nncpPopwUbpO/qpB5oOFfVmWCGfsZv2GM4Uc=\r\n=AFxj\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.15.0-canary-20221208041053_1670472657234_0.5765284382456066"},"_hasShrinkwrap":false},"0.15.0-canary-20221208172311":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.15.0-canary-20221208172311","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.0.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/query-string":"^5.1.0","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^12.1.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"react":">=16.x <=17.x","react-dom":">=16.x <=17.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"188d161cf16255bcdfd5131690e4abdcc9b202ef","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.15.0-canary-20221208172311","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-y4RGYC4t2bi2OxUG2vWxydp634fAwLceNKz/W+/KayKvlXwgAsbJLjfzgU/EmKmYe/2eAoBnDp6THZc3wKnlCg==","shasum":"62764835277100cad462d373b728cbd77fbc3cc9","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.15.0-canary-20221208172311.tgz","fileCount":41,"unpackedSize":140211,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFM76lPUiR1cyPt+kX7/a+MWbU97lyeIcSEIMzkMTRsfAiBMGpS6bBWHd4e7xRblMRAUldiWQwzwQhj7UtywO/DeuA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjkh2EACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq5Yw//S2E/OB0k8z09gO3MbBIGQCDOX1y9c/BKNAudoJOMlWD1oQ96\r\nJcwfNnfouhq6ixAcQNL7wOwlHQcliEkpm0Urn/hlbNKSWa9CSTcGY5trjmf7\r\nmgNV1m33yCr7H5b0+45Gq4h8ffOfxCgyCzm/gvDvvlx0xzV+B2PWrNPwWhUp\r\nwwNwgWmfi/lLZuyaNQ2fVkEbjsdFf5YjjkIC4OVdZ+/bD5WYRsUxmjV0kVD0\r\nvcb1nGqlcrOunsPp1tVg4cfuLuB8vBWrtzfWZS/3qTMOS2UX1Pd+inBcep/C\r\nqQDXvnhjuIrArpoQkibWdnu18vdxpcnqKVTYJHUN9VPI4Dm1HtC2rLE9GbiP\r\nH6yPvezE4fnC5HpddVAk98rvStv9M6VVUVjcdZhmg+dKUMR2kxxnyqWm1y0I\r\nmlI1UWFnOS80kUA9gNbQh5pT29TJqpksaIEQ/wPBA/UK83KhmN0puHUTDMr4\r\nJx7K23xcvq2IrzSOaubNX6howaHiRjcyIYgV60uDxvhuhZpKvT6tE95PtlEx\r\nJIFcSTusMi3W039ZgHgOi9vLGLI4yarhzHVSOC/nLTauyBGU1gFLxAsgJ/jU\r\nzbRin7r2KTjlAL6fRbDPNvssLJOMj91EIslaFf0g5AAwPzkho+FoIPLpSVKp\r\n46rN4SjthjuDYHf8AYf0LHqCy3TCLsQmnEA=\r\n=eg83\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.15.0-canary-20221208172311_1670520196254_0.8909515473636662"},"_hasShrinkwrap":false},"0.15.0-canary-20221208173207":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.15.0-canary-20221208173207","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.0.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/query-string":"^5.1.0","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^12.1.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"react":">=16.x <=17.x","react-dom":">=16.x <=17.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"4299a968e13f11d0db4ad858b64ed2eb575ee5ba","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.15.0-canary-20221208173207","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-uDKME6dpeY3DIiVdKxWuk3AJOCI02vIPRIZuKII89hFR4zeokhRBp3MVyhAQMelVOe/BR6Er20GdwOyrrAJPDQ==","shasum":"6b85d2ebe2fc598420c37305e0fe1af4ce4a37a2","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.15.0-canary-20221208173207.tgz","fileCount":41,"unpackedSize":140212,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGc5/ay39rGakgOH2vjw6ZmfJatn3DsA2ZhqxK/RS+xzAiByxgmPsoHniY1Pqts1JEE6J56/rTOFkBLh2DzQ/KmiTg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjkh+bACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoADQ/+JEvKpKnPzbs9fxDJGZOMO6AOZnpxUWx4C7AU5DxRQL9NU1OH\r\nCwnTiSXgMpX8dS7ZSY+jXBd9lFtRhU+td0y2tTHXjsEOvCeBiYXE/oqZfgDV\r\nq8qbLY6pEXQLsheqbXA9AYHrWgP/ZFtwmia0jT8tV0lUnpKTtHj6t9vSEVbX\r\n3nGZB+Od2/FJXJ+9dU+06AVHGmvlrcwZTZYtx4TpqGB4VbA8ngWhjdcs6w7z\r\nbEPQgGk+F8o6SCNGA5/QbogD78DdgpWOff0px/Ce2K+yllA6hkSmljGl1dH6\r\neQKZUJ2jpfzpcSJgqnR0Vun6co5l34aqQ7s2xSajUpoU4k6huYuFdm50cF6u\r\nd1yRCUcGNpN0Hth/InpFEhL6w3PtXY2bJg7rA8XCRhjy3O2ybksSIg5tIesC\r\naOhKPmMcohfeqTKBy+oFhBW3Qg4bCdhwgT+T6eTd80pPuT5re7/VwpOaGq+n\r\n51otB6Wsw3p0vjQmKC+//2ckgswd5psncF1PryfGklUWAR94k2b7lJt1uWsF\r\nOqJzQxFK2jXJJVHBFe1/gxN5O1UhzBgf0avmVZo0uo5zU5XKPjH4F7Cwz4/F\r\nUrWQFkFsX+uOxohgfZRAozvSp/81Q/riUloFnnutYzs9Ebe2tdkiU2UeZqB/\r\nSVCt+YuIJg1/os/FOqwPYBw4C4AL3jYCY54=\r\n=tVpe\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.15.0-canary-20221208173207_1670520731572_0.8552232677170581"},"_hasShrinkwrap":false},"0.15.0-canary-20221208181311":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.15.0-canary-20221208181311","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.0.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/query-string":"^5.1.0","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^12.1.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"react":">=16.x <=17.x","react-dom":">=16.x <=17.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"ed13163d3f75c80beb8c52dc9c11da15799ac65a","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.15.0-canary-20221208181311","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-IyFfNdntncaBWNNnquWQaWG9UftsBJ779dvgKPBon4hJN+IIvdzyW+RpG2DXmaJEDQRMcAqhEDjS4/PBnv1QuQ==","shasum":"c399c30c15b4f01ed5cd1e4523ba79c24d5d4448","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.15.0-canary-20221208181311.tgz","fileCount":41,"unpackedSize":140348,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEqTblit+INcX7L7fYJ9kWI/VhnforgEie9SPhgmuilxAiAYSPspgbCZaSHZ1l7yf2ONAOqFVLrfMGJdIJMUMjpXoA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjkik7ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqJYQ/+LB7y9+7mT6LzOB9JDS9iQoq6a0JNwTjRkqeUEd0H/GcrKgjV\r\nmi8w8tKYEHT0bXkHpYe9FxvsObLsnC/3p40ricAWkcIrQb2mXWn0FpQlswac\r\n72/83GYlNZtxoNqE6Kwr+nKz1KbXRTLLVcJzJ+B3SJCYkmz/pPQ3h187QxFL\r\nQgQ026nHtan9OgCL4f+n7zI8QEYg/4l3DJvyHVGSZGAM64TNzOIE/1f4hOqB\r\naFFBJJyEq7jlLtw4cSIoLfJu6N3afaMzxGHpupEFg/EvDqMEqaqDJdjWn+3p\r\nLLaihOh7nN40umPSf43/rTWU0as01XzGmvI89XaI+amAXBhbBSYGbwmTV+3s\r\naH1L/HRNumgRkat2nQ+mNfPv1+n/YYKxnrjWyTGENoNZu9voXh1mSU0afEue\r\noqYOL6wg1PW2xXccKz5N2JpF6r74jpZoECthyI0mqLzr+bQorgDbq8GWGhMU\r\ngfZPQtgaK9lrW5hgRSQnFywczYv9ShstlDL7aNN7tGxyWuUzawLyFNaKadq5\r\nKNGfBNMFEac/NAAqWSscLTnJZT5/rhbZj3CkH39aGUBzZWZOgErfye8/yNnW\r\nNp2Qo/9IJoS3DqBFxEPN8kB6Vbv2lO/DL2PhztcEMa8trRACk6Ke6xoRZTai\r\n8b+MPfJTakE6k2r1F6ncK0csc5URNOzmSd4=\r\n=XClB\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.15.0-canary-20221208181311_1670523195497_0.38926235038922563"},"_hasShrinkwrap":false},"0.15.0-canary-20221208181706":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.15.0-canary-20221208181706","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.0.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/query-string":"^5.1.0","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^12.1.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"react":">=16.x <=17.x","react-dom":">=16.x <=17.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"c198eb362c832e666325bd90156c0cf9a162a21a","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.15.0-canary-20221208181706","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-95T8meZGnDhgS1GRrQWCMVpqNb2Egq8XtLbBBb0b9y0/7x/j26sF39y5C+acVM5TWKb952NdFBfZoACbtCGP/A==","shasum":"e28246970fcf7563e5b59fee82c4c83db112b92f","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.15.0-canary-20221208181706.tgz","fileCount":41,"unpackedSize":140359,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCqXvmMg4EJX5B0g5wZXCNFTZ+VL8K1FcXRAEkh2sTeWAIgSPpG4UzIDA0XECHgkQ858iQGmqg+s1rf0AhC3pv6TlI="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjkiopACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpy8hAAmauFA0n0JpsVF+ZifN1DzLBcFJ0bmqYy/E/wwHhq1frS2WJY\r\nS1VC4dzo1lB88ulNq7GUGtCTDDLr8wY/bEI4u7nxtB3hRyvFZMvSk3uDxTsj\r\nHDDdoNquaOVTqLvSoAg5bNb0izw1fyKKHwld1H4xkuFQOavvHMb5c5rztX4m\r\nzFu0N3JLBDbE+uelYcLn+8jt7hrpj6t8XGjPOCtxvhzvarBsRLDToxVE05lj\r\nPYApJOma7BxxPulNfW/zmUJUN3X8wZ7hM0gDmgiBpRGygK86KSmcudbuIRF1\r\n1y6jigQ05UFbqhJem56w0tsbWty7NyJ8Y4IS0dO89Qc30D6M7fiywbf2BZPU\r\nfMNH8EklTtOugn2QN38nSGN4XV6W3x/1niSUWXREDpLmAIRO3jVzR+ZdEKL/\r\nq7YT6JzsuOeLbciJHYdhmcWvQlpa6uaNAKEXrPfgYEFKtQ3C5VYrRcf0QOSb\r\nAn6IvcBrnazkTUX7SwXe/RylLeg1DDFntn7JvXCmv6cE5s6gUBtaz8jeXFCS\r\nCga0TV0sLSOw5yhpIvsQS5UbvRzkNq8QTODMgh/BWzxOXYqevN9c2t4elfGw\r\ngOL2WoA247+0L2FhOrCz47sndB4v6mma8HvjSUhzpkUPd10TO3x1xauiK6wg\r\n1qM8nq1GB4An1g9c1im+PwKbrNonuTLwZTs=\r\n=x2jv\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.15.0-canary-20221208181706_1670523433505_0.6220451421504873"},"_hasShrinkwrap":false},"0.15.0-canary-20221208201832":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.15.0-canary-20221208201832","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"@reach/visually-hidden":"^0.17.0","classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.0.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/query-string":"^5.1.0","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^12.1.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"react":">=16.x <=17.x","react-dom":">=16.x <=17.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"f0ab40e69ae52041c64be0b4f739616fc3cd2d82","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.15.0-canary-20221208201832","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-NPG3Ib8jsfYOezzK4v00TEedGOekOkmTMZIUKdPFUpOKSYFnbz/WWhc/iI7YV02v4Un7SaiZtZq4Uzbzcn2+5Q==","shasum":"ba0513534ea223244b2dc53bb22e566d87886092","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.15.0-canary-20221208201832.tgz","fileCount":41,"unpackedSize":140418,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD1/KhdkLuk/V4w1FV5Feqz8k5hgyjIqQgIQBsrFKdhLQIgc0S1D/coMgGAgAD/XxpPiKPqCJvQA/FG5iHfOIq8aKA="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjkkagACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrFvQ//R7mqVZVYgVV4TZb+LyPawaUM8iGT9ubzEyA+NPqGF/L9u9hX\r\nbeM6KDdi20of7xwysFbx2KVblh+7gHb/eTms/2BaxM19cEMSG7BcfP101guV\r\nuylPYiPz4Dq7XFaCTXPEcamA9zXmWI7iUeIuvFkaQbI7zOnNWgnzdHSk09Ho\r\nsD4mW++C8RYgDN7tXOoen3JfEEJqkSb5y4nYMiaSL0RmrfAen1tWwLbKiEjv\r\nMmjcQfOvygUj9Z2+dPe5z1zvxcnaTjYNqbGojMy2oC73VQpR/iM6JKJYjgkB\r\n1dO0dhvTxtyNZYssrx64vJIqlqWyww/0Z7n/Hdyl5958oqslnpNpxosWMCrI\r\n7KmMqITZXcY2QYI131qUyipxFoH4nLHeQK2j6Z0vnAE5qk460H6VqlqLEl+2\r\nRXa0dYz/iqtTZaZZiqYwZOi0Vr6BcNczkCEplcglHqZ8zFLAtW6edsgchBOY\r\noMqqcov5NmZ3ix+2OPQq+VY0AmzPFSlfLzftPkF2UKOyPoPbGfWWio7nqEhZ\r\nc87GZ/K6jhddjyCmoUo2JLsYIuq1c12XoX/8UoMdZqeZVOqtpqZDe1yCVUiU\r\niG/kXoyCw1i/E4rv4PWRoRt+mNg2CwJ6s3sl9qJr25k6P9qxV+CBwaxBBUWs\r\nJCPBfilwly4ohZMGjCCNwAInwYpEF+ql94E=\r\n=pk1V\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.15.0-canary-20221208201832_1670530720178_0.2787535817958253"},"_hasShrinkwrap":false},"0.15.0-canary-20221208203712":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.15.0-canary-20221208203712","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"@reach/visually-hidden":"^0.17.0","classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.0.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/query-string":"^5.1.0","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^12.1.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"react":">=16.x <=17.x","react-dom":">=16.x <=17.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"195e00cabe5ed93c80053cbce49eb17932db931e","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.15.0-canary-20221208203712","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-9h+Hb+ERUZdzy+CgdjKLPrPsE1Qf30MYc1beZ0TpM1XBQnTNCpYsWBCsSp1Vm0ZsrHWix4RZHTyKGaeYfBv1NA==","shasum":"265095c0a4b59b797a424a027b8c3ddb02d11aca","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.15.0-canary-20221208203712.tgz","fileCount":41,"unpackedSize":140456,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC9mpaYRY7yYIXCKkihVOyyUl9+sgl9pG73ZCc8UcfpGgIhANAKO1qRx9iHWCVhFHjzxe3wgnpRUD2+1QOo08YkZV5s"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjkkr+ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrDeQ/9HOYfRHxsycdPJ52z3dM2gWk2YqLDTExVuiw9TyizfEnQnuFQ\r\nem/bkmJ6zVSeC22uUk8HpKCQUm47kExgVTu4o+w1jb8s4BYrgppShpzD3bqV\r\nBUxI30yLQLCQCfuEXeO0ObsdbQM2QC9GFepYv7QVnPHVN1L2x6pGQ8W+ut06\r\nKezGDY15ilH2C5G9A3KtQhMPpTrJQ27cVhUlb129F3lqby+5vwCFmaElOEGJ\r\nvv1uw7e9HVpk41ho/CtalYypWAWBCfG4ZPnGIeG1DWJYDIrL5H1BDn0PZqWO\r\nmKd9IkStx7JpHHKO0iioIkUUztahtmGXBAlXH/buu+Nb9cpb59RBr5I8eo5r\r\n/fahVc8XJD8dv9daKH03eQX68txjyU18fnyM/1kTokwBikQHZHCEyy3xoGKY\r\nmII+4z3YyBGsaVbXGbaTEtO9FPIs8OrT/ki9LycO5BZxFodaqzTUBNtL8UG+\r\nRieLjSiuElWWR+SNH2PZ1+PB4MexMEJ0x7ZFeqX7uKIU72YaIrahxhrB3ADZ\r\nFxwwM8xMSIz7humZrMSTU37dMuZ5+o8RzPiKAmYloliYZ8v9e72kIEpA+VYo\r\nWxZeTr2G5DCdsi0bnyGW9mCrulqpbXDKEzDP19RqyG8Vha9D3HVOllaXKnIw\r\nqdl/XHnvlv/cYuNiHpljbL9KIBF638DETeo=\r\n=uko0\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.15.0-canary-20221208203712_1670531838017_0.9516425100322927"},"_hasShrinkwrap":false},"0.15.0-canary-20221208213251":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.15.0-canary-20221208213251","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"@reach/visually-hidden":"^0.17.0","classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.0.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/query-string":"^5.1.0","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^12.1.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"react":">=16.x <=17.x","react-dom":">=16.x <=17.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"c40c969d0094e36e37e51adbd35107ed0f99d2c6","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.15.0-canary-20221208213251","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-RfH8b08WFGIensLBFhOpQCpAbfThcCVEGqquUaIsla2JyxCOYdkkdp1MhfvJczA94VoTZqr+vreY4a9bgRvkxw==","shasum":"11f49b985a3e2cf95ed4ff9c7d1907c23253b569","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.15.0-canary-20221208213251.tgz","fileCount":41,"unpackedSize":140551,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDwPmsoyXjesKFJMNOlXw9XlKi2OWG4m7OaITNfdm0wwAIgVeP3L5F+JveYvlG+o7QhINGUFTodmeZhXq+9UZj6qqQ="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjklgJACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmolhA/7BOtK6IR3MtEc+ogJbXl7BwinsnqsWOcl05mqO2UOp/0aVYbj\r\ngf8pYvharhRRGLTnY6aHI/NaJznK/FpVVEYxZcuCeY/gfyOIAFAciQRKWfVa\r\ndJ8Fn0jFN8sYz8xLEjxPTCQmujUzrbJMxCBDevcTMqCNr7/FP9towUde/9BG\r\n7nI5QZ6kJkGg6OIiYeFBZsRBCImZh24oo43UhTt4FbPDNC/InHuBZy7iMAlR\r\nG0TO/1MdtRlBPfMN0o6DqgukbTuNtt7VMp2q4gBXYYPZ0hHrCq3IyghLC/ZZ\r\nMin4ClynrLpSckyosK3MnTlcg/O6Xq6G54R0M4loDEXJT59CjN9c6u+JC2Pg\r\nbhdumn2hJxB3vXnceFrxbfaaUJlirPEX/p0NJNGiIVGAmOMc+G4TreX4NB0d\r\nKmiH4roxfrPy0D1HBo4e8QfaeO8sHZRoTgMCdqx6lBYBHTUeZhZ/eVL74Ya0\r\n51nYogOENkzABS4IAehucM79iM4vt2ykCbW8BBkFbxwOLXiuRi5+stVG0E3x\r\nY7aTh1HscBqWP+axZZsO/Zs1ayq/N+ryxS0prQ6DOQmz2pg3J8ZDAPhhDao3\r\nqNUIbXgnI5wlhS72GHwmF7PTV7jcnV1SLsHbxTruQd++8M7M7MnFFyBNuKF3\r\n78p/BrggtE2T6JuDj53nBr8merLgPS+DzrQ=\r\n=dCCO\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.15.0-canary-20221208213251_1670535177594_0.5634922124394897"},"_hasShrinkwrap":false},"0.15.0-canary-20221212171910":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.15.0-canary-20221212171910","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.2.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/query-string":"^5.1.0","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^13.0.6","react":"^18.2.0","react-dom":"^18.2.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=12.x <=13.x","react":">=16.x <=18.x","react-dom":">=16.x <=18.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"45b4bde7946c9697f87c0cdf95033356d0dbe002","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.15.0-canary-20221212171910","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-Yvvg1jvHxz2wa1OwmxRREpQObLrMzZ4gD425ZQrzZWQYf4diNae06xkYhScnq72Sx9xbj6W3ZbJyY869UiUI8A==","shasum":"0dcbda74addc026fd711465718b2c1bcf6c569db","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.15.0-canary-20221212171910.tgz","fileCount":41,"unpackedSize":138796,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQChmEt+iiQgePzsvyhmQCvH1B2DOuHK02m+Cv1PoK3qagIgfhFI2CA3ySw86prXXGO//uDIE33dk8BtrBmopB/S0wg="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjl2KTACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmquwRAAiHQG3n+sSYvn5VybWC/L1nNbkVrDkWvNY6MOWv7E4p9WwDIO\r\nQH34K0wZ8UBRJriD0mY+0gfl/K9pR9lreT8ykL083H37/3f/5MIFz8wJIBsX\r\ndIwxJQV/aGzgAQq061GHT8LdaDCi+CR+bChEHTn56MP6TlGal5CHR8WQbzHu\r\n9h0u3cH9B38R1gM3K262MwsJr0mARmBDuwpdJ+FRrNGeQT0oz8+0ZoY/VrdG\r\nOGjceQDCvZOpBMcTViY7FasHYhUv+ELmegBGNYYrrHl9Bvt2LVp8nF8AQi9h\r\nuyu7X6+5KD6ZFz93pjTSqgfqa+J7q+KTOS+rmV+h2ObODfsS5Mgw77edk0Wy\r\nDII2QhRepRAwLqNK7j4Hl+prqyeVadoeqN8E7MgYQGrqYAc/m9Yp2qW/eZvF\r\n1Rv1OL+UQPPMNd0HMfBWNthz/+QbsLi3C/TXTtceYjM0xp7ztKiHrICXwx5y\r\nRbcj1PMRw6hmIx9+ghanpWjB8q7HfTMmVHhWfNR2m1YOv3lcsHw/yoyt59dg\r\n/0xiPPjSN7Lp+2fdNVh0pH0yD3QeoQmYSN6SlIDDXApY6ienmmxAUq30sWJo\r\nOON+pIXcEnVa/p+QEnsVN3sXIDrzi+IwjXfAl1+PD28xnn/m7vT9Mqpyf88Z\r\nS5HxdyooBWzXLFWRpaBuHX/1vH5wFoKKJtU=\r\n=2GGy\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.15.0-canary-20221212171910_1670865555320_0.7574922271179492"},"_hasShrinkwrap":false},"0.15.0-canary-20221212174158":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.15.0-canary-20221212174158","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"@reach/visually-hidden":"^0.17.0","classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.0.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/query-string":"^5.1.0","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^12.1.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"react":">=16.x <=17.x","react-dom":">=16.x <=17.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"2617b88630b11ae5edc35d6960abea1803243b19","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.15.0-canary-20221212174158","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-dRUzaG4SjKsbusTyDABGlf+JfMsHo6oIYQ0CYmNOeR9RG/3+EqYAQImq1nBsCbDAN33JSKOc8iJPaSx5yLbkYg==","shasum":"7d0628ee619ae6766eb901a37826a9f57bdfc75d","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.15.0-canary-20221212174158.tgz","fileCount":41,"unpackedSize":140364,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCO9mAUx87qyyaDCTLgR0Ym9jnm6BEcoiktvym58fDSYwIgK99P+Dmo1cm40k/uOtclIc5nWzcpbyTbFm4xSkWm7tQ="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjl2fsACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqmmQ/+OzUTDXiOhLO3H099/mD44Cn8vex0b1kHhKtcq+QSigy+ej6e\r\ns74X7/OHmey7UMEKVekD6YLFGakDDcLQ4Ju80YOsclGasBsU2Mgk6JlMjVSb\r\nWeK+gzaPQXZtcU85eQjKFcrYU/vwlt28yqAwc8s4Q63l15nK7yhLHqU98TzO\r\nf3GPglFQ8m4szGVJfiN3VmcalYHpUPsT6UCu94e//S+4HLDjS+tTpg57HVaP\r\npxcL6r8OShVBSzwWTn60MaTVZXCLf6uQaKbvfOdw/uF7BAynsl7eUb1B16us\r\nATpT1W0rEnivUTwZsb6iEhZYJMaRYh/FquoXiE1wyPHq4z0AXqOfsLcyd7Ws\r\nuFNvDRa+z5bd/3QVqlD3GsU54xB4W4RZaZqqMbUf7NbADM+BASY1MeP3pijZ\r\n8nOQHYXG2Z/poKePywGmD1w30ifWna5X1qDCqo7ldCKt0oYdBQ1MECT29Y7J\r\nfpFn9kmoTuGZz/6SIY2y68Hg7S9Pz9ErFOVE+C6d9RYSGsrj/PgTNIB//2za\r\n9Bm3iYqU06n7l9T7wD9mqM9YOUg15eAhSNQzfEF01D0mJCdUDGzO+kjkR0gO\r\n1RJS3G1Pb2u98WaExg499n0ZI0l7eBkjxSapdRWEqwQI22sKvX8kISLfHIxU\r\nOKcC+slyktducmM7NYTAI21uFj1ILml5pBs=\r\n=KTOV\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.15.0-canary-20221212174158_1670866923878_0.8368257160800263"},"_hasShrinkwrap":false},"0.15.0-canary-20221212183553":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.15.0-canary-20221212183553","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"@reach/visually-hidden":"^0.17.0","classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.0.0","query-string":"^5.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/query-string":"^5.1.0","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^12.1.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"react":">=16.x <=17.x","react-dom":">=16.x <=17.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"bd23031bde0dd89e92940ea664c3f90d3ec2c76d","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.15.0-canary-20221212183553","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-rWo02drAOCc+bmcrQPSUr24AQul0mOwwXY9l0trMsPhMtnsgzvlVsJ9xRfZgLq9LUc+mE8Z7pgg/3naDB3VKYA==","shasum":"00cb86766c99ee4439f3871c7e2a8d71de44bd04","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.15.0-canary-20221212183553.tgz","fileCount":41,"unpackedSize":140448,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGOSc50cVgZnxnPI3zsSPoEvWw0Ec8lldAiSnYxD3KhaAiEAx7ESQvNtEnns8qXxezSd9Ns2BZuCNJIN34XhRWSBPY0="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjl3SOACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpKmg/+LzGuxQ8jl/eaZtFwTRBerfi7RCvNB/pviOMnRBZhQJefrSMU\r\ncsfKg0gM2g9Yk1vaVujvIH/cTZLU8Liuzqirfz+tI33wYukx5twlNqq06pvN\r\n1fP4TAFOkmeRgxq1Xki6wXZK6x3kJfRDF3nUoSzt3j9aqxbk777BJe8OAiJ3\r\nhOpzEWageCKiDcTTXLovaFszvm0wwVN24+7L8scXEeUiy69kcEjTG0e1jCak\r\njcJawrYWV03vetLlDPr2VtqLchrdsOv5D3Ar9ynvd3tt41XyzG93owS2Af2+\r\n3YQZIOE1QcIf9pTcDch5suqzud4UFxFQ1XeeOsc1iWfmmAW0QXsjizv2s7p6\r\nIEu5xoKdxR7YtoxSalMCX/p4/2OeBvsykbRNdg0QURsYNK++Bakw+IUDF/XU\r\nTu+OL343wWYqVeza5FbWtEJAqU9xsn+Eb8o61uprCXzwOc854SRkNOOMc3AB\r\n61GQ+HioFVqU3NM5XO4pxG1x+pBB5mYDO3a8boKnBJPeyIA7axs98BElV+V8\r\nFXTb1jTUJZ3+VyNJPi3mrzqDwY517hec5L3o9XYfacV2NnIrRjZxfQiJFRok\r\nZqEZwvJrNLaZVInG8iNyjjYvjq9KlYxlqSKsdTyxF+tpSMk6yGDzlUzIC1YO\r\ngzCZaHEHtVUtZx0dDrnBmZy0z8YxKJIicNw=\r\n=vNR6\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.15.0-canary-20221212183553_1670870157795_0.23375106794696343"},"_hasShrinkwrap":false},"0.15.0-canary-20221212190516":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.15.0-canary-20221212190516","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.2.0","query-string":"^7.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^13.0.6","react":"^18.2.0","react-dom":"^18.2.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=12.x <=13.x","react":">=16.x <=18.x","react-dom":">=16.x <=18.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"8433360cba2203d44fd3c316837c2feb85e10972","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.15.0-canary-20221212190516","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-wokAa/rHtyYFqEZdwruF1QTP4XZfALNqQoI69VuEIyCS5uDsdpIB6GF2TiBhG3vqJpRkWFwbdc17M4+WL5Uiww==","shasum":"cb31f63f62eb5a81f86ae58ea4705be50488f3bc","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.15.0-canary-20221212190516.tgz","fileCount":41,"unpackedSize":138743,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFLOSOqFfEgIix9DKHkaDDPnthenyu9FTLOr8NrmF8pPAiBrMxWJUERuiuz/OqPz2oc1fhzfBAD6qMLxKM9QYatKQQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjl3tyACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoVww/9HWC3CV7XAOgemxhdfWVA1ngUtgdIqvRkdHVZ32y7yF4LPVBG\r\nwAkmFHnJASMO/x1OkHKuewHY2OpH5ikne+A7euRNtJMlajXwbiuXZbtAactU\r\nzVuZBOD73gPCIXsxKjk9FhBOCVnZCdFmPmXU5CokfiJP0y8SsJIsGlVEj+JC\r\nqi9ImshOb6N2282RbAgHVahaKUHE3JYc71faagx+CvqWd1853F4sPOnyAHiA\r\nFAK1ZAjJhVguF/BFTxXvIx7/bVWg5s4L1qOOwGrqq8yh9pVMSo1FVDqUH4Yz\r\n0Q9yVREjAOSkgxhPUblSO4CG1q1nWR31AqsL2kS8igZf7Bgnt7515oxWFC8a\r\nsFEx3kuGsgIhzAKeC4IsdksYwQ3zPj9LOy4ervYe2N49iNQDjlMucum0HHRj\r\nMLeeaia5E/Sou0BAexAXbP7tpZGZvmeizYh5NIGY9rNkf8HQWSCLdajrnt2W\r\nVPDGcYI79nrVhsLiV84TCavskm4vjJMjUt94H9KhrKBW1kd/yrlHjE5DflH9\r\n2SNhwL51kxgASAauXgMAI8GklmnKY+5RjZGlXWYWQpYEj0DUHFwxlc1AGw9r\r\nAtUJYiDuFumZsz96ZieiZpZ1GhSV+q1uGUWjJ4Xzk31ciRXGq4C1GE2/+cGV\r\npmnHbhG0eTntGGB/4MVAhK+pa9MOt7bwAa0=\r\n=xcZH\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.15.0-canary-20221212190516_1670871922764_0.3156392836472961"},"_hasShrinkwrap":false},"0.15.0-canary-20221212191059":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.15.0-canary-20221212191059","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.2.0","query-string":"^7.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^13.0.6","react":"^18.2.0","react-dom":"^18.2.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=12.x <=13.x","react":">=16.x <=18.x","react-dom":">=16.x <=18.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release:major":"release major && npm publish .","release:minor":"release minor && npm publish .","release:patch":"release patch && npm publish .","release:pre":"release pre canary && npm publish --tag=canary","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"42333582c2b5e3d916311a6b16d4f277b2b499c2","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.15.0-canary-20221212191059","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-EdpsDNaB3vFDr7Up9vq789Z3mN2xaCl4be77PCMyB39RqL6G8zPTdEK2mXk5n3XTOxWZlcwne3rCvYTrHHU5nw==","shasum":"e163e850e1813433ac453ea581b676eae893ab68","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.15.0-canary-20221212191059.tgz","fileCount":41,"unpackedSize":138664,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDbC8So7B+78pOCpltGHCgzL/sXbHN+Kf7oXarqC1ZBCAIhAI1Ol8iHDRLfa7ymrY/yNdEP35/sWm+JSIzkwEYu6aGf"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjl3zKACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqepQ//fa9bvy00SPOQODQPUfmLDOtZ9K73Cb6CDew4YpPr1gvMPQuK\r\ncVCWeZGuqr9on9bmVAFTmBDzJApve18nsEhOn7ACMnxMWGXMnAMgxv2qQu9+\r\nt3JsWrxfPh0QV0ZSPW6O51knHhThQMhxux3yNPhFDL38ykIcFUowoWvT1Nj7\r\nwhW03wKAHtI5PYWKu06mf+23ly9nP/y0lln0uIYwSUgSPwa69BFtRTjQpjt9\r\nhEwfzL9MqNMvAeUcoXBQmtz0Iyas47H1Ruv15Le1Wd/6VK60aZ+V7l67n5Vj\r\nsTvNoBA386Bl6fw9h/Kr2K8Cch26Efu2exO6Rj5FdQluBNSpwktoKClJC7P1\r\nWh2AHEeKM7mR7qbybfvJuL+RUEI+ipzRTo9oIU4sNUyAHNiyVqdc3fqfpaH1\r\n0E3k9UGQd/vu1pfSP0T+NhEeLfjBCEdwwUS1siabeJYVpzzT3roXsSQP9k6C\r\n0b+2icpb9PqlqvqpBgC4RgycR0E9IGjNlWzjUuPCpfUhQ83OAhXP2yk34cqF\r\nH8p3G7vciWUWPKipWSJFYqIT1zRfiTGe/tfU/tuh2KdtsjVyDBHTYgvz/Asv\r\ngzgYwmgbgtCgCYMGOwITiRBHED1qjYykFLHj//vEyE0bR0umY3K2VeiOt/Ec\r\nXjr3P2RJ/8W1XAQKfdO5uERbUNXVsgf4CE8=\r\n=0DC1\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.15.0-canary-20221212191059_1670872266402_0.25949815980884083"},"_hasShrinkwrap":false},"0.15.0":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.15.0","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.2.0","query-string":"^7.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^13.0.6","react":"^18.2.0","react-dom":"^18.2.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=12.x <=13.x","react":">=16.x <=18.x","react-dom":">=16.x <=18.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release":"changeset publish","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"b939c1d9ee59f55d43b1b2668ff3c07f11286629","_id":"swingset@0.15.0","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-9rQFcrtICmQEOUT9T5oIITgx6C9ROgTPz6fUiC6mkk5gIKiTt+si2LrmErK3TsDSH75WTmgmrgRYbQJOidsafg==","shasum":"f5daeb97595f1c3211e1816e9722a28c59c0a407","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.15.0.tgz","fileCount":42,"unpackedSize":138720,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD8tyt0YV3AAhfjp5jcqgvS6+JJefWNVutNUrYuxlWQ0gIhAKA7vDFU8tvg/0sEfpxfqYFTjFv8orOtv0FFKnJE5c3u"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjl4RJACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqGJg/9HO+Qo7v/u709LcFPjRGeMib/46D3voOahMJzh8CUUv/Ekc2/\r\nGOAhbIm1/PuaNFVAEEJTPcvjHvJTZdcLL6ri2gDjj0LQxC26R4DPMDeVZage\r\nxGlldXGz0tWzCuojzsHEU+NRt9u5tLcZ24M97LFwFE3nuReI/YYT1ergwcO2\r\ncQ+0AtunO0ihneYIknXc0nZTA/wDIl5/oBIl4TgZ6Hkw5BOp4XaVldJekpQ7\r\naDFhvpw6mzhKvVKmp3QYBiya4e35KQ1VFmzZs8x36u/79Fv87b56bRvbDHrN\r\nLxobbRZjkTxBFBdZ66wCzCn6aSMJo4b+v6Cy/2L8Pt97u+5uOXBpH9a75VgN\r\n3A7pz9vsmE6iXpuzattTeh4o3ySSMS+GsgJD8nALcW9YVmlI4xxBqn1OEa47\r\n2Zejdrcx7Q55zsWYdAEj1KU35ane0wU/UW5EGZ9brgtywcpzuGsBGXt1376h\r\nRtdWmWens3DGmhSycWNpDZtnYPbvCUmdbqUYbi5GsbIyEEjEH00Lde6WPbuh\r\nNQaQ5DQdIkDYzwmz62fTTelYVvYbp50irQCugSINF9tDExCZHhplka0DVVYr\r\nXXqplf2xHZiTL0I+lqiJ+6Z4nW2amxSiq6+NR052B5Z85jhBm2e8H5gQiPNB\r\nTqOa3xNIp71cw2HeuFDMdqfnk3UQtyTc0Rs=\r\n=9uUG\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.15.0_1670874185075_0.6057901669385422"},"_hasShrinkwrap":false},"0.16.0-canary-20221212234150":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.16.0-canary-20221212234150","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"@reach/visually-hidden":"^0.18.0","classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.2.0","query-string":"^7.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^13.0.6","react":"^18.2.0","react-dom":"^18.2.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=12.x <=13.x","react":">=16.x <=18.x","react-dom":">=16.x <=18.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release":"changeset publish","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"afc71f985ae82c128ef7808f14eede7325f39b63","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.16.0-canary-20221212234150","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-kheZjPBm7lSl1nqsrsG5Rb0D7kGWlykC6tFI5aHiNSl/zUdWgP3AOdvn1ljnPNcPVFN9MZOP5acrUyD20AL3nA==","shasum":"bcb16a04fff459af7252e59b18b4451287321cfe","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.16.0-canary-20221212234150.tgz","fileCount":42,"unpackedSize":140823,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHXAlSr1mlsNXv6iDolnk2MRLFWksvDSKw3iN+WZkzclAiBDIZTxCAWpRlIuEkqUmy3on8ff2kj10iXts9+/k/ft+w=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjl7xDACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqothAAmYvc6fmX29TKrN8mS15baCxITXp+oxkhDCwwh01nZwVptc6V\r\no5k1BxvP9nP6l4haHOFuYx1blg0BCqt3+rZf1kXJyhrBR0qprn2NYZ0i1qet\r\nyqi4MLxrZNaAhX3wUHB8Py5iVQ+GVxAjCgLVgn/5Wtt4zn1ZGKl+C+v4YtJv\r\ndcW/zoYt5xc92nzcoaYL1cC1oU6l8M5zReyDRsBHGz3WcP/qaofHLXy9vmMc\r\nN3QHKaIMwE41Pl8uBlDnRl+qZaCPh3kkQ1bjYs1OhuGyvC4UepVSKGD3kipB\r\n0xKvFAUM+OCZy+XyrNeaXmahNCI6wQQ/2jnxZnSK+rp96giFceplMxWHO+F1\r\nu9b1wxFbyo9GdR3Y/HkLMfiR6SVfUeW2t1WcXVk3RCel9f4cRs20RjQwKDev\r\nvw6n6jC/3mToGvU9k4XThHgxLca1SQrRWUib1cpnxNta270VMfrgr2itsIcJ\r\nYjgUh6eTQldwdE+jUIjQfCi6GJbQBUgVvCtbYAozxd3FHafA7d0cRkFQaOGd\r\nKHP6UJZmKPd2pQeBtmrLgreUUIjgIqcq1eRssz8WD9L0637tZcfmqVs3QXoc\r\nMN4cOeEZ4VNYzkMjLwMNQgHii+OqzMxtBxtzBFwUKEvpYIg2Nd6W2t/YnfWd\r\nIILMPibA5kbuct+MxSlKelkVJfRDM7y/N9s=\r\n=C+BG\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.16.0-canary-20221212234150_1670888515041_0.9692747428722082"},"_hasShrinkwrap":false},"0.16.0-canary-20221212234807":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.16.0-canary-20221212234807","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"@reach/visually-hidden":"^0.18.0","classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.2.0","query-string":"^7.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^13.0.6","react":"^18.2.0","react-dom":"^18.2.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=12.x <=13.x","react":">=16.x <=18.x","react-dom":">=16.x <=18.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release":"changeset publish","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"07073c966f3047510d8b305bf73526ec5693016e","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.16.0-canary-20221212234807","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-lqQTu338LWVE+MUQ9zRv54Dmb5sW5PcGEW1CQtzgpx3jpCoaFKpCpDEDXMOYNj75OEKCSEmY0lzWEbalYHBzLg==","shasum":"415e23ef5634c42aaf21886dd91d6bfab2c77fe5","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.16.0-canary-20221212234807.tgz","fileCount":42,"unpackedSize":140827,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIApR71S5yqzJHv8RE2U/ztTYq2XAl14IrTKSOwTEJXtHAiBdCvPEvocHUlo93r3SbZLymJ9XqR8RDydGuuHP4pY4Ng=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjl729ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqcKBAAiqwcDRCJv8xplHGCCU2/Y5dg3SNCvEviI8966UHS5epgTKLL\r\no3rIm3GNPMd7+4M3nGzdEU2aF2M98pKnl1qYEgRKKRto0TLlJo5cZMz7Bx7B\r\npFCMW7q8bm2lgq7GVgGST3u/iuFzgebZPINqp0/Q3QAq6tmLml7ruMGieKHL\r\n2atji+2ODptdHapeI00pfV3nKgnqFE6lcuOGO45RxPEbK5gemo5OFqQBcUzH\r\nWRtHt420KVkbKcON+5FVy5PZJZW0n3qtbmH85hoh2FXsMHcdIGH7NndAexwg\r\nPgtX5EX1/J9RY57I3b6lBRGo6pTPVAU5icVbI6cv8L28XfeODvI1pkigM2XV\r\n3NDkRfnK1fVpvZwzjeYtBnAG0J8EXu87sUYPQnph1YVHA0ilysFeS2L2JHFM\r\nLgvB9K43lb+7PJbKpYIq9izpQ26dKHM679yx6H9QXDhtNUyaAVyoVaIxmJ9+\r\nEOk4f2RnqeDmZGbTB/Hptxs68yEEsi33hg2TAAJSR7+Zh7zpHPlXWEbDBpr1\r\n4krD+pCceHdiEi/CXAefLsaaKudfr3K1Ii21h6p0bVqCGmK093fFcCImVh2j\r\nbgumHwz8+nCXOyfyDVvj1QdPLZ/TVGt2b3plnEp1myv5LgtdZCQkj6KLSyq7\r\nKohHNiqu56W3NHyxG/w6nQt0AA8NA9G3AFk=\r\n=/z9V\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.16.0-canary-20221212234807_1670888893352_0.33827524827377964"},"_hasShrinkwrap":false},"0.16.0":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.16.0","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"@reach/visually-hidden":"^0.18.0","classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.2.0","query-string":"^7.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^13.0.6","react":"^18.2.0","react-dom":"^18.2.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=12.x <=13.x","react":">=16.x <=18.x","react-dom":">=16.x <=18.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release":"changeset publish","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"6ad9eca65d2651241c57c00abfe7ab8be174b833","_id":"swingset@0.16.0","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-oKtJ5lkZjdHXpxTnYfcD8SSTk4szx9zMT8rCxak4kendzKaHQiLrYR1MAONI//PfvJNj/eWXglkp6+MHGO25uw==","shasum":"608db97c313ce6ec0eb9faa5e5fdce24f975e554","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.16.0.tgz","fileCount":42,"unpackedSize":140783,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCxiCQY7URwJGpyz38MaY1HC/ClHKyOaxgG3KnpOFwpHAIgdZWpl8BdCEr/BIvknWqZy8ODveSK5ir1HRNv3KfCFPE="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjl8FCACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqDnQ/+JjdFlplvIPtFOEM693kVi6dXm2QjbIAGoR6P30mVphnEOebz\r\nuN1giL4sXXMWbN4sblXlM/UKe6LU2MwBH4ID+eyQ1RXJ/VPwpO1qd0CSyys+\r\nuwXnkexdW0iQZZGs2X2SQ3hJuLcE85eaNMR/SKAt2Xm1kQsbtMpMwPEdKOQt\r\nly5LWsv+ti9Cjbs4iNnM/WOXcS0fHV9UBg5ccC/zVzrViAcJ47hXV2Yguz7m\r\n368zNQnJTjAWJ+T8bMEtGMIftHDey0YDy3t3oapjUTooipLVUKDjl4hwFZzT\r\nk5dcpMSMnIEXV3UPOkCTCvKJtRKaAqHE5T/vFDARYNgD1q7nYUeSZhQfaHHM\r\nCMvhNM3uMW2ZU+ytxforcTVXefghEQqJzNRpMpxJUCLdf6pAhW7vydsgpGBm\r\nUDs9RwP6XtBJmzWLXXWGRia71NzaLu0+pL4VsTWCe2zyyl2nWD8ySnYJET+Q\r\nyXN/GEPqZOCVcVk49P5HExvz7bD0NHXk2jpIfRBGjhz7TjnVgGujiPaHFgJW\r\njBDGxkO137fyqhAV0SZHziO5Sw/hYkYn795cA7PjrS1J5Dh/qgBgvptp7tAD\r\n5VRwgML9d8lVYO4fvHRc77w+CmNceCg8ZwvNk/KxMWfPoBh0WE+2svaMa59U\r\nCbFlf+8N0AsE8sCDAVr32GKQpRq+HFu6kzY=\r\n=C8En\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.16.0_1670889794534_0.4673000087054815"},"_hasShrinkwrap":false},"0.17.0-canary-20221213190039":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.17.0-canary-20221213190039","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"@reach/visually-hidden":"^0.18.0","classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.2.0","query-string":"^7.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^13.0.6","react":"^18.2.0","react-dom":"^18.2.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=12.x <=13.x","react":">=16.x <=18.x","react-dom":">=16.x <=18.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release":"changeset publish","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"64e628b1ec2a00b11b836741eaf894a8510c91c1","readme":"![Swingset](https://p176.p0.n0.cdn.getcloudapp.com/items/NQu14DNO/swingset-light-github.svg)\n\nAn opinionated, drop-in component library for next.js apps.\n\n> **NOTE**: This project is in early alpha stages, and the readme is still not accurate. It is not recommended for use currently. If you really want to use it still, reach out to the author.\n\n### Installation\n\nInstall via npm with `npm i swingset`, then add the plugin to your `next.config.js` as such:\n\n```js\nconst withSwingset = require('swingset')\nconst withTM = require('next-transpile-modules')\n\nmodule.exports =\n  withTM(['swingset'])(withSwingset(/* swingset options */)(/* normal nextjs config */)\n```\n\n> **Note:** Swingset is not transpiled, and requires you to use it with `next-transpile-modules`.\n\nYou then need to create a page in your nextjs app where swingset will live. You can \"inject\" swingset on to any page of your choosing. Something like `/components` might be a nice choice. When you have decided on a page, swingset can be injected as follows:\n\n> **Note:** `createStaticProps` accepts `mdxOptions`, which allow you to customize how your markup is rendered. For details, see [`next-mdx-remote`](https://github.com/hashicorp/next-mdx-remote/blob/main/render-to-string.d.ts#L36-L42)\n\n```jsx\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nexport default createPage()\nexport const getStaticPaths = createStaticPaths()\nexport const getStaticProps = createStaticProps({\n  /* mdxOptions = {} */\n})\n```\n\nWith this in place, if you go to the page you injected it on, it should work, although it will be empty. Next, let's talk about how to get some components loaded in there.\n\n### Usage\n\nSwingset points to `components/*` as its default location for components, in line with next.js convention. This is configurable if needed though, see [the options section, below](#options). It expects your components to live in folders, perhaps they contain an index where the components lives, and some other stuff like css. It doesn't matter what else is in the folder, as long as it has an index. To start writing docs for a specific component, add a `docs.mdx` file to the component's folder, and make sure that this file has a front matter block containing a key/value pair for `componentName`. Let's look at an example. Here's how your folder structure might look:\n\n```\n.\n├── pages\n│   ├── index.tsx\n│   └── [[...swingset]].tsx <- here's where you injected swingset\n└── components\n    └── button\n        ├── index.tsx <- this is what's returned when you import `components/button`\n        ├── style.module.css\n        └── docs.mdx <- here's the docs file you created for swingset\n```\n\nSo, you have only now added two things to your app -- a file in `pages` called `[[...swingset]].tsx` where you injected the component library itself, and a `docs.mdx` file in one of your components. And remember, the `docs.mdx` file needs frontmatter, or you will get an error. Here's how a minimal `docs.mdx` file might look:\n\n```\n---\ncomponentName: 'Button'\ncomponentCategory: 'UI Elements'\npeerComponents:\n  - 'ArrowIcon'\n---\n\nHi there, welcome to the button docs!\n\nHere's an example with an arrow:\n\n<Button cta=\"Click the arrow!\">\n  <ArrowIcon />\n</Button>\n```\n\nIf `componentCategory` is not specified, components will fallback to a catch-all \"Components\" category.\n\nWith this in place, you should see your component's name render in the sidebar and show the contents of your markdown file. Not so bad! You are of course welcome to add docs files to multiple components, we're just starting with one.\n\nNow let's actually make these docs useful. There are a few components that are made available within `docs.mdx` files that will help you to showcase your components.\n\n1. Your actual component. So in the example above, you can use `<Button />` right in that mdx file, and it will render an example however you please.\n1. Any components exposed as named exports from your component index file.\n1. Any components you list in the `peerComponents` frontmatter key.\n   1. In the example above, `<ArrowIcon />` is added to scope.\n   1. **Note:** `peerComponents` must also be present in Swingset (i.e., they must have a `docs.mdx` file). A warning will be emitted if any unknown components are passed here.\n1. `<LiveComponent>` - a component that can be used to render a live code editor that will display and update your component\n1. `<KnobsComponent>` - a component that can be used to render a set of UI controls that will live update a rendered version of your component\n1. `<PropsTable>` - a component that will render a full or partial list of your component's props.\n1. Any of your own components you specified in the [swingset options](#options)\n\nWe'll dig into how each of these work in the following sections, and give plenty of examples.\n\n#### `<LiveComponent>`\n\nLet's look at an example of this component first:\n\n```jsx\n<LiveComponent>{`<Button\n  url='http://example.com'\n  theme='primary'\n/>`}</LiveComponent>\n```\n\nAssuming that you're in a `docs.mdx` file with a `componentName` of `Button`, this example would render a live code editor containing the string specified, in addition to a preview pane which contains the rendered component. As the code editor is adjusted, the component would be re-rendered accordingly.\n\nThis is a very simple component - it just expects a single child, as a string, which it renders into the code editor.\n\nIf you have a need for components other than the component being documented in your example, these can be provided through a `components` prop, as such:\n\n```jsx\n<LiveComponent\n  components={{\n    SomeContent: () => <p>content yay</p>,\n  }}\n>{`<Button url='http://example.com'><SomeContent /></Button>`}</LiveComponent>\n```\n\nThis is best used when you want to represent another component in your example, but the actual implementation of that component would distract from the point trying to be made in the example.\n\nThere's one more useful prop to `LiveComponent` -- `collapsed`. If this prop is set to `true`, the code editor will be collapsed by default - when clicked it will expand. This is useful for examples that contain a lot of code - you can collapse the editor by default to make it easier for users to scroll through examples, then expand the code editor only when they want to see/edit the source code. It is `true` by default.\n\nTODO: screenshot here\n\n#### `<KnobsComponent>`\n\nAs usual, a usage example upfront:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    text: {\n      control: {\n        type: 'text',\n        value: 'http://example.com',\n      },\n      required: true,\n    },\n    disabled: {\n      control: { type: 'checkbox' },\n    },\n    theme: {\n      control: { type: 'select' },\n      options: ['foo', 'bar'],\n    },\n  }}\n/>\n```\n\nThis would render your component, like `<LiveComponent>`, but rather than a code editor, a set of UI controls. These UI controls follow the [props spec](#props), and using a props file with this component is strongly recommended.\n\nTODO: screenshot here\n\nNested props are supported as well, to infinite depth. For example, a nested `theme` prop might look like this:\n\n```jsx\n<KnobsComponent\n  knobs={{\n    theme: {\n      color: {\n        control: { type: 'select' },\n        options: ['red', 'blue'],\n      },\n      style: {\n        control: { type: 'select' },\n        options: ['primary', 'secondary', 'tertiary'],\n      },\n    },\n  }}\n/>\n```\n\nControl types currently available are:\n\n- `text`\n- `select` -- requires `options` to be set\n- `checkbox`\n- `json` - freeform input for any js object, not recommended\n\nTODO: screenshot here\n\n#### `<PropsTable>`\n\nExample as always:\n\n```jsx\n<PropsTable\n  props={{\n    text: {\n      type: 'string',\n      description: 'text displayed in the button',\n      required: true,\n    },\n    theme: {\n      color: {\n        type: 'string',\n        description: \"sets the button's color\",\n        options: ['red', 'blue'],\n      },\n    },\n  }}\n/>\n```\n\nThis component is quite straightforward as well, given an object containing data about props, it displays a nicely formatted table that shows the component's props. This component pairs particularly well with the [props file](#props), which we will discuss below, as its objects can be piped in directly.\n\nTODO: screenshot here\n\n### Props\n\nAn additional, optional convention is to define your component's props in a separate file. You may ask yourself, \"but why can't I use typescript, or jsdocs in my component, or PropTypes?!\" The answer in this case is because swingset does not want to impose anything upon the way that you choose to build your components, so instead it offers an optional manner of detailing your props outside of your actual component.\n\nIf you include a `props.js` file in the folder with your component, it will be picked up, parsed, and injected into your `docs.mdx` file as `componentProps`. You can then pass it into the `<PropsTable>` and/or `<KnobsComponent>` components, either fully, or splitting out individual props or sets of props, to save yourself lots of repetition and make your docs file much more terse.\n\nThe `props.js` file does have an expected object structure, which is detailed below in psuedo-typescript style:\n\n```typescript\ninterface Properties = {\n  propName: {\n    type?: string, // write out the type you expect however you please\n    description?: string, // a short description of your prop\n    required?: boolean, // is it a required prop?\n    control?: {, // for knobs, see <KnobsComponent> docs above\n      type: string, // type of control\n      value?: any // starting value for the control\n    },\n    options?: []string, // if there are only a specific set of values allowed, detail them here\n    default?: string, // if there is a default value to this prop\n    testValue?: any, // value to be used as a test fixture, pairs with `fixtureFromProps`\n    properties: Properties | []Properties // if the prop is an array or object with nested items\n  }\n}\n```\n\nAs with other components, props can be nested here as well. There are a few specific caveats with the `control` value in nested properties though:\n\n-\n\nLet's lock this all in with a real example of a simple `props.js` file:\n\n```js\nmodule.exports = {\n  headline: {\n    type: 'string',\n    description: 'The headline displayed above the content',\n    required: true,\n    testValue: 'Test Headline',\n    control: { type: 'text' },\n  },\n  data: {\n    type: 'object',\n    description: 'data that the component will render',\n    properties: {\n      theme: {\n        type: 'string',\n        description: 'color theme of the rendered data',\n        options: ['dark', 'light'],\n        control: { type: 'text' },\n        default: 'light',\n      },\n      logos: {\n        type: 'array',\n        description:\n          'company logos to be displayed and show how cool your product is',\n        control: { type: 'json' },\n        properties: [\n          {\n            type: 'string',\n            description:\n              'a string specifying a known company slug for which the logo will be displayed',\n          },\n          {\n            type: 'object',\n            description:\n              'if its not a known company, a custom object containing the necessary info to render',\n            properties: {\n              name: {\n                type: 'string',\n                description: 'the company name',\n              },\n              logo: {\n                type: 'string',\n                description: 'url of the company logo to be displayed',\n              },\n            },\n          },\n        ],\n      },\n    },\n  },\n}\n```\n\n### Options\n\nWhen initializing swingset in `next.config.js`, there are a few options you can pass it to customize its behavior. The example below shows how that might be done. None of the options are required, they all have defaults.\n\n```jsx\nconst withSwingset = require('swingset')\n\nmodule.exports = withSwingset({\n  // Where your components live. \"components/*\" is the default.\n  componentsRoot: 'components/*',\n  // Where your generic docs pages live. No default\n  docsRoot: 'docs/*',\n  // Extra logging. Default is false\n  verbose: false,\n})(/* normal nextjs config */)\n```\n\nThere are some additional options that can be passed in to the page configuration for customization, example below:\n\n```js\nimport createPage from 'swingset/page'\nimport { createStaticProps, createStaticPaths } from 'swingset/server'\n\nconst swingsetOptions = {\n  // if you have custom components you'd like to have available for use across all docs pages,\n  // the can be added here. No default.\n  components: { Tester: () => <p>testing 123</p> },\n  // Any React element\n  logo: <MyLogo />,\n  // if a link is returned from this function, it will display a link to the source code\n  // under the header automatically\n  customMeta(componentData) {\n    return {\n      github: `https://github.com/your/repo/components/${componentData.slug}`,\n      npm: `https://npmjs.com/package/${componentData.slug}`,\n    }\n  },\n}\n\nexport default createPage(swingsetOptions)\nexport const getStaticPaths = createStaticPaths(swingsetOptions)\nexport const getStaticProps = createStaticProps(swingsetOptions)\n```\n\n### Test Utilities\n\nSwingset currently ships with a single test utility that can be used to extract deep-nested `testValue` data from props for use as test fixtures. Lets go through an example, starting with a sample `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'string',\n    description: '...',\n    testValue: 'value',\n  },\n  bar: {\n    type: 'object',\n    description: '...',\n    properties: {\n      baz: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nNow let's look at how this could be used in some tests:\n\n```js\nconst props = require('./props')\nconst { getTestValues } = require('swingset/testing')\n\ngetTestValues(props) // => { foo: 'value', bar: { baz: 'value' } }\n```\n\nThis set of props can now be used as a fixture for component tests, perhaps like this with `jest`:\n\n```js\nconst props = require('./props')\nconst Component = require('./')\nconst { render } = require('@testing-library/react')\nconst { getTestValues } = require('swingset/testing')\n\nconst defaultProps = getTestValues(props)\n\ntest('default props renders without error', () => {\n  const render(<Component {...defaultProps} />)\n  // ....\n})\n```\n\nIt's worth noting that for nested props, the root and children can both have `testValue`s, and they will be merged together. For example, the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n      baz: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'root value', baz: 'root value' },\n  },\n}\n```\n\n...would produce `{ foo: { bar: 'value', baz: 'root value' } }`. If the root does not have a `testValue`, however, none of its children will be reflected in the output at all. So the following `props.js` file:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n  },\n}\n```\n\nWould produce `{}` as its output, since `foo` does not have a `testValue`. There are two options if this is not your desired output. First, supply parent values with an empty object/array default, depending on the property type, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n        testValue: 'value',\n      },\n    },\n    testValue: {},\n  },\n}\n```\n\nSecond, supply your entire fixture at the root level, rather than breaking it apart and distributing it to sub-properties, as such:\n\n```js\nmodule.exports = {\n  foo: {\n    type: 'object',\n    properties: {\n      bar: {\n        type: 'string',\n      },\n    },\n    testValue: { bar: 'value' },\n  },\n}\n```\n\nChoose whichever option feels more clear for your use!\n\n### Notes\n\nAny global styles that you specify by importing to `_app.tsx` will be reflected in your component library. Normally, this is a good thing, as your components will be showcased as they normally would within your app, but if any styles are not rendering as expected in the component library, it may be due to global overrides.\n\n### Local Development\n\nThis is a complicated library to test due to the way it operates - it must be hosted inside a nextjs app, so the minimum viable integration test fixture is a full blown next app. There are also a variety of issues with the way that dependencies are installed and flattened that make it even more difficult to integrate locally.\n\nAs such, the easiest way to work on this library itself is using the wonderful tool [`yalc`](https://github.com/wclr/yalc), which is like `npm link`, except it actually works the same as a normal `npm install` instead of breaking in most situations. Here are the steps to getting set up with a local dev environment that will allow you to iterate quickly.\n\n- Install yalc with `npm i yalc -g`\n- From the project root, run `yalc publish`\n- Go into your fixture directory, for example, `cd examples/basic`, then run `yalc add swingset`\n- From the fixture directory, run `npm start` to run the app\n- In another terminal tab, run `yalc push` from the project root whenever you have made changes to the core library and want to see them update in your app.\n\nWe'd love to get a watcher set up that will run `yalc push` for you automatically on changes to source files, if anyone wants to contribute this it would be lovely 💖\n","readmeFilename":"README.md","_id":"swingset@0.17.0-canary-20221213190039","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-5JoubvlC80oS6P99781llfepNYtMAT6LoVu+NmYnRtkcPT8LIg1+CnmE1eOTH+9OTjYTsZBTuwM1YApqDPSI8w==","shasum":"5e91ecd1cd9af3728eaac2f3e75eef297fc3d304","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.17.0-canary-20221213190039.tgz","fileCount":42,"unpackedSize":141216,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDlju9scUm3zwHQAbWs6aXranyGhW86tOokE9o55MshiwIhAPHRq/ThUwVkwJ4JI2h1/Sc2jeyWzkpyY2jh2xuljwp/"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjmMveACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr9yxAAkPbe63ynJ2MxeVf+P5JR6VNkwr4ly5UuJN7eJTV4hUkhI03L\r\nrropolW72tkFqn94n7RQe76ITzi33aVl8wGNnc2VZb/BPdSe5+eDPqUpQm6U\r\nAXOgnXjKNw6mbbQKBnb0/2kBRHnrfSUbJ6WvlXJTBUgdPvKo+FwNYAsWkwvt\r\nqZAIv22NbpoK/dGXX+SZ6BD6T0Rn1R72AaJArwFQ2KtBSFoc2g8bIRyQmBIy\r\nDon6fYV9nEa/pxJD9x9BLiJlxJDa35J2D0KccNEbdjEJIbLeuur8YEeYuoR7\r\nsiAPejJdT7d1c7iqPE7ycR9t6nwSnHCf3g6vlr71jOdi3iQKL25RaX9nmpHF\r\nOQAWuwhDfewoBMSHuqHJjWi1UK29P54J/Ge00QGupuvwyKt7+NuuFynfIr4D\r\nqoU2equyUrLE42ejPrdOOFyar889qYoeouMCYuTpbg3PqlGGb9MDJXFcpTAf\r\ngOVivYXz+dVQWLCepguB3aNLkrImm0dZbYHyqBuUDrvK/k/iZQN+0oymjwEW\r\nMMr+GWj1QOZb7VKFzZadNfvw43StHMZClr5EdCUM/qFjyTzI9FdxogT3er4Z\r\ngpm6si0K9LHdeW/S5OHllOc/p7C2OPsWzu5I2PXb3Z2iBGKBZ0JDtIc5RN51\r\nI0YdsLmpE/x3JErTrbF8z5jHTdk+FeZP0zs=\r\n=W1h+\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.17.0-canary-20221213190039_1670958046006_0.5026749695691888"},"_hasShrinkwrap":false},"0.17.0":{"name":"swingset","description":"drop-in component library and documentation pages for next.js","version":"0.17.0","author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"dependencies":{"@reach/visually-hidden":"^0.18.0","classnames":"^2.3.1","copy-text-to-clipboard":"^2.2.0","fsexists":"^1.0.1","globby":"^11.0.3","gray-matter":"^4.0.3","loader-utils":"^2.0.0","marked":"^1.2.2","next-mdx-remote":"^4.2.0","query-string":"^7.1.1","react-live":"^3.0.0","require-from-string":"^2.0.2","slugify":"^1.6.0"},"devDependencies":{"@changesets/changelog-github":"^0.4.7","@changesets/cli":"^2.25.2","@types/require-from-string":"^1.2.1","jest":"^27.0.6","next":"^13.0.6","react":"^18.2.0","react-dom":"^18.2.0","release":"^6.3.0","typescript":"^4.6.3"},"homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"license":"MIT","main":"index.js","peerDependencies":{"next":">=12.x <=13.x","react":">=16.x <=18.x","react-dom":">=16.x <=18.x"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"scripts":{"example":"cd examples/basic && [ ! -d 'node_modules' ] && npm i || npm start","build":"rm -rf ./dist && rollup -c rollup.config.js","typecheck":"tsc --noEmit","release":"changeset publish","release:canary":"changeset publish --tag canary","test":"jest"},"gitHead":"ce5fccd4c2d65926a87ec5fbe8de3a3dba1f86b8","_id":"swingset@0.17.0","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-4e9iLr4wA9N95H60HpMGGeejOU+kQEW/MQPvml7Et94+ofuOo9Q6Zsr0Szqz5UT6GqkFMW2GgFT/LpphAW91Jg==","shasum":"3c47df70d7e442c86349c47facfd66ec424f6b76","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.17.0.tgz","fileCount":42,"unpackedSize":141172,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE2ucmeJOSYBsMA6PlRXrfk1/q76HpuK759ThCGgA3QpAiEAj9HetcOc8E0TD2Du2NywsSaeH9zpKL7bYvSJvaf5+jA="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjmOtdACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrLuBAApSDlvgb0MplB/EYSDpUkch72KJn5a99QddFESiOBWg7yhzh1\r\n8qKpzoLRQHjWsI5P6r2wopf1xs8wcuZR+7QjKOmlhWCw/EE4ZEezWN6+NAZs\r\nJxkCuSKkHW6fLoaGZCsXz1BMx+7aAnyftLM+u2Gq85iV1DiMuDAiURuDRlBb\r\nOtYnyKou2VhNefYiEiExlfjAd/ZDdMdlfz7FjM2ZgCvaIt+sGXLrfCFCykNR\r\nke23U0m1Kowg2GmWHM6OO59cG+WDkY+B4ok3uDVKbZE+4dJ1D+alsmxF6hcN\r\nJggEMRfu/2GPmtR6MOpwSw8nICMLrg942R4MECbGNuEvmOdpjSl8iofCcrhx\r\nOrKLnH3Cz90GXxRo/6tyWI8IabhQo8xSPfxUPjDRVjF9n/hO74cFOdKdLL05\r\ncIhGveduHfT042KI4xi3nUqWa5TwLXt8K+Kq4gUfuaCitVO+SEF21NDMBs5R\r\nI7AfHDaLf2gnwKsiqQofa8TcEqQnlDEDVBSioGmdIXbqvLHqejgT2Zi/bzJx\r\n9515UKNIvYhXwiiM0T1MOK1364T/KU4B8U9NdihGKUZe4Ea1jLDqxPGD4y/v\r\n4Lq4a3tnfcOuTXd3obi0bwMtgSCxQUO1x5lsR1aHX7pUmx0qmBl2ttSZx74D\r\nzXM1r+ZQUgeH+MOSza0ZBumilxuacT9qSkM=\r\n=S+Yr\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.17.0_1670966109677_0.020648310846563822"},"_hasShrinkwrap":false},"0.18.0-canary-20230321185651":{"name":"swingset","version":"0.18.0-canary-20230321185651","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"dependencies":{"@mdx-js/mdx":"^2.3.0","directory-tree":"^3.5.1","github-slugger":"^2.0.0","globby":"^13.1.3","next-mdx-remote":"^4.3.0","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.0","@types/webpack-env":"^1.18.0","autoprefixer":"^10.4.13","next":"^13.1.6","postcss":"^8.4.21","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.2.7","vitest":"^0.28.5"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts'"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"readme":"# swingset\n\n## Goals\n\n- [ ] Fast, automatic HMR for content\n- [ ] Document components in your repo via a glob pattern\n- [ ] Support arbitrary pages as well\n- [ ] layout / theme fully customizable\n","readmeFilename":"README.md","gitHead":"63f283eb7ac24fc5425e9e00f977da00506ef5b0","description":"## Goals","_id":"swingset@0.18.0-canary-20230321185651","_nodeVersion":"16.19.1","_npmVersion":"8.19.3","dist":{"integrity":"sha512-zCNYoSB/7WG02KBpRJjuhpbXZySoUMegpx5M/ewHekraqEe/rJI7KnJMgGitDV6XKkaePvhc0xVHKLvQUotjCQ==","shasum":"0295167be28d95aaf383aa4b4f4b9a20512fb082","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230321185651.tgz","fileCount":29,"unpackedSize":26970,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDYB05BK37rkptV4qro1q3jt3tvEJk8RJIv8pvj4LWmRgIhAK6p3yxcavW4SZ5aBrFFJ2jAwaiDiiINtRH5N1BUgj5X"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkGf4YACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqy9xAAiF05o+tEqGGW1vZt6Zy6/NnwetdNoixJTnQOg0X+8PGuW2K9\r\nV7/QmabbmeO2SeYJx1xEsBJLItDY6CPIDfCNOy6zWCf01ps1OvbSvsMDf1nb\r\nTQJF2VPmXaEoXlQMigcB9oRxwaG3ziksVEqF/YdhXEXwVA4mLTADhGqzYORZ\r\n5V83PKHOFVrPt8prTLqW9F+eNE/w6o+MHhNkPsYblATfjAbIkSOIIbyiVvwG\r\nYmXxbI8tx6ny9BioxyHb2PaUfRHrJ2prvoa3ApU+0DHlFgq31BS05sgPQti1\r\nPEltpWuoKLqNb92e2rBu8q2YKmCGsSNMcQf3jks/B1d4Ue95M74naxdCkbGn\r\n6hNQ6+TH7++KeCxK/LmE27ar20JhcEESKxKxHPfGIENdgnxlb0K8KVoatQgP\r\nYKGTcmWY2jvYe9HNewt6Pe/nZDnAjJ51e+UTaGMiWyLn7kB8gLrJfp0ZVR1E\r\nQnhZiFjgs+XQpVwOi6bFngX5ffh5mwRpWyFdzVK9NPtljweYlWTQb/Qz0QaZ\r\n+GvPb+3rgwZZD8WYX8CAbaIGxzIFvFjaoYEZgT0d/k6Ie192d717WhKUHbdH\r\nHiBcDmxYdeIdgcNvyYSryzUP74qt6VPu6osrMj/rf/RlGcNZ1BHy6ULBCIKy\r\nyOJDRTvzqQYvWE+5TXHG1QkDJtGfNbm4Puc=\r\n=gnnL\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230321185651_1679425048233_0.7381652774222751"},"_hasShrinkwrap":false},"0.18.0-canary-20230321200711":{"name":"swingset","version":"0.18.0-canary-20230321200711","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"dependencies":{"@mdx-js/mdx":"^2.3.0","directory-tree":"^3.5.1","github-slugger":"^2.0.0","globby":"^13.1.3","next-mdx-remote":"^4.3.0","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.0","@types/webpack-env":"^1.18.0","autoprefixer":"^10.4.13","next":"^13.1.6","postcss":"^8.4.21","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.2.7","vitest":"^0.28.5"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts'"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"readme":"# swingset\n\n## Goals\n\n- [ ] Fast, automatic HMR for content\n- [ ] Document components in your repo via a glob pattern\n- [ ] Support arbitrary pages as well\n- [ ] layout / theme fully customizable\n","readmeFilename":"README.md","gitHead":"c92b4b062a489bbfc984903bda0c6551b65cc5c1","description":"## Goals","_id":"swingset@0.18.0-canary-20230321200711","_nodeVersion":"16.19.1","_npmVersion":"8.19.3","dist":{"integrity":"sha512-ytkKimPdSg50bFHBVoEoVMNkolPtd47VaA/MRLFDeHrFGoZuGuAjZqvVvamNeL7WIiI4NaPSA/jMCFCrgfBz+Q==","shasum":"24438b246e73429014612909feab75db2125203b","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230321200711.tgz","fileCount":40,"unpackedSize":35393,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDyouqOAoIV0MLvwgZJMFvivObODZgCGP/xMXrPPp/PHAIhAKzshHp9PsRP//AsMi956fQsP5ojlgvZlZrKnYLJW7WQ"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkGg6WACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp2bw//ZAhR6C/qkrG3zGQJowJwGD8joQeuoLSSPtLi+Q6L7UFLocq6\r\n5bPUSuXmcR2Eeb5V3VALHBGL5K8Gs1W7ErSqrLblPjaMnTxvjwQOuYBSWoRP\r\nB/lmcHjtwYd3xqhLygSGSk0gBE4bT3LIhm0TUxR3DRwEpSbLjUf8qDWfVmuL\r\nKmGTbHf3LnPyCGAv94C9v3NQARYE6dSNm2vRPV9Lq86tdSJVClPtVYq1kHA8\r\nr0K+LdPB8bmQoQbsaBil4CegI7dqPEI7oA+3z4e3pHyOdaZ/gKXCk9O+XdF5\r\nmWB2tU+x9+YafEBEdWKH8TM68e2tP0KoPpHG4VdXCNUyeo9rP6xIZPz+Bv/B\r\nVvASnwTcP4ffFj+ezKWE5ZS4jONsdxeakUkr3ZkKJEe3FhomDUl1RhQOkR9l\r\na1P7VVXsnEHgpW315PvewJ3CFGGxQulF9sqgtoJJ5MjZQbn05dN/ynbesX8D\r\nq1qcfDZToFYBcLL6oWfO8nrLwOUiRTt/nIh1nGyobSxTJMvNQWDpww69iq2c\r\nPJZbTX4NgpvlOd4TSXjInRbN5vZlH6YqJJY+cvFTwROBO7mmYai5SCNNBIus\r\nK/VdafxxF4itt9xLnNy9lyyHNKXsLZsU2fa8yqhwcbN/btRZKSJMzC1E1t0w\r\n786upCflTx1Gm37o87e0yh9eQS2HZtMedxs=\r\n=N75s\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230321200711_1679429270586_0.5196143873851475"},"_hasShrinkwrap":false},"0.18.0-canary-20230412151215":{"name":"swingset","version":"0.18.0-canary-20230412151215","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"dependencies":{"@mdx-js/mdx":"^2.3.0","github-slugger":"^2.0.0","globby":"^13.1.3","next-mdx-remote":"^4.3.0","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.0","@types/webpack-env":"^1.18.0","autoprefixer":"^10.4.13","next":"^13.1.6","postcss":"^8.4.21","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.2.7","vitest":"^0.28.5"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts'"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"readme":"# swingset\n\n## Goals\n\n- [ ] Fast, automatic HMR for content\n- [ ] Document components in your repo via a glob pattern\n- [ ] Support arbitrary pages as well\n- [ ] layout / theme fully customizable\n","readmeFilename":"README.md","gitHead":"e63e06f4c0bb125b7873cea973727692e1822926","description":"## Goals","_id":"swingset@0.18.0-canary-20230412151215","_nodeVersion":"16.20.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-p2u602HDLB1hWdlGnz5il+4WkDMu/sFSvddvOsW2bVFAE6//Tqicrnj2rM/8pDmS7judSaR8y+laqY9+DV8Jzg==","shasum":"8cd2742172ddae13f0c02b0316f8f155270cc008","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230412151215.tgz","fileCount":40,"unpackedSize":35361,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBYuQMZU/h/XQet/rsCrQAVai20k8X4fDAXQ9kgwiAK3AiAKiczsPjzlSGo6HRAvluhemSss8mWOYhlIJ5pALYR3Sg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkNsp3ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoPCA//dFhRAAEo2lxC7nZes2YgzhCl2lnnSkapkxZusYXGpaOAFyq8\r\n0v/aft2qstTqtw8chR0ZUJWYJnPQorSaROCPlo+eH2YBJ5MRiYL8dlcFOLkY\r\nwUA9gpL9LwzB+8+puv5qKwLVrUIrQCN+mj++GS2Q8KxJzWRKCFReVZMeMZv/\r\ntDDCoCeRdVq1WjNcnT9T9uKzkAHR/YioowxgBDasNCxqO1qDxCypgGzWBaw4\r\nr9GSDMKPG1S5Edmgurr/D3SfAN/HYHWGW2niccfvvMDsRSdEWcFkr3iuzBBD\r\nkPpwsOG5Gi+6i1yqUV9E71df+j13v9fEoEJt16RJJOvhk6WDZQIK1O8cQf+z\r\nElABo0Aw4nqlunL9drpK81oJQXZYh4aqia0r8Hkeumxmy1m2DgNQN+UBHna7\r\ntKzGqrzc5PYyJZi1VRdS+quuwKDjmrAzDWHv7y2LOW6gM4VauzQuUFD7YhMs\r\nrmXiisGfJ4DKOWC7HWrY9sIJNJ3FzoeLCA1/Onqk9ZE8PusZgWArSWLWYyRt\r\ntQv4XFPl4aX9Q2pIaAnEXSvH2iaxBhVoYgTj/Uod/zuXBCmh1sLUCDUSN7PQ\r\nQa6UXvjkRfzLRnBhTT5/cDM/e7WZ+LuJ4asIWG/ihLbfDAnvw+87kUHOxI97\r\nrmoMYaxZInYQHCbQ/oA9URyIjJ83o5k+krA=\r\n=HGL6\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230412151215_1681312375634_0.20803616175395367"},"_hasShrinkwrap":false},"0.18.0-canary-20230412152225":{"name":"swingset","version":"0.18.0-canary-20230412152225","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"dependencies":{"@mdx-js/mdx":"^2.3.0","github-slugger":"^2.0.0","globby":"^13.1.3","next-mdx-remote":"^4.3.0","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.0","@types/webpack-env":"^1.18.0","autoprefixer":"^10.4.13","next":"^13.1.6","postcss":"^8.4.21","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.2.7","vitest":"^0.28.5"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts'"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"readme":"# swingset\n\n## Goals\n\n- [ ] Fast, automatic HMR for content\n- [ ] Document components in your repo via a glob pattern\n- [ ] Support arbitrary pages as well\n- [ ] layout / theme fully customizable\n","readmeFilename":"README.md","gitHead":"5ba2eca272fff6265c2fb1068c284a6bbfd0ed40","description":"## Goals","_id":"swingset@0.18.0-canary-20230412152225","_nodeVersion":"16.20.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-vhyMZBcOLxGHx5L10HhTnQBSD5NRC1osYuIe+WYuoCI3ZZONm0pNUm8tlgjT6KlO2ghP6xxCcnJkwfUbftoDJQ==","shasum":"7a9a0d1d2cd65b5910a6cfa0acb9221b1448443e","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230412152225.tgz","fileCount":40,"unpackedSize":35361,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAKLRxoc8vmQ7dcKNj30WJ3s7vWCUKH1wmrpR2UBnyV3AiBQqD4D5i6iAiwVRyGTB1Q6xEykTaYpDsZx3w8st6iQDw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkNszcACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoNrw/+IH5faidL+d8bYeNU1a3OznB/gwerm+bT76IuGpP3Wpny6sQi\r\n5G7AIHPXUawJpwN0GecepwQ+e+PTrOdcm/lG12CxaoEuEieZYojHIq2YixEB\r\nQnjDbNgZ6f+ZgjTD8gLptX/USxyDcs6U2krxPomTYvDCM6SI+lI3FFNKdzAq\r\nEO7tXyEj6vubJSpDDF8BUe+RTMg0T9biP/URZJWfjisFOUz+lwgDtMLV1L4i\r\nODbMTnMbYyiqzFaLyIPakL7r9EC4iWeI8FG3dntvsH/XwU/VA7xZ+Y9qg2zT\r\ny4/cyk38RY6LyRmRiY16MIDrlSB2ezmq9Ynu8xUH4ToY0LfkhD8ElnLqZb/p\r\nG3TcxWJ0C3lI0kRI0+jXIg2m7nVF2GySDjBrqgK7gS/IOPkngxK2m1UXhk8y\r\naKY7V8TwRbzVReLLVzX1nBMTM5ctxT1lNCoItQTb0cqkOf766nEF4Cj5rJHn\r\nFt/JkhnYloIIKdVBXdqx2VF3y9dmZ8hH5gabwFWWcCvcEVAw4tSfZLG4o3LB\r\nw0NTas/4oneBa7dHV0ZpXW948WVpl/9GBhM5Wl+b2SOjK72ReZIoMeNj1WCq\r\nX/vxQBu1+F6L14afeFQB8jyUPlYF3vgHojbPN+t/wbp8/xt5rHrhmQkDxOoI\r\nzWKwhRhWk86kpQmZj1QmaoFBueha0A5IQyI=\r\n=4LTK\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230412152225_1681312988134_0.8024340918957138"},"_hasShrinkwrap":false},"0.18.0-canary-20230412162055":{"name":"swingset","version":"0.18.0-canary-20230412162055","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"dependencies":{"@mdx-js/mdx":"^2.3.0","github-slugger":"^2.0.0","globby":"^13.1.3","next-mdx-remote":"^4.3.0","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.0","@types/webpack-env":"^1.18.0","autoprefixer":"^10.4.13","next":"^13.1.6","postcss":"^8.4.21","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.2.7","vitest":"^0.28.5"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts'"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"readme":"# swingset\n\n## Goals\n\n- [ ] Fast, automatic HMR for content\n- [ ] Document components in your repo via a glob pattern\n- [ ] Support arbitrary pages as well\n- [ ] layout / theme fully customizable\n","readmeFilename":"README.md","gitHead":"92e54a9a065b70bdd0508139e64f74443f58b615","description":"## Goals","_id":"swingset@0.18.0-canary-20230412162055","_nodeVersion":"16.20.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-UG7KdhE7HY+eofypp1EYwxev6DTgpdtEpOE8H4/22hQh1GmQSdCbX1OxINi4Hs9Ggo/mOBi9YvFdcbh4DD9YDQ==","shasum":"bfa98102f604b56bd00fa3e7e49e1888f7bf87d1","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230412162055.tgz","fileCount":40,"unpackedSize":35361,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCL1DWbbMJO44RIst43P9W0Ls1aEFFYgRNo8pJtsRLQsAIgMe4aT6XxhEfGm7gDH6JZWw+kBKj9DQ1HuHF4sKOVqiQ="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkNtqSACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo2Xw//fMs0gbt/HCe7jkPh5cgs59bq0D5KR4aK2WobrBC/pLdlaMf+\r\nfJf9MX8BtqJgkjJjeAN0qSnaEHnHxDFrDSsT81du4fLsoCOoy5KgUQEzsQPx\r\n2kQ7UguzwKpYhVB9ydIV0F7ehASaiYWyYh1/M0sLVcIk5i33QKjhTbeWREbY\r\n1naiXc6fVm0PCYmEczggEbJVn0wx0LhUm+2uEqW1KN/wNmGLKRgkwKeqZSCv\r\nnFXg4uQm5ilxGhnwlq4vGsmvctX6OjgSo966+KZEuR5iQln1neh8Z7e6qAh/\r\n9vyaNiCPSIHFiWuVMLKpIxcZAslk9SGvDvZTaYUkBmaismcS8bkFQfmKDwAT\r\n7lPd+xPSTnYueNM+LVItf2l8OYZD/G567VS+Upp4Bl40BkAoXY/r2FzOrbcY\r\nuJsPQG7MGfd3lSRrIPJTpOmMU9nzaH+eyntrCyJxWCBvOCOL27fY+SXTn4VN\r\nW08Ua49X15zV2VUbFIA1xorQ/kThZuFvoGrxyyMdyFknrLmSmCBD+2ILqAi1\r\nFRybkMf2B0SqAEkbUBeVXMbtyVdscZR0ZimfmA0xQ4yj3T11D4HZKZbWGla2\r\nvlE0WwyNQ6Cww9tnPjSFjBbgr0Hmomod8YH8XqpCMM2Qjz5SKJzdg0KgwoSf\r\nT/B8JjzkxGvvEOSoLGXmikWkbqPGRSURw7k=\r\n=Gy7H\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230412162055_1681316498003_0.9698731813967132"},"_hasShrinkwrap":false},"0.18.0-canary-20230412170738":{"name":"swingset","version":"0.18.0-canary-20230412170738","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"dependencies":{"@mdx-js/mdx":"^2.3.0","github-slugger":"^2.0.0","globby":"^13.1.3","next-mdx-remote":"^4.3.0","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.0","@types/webpack-env":"^1.18.0","autoprefixer":"^10.4.13","next":"^13.1.6","postcss":"^8.4.21","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.2.7","vitest":"^0.28.5"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts'"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"readme":"# swingset\n\n## Goals\n\n- [ ] Fast, automatic HMR for content\n- [ ] Document components in your repo via a glob pattern\n- [ ] Support arbitrary pages as well\n- [ ] layout / theme fully customizable\n","readmeFilename":"README.md","gitHead":"6709eb483de961e48f1d353b1dc6a922a6064aab","description":"## Goals","_id":"swingset@0.18.0-canary-20230412170738","_nodeVersion":"16.20.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-5kb7myM/r08BfUBo392WKKdMpkz8gAGqT43XXruisF5gg/KDq1rdzwb4DB3tr9gitEmT4AxwLMRbRJ9INqzRKw==","shasum":"a90c99e5913d2ad6bae5a096675b94af629babfe","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230412170738.tgz","fileCount":40,"unpackedSize":35361,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDEwA+BbIxOW/lZO3wMHuKiYRfaaci/AYz2fwRG6LD5FwIgPlA8nCWGIGmtsOmuD8g58/HqvHDllD4CNODMa6X6PE4="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkNuWBACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqKmg/7B9QTXeVF7SLJNxum4KYnRqIXj1a22IpFjiheUTe3pfrNuL0B\r\njjPplHkO4WQq7bPjCZ8M6f4ky2SixxBpS/oxygCuFdOE4ooASF6VYWbhn/IW\r\nEzaQkVrzgEMI4RajmEX0rH9s5dIrlAUWikufG2HSlrZJZNTmhvndH6p8o724\r\nGtlZizQQLJL6lZZy4yVx6Ele178pDq0JnXhqCLqoyaJNBFkLIJCTqnkdMLx/\r\nrf5Nqk5ji1Kg5oe9qTCtmw/j0wn4fBO0rogR4MQz4BcTG33M8HWfqtalMnAO\r\n5NgaauI3RlQ+UrP8QPO/1LQ5YH/twrLceXirezGGr0t0LJF6aaQ8enlhBXSe\r\nG2gUmlYvLosUaVyC9pLr55DWKrm4Wcb/Ji+muIR2T+9l7Lk8ORvvERYTw7Po\r\nDLrJDu1kJ8uSnrruYbXQREULqDqiwybnTqcUL65HwaetIv7twJFZpaSXGeuo\r\nou4zI87IBNO2QXayh3okxQHFwC/zlYq/tHsziClNPGI3xDGk8+MqxxVZGJup\r\nrz7Sf/JWCY3hHo/EsRFPZpWjrjQAZmT4OrfE2fPanjax7a/B42bvBuNlNx3z\r\nKo7xWTOE91YnQ5aGbg2pUVy7d7KzrhnGo/OBhb8Km4FsAYwVM+gXuX5NrDQY\r\n1YLXVUfTsQR+D9CD4aMyaELP1gKAUyA2Myk=\r\n=ieW8\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230412170738_1681319297184_0.7377428396143833"},"_hasShrinkwrap":false},"0.18.0-canary-20230413025426":{"name":"swingset","version":"0.18.0-canary-20230413025426","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"dependencies":{"@mdx-js/mdx":"^2.3.0","github-slugger":"^2.0.0","globby":"^13.1.3","next-mdx-remote":"^4.3.0","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.0","@types/webpack-env":"^1.18.0","autoprefixer":"^10.4.13","next":"^13.1.6","postcss":"^8.4.21","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.2.7","vitest":"^0.28.5"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts'"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"readme":"# swingset\n\n## Goals\n\n- [ ] Fast, automatic HMR for content\n- [ ] Document components in your repo via a glob pattern\n- [ ] Support arbitrary pages as well\n- [ ] layout / theme fully customizable\n","readmeFilename":"README.md","gitHead":"4413fad27316a524f6e03778366b40ca83ec1be3","description":"## Goals","_id":"swingset@0.18.0-canary-20230413025426","_nodeVersion":"16.20.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-M9KQJFZFbiuCvTMXjeMR+mEAKai9YxqcCkzVnBticNZHU6A84FkZqVHUmU2jqz160U7SfDRdmk7F+/IByIzdYQ==","shasum":"62e325e6b3b544770db92c93aaff02511f6af118","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230413025426.tgz","fileCount":40,"unpackedSize":35548,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDTYkSYDr2sMyDnLyJfWo8/sfvch/wnES9bvxo9cn0/jAIgTsOcRq/hbs5XeG0HsYWSutwVQqkt74ay74Rmy9AJ9Jw="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkN28HACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqJYg//Tx9UuPQjDsBU6HkSoRJNQMXMOPOOcOFZ/ueqMhxfqbJpxrih\r\nZem9ZSmKQJC/eixFNrrANfv6eTcNoo9HCBbWDePgnsDskriPlv6z2pwPv7Ne\r\niHC0/aOQ9wzNf+WY5l94E0F+deqgjepNKqqBIT89NeRZubouFblEmVFOA1WB\r\nEPSvuITPptCkXnSuOpySUKfGJY4r9Umx1UQwKaT+p1ddDlEQJH1so+seBlJI\r\nlMcpDfN3WXb+oX0zbVsu5MoVQsELR1xWN6aNsYKbwiZjQu5xmwb54vWld9/d\r\nKDuYRna+0p6mjBYCWGuLQzL/NwRYRjrlOCOTCak5YOJA0Y7H510Pbcw9R1pI\r\nUiuAZTxnGHCUno8oHRGeoeIG9ycXa/CQ5Lk/bK0fIf1HlLCj8nZlCYzjkNyI\r\nr4z+gHup47MU8cE7AHchDE5q7r6uxf8LHkK/C+64wz6PgVzw5beJIp3pSDXx\r\nXeyFEvU8wWW/PfBBYYobQKhY99UJtvSzqASVYSDq/RdtzKmycX7g4tNljsy3\r\nbpJ61jDPXuXiY8b3ZDN7/o2oGXD3KWglb+ySAQTEGUC4pjHFjxvaL6j52btP\r\nV4GYYzkHgSSnaaqF1shTg13Jo/o/2kDTuZN/M1BAwm25UViyaMgTU7/KzXCR\r\n2FLIPNDWwTHG9NJkBVm94j7KysRPWkICQDQ=\r\n=wZPZ\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230413025426_1681354503720_0.5614338265536463"},"_hasShrinkwrap":false},"0.18.0-canary-20230413025741":{"name":"swingset","version":"0.18.0-canary-20230413025741","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"dependencies":{"@mdx-js/mdx":"^2.3.0","github-slugger":"^2.0.0","globby":"^13.1.3","next-mdx-remote":"^4.3.0","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.0","@types/webpack-env":"^1.18.0","autoprefixer":"^10.4.13","next":"^13.1.6","postcss":"^8.4.21","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.2.7","vitest":"^0.28.5"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts'"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"readme":"# swingset\n\n## Goals\n\n- [ ] Fast, automatic HMR for content\n- [ ] Document components in your repo via a glob pattern\n- [ ] Support arbitrary pages as well\n- [ ] layout / theme fully customizable\n","readmeFilename":"README.md","gitHead":"2f696d6d740c1afdde451d025792dd5a4da892e2","description":"## Goals","_id":"swingset@0.18.0-canary-20230413025741","_nodeVersion":"16.20.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-tX06X932XCfMLF1B3q0kSewX5XflUuNWxLllcZHgrcecAYkpzLeXhoSpaW/skzxpwLisNq8+Ufnup0lRt9+JxA==","shasum":"f1dd19c61ba09d0dc058b12623cd9bf8ed69c3ec","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230413025741.tgz","fileCount":40,"unpackedSize":35764,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIE4lZFnJkvrl++yGi5gnQSii3/w6Ciy0p8I9N3pgVjezAiEAiw+bo4yAoWI8fC2DNoS4j7LW9QVL4Hnsd323dGGH1Wg="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkN2/NACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq7DhAApI4bgRezqTkwrujKRwcemK4xQBll3fw7LmUwnlOtFlI6xkFE\r\nLpjeONt9jDbMBa/5YXm/OwfBMVn6bJyf6zscO6SJb1Fj8z9TUtZ82LiRYIyv\r\n9kclV+YykHoksK1vb1CQ6zEWxTsvF0Ko9tjHr0P28prLXpy1jRqf+YpboFPl\r\nUvVa3zZ5GPF/jUcsJLPXw33Q6M503AiCFnIcADd9EuvAK2733JpMoSWroQHw\r\nsvU02PNZqPsbelR5o1ayhI6++AXNLVUr2jN+GCrZ1IFw+l8Y38O3J8QXHzUt\r\ndRxPM/fKob6m1Vd0z+Kt6CgLrCAI4U02qdDi2B6f/FNDhAzdAuJyn6QS14JM\r\nDl8Sb+I3Q45i9mjT2i2YpepAey4dU/NxT3gmbUg3cVeWy3+4N1NYCeG3KMo3\r\nvR6X/AtEO4NG8rRGtCRyxHygJ3jc/sKhRbuFxtE2Kjn4Q8ZQdaN8yfrkdsYv\r\nwHN/65V5qWt7HPllFbuBG2r5Ih7/eqquoIggz8wBS1dx4Tn8OUb6SUiS7/5P\r\nt5njC0KUhCjWVVktsccbeatdEPSc5Sr3mQibLVSy16ygFy//a6qDAW9VeK1P\r\nLEWs+Ee9PMej5lMHhS4c6oDgpu0jW5rSM8Yv8W1LmS/YiClnWunEvo6YRaOF\r\nBQkufLUOtRn+nosrGA+2Qko0qMiHYKOLjG8=\r\n=uPmd\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230413025741_1681354701583_0.8047973509949939"},"_hasShrinkwrap":false},"0.18.0-canary-20230413143320":{"name":"swingset","version":"0.18.0-canary-20230413143320","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"dependencies":{"@mdx-js/mdx":"^2.3.0","github-slugger":"^2.0.0","globby":"^13.1.3","next-mdx-remote":"^4.3.0","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.0","@types/webpack-env":"^1.18.0","autoprefixer":"^10.4.13","next":"^13.1.6","postcss":"^8.4.21","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.2.7","vitest":"^0.28.5"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts'"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"readme":"# swingset\n\n## Goals\n\n- [ ] Fast, automatic HMR for content\n- [ ] Document components in your repo via a glob pattern\n- [ ] Support arbitrary pages as well\n- [ ] layout / theme fully customizable\n","readmeFilename":"README.md","gitHead":"e7d2de50a1944a6f3093fe1cd2de49b37ea226e8","description":"## Goals","_id":"swingset@0.18.0-canary-20230413143320","_nodeVersion":"16.20.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-O9+L5QZus99CP1Uxe/+/eoAhZs08PSYGQ0i1ULG9es97qGxlFAv20uy1lZIkFhriIUftqr7Ck3wK24JubYnNyQ==","shasum":"573134c17f2457257f8e93555d2764bbc5c037f0","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230413143320.tgz","fileCount":40,"unpackedSize":35764,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDVmNU/yVMcyZF+8VVhD+AAn7Vg2n/R3xVAAijm0wfQcwIgPFUmCf2dJTlWmoWBg40aj5isUnCNutw8Ll4FGoPeBok="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkOBLkACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqYDRAAlY8uhh5b66uGryPKMlhsWajfuKL1li/yOjP3GeqkGbWN6VuW\r\nja8r0L0gF0PD85mAJu7QS3iT0vRKvcmsff48/ZX9jL0H+sJ47rgj0gxJN/1Y\r\nVnEuGu8cNciybGLCAUTNdCUbk58motqje1hjpUz33tfbUXEiPShs+/CWT0w6\r\nqKMTDwGQvQ8lLmFFl/SNWPwP/Us7UMd92MS8vLpZXWme6Icv3u/7FKnJr7gP\r\np1ddVL1ZF/3yGX8PIcxLW75q6IG4hvjwyzxipUdDySt0Sl6gEpfCQ3W4i/4H\r\njELFsj3wdKLjrQE83sVpFHZcrGo5Q4DQTKzilKdYeMUASDF79C+1c12hkSfx\r\nIGsfoqfB76QBcZgdvvcp05LNPKu9vp0kt42GSCGRKb/IvLoduSI0KfO9St0n\r\nkCtreNiOjd1K3YmhGEFcY51NMlfpUhXozp9mNxaySwJHQRggf2G/4oG+MY1M\r\nFyc/u/B1S/H/ggElnXkpfJ+2WBqeG7AIviV7FTEvtGIJmfhc5Hgs12CsE2VU\r\n7sozhv43DuwDDOZ9X9MFdyjshF3s37Ipu+sESUplHujMzYZVWSfwvUEzNCBs\r\npk/kQkT96Hz+F4OT1AbiQ5Xz2u4OH5WBRzyscr0NLIDpPgwJ2TaO1TOB3uK9\r\n8c1qNHsZxLIio2Dr5jhQ4wY0zE6hINb/IIM=\r\n=eTA+\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230413143320_1681396452317_0.10705945076711898"},"_hasShrinkwrap":false},"0.18.0-canary-20230427173422":{"name":"swingset","version":"0.18.0-canary-20230427173422","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"dependencies":{"@mdx-js/mdx":"^2.3.0","github-slugger":"^2.0.0","globby":"^13.1.3","next-mdx-remote":"^4.3.0","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.0","@types/webpack-env":"^1.18.0","autoprefixer":"^10.4.13","next":"^13.1.6","postcss":"^8.4.21","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.2.7","vitest":"^0.28.5"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts'"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"readme":"# swingset\n\n## Goals\n\n- [ ] Fast, automatic HMR for content\n- [ ] Document components in your repo via a glob pattern\n- [ ] Support arbitrary pages as well\n- [ ] layout / theme fully customizable\n","readmeFilename":"README.md","gitHead":"18f8fffccd324c55a15c3ae06e64bc0b3272788b","description":"## Goals","_id":"swingset@0.18.0-canary-20230427173422","_nodeVersion":"16.20.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-rVF22YyUWBw1eDeg6rxuJCMpG1tyMPo9Yj7Ko631TDRiwZ98JtU2WvKZwu6wgpvRt2PhIBiVdCmwJg1EWgqXpw==","shasum":"5fac8c62360af6f694ab19e1ae31ecbb171e9ff9","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230427173422.tgz","fileCount":40,"unpackedSize":35646,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEw4SEsWasWANENP86D1wNSsJ/z7BK9O8rzqi16u/rCqAiBJUyQwawivmVkg+GsVEIyS67lFg2OD7Ad0Sytk4RQiOg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkSrJVACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoFeA//dr6U4FQPNXN1DgtOylJ6HNAsi3IYZh4qhLjh23TLsEt3dA0y\r\neju6ObKbD8XBa7WCXu1wgd+Wq3UbsNYF2hUVb39nIzYU0f4TZ2+1wtYsH/wR\r\nMleiO1wwC3YhW+Sg1T4h5rysoB1ZVrorY5z/fobpr3NBRwWLdX7S4yT1J3QT\r\nbVIbDWXiQgQ5QNOhTeJAzbmq3EY/pG9zHeeBBbXvaEFPEtNTOI4gaPjj/Fzh\r\nv2IZ9bhxF99T2KYResmMkjYx9egvQRtAbR41UFbu6uNDYMQEWCjr41i9otBP\r\nO+HZzsCI9Urb0VsP9L344iXgGdXDvmJ/SLPK1sxrDsJ/ch7F8i+IAlwBHb7M\r\nSbpiZvla/gQm+CKeTNITwLePk2t+4I+mKK6AfkSpLzOZe2S7Zy+UdD1BhaJv\r\nMxBs7GpCvppCqGX/LK/qNbqgNo28WMIOictabqGyTuKncBy4Lbp9mRRED1eL\r\nIZIl4e/H3MCwF9qNZ+byNhFSmDkbMtSZTI4/m1A7Fv/7cCWNp5+x+5iFvbA0\r\nUtWBntHZHYbguXSJfiScAHqWp4hhyeJbGBWg7XD7RmsqZG4BE87SKIKbGDBl\r\nEFeRpFL+yuHAHJx31+2mnTHEvG4C4uvW9xZZwaPAT2sPCqI9mVSGfOxHj4Am\r\nxqaIr3cR0Izpq4fhiI+pTIWpSFXRCWWLgxw=\r\n=lkEU\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230427173422_1682616916802_0.9623673521938731"},"_hasShrinkwrap":false},"0.18.0-canary-20230602203622":{"name":"swingset","version":"0.18.0-canary-20230602203622","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"dependencies":{"@mdx-js/mdx":"^2.3.0","github-slugger":"^2.0.0","globby":"^13.1.4","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.1","@types/webpack-env":"^1.18.1","autoprefixer":"^10.4.14","next":"^13.4.4","postcss":"^8.4.24","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.3.2","vitest":"^0.31.3"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"typesVersions":{"*":{"*":["./dist/*"]}},"readme":"# swingset\n\nWelcome to Swingset. Swingset is a drop-in component documentation system built for Next.js's App Router and React Server Components.\n\n> **Note**\n> Swingset is currently under active development. We're actively iterating on the core features and APIs, and some things may change.\n\n## Installation\n\nInstall `swingset` with your package manager of choice:\n\n```\nnpm install swingset\n```\n\nImport the plugin in your `next.config.mjs` file:\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\n\nexport default withSwingset({\n  componentRoot: './components',\n  theme: 'swingset-theme-custom',\n})()\n```\n\n## Features\n\n### App Router native\n\nSwingset is built for the new App Router and React Server Components. Running the bootstrap command will generate a route group for swingset:\n\n```\n$ swingset bootstrap\n\nGenerating swingset route group...\n\nSuccess! Route group created:\n\n(swingset)\n  ├ /layout.tsx\n  └ /swingset\n    ├ /page.tsx\n    └ /[...path]\n      └ /page.tsx\n```\n\n### Component documentation\n\nDocument your components with MDX by placing a `docs.mdx` file next to your component source:\n\n```\ncomponents/\n  button/\n    docs.mdx\n    index.tsx\n```\n\n#### Component prop extraction\n\nSwingset automatically exposes prop metadata for components imported into your documentation.\n\n```typescript\n<PropsTable component={Button} />\n```\n\n### Custom documentation\n\nSwingset also supports standalone documentation pages. By default, `.mdx` files in `/app/(swingset)/swingset/docs/` are rendered.\n\n### Custom themes\n\nBy default, Swingset only exposes the data necessary to fully render your documentation content. Swingset can be configured with a custom `theme` to control rendering.\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\n\nexport default withSwingset({\n  componentRoot: './components',\n  theme: 'swingset-theme-custom',\n})()\n```\n\n### Custom remark and rehype plugins\n\nWant to add support for GitHub Flavored Markdown? Swingset accepts `remark` and `rehype` plugins.\n\n- [x] Add `remarkGfm`\n- [x] Restart your server\n- [ ] Render task lists!\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\nimport remarkGfm from 'remark-gfm'\n\nexport default withSwingset({\n  componentRoot: './components',\n  remarkPlugins: [remarkGfm],\n})()\n```\n\n### Integrates with `@next/mdx`\n\nSwingset integrates with `@next/mdx` by supporting the same `mdx-components.ts` file at the root of your application. Swingset will make the custom components declared there available.\n\n### Use with Storybook\n\nDocumentation pages within Swingset are treated as modules. This means that you can import other modules into your `.mdx` files as you would any other JavaScript file. This works great if you leverage Storybook for component development, as stories are directly consumable from your documentation:\n\n```tsx\nimport * as stories from './Button.stories'\n\n# This is the Primary story\n\n<stories.Primary />\n```\n\n## Contributing\n\nSee [CONTRIBUTING.md](../../CONTRIBUTING.md).\n","readmeFilename":"README.md","gitHead":"d0c91929602257805a1c66d856595735f2a64c43","description":"Welcome to Swingset. Swingset is a drop-in component documentation system built for Next.js's App Router and React Server Components.","_id":"swingset@0.18.0-canary-20230602203622","_nodeVersion":"16.20.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-eY2gxKl7VbRmpukeonMj1eKnzQ0pGBqWRRiMGxck7wa4smegvAB3aX0IWdLQhuqX/Qv5p8kvaO0RFy5yQD+JOg==","shasum":"d0775206bd8e5cab77f45aa180676cf0d08ae762","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230602203622.tgz","fileCount":40,"unpackedSize":43135,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC8aclDJv17pQhva75oms8rroQ0G/zzHL5Uub2sdFaUgAIhAOwCcsTGIoRNrUOrM39uV1820ssTx9t7FxlKudYaeMMX"}]},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"bkalow@hashicorp.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230602203622_1685738232067_0.8521835595302418"},"_hasShrinkwrap":false},"0.18.0-canary-20230628143729":{"name":"swingset","version":"0.18.0-canary-20230628143729","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"bin":{"swingset":"dist/cli/index.js"},"dependencies":{"@mdx-js/mdx":"^2.3.0","detect-package-manager":"^2.0.1","github-slugger":"^2.0.0","globby":"^13.1.4","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.1","@types/webpack-env":"^1.18.1","autoprefixer":"^10.4.14","next":"^13.4.4","postcss":"^8.4.24","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.3.2","vitest":"^0.31.3"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"typesVersions":{"*":{"*":["./dist/*"]}},"readme":"# swingset\n\nWelcome to Swingset. Swingset is a drop-in component documentation system built for Next.js's App Router and React Server Components.\n\n> **Note**\n> Swingset is currently under active development. We're actively iterating on the core features and APIs, and some things may change.\n\n## Installation\n\nInstall `swingset` with your package manager of choice:\n\n```\nnpm install swingset\n```\n\nImport the plugin in your `next.config.mjs` file:\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\n\nexport default withSwingset({\n  componentRoot: './components',\n  theme: 'swingset-theme-custom',\n})()\n```\n\n## Features\n\n### App Router native\n\nSwingset is built for the new App Router and React Server Components. Running the bootstrap command will generate a route group for swingset:\n\n```\n$ swingset bootstrap\n\nGenerating swingset route group...\n\nSuccess! Route group created:\n\n(swingset)\n  ├ /layout.tsx\n  └ /swingset\n    ├ /page.tsx\n    └ /[...path]\n      └ /page.tsx\n```\n\n### Component documentation\n\nDocument your components with MDX by placing a `docs.mdx` file next to your component source:\n\n```\ncomponents/\n  button/\n    docs.mdx\n    index.tsx\n```\n\n#### Component prop extraction\n\nSwingset automatically exposes prop metadata for components imported into your documentation.\n\n```typescript\n<PropsTable component={Button} />\n```\n\n### Custom documentation\n\nSwingset also supports standalone documentation pages. By default, `.mdx` files in `/app/(swingset)/swingset/docs/` are rendered.\n\n### Custom themes\n\nBy default, Swingset only exposes the data necessary to fully render your documentation content. Swingset can be configured with a custom `theme` to control rendering.\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\n\nexport default withSwingset({\n  componentRoot: './components',\n  theme: 'swingset-theme-custom',\n})()\n```\n\n### Custom remark and rehype plugins\n\nWant to add support for GitHub Flavored Markdown? Swingset accepts `remark` and `rehype` plugins.\n\n- [x] Add `remarkGfm`\n- [x] Restart your server\n- [ ] Render task lists!\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\nimport remarkGfm from 'remark-gfm'\n\nexport default withSwingset({\n  componentRoot: './components',\n  remarkPlugins: [remarkGfm],\n})()\n```\n\n### Integrates with `@next/mdx`\n\nSwingset integrates with `@next/mdx` by supporting the same `mdx-components.ts` file at the root of your application. Swingset will make the custom components declared there available.\n\n### Use with Storybook\n\nDocumentation pages within Swingset are treated as modules. This means that you can import other modules into your `.mdx` files as you would any other JavaScript file. This works great if you leverage Storybook for component development, as stories are directly consumable from your documentation:\n\n```tsx\nimport * as stories from './Button.stories'\n\n# This is the Primary story\n\n<stories.Primary />\n```\n\n## Contributing\n\nSee [CONTRIBUTING.md](/CONTRIBUTING.md).\n","readmeFilename":"README.md","gitHead":"c0aeb7b8e5cbada4af1ec1dc123e384b56e8bd94","description":"Welcome to Swingset. Swingset is a drop-in component documentation system built for Next.js's App Router and React Server Components.","_id":"swingset@0.18.0-canary-20230628143729","_nodeVersion":"16.20.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-nTiSCwpLjUysUFilcdGwqw6Na86SGUwzdOmlqm9dQQYFcAK5hGmBHbE/RKKZTUOuzugiB7rptWcAEBPEUA1LJQ==","shasum":"37c03e227a7e9bbe7c10e8a18a26b76575e8e0a9","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230628143729.tgz","fileCount":56,"unpackedSize":258006,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEPWBmFunlo47UfMHtFlBx9FQ+MRUtdJZ/obK+cgg9e1AiASOWSMhnoP1PjfXBDx8LzEBxDFk4kuB84U8VqUFE93TQ=="}]},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"hello@brycekalow.name"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230628143729_1687963111042_0.6736241456002976"},"_hasShrinkwrap":false},"0.18.0-canary-20230628145658":{"name":"swingset","version":"0.18.0-canary-20230628145658","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"bin":{"swingset":"dist/cli/index.js"},"dependencies":{"@mdx-js/mdx":"^2.3.0","detect-package-manager":"^2.0.1","github-slugger":"^2.0.0","globby":"^13.1.4","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.1","@types/webpack-env":"^1.18.1","autoprefixer":"^10.4.14","next":"^13.4.4","postcss":"^8.4.24","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.3.2","vitest":"^0.31.3"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"typesVersions":{"*":{"*":["./dist/*"]}},"readme":"# swingset\n\nWelcome to Swingset. Swingset is a drop-in component documentation system built for Next.js's App Router and React Server Components.\n\n> **Note**\n> Swingset is currently under active development. We're actively iterating on the core features and APIs, and some things may change.\n\n## Installation\n\nInstall `swingset` with your package manager of choice:\n\n```\nnpm install swingset\n```\n\nImport the plugin in your `next.config.mjs` file:\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\n\nexport default withSwingset({\n  componentRoot: './components',\n  theme: 'swingset-theme-custom',\n})()\n```\n\n## Features\n\n### App Router native\n\nSwingset is built for the new App Router and React Server Components. Running the bootstrap command will generate a route group for swingset:\n\n```\n$ swingset bootstrap\n\nGenerating swingset route group...\n\nSuccess! Route group created:\n\n(swingset)\n  ├ /layout.tsx\n  └ /swingset\n    ├ /page.tsx\n    └ /[...path]\n      └ /page.tsx\n```\n\n### Component documentation\n\nDocument your components with MDX by placing a `docs.mdx` file next to your component source:\n\n```\ncomponents/\n  button/\n    docs.mdx\n    index.tsx\n```\n\n#### Component prop extraction\n\nSwingset automatically exposes prop metadata for components imported into your documentation.\n\n```typescript\n<PropsTable component={Button} />\n```\n\n### Custom documentation\n\nSwingset also supports standalone documentation pages. By default, `.mdx` files in `/app/(swingset)/swingset/docs/` are rendered.\n\n### Custom themes\n\nBy default, Swingset only exposes the data necessary to fully render your documentation content. Swingset can be configured with a custom `theme` to control rendering.\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\n\nexport default withSwingset({\n  componentRoot: './components',\n  theme: 'swingset-theme-custom',\n})()\n```\n\n### Custom remark and rehype plugins\n\nWant to add support for GitHub Flavored Markdown? Swingset accepts `remark` and `rehype` plugins.\n\n- [x] Add `remarkGfm`\n- [x] Restart your server\n- [ ] Render task lists!\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\nimport remarkGfm from 'remark-gfm'\n\nexport default withSwingset({\n  componentRoot: './components',\n  remarkPlugins: [remarkGfm],\n})()\n```\n\n### Integrates with `@next/mdx`\n\nSwingset integrates with `@next/mdx` by supporting the same `mdx-components.ts` file at the root of your application. Swingset will make the custom components declared there available.\n\n### Use with Storybook\n\nDocumentation pages within Swingset are treated as modules. This means that you can import other modules into your `.mdx` files as you would any other JavaScript file. This works great if you leverage Storybook for component development, as stories are directly consumable from your documentation:\n\n```tsx\nimport * as stories from './Button.stories'\n\n# This is the Primary story\n\n<stories.Primary />\n```\n\n## Contributing\n\nSee [CONTRIBUTING.md](/CONTRIBUTING.md).\n","readmeFilename":"README.md","gitHead":"be222a7803df92c65a69fd4437aca760d3d5223b","description":"Welcome to Swingset. Swingset is a drop-in component documentation system built for Next.js's App Router and React Server Components.","_id":"swingset@0.18.0-canary-20230628145658","_nodeVersion":"16.20.1","_npmVersion":"8.19.4","dist":{"integrity":"sha512-QEIXrwWZKeJQ/V7+EjWuNmKIoWOSmfCfBNsdI+gtYtgmub64vtoZ0WKcW16w8WgZlUK24/EoRBGuI9DhSqel8Q==","shasum":"53312fc740708591a9bd7a39f5d3f73b1fae68b4","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230628145658.tgz","fileCount":54,"unpackedSize":257771,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC8fPaEIRt5XbTvYqU+lxnqJWkVJmYAAENhnLD0i7Pf1QIgSZQFcv4lQihhAOYrHXeVhsm32OgQ++kq0ah83LL0cZw="}]},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"hello@brycekalow.name"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230628145658_1687964271452_0.6871922189862865"},"_hasShrinkwrap":false},"0.18.0-canary-20230628145726":{"name":"swingset","version":"0.18.0-canary-20230628145726","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"bin":{"swingset":"dist/cli/index.js"},"dependencies":{"@mdx-js/mdx":"^2.3.0","detect-package-manager":"^2.0.1","github-slugger":"^2.0.0","globby":"^13.1.4","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.1","@types/webpack-env":"^1.18.1","autoprefixer":"^10.4.14","next":"^13.4.4","postcss":"^8.4.24","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.3.2","vitest":"^0.31.3"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"typesVersions":{"*":{"*":["./dist/*"]}},"readme":"# swingset\n\nWelcome to Swingset. Swingset is a drop-in component documentation system built for Next.js's App Router and React Server Components.\n\n> **Note**\n> Swingset is currently under active development. We're actively iterating on the core features and APIs, and some things may change.\n\n## Installation\n\nInstall `swingset` with your package manager of choice:\n\n```\nnpm install swingset\n```\n\nImport the plugin in your `next.config.mjs` file:\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\n\nexport default withSwingset({\n  componentRoot: './components',\n  theme: 'swingset-theme-custom',\n})()\n```\n\n## Features\n\n### App Router native\n\nSwingset is built for the new App Router and React Server Components. Running the bootstrap command will generate a route group for swingset:\n\n```\n$ swingset bootstrap\n\nGenerating swingset route group...\n\nSuccess! Route group created:\n\n(swingset)\n  ├ /layout.tsx\n  └ /swingset\n    ├ /page.tsx\n    └ /[...path]\n      └ /page.tsx\n```\n\n### Component documentation\n\nDocument your components with MDX by placing a `docs.mdx` file next to your component source:\n\n```\ncomponents/\n  button/\n    docs.mdx\n    index.tsx\n```\n\n#### Component prop extraction\n\nSwingset automatically exposes prop metadata for components imported into your documentation.\n\n```typescript\n<PropsTable component={Button} />\n```\n\n### Custom documentation\n\nSwingset also supports standalone documentation pages. By default, `.mdx` files in `/app/(swingset)/swingset/docs/` are rendered.\n\n### Custom themes\n\nBy default, Swingset only exposes the data necessary to fully render your documentation content. Swingset can be configured with a custom `theme` to control rendering.\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\n\nexport default withSwingset({\n  componentRoot: './components',\n  theme: 'swingset-theme-custom',\n})()\n```\n\n### Custom remark and rehype plugins\n\nWant to add support for GitHub Flavored Markdown? Swingset accepts `remark` and `rehype` plugins.\n\n- [x] Add `remarkGfm`\n- [x] Restart your server\n- [ ] Render task lists!\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\nimport remarkGfm from 'remark-gfm'\n\nexport default withSwingset({\n  componentRoot: './components',\n  remarkPlugins: [remarkGfm],\n})()\n```\n\n### Integrates with `@next/mdx`\n\nSwingset integrates with `@next/mdx` by supporting the same `mdx-components.ts` file at the root of your application. Swingset will make the custom components declared there available.\n\n### Use with Storybook\n\nDocumentation pages within Swingset are treated as modules. This means that you can import other modules into your `.mdx` files as you would any other JavaScript file. This works great if you leverage Storybook for component development, as stories are directly consumable from your documentation:\n\n```tsx\nimport * as stories from './Button.stories'\n\n# This is the Primary story\n\n<stories.Primary />\n```\n\n## Contributing\n\nSee [CONTRIBUTING.md](/CONTRIBUTING.md).\n","readmeFilename":"README.md","gitHead":"cf3f979461d79e5c2782ddf35d1891b28f87e189","description":"Welcome to Swingset. Swingset is a drop-in component documentation system built for Next.js's App Router and React Server Components.","_id":"swingset@0.18.0-canary-20230628145726","_nodeVersion":"16.20.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-g31/eu92TV0sAqSVI9nh+/c4VwTLleJFJT+On6p+pYU5AAdZcf9/yXSRE0zlqhfFJD6O83o10Fho7+Pj9DIzVA==","shasum":"a3267cb1190286f0124e01b9390d23877b39882e","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230628145726.tgz","fileCount":54,"unpackedSize":257771,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC5n6QlGBpq7jhEQbimFGaHgEtl6IgjQi6Lw7XJsw5RbwIhAKX+mqUYwheRZA+Eiw3c5F4WGL6K0KpGUj3NXl+x4Z5V"}]},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"hello@brycekalow.name"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230628145726_1687964297489_0.23997791825935288"},"_hasShrinkwrap":false},"0.18.0-canary-20230628233900":{"name":"swingset","version":"0.18.0-canary-20230628233900","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"bin":{"swingset":"dist/cli/index.js"},"dependencies":{"@mdx-js/mdx":"^2.3.0","detect-package-manager":"^2.0.1","github-slugger":"^2.0.0","globby":"^13.1.4","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.1","@types/webpack-env":"^1.18.1","autoprefixer":"^10.4.14","next":"^13.4.4","postcss":"^8.4.24","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.3.2","vitest":"^0.31.3"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"typesVersions":{"*":{"*":["./dist/*"]}},"readme":"# swingset\n\nWelcome to Swingset. Swingset is a drop-in component documentation system built for Next.js's App Router and React Server Components.\n\n> **Note**\n> Swingset is currently under active development. We're actively iterating on the core features and APIs, and some things may change.\n\n## Installation\n\nInstall `swingset` with your package manager of choice:\n\n```\nnpm install swingset\n```\n\nImport the plugin in your `next.config.mjs` file:\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\n\nexport default withSwingset({\n  componentRoot: './components',\n  theme: 'swingset-theme-custom',\n})()\n```\n\n## Features\n\n### App Router native\n\nSwingset is built for the new App Router and React Server Components. Running the bootstrap command will generate a route group for swingset:\n\n```\n$ swingset bootstrap\n\nGenerating swingset route group...\n\nSuccess! Route group created:\n\n(swingset)\n  ├ /layout.tsx\n  └ /swingset\n    ├ /page.tsx\n    └ /[...path]\n      └ /page.tsx\n```\n\n### Component documentation\n\nDocument your components with MDX by placing a `docs.mdx` file next to your component source:\n\n```\ncomponents/\n  button/\n    docs.mdx\n    index.tsx\n```\n\n#### Component prop extraction\n\nSwingset automatically exposes prop metadata for components imported into your documentation.\n\n```typescript\n<PropsTable component={Button} />\n```\n\n### Custom documentation\n\nSwingset also supports standalone documentation pages. By default, `.mdx` files in `/app/(swingset)/swingset/docs/` are rendered.\n\n### Custom themes\n\nBy default, Swingset only exposes the data necessary to fully render your documentation content. Swingset can be configured with a custom `theme` to control rendering.\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\n\nexport default withSwingset({\n  componentRoot: './components',\n  theme: 'swingset-theme-custom',\n})()\n```\n\n### Custom remark and rehype plugins\n\nWant to add support for GitHub Flavored Markdown? Swingset accepts `remark` and `rehype` plugins.\n\n- [x] Add `remarkGfm`\n- [x] Restart your server\n- [ ] Render task lists!\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\nimport remarkGfm from 'remark-gfm'\n\nexport default withSwingset({\n  componentRoot: './components',\n  remarkPlugins: [remarkGfm],\n})()\n```\n\n### Integrates with `@next/mdx`\n\nSwingset integrates with `@next/mdx` by supporting the same `mdx-components.ts` file at the root of your application. Swingset will make the custom components declared there available.\n\n### Use with Storybook\n\nDocumentation pages within Swingset are treated as modules. This means that you can import other modules into your `.mdx` files as you would any other JavaScript file. This works great if you leverage Storybook for component development, as stories are directly consumable from your documentation:\n\n```tsx\nimport * as stories from './Button.stories'\n\n# This is the Primary story\n\n<stories.Primary />\n```\n\n## Contributing\n\nSee [CONTRIBUTING.md](/CONTRIBUTING.md).\n","readmeFilename":"README.md","gitHead":"05e87f8abb0c3be01436c7ef600ccbd5e5963fed","description":"Welcome to Swingset. Swingset is a drop-in component documentation system built for Next.js's App Router and React Server Components.","_id":"swingset@0.18.0-canary-20230628233900","_nodeVersion":"16.20.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-ujm+d3tCCZYNa1fbJjaQGXIHPU49wvU4TxJlqwAY7qyhHN9ty9U2jYOOVTjFZJvWeuAgUQmDNQmTAtW8hxXsUA==","shasum":"f6d9174ffb10122c803bc11f0e9f94e4abcfca42","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230628233900.tgz","fileCount":54,"unpackedSize":260852,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCvDcyUVhXc1/kvxuq9mdP7xSV168BY3AYnw+Scz5wfSQIhAJ32/pjhBcT9ETtdbuJymze2qp18eIVP4oYDq9Dbc8Iy"}]},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"hello@brycekalow.name"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230628233900_1687995604272_0.14518841371429736"},"_hasShrinkwrap":false},"0.18.0-canary-20230629001205":{"name":"swingset","version":"0.18.0-canary-20230629001205","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"bin":{"swingset":"dist/cli/index.js"},"dependencies":{"@mdx-js/mdx":"^2.3.0","detect-package-manager":"^2.0.1","github-slugger":"^2.0.0","globby":"^13.1.4","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.1","@types/webpack-env":"^1.18.1","autoprefixer":"^10.4.14","next":"^13.4.4","postcss":"^8.4.24","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.3.2","vitest":"^0.31.3"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"typesVersions":{"*":{"*":["./dist/*"]}},"readme":"# swingset\n\nWelcome to Swingset. Swingset is a drop-in component documentation system built for Next.js's App Router and React Server Components.\n\n> **Note**\n> Swingset is currently under active development. We're actively iterating on the core features and APIs, and some things may change.\n\n## Installation\n\nInstall `swingset` with your package manager of choice:\n\n```\nnpm install swingset\n```\n\nImport the plugin in your `next.config.mjs` file:\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\n\nexport default withSwingset({\n  componentRoot: './components',\n  theme: 'swingset-theme-custom',\n})()\n```\n\n## Features\n\n### App Router native\n\nSwingset is built for the new App Router and React Server Components. Running the bootstrap command will generate a route group for swingset:\n\n```\n$ swingset bootstrap\n\nGenerating swingset route group...\n\nSuccess! Route group created:\n\n(swingset)\n  ├ /layout.tsx\n  └ /swingset\n    ├ /page.tsx\n    └ /[...path]\n      └ /page.tsx\n```\n\n### Component documentation\n\nDocument your components with MDX by placing a `docs.mdx` file next to your component source:\n\n```\ncomponents/\n  button/\n    docs.mdx\n    index.tsx\n```\n\n#### Component prop extraction\n\nSwingset automatically exposes prop metadata for components imported into your documentation.\n\n```typescript\n<PropsTable component={Button} />\n```\n\n### Custom documentation\n\nSwingset also supports standalone documentation pages. By default, `.mdx` files in `/app/(swingset)/swingset/docs/` are rendered.\n\n### Custom themes\n\nBy default, Swingset only exposes the data necessary to fully render your documentation content. Swingset can be configured with a custom `theme` to control rendering.\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\n\nexport default withSwingset({\n  componentRoot: './components',\n  theme: 'swingset-theme-custom',\n})()\n```\n\n### Custom remark and rehype plugins\n\nWant to add support for GitHub Flavored Markdown? Swingset accepts `remark` and `rehype` plugins.\n\n- [x] Add `remarkGfm`\n- [x] Restart your server\n- [ ] Render task lists!\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\nimport remarkGfm from 'remark-gfm'\n\nexport default withSwingset({\n  componentRoot: './components',\n  remarkPlugins: [remarkGfm],\n})()\n```\n\n### Integrates with `@next/mdx`\n\nSwingset integrates with `@next/mdx` by supporting the same `mdx-components.ts` file at the root of your application. Swingset will make the custom components declared there available.\n\n### Use with Storybook\n\nDocumentation pages within Swingset are treated as modules. This means that you can import other modules into your `.mdx` files as you would any other JavaScript file. This works great if you leverage Storybook for component development, as stories are directly consumable from your documentation:\n\n```tsx\nimport * as stories from './Button.stories'\n\n# This is the Primary story\n\n<stories.Primary />\n```\n\n## Contributing\n\nSee [CONTRIBUTING.md](/CONTRIBUTING.md).\n","readmeFilename":"README.md","gitHead":"02aa56efddceac1497b57b53dfb35679b0a33396","description":"Welcome to Swingset. Swingset is a drop-in component documentation system built for Next.js's App Router and React Server Components.","_id":"swingset@0.18.0-canary-20230629001205","_nodeVersion":"16.20.1","_npmVersion":"8.19.4","dist":{"integrity":"sha512-H2ER4/f1SmKVRMARAKXoVrDE8oPjJTx0RXJRcm76LuHpErd+Q8qErxjGxWifE+RfIdRw8nUh79/B98/TNdrK3Q==","shasum":"c1b7828e6bc8f5b6e644fc2bbaa3d720e06da471","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230629001205.tgz","fileCount":54,"unpackedSize":260852,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDQnRv9Pb1v/P2yZqr0XlJXh4nG0b+BoCvzi4i4wBnAiAIhAN6LXH1B7lC+TakbqqxKh804QFFxT0rWYNw7RoucXqMY"}]},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"hello@brycekalow.name"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230629001205_1687997580480_0.6966408541269999"},"_hasShrinkwrap":false},"0.18.0-canary-20230629001352":{"name":"swingset","version":"0.18.0-canary-20230629001352","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"bin":{"swingset":"dist/cli/index.js"},"dependencies":{"@mdx-js/mdx":"^2.3.0","detect-package-manager":"^2.0.1","github-slugger":"^2.0.0","globby":"^13.1.4","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.1","@types/webpack-env":"^1.18.1","autoprefixer":"^10.4.14","next":"^13.4.4","postcss":"^8.4.24","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.3.2","vitest":"^0.31.3"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"typesVersions":{"*":{"*":["./dist/*"]}},"readme":"# swingset\n\nWelcome to Swingset. Swingset is a drop-in component documentation system built for Next.js's App Router and React Server Components.\n\n> **Note**\n> Swingset is currently under active development. We're actively iterating on the core features and APIs, and some things may change.\n\n## Installation\n\nInstall `swingset` with your package manager of choice:\n\n```\nnpm install swingset\n```\n\nImport the plugin in your `next.config.mjs` file:\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\n\nexport default withSwingset({\n  componentRoot: './components',\n  theme: 'swingset-theme-custom',\n})()\n```\n\n## Features\n\n### App Router native\n\nSwingset is built for the new App Router and React Server Components. Running the bootstrap command will generate a route group for swingset:\n\n```\n$ swingset bootstrap\n\nGenerating swingset route group...\n\nSuccess! Route group created:\n\n(swingset)\n  ├ /layout.tsx\n  └ /swingset\n    ├ /page.tsx\n    └ /[...path]\n      └ /page.tsx\n```\n\n### Component documentation\n\nDocument your components with MDX by placing a `docs.mdx` file next to your component source:\n\n```\ncomponents/\n  button/\n    docs.mdx\n    index.tsx\n```\n\n#### Component prop extraction\n\nSwingset automatically exposes prop metadata for components imported into your documentation.\n\n```typescript\n<PropsTable component={Button} />\n```\n\n### Custom documentation\n\nSwingset also supports standalone documentation pages. By default, `.mdx` files in `/app/(swingset)/swingset/docs/` are rendered.\n\n### Custom themes\n\nBy default, Swingset only exposes the data necessary to fully render your documentation content. Swingset can be configured with a custom `theme` to control rendering.\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\n\nexport default withSwingset({\n  componentRoot: './components',\n  theme: 'swingset-theme-custom',\n})()\n```\n\n### Custom remark and rehype plugins\n\nWant to add support for GitHub Flavored Markdown? Swingset accepts `remark` and `rehype` plugins.\n\n- [x] Add `remarkGfm`\n- [x] Restart your server\n- [ ] Render task lists!\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\nimport remarkGfm from 'remark-gfm'\n\nexport default withSwingset({\n  componentRoot: './components',\n  remarkPlugins: [remarkGfm],\n})()\n```\n\n### Integrates with `@next/mdx`\n\nSwingset integrates with `@next/mdx` by supporting the same `mdx-components.ts` file at the root of your application. Swingset will make the custom components declared there available.\n\n### Use with Storybook\n\nDocumentation pages within Swingset are treated as modules. This means that you can import other modules into your `.mdx` files as you would any other JavaScript file. This works great if you leverage Storybook for component development, as stories are directly consumable from your documentation:\n\n```tsx\nimport * as stories from './Button.stories'\n\n# This is the Primary story\n\n<stories.Primary />\n```\n\n## Contributing\n\nSee [CONTRIBUTING.md](/CONTRIBUTING.md).\n","readmeFilename":"README.md","gitHead":"cabad9ea7b42b3a111d917689dad59a890e4ea8e","description":"Welcome to Swingset. Swingset is a drop-in component documentation system built for Next.js's App Router and React Server Components.","_id":"swingset@0.18.0-canary-20230629001352","_nodeVersion":"16.20.0","_npmVersion":"8.19.4","dist":{"integrity":"sha512-24PIvzDtydRbnncsS6M2YTNTLXIAf2B2zPDioGqpvVTXb4vRrCi9wWfWeJwC7PlH0m2e8eractR0LufiEWLiqg==","shasum":"3b37ae939d6e9da6f332fedc3b5ad3308a989a4c","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230629001352.tgz","fileCount":54,"unpackedSize":260852,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEMWF8k0suu01iJiOI/OZ2YdWXm074/KG6bVvqcBLRHtAiAM2ecs4WnNHFLcMZNi4/hFgToFhgx0e9tJTDJHiG4EZQ=="}]},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"hello@brycekalow.name"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230629001352_1687997700472_0.7611553454497735"},"_hasShrinkwrap":false},"0.18.0-canary-20230629193328":{"name":"swingset","version":"0.18.0-canary-20230629193328","type":"module","scripts":{"build:js":"tsup","build:styles":"postcss src/default-theme/css/styles.css -o style.css --verbose","build":"concurrently npm:build:*","dev:js":"tsup --watch","dev:styles":"TAILWIND_MODE=watch postcss src/default-theme/css/styles.css -o style.css --verbose --watch","dev":"concurrently npm:dev:*","test":"vitest run"},"bin":{"swingset":"dist/cli/index.js"},"dependencies":{"@mdx-js/mdx":"^2.3.0","detect-package-manager":"^2.0.1","github-slugger":"^2.0.0","globby":"^13.1.4","react-docgen":"^6.0.0-beta.5","readdirp":"^3.6.0","vfile":"^5.3.7","vfile-matter":"^4.0.1"},"devDependencies":{"@types/webpack":"^5.28.1","@types/webpack-env":"^1.18.1","autoprefixer":"^10.4.14","next":"^13.4.4","postcss":"^8.4.24","postcss-cli":"^10.1.0","react":"^18.2.0","react-dom":"^18.2.0","tailwindcss":"^3.3.2","vitest":"^0.31.3"},"peerDependencies":{"next":"13.x","react":">=18.2.0","react-dom":">=18.2.0"},"exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./loader":"./loader.cjs","./meta":{"import":"./dist/meta.js","types":"./dist/meta.d.ts"},"./theme":{"import":"./dist/theme.js","types":"./dist/theme.d.ts"},"./default-theme":{"import":"./dist/default-theme/index.js","types":"./dist/default-theme/index.d.ts"},"./style.css":"./style.css","./*":{"import":"./dist/*.js","types":"./dist/*.d.ts"}},"typesVersions":{"*":{"*":["./dist/*"]}},"readme":"# swingset\n\nWelcome to Swingset. Swingset is a drop-in component documentation system built for Next.js's App Router and React Server Components.\n\n> **Note**\n> Swingset is currently under active development. We're actively iterating on the core features and APIs, and some things may change.\n\n## Installation\n\nInstall `swingset` with your package manager of choice:\n\n```\nnpm install swingset\n```\n\nImport the plugin in your `next.config.mjs` file:\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\n\nexport default withSwingset({\n  componentRoot: './components',\n  theme: 'swingset-theme-custom',\n})()\n```\n\n## Features\n\n### App Router native\n\nSwingset is built for the new App Router and React Server Components. Running the bootstrap command will generate a route group for swingset:\n\n```\n$ swingset bootstrap\n\nGenerating swingset route group...\n\nSuccess! Route group created:\n\n(swingset)\n  ├ /layout.tsx\n  └ /swingset\n    ├ /page.tsx\n    └ /[...path]\n      └ /page.tsx\n```\n\n### Component documentation\n\nDocument your components with MDX by placing a `docs.mdx` file next to your component source:\n\n```\ncomponents/\n  button/\n    docs.mdx\n    index.tsx\n```\n\n#### Component prop extraction\n\nSwingset automatically exposes prop metadata for components imported into your documentation.\n\n```typescript\n<PropsTable component={Button} />\n```\n\n### Custom documentation\n\nSwingset also supports standalone documentation pages. By default, `.mdx` files in `/app/(swingset)/swingset/docs/` are rendered.\n\n### Custom themes\n\nBy default, Swingset only exposes the data necessary to fully render your documentation content. Swingset can be configured with a custom `theme` to control rendering.\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\n\nexport default withSwingset({\n  componentRoot: './components',\n  theme: 'swingset-theme-custom',\n})()\n```\n\n### Custom remark and rehype plugins\n\nWant to add support for GitHub Flavored Markdown? Swingset accepts `remark` and `rehype` plugins.\n\n- [x] Add `remarkGfm`\n- [x] Restart your server\n- [ ] Render task lists!\n\n```js\n// next.config.mjs\nimport withSwingset from 'swingset'\nimport remarkGfm from 'remark-gfm'\n\nexport default withSwingset({\n  componentRoot: './components',\n  remarkPlugins: [remarkGfm],\n})()\n```\n\n### Integrates with `@next/mdx`\n\nSwingset integrates with `@next/mdx` by supporting the same `mdx-components.ts` file at the root of your application. Swingset will make the custom components declared there available.\n\n### Use with Storybook\n\nDocumentation pages within Swingset are treated as modules. This means that you can import other modules into your `.mdx` files as you would any other JavaScript file. This works great if you leverage Storybook for component development, as stories are directly consumable from your documentation:\n\n```tsx\nimport * as stories from './Button.stories'\n\n# This is the Primary story\n\n<stories.Primary />\n```\n\n## Contributing\n\nSee [CONTRIBUTING.md](/CONTRIBUTING.md).\n","readmeFilename":"README.md","gitHead":"128bbaf6e40696a20f9873ec8171fbcf4bc195d6","description":"Welcome to Swingset. Swingset is a drop-in component documentation system built for Next.js's App Router and React Server Components.","_id":"swingset@0.18.0-canary-20230629193328","_nodeVersion":"16.20.1","_npmVersion":"8.19.4","dist":{"integrity":"sha512-vHpSbf1RRBwrQeppEx6fFP3ufoxmlB509PcU6w1g9bjr+/wBodvOZsA0yibmOnq29nGG+AwH7HKsLWPAwaP7Ig==","shasum":"42de0c0e3f2af2be12e5b3eed5ec2ccf1ecbf9db","tarball":"https://registry.npmjs.org/swingset/-/swingset-0.18.0-canary-20230629193328.tgz","fileCount":54,"unpackedSize":260797,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGZEF5cEtd9wmPUlEJIT7MixZjKa2KjlfqCICxkq0G1bAiEAqNzsautWd+1tye8I8BGH8YIbvRIfn1bttjVMbllqb8w="}]},"_npmUser":{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},"directories":{},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"hello@brycekalow.name"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/swingset_0.18.0-canary-20230629193328_1688067266819_0.6038158062366543"},"_hasShrinkwrap":false}},"time":{"created":"2020-10-26T21:11:48.013Z","0.3.0":"2020-10-26T21:11:48.198Z","modified":"2023-06-29T19:34:27.165Z","0.4.0":"2020-11-02T21:21:19.077Z","0.4.1":"2020-11-05T18:02:54.117Z","0.4.2":"2020-11-09T18:02:53.883Z","0.5.0":"2021-01-22T17:02:34.321Z","0.5.0-canary.0":"2021-01-22T20:23:20.531Z","0.5.1":"2021-01-25T15:30:47.799Z","0.6.0":"2021-03-08T15:21:11.462Z","0.6.1":"2021-03-08T16:43:03.847Z","0.7.0":"2021-04-01T20:50:50.417Z","0.7.2":"2021-04-22T21:57:21.878Z","0.7.3":"2021-04-22T22:05:03.581Z","0.7.3-canary.0":"2021-05-04T19:03:14.315Z","0.8.0":"2021-05-04T23:04:05.538Z","0.9.0":"2021-06-04T19:40:51.518Z","0.10.0":"2021-06-16T15:25:15.590Z","0.10.1":"2021-08-09T23:21:08.870Z","0.10.2":"2021-09-30T19:22:37.969Z","0.11.0":"2022-01-13T17:54:14.081Z","0.12.0":"2022-03-21T15:30:48.482Z","0.13.0":"2022-05-07T15:21:45.535Z","0.14.0":"2022-06-07T20:18:54.261Z","0.14.1":"2022-06-23T18:47:08.738Z","0.15.0-canary-20221115193513":"2022-11-15T19:35:20.352Z","0.15.0-canary-20221208035901":"2022-12-08T03:59:06.697Z","0.15.0-canary-20221208040638":"2022-12-08T04:06:44.559Z","0.15.0-canary-20221208041053":"2022-12-08T04:10:57.417Z","0.15.0-canary-20221208172311":"2022-12-08T17:23:16.488Z","0.15.0-canary-20221208173207":"2022-12-08T17:32:11.753Z","0.15.0-canary-20221208181311":"2022-12-08T18:13:15.688Z","0.15.0-canary-20221208181706":"2022-12-08T18:17:13.714Z","0.15.0-canary-20221208201832":"2022-12-08T20:18:40.310Z","0.15.0-canary-20221208203712":"2022-12-08T20:37:18.186Z","0.15.0-canary-20221208213251":"2022-12-08T21:32:57.859Z","0.15.0-canary-20221212171910":"2022-12-12T17:19:15.574Z","0.15.0-canary-20221212174158":"2022-12-12T17:42:04.053Z","0.15.0-canary-20221212183553":"2022-12-12T18:35:57.969Z","0.15.0-canary-20221212190516":"2022-12-12T19:05:22.956Z","0.15.0-canary-20221212191059":"2022-12-12T19:11:06.549Z","0.15.0":"2022-12-12T19:43:05.251Z","0.16.0-canary-20221212234150":"2022-12-12T23:41:55.284Z","0.16.0-canary-20221212234807":"2022-12-12T23:48:13.567Z","0.16.0":"2022-12-13T00:03:14.726Z","0.17.0-canary-20221213190039":"2022-12-13T19:00:46.174Z","0.17.0":"2022-12-13T21:15:09.884Z","0.18.0-canary-20230321185651":"2023-03-21T18:57:28.378Z","0.18.0-canary-20230321200711":"2023-03-21T20:07:50.762Z","0.18.0-canary-20230412151215":"2023-04-12T15:12:55.832Z","0.18.0-canary-20230412152225":"2023-04-12T15:23:08.355Z","0.18.0-canary-20230412162055":"2023-04-12T16:21:38.176Z","0.18.0-canary-20230412170738":"2023-04-12T17:08:17.375Z","0.18.0-canary-20230413025426":"2023-04-13T02:55:03.891Z","0.18.0-canary-20230413025741":"2023-04-13T02:58:21.786Z","0.18.0-canary-20230413143320":"2023-04-13T14:34:12.464Z","0.18.0-canary-20230427173422":"2023-04-27T17:35:16.995Z","0.18.0-canary-20230602203622":"2023-06-02T20:37:12.303Z","0.18.0-canary-20230628143729":"2023-06-28T14:38:31.282Z","0.18.0-canary-20230628145658":"2023-06-28T14:57:51.655Z","0.18.0-canary-20230628145726":"2023-06-28T14:58:17.699Z","0.18.0-canary-20230628233900":"2023-06-28T23:40:04.491Z","0.18.0-canary-20230629001205":"2023-06-29T00:13:00.706Z","0.18.0-canary-20230629001352":"2023-06-29T00:15:00.816Z","0.18.0-canary-20230629193328":"2023-06-29T19:34:27.052Z"},"maintainers":[{"name":"jescalan","email":"soft.joy1514@fastmail.com"},{"name":"wkentdag","email":"hi@wtkd.info"},{"name":"zchsh","email":"hi@zch.sh"},{"name":"ashleemboyer","email":"ashleemboyer.dev@gmail.com"},{"name":"hashibot-web","email":"mktg-dev-github-bot@hashicorp.com"},{"name":"zacktanner","email":"zacktanner@gmail.com"},{"name":"bkalow","email":"hello@brycekalow.name"}],"description":"drop-in component library and documentation pages for next.js","homepage":"https://github.com/hashicorp/swingset#readme","keywords":["component","component-library","library","next.js","storybook"],"repository":{"type":"git","url":"git+https://github.com/hashicorp/swingset.git"},"author":{"name":"Jeff Escalante"},"bugs":{"url":"https://github.com/hashicorp/swingset/issues"},"license":"MIT","readme":"","readmeFilename":""}