{"_id":"@aikuma/webcomponents","_rev":"7-e32334297132ea9e4b3cacc05715bbb1","name":"@aikuma/webcomponents","dist-tags":{"latest":"0.3.2"},"versions":{"0.0.1":{"name":"@aikuma/webcomponents","version":"0.0.1","description":"Web components for language apps","main":"dist/aikuma.js","types":"dist/types/index.d.ts","collection":"dist/collection/collection-manifest.json","files":["dist/"],"browser":"dist/aikuma.js","scripts":{"build":"stencil build","dev":"sd concurrent \"stencil build --dev --watch\" \"stencil-dev-server\" ","serve":"stencil-dev-server","start":"npm run dev","test":"jest --no-cache","test.watch":"jest --watch --no-cache"},"dependencies":{"@fortawesome/fontawesome":"^1.1.3","@fortawesome/fontawesome-free-solid":"^5.0.6","@ionic/core":"0.0.2","@stencil/core":"0.6.4","aikumic":"^0.2.2","prettyprint":"^1.1.1","randomcolor":"^0.5.3","swiper":"^4.1.6"},"devDependencies":{"@stencil/dev-server":"latest","@stencil/sass":"0.0.2","@stencil/utils":"latest","@types/jest":"^21.1.10","jest":"^21.2.1","tslib":"^1.9.0"},"repository":{"type":"git","url":"git+https://github.com/Lingomat/aikuma-components.git"},"author":{"name":"mat Bettinson"},"license":"MIT","bugs":{"url":"https://github.com/Lingomat/aikuma-components"},"homepage":"https://github.com/Lingomat/aikuma-components","jest":{"transform":{"^.+\\.(ts|tsx)$":"<rootDir>/node_modules/@stencil/core/testing/jest.preprocessor.js"},"transformIgnorePatterns":["<rootDir>/node_modules/(?!aikumic)"],"testRegex":"(/__tests__/.*|\\.(test|spec))\\.(tsx?|jsx?)$","moduleFileExtensions":["ts","tsx","js","json","jsx"]},"keywords":["web","components","language","documentation"],"gitHead":"6ac651090c5d02a2e675f7679ffa7d97188ed7e7","_id":"@aikuma/webcomponents@0.0.1","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"aikuma","email":"langtechresearch@gmail.com"},"dist":{"integrity":"sha512-871S16P06pF4vh6MzN/8dZH9UY1LXaKHKJZf1yc7Z4DA8Uk10Xr1UUtD/WQTPx6krjK1BBevPC/ZQcU/A5FbiQ==","shasum":"e1df7ba76f75d958eb3d7ff4f4d647984bd59a92","tarball":"https://registry.npmjs.org/@aikuma/webcomponents/-/webcomponents-0.0.1.tgz","fileCount":44,"unpackedSize":2601178,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCfNfs3xAwsSYUkNJkLWrjeFWfGpOZaNnSAKKVEgeLwhwIgP4r8rVQOk/6IcCZbFRbGOHQfB0ew8X82YaCTCqknHbY="}]},"maintainers":[{"name":"aikuma","email":"langtechresearch@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/webcomponents_0.0.1_1519691756563_0.4732020615333601"},"_hasShrinkwrap":false},"0.0.6":{"name":"@aikuma/webcomponents","version":"0.0.6","description":"Web components for language apps","main":"dist/aikuma.js","types":"dist/types/index.d.ts","collection":"dist/collection/collection-manifest.json","files":["dist/"],"browser":"dist/aikuma.js","scripts":{"build":"stencil build","dev":"sd concurrent \"stencil build --dev --watch\" \"stencil-dev-server\" ","serve":"stencil-dev-server","start":"npm run dev","test":"jest --no-cache","test.watch":"jest --watch --no-cache"},"dependencies":{},"devDependencies":{"@stencil/dev-server":"latest","@stencil/sass":"latest","@stencil/utils":"latest","@stencil/core":"^0.8.0","@types/jest":"^21.1.1","jest":"^21.2.1","tslib":"^1.9.0","@aikuma/webaudio":"^0.4.0","@aikuma/gestate":"^0.3.2","@fortawesome/fontawesome":"^1.1.5","@fortawesome/fontawesome-free-solid":"^5.0.9","prettyprint":"^1.1.1","randomcolor":"^0.5.3","swiper":"^4.2.0","wavesurfer.js":"^2.0.5"},"repository":{"type":"git","url":"git+https://github.com/Lingomat/aikuma-components.git"},"author":{"name":"mat Bettinson"},"license":"MIT","bugs":{"url":"https://github.com/Lingomat/aikuma-components"},"homepage":"https://github.com/Lingomat/aikuma-components","jest":{"transform":{"^.+\\.(ts|tsx)$":"<rootDir>/node_modules/@stencil/core/testing/jest.preprocessor.js"},"transformIgnorePatterns":["<rootDir>/node_modules/(?!aikumic)"],"testRegex":"(/__tests__/.*|\\.(test|spec))\\.(tsx?|jsx?)$","moduleFileExtensions":["ts","tsx","js","json","jsx"]},"keywords":["web","components","language","documentation"],"gitHead":"4ba5205eb30023ac900a454e41ef7430c3d74bd1","_id":"@aikuma/webcomponents@0.0.6","_shasum":"c3f538c80e74514102ed5019c5a95c37057f076b","_from":".","_npmVersion":"4.6.1","_nodeVersion":"8.9.0","_npmUser":{"name":"aikuma","email":"langtechresearch@gmail.com"},"dist":{"shasum":"c3f538c80e74514102ed5019c5a95c37057f076b","tarball":"https://registry.npmjs.org/@aikuma/webcomponents/-/webcomponents-0.0.6.tgz","fileCount":62,"unpackedSize":2292792,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa8Rd5CRA9TVsSAnZWagAAkxEP/iU8O1cIJ3sYcYqk43pa\ncz/ex8v7mfht0n/NLL1Quaky99eb1imZgYILOl+y0ij56EBfcptX4GpsjU+5\ngQ4RZ4T5/7HovCOxzDEvZrJL0Vmvm2M9+WoTGvl6qS8UBlbpGpu/LYZawJ2H\ndXZfvPBJqy+6SSNzOF+otgSvLDj0wV8ZKlBqiPLwGnHO6ptKNJ3/H+1vm/yz\nNrBkJk6BtH723NWqxiwzovapbY58iH348CO666Xf8mqvYbIbMuEFdRGXY22+\nAT1lDvIGG+Yr98YseAkJxuyjUfcjhbVwRuNrOP5RpczHvzKT5owU5xq/m+cl\nUKKju4C2ZP7LSH4xuWTzE5/iG5Y00T6U9HYz7e2C30DMAFqvlk5kuNbLo+xP\naN4Uq7kBYMdVEtmhd1qniU2pSu+TSuzrveZDADVZHSQv0lvXWmMRszqyONby\n5+PwEhkLfzNixMzMD+jypxiUoIy8D73Nh5qNIRv+o+rw1EJe0Yi7kbLUautw\nWf7n8GU9mj5ZB1m18HWEyS6X2SHitEcNgfV5UE+t1DaDA22GhPQOgpLeKreU\nmh1XTsDF6Y0hKEeJkg8UIOPaL6ybgdcYKfTvmJw39wNkGiv2nk4L6riZcvJc\nzIUnnQNXnZkBZBcngJ9ohnzU1KelojBbfGWvj3OsA1AWJGMSpp7a27QUnNwq\nGxwP\r\n=MvJc\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-l1TabnFbwg8EuN+vfQGkipsIdMzsNn3ZUVM3em+skeiBBli63gFc2aEX/SRJ3x/sHHDy+1uasH7ZAhVn9Pr0gg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDbCxkofH3y9an5lvN/sbuiLfcyzJIPw64cBkbIynn7dwIgfdZm0HQh4ge2ADqCfXPdHzkU3cNNqUlrTND22YQ5jsQ="}]},"maintainers":[{"name":"aikuma","email":"langtechresearch@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/webcomponents_0.0.6_1525749623533_0.2772551302701831"},"_hasShrinkwrap":false},"0.0.7":{"name":"@aikuma/webcomponents","version":"0.0.7","description":"Web components for language apps","main":"dist/index.js","module":"dist/esm/index.js","types":"dist/types/index.d.ts","collection":"dist/collection/collection-manifest.json","files":["dist/"],"scripts":{"build":"stencil build","dev":"sd concurrent \"stencil build --dev --watch\" \"stencil-dev-server\" ","serve":"stencil-dev-server","start":"npm run dev","test":"jest --no-cache","test.watch":"jest --watch --no-cache"},"dependencies":{},"devDependencies":{"@stencil/dev-server":"latest","@stencil/sass":"latest","@stencil/utils":"latest","@stencil/core":"^0.9.7","@types/jest":"^21.1.1","jest":"^21.2.1","tslib":"^1.9.0","@aikuma/webaudio":"^0.4.0","@aikuma/gestate":"^0.3.2","@fortawesome/fontawesome":"^1.1.5","@fortawesome/fontawesome-free-solid":"^5.0.9","prettyprint":"^1.1.1","randomcolor":"^0.5.3","swiper":"^4.2.0","wavesurfer.js":"^2.0.5"},"repository":{"type":"git","url":"git+https://github.com/Lingomat/aikuma-components.git"},"author":{"name":"Mat Bettinson"},"license":"MIT","bugs":{"url":"https://github.com/Lingomat/aikuma-components"},"homepage":"https://github.com/Lingomat/aikuma-components","jest":{"transform":{"^.+\\.(ts|tsx)$":"<rootDir>/node_modules/@stencil/core/testing/jest.preprocessor.js"},"transformIgnorePatterns":["<rootDir>/node_modules/(?!aikumic)"],"testRegex":"(/__tests__/.*|\\.(test|spec))\\.(tsx?|jsx?)$","moduleFileExtensions":["ts","tsx","js","json","jsx"]},"keywords":["web","components","language","documentation"],"gitHead":"8350db94fb7cfa180bdf6bcbb9abeea48f50d8c0","_id":"@aikuma/webcomponents@0.0.7","_shasum":"09450522b19d5a60770aebd23d0197fb6a36f8b5","_from":".","_npmVersion":"4.6.1","_nodeVersion":"10.3.0","_npmUser":{"name":"aikuma","email":"langtechresearch@gmail.com"},"dist":{"shasum":"09450522b19d5a60770aebd23d0197fb6a36f8b5","tarball":"https://registry.npmjs.org/@aikuma/webcomponents/-/webcomponents-0.0.7.tgz","fileCount":90,"unpackedSize":3585721,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbFeh2CRA9TVsSAnZWagAAO/IP/2rQdcdj56/AT/SBos7I\nuoXyRaZ1ix7SAnAPwEtpvDCgJ1GA+VXAcBcxNm+bHUoLUhCcH7LvcYhcOI7c\nBMfzxQV2J6CNuGkWSTSchRUbcssoNXwE2rfXjHPATUJohHnIbCffjzy+0qbQ\nSNMVwNV7fhsBrYwDsVTHXvO9vx0z0U2F2S2C1RpBVrg3DfNAXLIF53HtGpYB\nc0gwAyjat+lZaKdm7P/yacejIF7tyBiKrKAxYs7Of/NXvkUcSVvgji2z7bbe\nTlryoi83O8gsui78f/5JVFv01uJYHMS/EjZCAgigFnbJncfRrlb5Whu3uEu7\nWFDFwbBH5p3kGtKjs5LB+T2b4mO4JCuA+8qhcih0VJFbpFBVs6f6w46rQpPR\nJ8dSAua1JvMs/+lfKyQr/aA+db+j3QrAGea0CFIW73/hkzH823QTVmdifcSQ\nSCoDpT6B/6qXcInYrYPmXE/UOJebomAnOB/Liiyoqe19Y+8Cofm74DiYmN/H\nzHjHF0KgFB3EjZpo0jBwvOpVnUiL05QEyiAxkZVhgGAKGCPqp6cLmmmefF5Y\nfDnvaB0kOvbpVtpmAmHKuJCVjooEH7fWcpX4k7wsbkth6mx/0hP92KXg/oyK\naweR07ovTi8gHKK2h3qhm+zm/P/vLJx6Da3DCVk756rq4Tqhdcmr0yfr5fCw\nboJX\r\n=Hd++\r\n-----END PGP SIGNATURE-----\r\n","integrity":"sha512-adDMTAikCV706VvSpWZVRrYz6yJESKTIj7rufG1rnNa7g4SeMV467G2iLv+1S24zJdJ4S+lwnQeM1cXv+3SWxQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDhTXrL1UbKRD6QB6h1EBvnlbdiRLNBm8i7dZUtUBl3rgIgC4xoQ4P2iQP8GOfA7QubNpR3On4O3bH1X2s2usvq8D8="}]},"maintainers":[{"name":"aikuma","email":"langtechresearch@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/webcomponents_0.0.7_1528162420711_0.8369015974295588"},"_hasShrinkwrap":false},"0.3.2":{"name":"@aikuma/webcomponents","version":"0.3.2","description":"Web components for language apps","main":"dist/index.js","module":"dist/index.mjs","es2015":"dist/esm/index.mjs","es2017":"dist/esm/index.mjs","jsnext:main":"dist/esm/index.mjs","types":"dist/types/index.d.ts","collection":"dist/collection/collection-manifest.json","scripts":{"build":"stencil build --docs","start":"stencil build --dev --watch --serve","test":"stencil test --spec --e2e","test.watch":"stencil test --spec --e2e --watchAll"},"dependencies":{"dynamic-class-list":"^1.0.82"},"devDependencies":{"@aikuma/gestate":"^0.6.2","@aikuma/webaudio":"^0.4.0","@fortawesome/fontawesome":"^1.1.8","@fortawesome/fontawesome-free-solid":"^5.0.13","@stencil/core":"^1.0.0","@stencil/sass":"latest","prettyprint":"^1.1.2","randomcolor":"^0.5.4","swiper":"^4.5.0","tslib":"^1.9.3","wavesurfer.js":"^2.2.1"},"repository":{"type":"git","url":"git+https://github.com/Lingomat/aikuma-components.git"},"author":{"name":"Mat Bettinson"},"license":"MIT","bugs":{"url":"https://github.com/Lingomat/aikuma-components"},"homepage":"https://github.com/Lingomat/aikuma-components","keywords":["web","components","language","documentation"],"gitHead":"6838c3ce446091cbee3078ef95b8c951502300db","_id":"@aikuma/webcomponents@0.3.2","_nodeVersion":"10.15.1","_npmVersion":"6.8.0","dist":{"integrity":"sha512-nzWBNHAK/YZvYTuusql752AgPO0M6YXLnZFTTcPvHEqy/YMFRHVgFc9vfK+DMf7OOWu2nYo2Xmtab6pcXc74bA==","shasum":"36a2a98135f2b778f16901c150a7ea5561526a61","tarball":"https://registry.npmjs.org/@aikuma/webcomponents/-/webcomponents-0.3.2.tgz","fileCount":150,"unpackedSize":10023409,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdVleSCRA9TVsSAnZWagAAgMgQAJMDLXD46Ae5WZoDnTKY\nG8mf3+svOlK/1pOggouGNJW2B53xqAL/QgxDKbREKDWCzlAriF3w5au6YIT1\nbNp+Pvx1lNzTWV0jNND2a6634jgsqdtKLsu7BnBME3njaxTUo4jLMIZRJDu4\nk0iNqe9OQ26zATuJcEQ7cWsuB5jIzsEKbNarw7OjMaoxIEhX0JXb8wcheo3B\nLhxiPxbu55PAGdbXTFrwjXb5sqS/czqJmWF1QUWlWhpnu9K3pUjtKkophuqF\nSgmsLyzkor3i4F+TbtkYIKMPrzqTxpmFMvJDRvkqpX5JOUXhpzIlZ0TZ3sCC\nZfvA2ODMWHWEsdLqjdErFxdhUsdEpfdQk4TG+EZVEzqJXuM5RiX7v3tIa3VR\nXNCdw3gjoV2NtNC1nhgrEvlbb+rIRbiTST8OfWtvq12sHZYJN4d20pGCoS/l\n5eaXDgM8AWS+inE1YL9uTLE2Gxsv6xbrswy8HpxHCan2Ae5QMrtQNzQm831I\n1/zZjJzifiso9iSqa5h98z9zulj61LJ3ZQ/r7zQz+8Z+horD+ZwhueQp4Ak5\nqA54qCjlYaADYlvgqWthDttuQtEB2qUmbu1AVWcDPYdaJuKKKREB2A9018MT\npjT2UqZLgdL89idAIrHqch/SLPo+cov/kKvJZ/XXRhPss1ajJftUPSrVuLcQ\npPmb\r\n=4WPb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEch/89X4yNbhSMnFu2NrSi1DIreOPaxmkdhWXgtmiMmAiAFyx8n9EF28rGN1f8iRPaGcY+LHdNHVuCJA8wRj1aDcA=="}]},"maintainers":[{"name":"aikuma","email":"langtechresearch@gmail.com"}],"_npmUser":{"name":"aikuma","email":"langtechresearch@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/webcomponents_0.3.2_1565939602059_0.09283394270066747"},"_hasShrinkwrap":false}},"time":{"created":"2018-02-27T00:35:56.507Z","0.0.1":"2018-02-27T00:35:56.677Z","modified":"2022-06-12T14:25:18.800Z","0.0.6":"2018-05-08T03:20:23.649Z","0.0.7":"2018-06-05T01:33:40.912Z","0.3.2":"2019-08-16T07:13:22.267Z"},"maintainers":[{"name":"aikuma","email":"langtechresearch@gmail.com"}],"description":"Web components for language apps","homepage":"https://github.com/Lingomat/aikuma-components","keywords":["web","components","language","documentation"],"repository":{"type":"git","url":"git+https://github.com/Lingomat/aikuma-components.git"},"author":{"name":"Mat Bettinson"},"bugs":{"url":"https://github.com/Lingomat/aikuma-components"},"license":"MIT","readme":"![Built With Stencil](https://img.shields.io/badge/-Built%20With%20Stencil-16161d.svg?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjIuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MTIgNTEyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI%2BCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI%2BCgkuc3Qwe2ZpbGw6I0ZGRkZGRjt9Cjwvc3R5bGU%2BCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik00MjQuNywzNzMuOWMwLDM3LjYtNTUuMSw2OC42LTkyLjcsNjguNkgxODAuNGMtMzcuOSwwLTkyLjctMzAuNy05Mi43LTY4LjZ2LTMuNmgzMzYuOVYzNzMuOXoiLz4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTQyNC43LDI5Mi4xSDE4MC40Yy0zNy42LDAtOTIuNy0zMS05Mi43LTY4LjZ2LTMuNkgzMzJjMzcuNiwwLDkyLjcsMzEsOTIuNyw2OC42VjI5Mi4xeiIvPgo8cGF0aCBjbGFzcz0ic3QwIiBkPSJNNDI0LjcsMTQxLjdIODcuN3YtMy42YzAtMzcuNiw1NC44LTY4LjYsOTIuNy02OC42SDMzMmMzNy45LDAsOTIuNywzMC43LDkyLjcsNjguNlYxNDEuN3oiLz4KPC9zdmc%2BCg%3D%3D&colorA=16161d&style=flat-square)\r\n\r\n# Aikuma Web Components\r\n\r\nThe repo is a library of reusable Web Components for knowledge preservation apps. \r\n\r\nWe offer an implementation of the Image Gesture Voice (IGV) method, as described in [Image-Gesture-Voice: a Web Component for Eliciting Speech](http://lrec-conf.org/workshops/lrec2018/W26/summaries/22_W26.html). IGV was previously developed as the key activity in the [Zahwa](https://zahwa.aikuma.org) mobile app implemented with Ionic (and Angular).\r\nThe web component ports are built with Ionic's [StencilJS](http://www.stenciljs.com).\r\n\r\n## Components\r\n\r\n* aikuma-image-gesture-voice\r\n* aikuma-translate-igv (wip)\r\n* aikuma-slide-show\r\n* aikuma-buttony\r\n* aikuma-modal\r\n* aikuma-progress\r\n* aikuma-camera\r\n\r\nThe first two components are higher order components that implement entire activities. Both use the the [@aikuma/gestate](https://github.com/aikuma/gestate) gesture record/playback library and [@aikuma/webaudio](https://github.com/aikuma/webaudio) web audio library.\r\n\r\nThe aikuma-slide-show component is a web component wrapper of [Swiper](http://idangero.us/swiper/). \r\n\r\naikuma-buttony and aikuma-modal are low-level UI elements we intend to replace with components from the upcoming web component-implemented Ionic framework. aikuma-progress renders a progress bar with optional segmentation. aikuma-camera is a simple video feed with camera capture functionality.\r\n\r\n## Using Web Components elsewhere\r\n\r\nThe easiest way is to use a script tag and the unpkg.com unpacker/CDN service. See the demo/index.html file (just open in Chrome to run) for an example of this, e .g:\r\n\r\n```\r\n<script src='https://unpkg.com/@aikuma/webcomponents@0.1.0/dist/aikuma.js'></script>\r\n```\r\n\r\nA more realistic way to consume components in the longer term is to integrate them into a bundler such as Web Pack. This [Ionic Blog Post](https://blog.ionicframework.com/using-webpack-with-web-components-built-using-stencil/) has more information. This opens the door to selectively importing components from a collection.\r\n\r\nThere might be some merit in publishing key components as separate NPM modules to smooth this process for people that just want to include a useful component on, say, a web page, archive or something, which otherwise doesn't use complicated web build tooling. This is best explored with real use cases, so get in touch if this affects you.\r\n\r\n## Consuming Web Components as APIs\r\n\r\nA common way of interacting with custom components is via attribute properties. For example; `<custom-tag prop={{data}}>`. JavaScript frameworks allow binding of data to properties with differences in syntax. This method is supported in WebComponents by watching for attribute value changes. We believe this is sub-optimal because implementations vary across JavaScript frameworks, there's a risk of degraded performance, and finally, this pattern differs from the pattern of consuming JavaScript module APIs at large.\r\n\r\nInstead, these web components offer JavaScript APIs consisting of public methods which are exposed directly upon the custom component in the DOM. For example, we include a custom component on a web page:\r\n\r\n`<aikuma-image-gesture-voice></aikuma-image-gesture-voice>`\r\n\r\nAnd then we get the instance of this component with: `let igv = document.querySelector('aikuma-image-gesture-voice')`\r\nThe API for the component is now available on the `igv` object, such as `igv.loadFromImageURLs()`.\r\n\r\nAnother motivation for this pattern is that web components in this domain will need to be initialized from different contexts. In one context, the component is initialized with raw data such as images. In another context, we need to launch the component with the data that enables restoration of a previous working state. With a JavaScript API we support this via alternative initialisation methods.\r\n\r\n## General pattern\r\n\r\nAikuma Web Components library adopts TypeScript, and for the purpose of this document, we assume that parent also uses TypeScript and/or modern ES6+ JavaScript features. The examples here use the `await` keyword for clarity, rather than the Promise pattern. This requires that the calling function is an async function.\r\n\r\n## Image Gesture Voice (IGV)\r\n\r\nIGV is a process whereby we import a series of image prompts and then record a spoken description of the images and any touch or mouse gestures on the images as the operator speaks. IGV was designed as a method to document procedural discourse (how-to knowledge) but is flexible enough to be deployed in other contexts. \r\n\r\nThe IGV Translate component, documented in the next section, provides the means to record a step-by-step spoken translation of an IGV session.\r\n\r\n### Example\r\n\r\n```\r\nlet igv = document.querySelector('aikuma-image-gesture-voice')\r\nigv.loadFromImageURLs(['http://...pic.jpg', 'http://...pic.jpg'...])\r\nigv.waitForComplete().then((igvdata) => {\r\n  if (igvdata) {\r\n    console.log('aikuma-image-gesture-voice returned',igvdata)\r\n  } else {\r\n    console.log('aikuma-image-gesture-voice cancelled')\r\n  }\r\n})\r\n```\r\n\r\nSee also src/index.html for the demo source. There may be things commented out.\r\n\r\n### Demo\r\n\r\n`npm start`\r\n\r\n### API\r\n\r\n`loadFromImageURLs(images: string[], opts?: <b>IGVOptions</b>): Promise<any>`\r\n\r\nInitialize the component from an array of URLs (strings). The order will be preserved as slides. Returns a promise that resolves once the images have been loaded. May also pass an optional object with valid <b>IGVOptions</b> properties.\r\n\r\n`waitForComplete(): Promise<IGVData>`\r\n\r\nReturns a promise that resolves with <b>IGVData</b> or `null` if the action was cancelled.\r\n\r\n`restoreFromIGVData(data: <b>IGVData</b>): Promise<any>`\r\n\r\nRestore the component from previous <b>IGVData</b>. Returns a Promise that resolves when loaded.\r\n\r\n### Types\r\n\r\n<b>IGVData</b>\r\n```\r\n{\r\n  segments: IGVSegment[]\r\n  audio: Blob\r\n  length: {ms: number, frames: number}\r\n}\r\n```\r\nAn IGVData object represents complete IGV data, consisting of an array of IGVSegments, a binary audio Blob (wav file) of the audio recording in the process, and a length object that specifies milliseconds and frames (samples). We can infer a virtual IGV timeline based on the length, which is always the length of the audio file. IGVSegments are aligned to this timeline so that they specify a start position that must be less than the total length.\r\n\r\n<b>IGVSegment</b>\r\n```\r\n{\r\n  prompt: IGVPrompt,\r\n  startMs: number,\r\n  endMs?: number\r\n  gestures?: Gesture[]\r\n}\r\n```\r\nAn IGVSegment object describes the utilisation of an IGVPrompt on the IGV time line. The prompt property is an IGVPrompt, and startMs represents the millisecond offset from the start of the time line, e.g. the time at which this prompt was displayed. An optional endMs property describes the end of the prompt display. The optional gestures property is an array of <b>Gesture</b> objects as defined in the `@aikuma/gestate` library, but duplicated in the Types heading below for convenience.\r\n\r\n<b>IGVPrompt</b>\r\n```\r\n{\r\n  id: string,\r\n  type: string,\r\n  image?: Slide\r\n}\r\n```\r\nAn IGVPrompt object contains a unique id string property, and an optional binary image Blob that represents this prompt. The type property describes the type of prompt, which is always 'image' for IGV. The optional image property is of type <b>Slide</b> from the `slide-show` component.\r\n\r\n<b>IGVOptions</b>\r\n```\r\n{\r\n  debug: boolean\r\n}\r\n```\r\nIGVOptions is an object that describes a set of options for the component, currently consisting of only the debug boolean property flag.\r\n\r\n<b>Slide</b>\r\n```\r\n{\r\n  url: string\r\n  width: number\r\n  height: number\r\n  id: string\r\n}\r\n```\r\nDefined by slide-show component, Slide is a description of a unique image. The properties consist of a url to the image (string), and numerical dimensions of the width, height properties and a unique id. The ids are created for the first time when the IGV compnent loads from raw images, e.g. `loadFromImageURLs() method.\r\n\r\n<b>Gesture</b>\r\n```\r\n{\r\n  timeOffset: number\r\n  type?: string\r\n  timeLine: {x: number, y: number, t: number}[]\r\n}\r\n```\r\nDefined by @aikuma/gestate, a Gesture object is a description of a gesture consisting of a timeoffset value in milliseconds of the start of the gesture for the current prompt, <em>not</em> since the beginning of the IGV timeline. The timeLine property is an array of objects which have relative floats of touch/mouse position x and y, ranging from 0 to 1, and t represents a millisecond offset from the start of the gesture, e.g. the first one will be 0.\r\n\r\n### Dependencies\r\n\r\n* @aikuma/webaudio microphone web-audio player library \r\n* @aikuma/gestate gesture recording library\r\n\r\n## Translate IGV\r\n\r\nTranslate IGV is typically called with data resulting from the Image Gesture Voice component. The operator may record a spoken translation of an IGV session, or perhaps respeak an IGV session more clearly for second language learners.\r\n\r\nThe component offers a step-by-step translation procedure similar to the earlier Aikuma Android app. The component produces data that consists of a new audio recording and a timeline map which describes the alignment of segments of the translated audio against segments of the source audio.\r\n\r\n### Example\r\n\r\n```\r\nlet tigv = document.querySelector('aikuma-igv-translate')\r\nawait tigv.componentOnReady()\r\nlet igvData = ... previous IGVData\r\ntigv.loadIGVData(igvData)\r\ntigv.waitForComplete().then((tigvdata) => {\r\n  if (tigvdata) {\r\n    console.log('aikuma-igv-translate returned', tigvdata)\r\n  } else {\r\n    console.log('aikuma-igv-translate cancelled')\r\n  }\r\n})\r\n```\r\n\r\n### API\r\n\r\n`loadIGVData(data: IGVData, opts?: <b>IGVOptions</b>): Promise<any>`\r\n\r\nInitialize the component from IGVData, e.g. the data object returned by the Image Gesture Voice component's waveForComplete() method. Returns a promise that resolves once the iIGVData has loaded. May also pass an optional object with valid <b>IGVOptions</b> properties.\r\n\r\n`waitForComplete(): Promise<IGVTranslation>`\r\n\r\nReturns a promise that resolves with <b>IGVTranslation</b> or `null` if the action was cancelled.\r\n\r\n### Types\r\n\r\n<b>IGVTranslation</b>\r\n```\r\n{\r\n  segments: IGVSegment[]\r\n  audio: Blob\r\n  length: {ms: number, frames: number}\r\n}\r\n```\r\nAn IGVTranslation object represents a complete IGV translation. A binary `audio` Blob (wav file) of the audio recording in the process, and a `length` object that specifies milliseconds and frames (samples) properties.\r\n\r\n### Dependencies\r\n\r\n* @aikuma/webaudio microphone web-audio player library \r\n* @aikuma/gestate gesture recording library\r\n\r\n\r\n## Slide Show\r\n\r\nSlide Show is a wrapper around the Swiper JavaScript module.\r\n\r\n### Example\r\n\r\n```\r\nlet ss = document.querySelector('aikuma-slide-show')\r\nawait ss.componentOnReady()\r\nlet slides = await ss.loadImages(['http://...image1.jpg', 'http://...image2.jpg' ...])\r\n})\r\n```\r\n\r\n### API\r\n\r\n`loadImages(images: string[]): Promise<Slide[]>`\r\n\r\nInitializes by taking an array of url strings for the slide images and returns a Promise that resolves with a Slide array. The Slide objects are useful because they add dimensions and a unique id for the image. \r\n\r\n`loadSlides(slides: Slide[]): Promise<any>`\r\n\r\nInitializes by being passed an array of Slide objects, generated from loadImages, e.g. restoring a session. The returned Promise resolves when complete.\r\n\r\n`getCurrent(): number`\r\n\r\nReturns current slide index.\r\n\r\n`slideTo(idx: number, instant: boolean = false, skipCallback: boolean = false)`\r\n\r\nTransition the slide show to the current idx index. Optional boolean instant argument specifies if the transition should be instantaneous and the skipCallback boolean flag specifies if callbacks should be disabled. If they are, Slide Show will not emit slide transition events.\r\n\r\n`lockPrevious()`\r\n\r\nStops the Slide Show from being navigated to the previous slide. Useful when recording IGV.\r\n\r\n`unlockPrevious()`\r\n\r\nAllows Slide Show to navigate backwards.\r\n\r\n`highlightSlide(idx: number)`\r\n\r\nHighlights the idx slide, as specified as an index of the current slides.\r\n\r\n`getCurrentImageElement(): HTMLImageElement`\r\n\r\nObtains the actual image element for the currently displayed slide. Useful if we wish to, say, resize an overlay to the real dimensions of the image element.\r\n\r\n`isChanging(): boolean`\r\n\r\nReturns true if there is a transition underway. Useful to check for debouncing actions.\r\n\r\n`getSwiperInstances(): {main: Swiper, thumb: Swiper}`\r\n\r\nReturns an object with the main and thumbnail Swiper instances if direct control of Swiper is desired.\r\nNote that the thumb Swiper is not slaved to the main Swiper (because that's buggy), so operations will often need to be performed on both instances.\r\n\r\n### Dependencies\r\n\r\n* Swiper JavaScript module\r\n\r\n## Camera\r\n\r\nUses getUserMedia to get a video stream and displays it.\r\nNo on-screen UI, all control is via methods. \r\n\r\n### Properties\r\n\r\nimage-type: string = 'jpeg', 'png' or 'webp\r\nimage-quality: number = between 0 and 1, only for jpeg and webp\r\nwidth: x resolution\r\nheight: y resolution\r\nfacing-mode: string = 'environment or 'user'\r\n\r\n### API\r\n\r\ntakePicture(pause: boolean) - returns Promise that resolves with Blob of image. Pause flag specifies if video should pause on photo.\r\nresume() - resumes video if it's paused\r\npause() - pauses video if it's not paused\r\nswitchCamera() - attempts to switch between cameras if there is more than 1\r\n\r\n# Why?\r\n\r\nThis project is motivated by the need to improve development productivity of knowledge preservation apps. Generally speaking, the environment of this genre is seriously resource constrained. We can ill afford continual cycles of reinventing the wheel. Reusing prior work is essential. Thematically we focus on knowledge preservation methods and applications which are intended to be operated by ordinary people rather than experts.\r\n\r\nPart of this work is Mat Bettinson's PhD research investigating suitable architecture and implementation pattern for reusable software components for language-related apps. \r\n\r\n\r\n\r\n","readmeFilename":"readme.md"}