(()=>{var e,n,t,i={62462:(e,n,t)=>{var i={"./01_overview/01_getting_started.md":43193,"./02_build/01_build_for_tidbyt.md":49444,"./02_build/02_installing_pixlet.md":61732,"./02_build/04_advanced_installation.md":64557,"./02_build/05_authoring_apps.md":37387,"./02_build/07_fonts_in_pixlet.md":76200,"./02_build/10_clock_app.md":61421,"./02_build/15_crypto_tracker.md":8596,"./02_build/16_private_apps.md":76889,"./03_integrate/01_pushing_apps.md":96960,"./03_integrate/02_building_integrations.md":81090,"./03_integrate/03_zapier_quickstart.md":78608,"./04_publish/01_community_apps.md":89014,"./04_publish/02_publishing_apps.md":13577,"./04_publish/03_modifying_apps.md":14081,"./04_publish/04_advanced.md":43623,"./04_publish/05_FAQ.md":51966,"./05_engage/01_community.md":36578,"./05_engage/02_code_of_conduct.md":54870,"./06_reference/animation.md":66706,"./06_reference/gifs.md":76481,"./06_reference/modules.md":33573,"./06_reference/schema.md":2501,"./06_reference/widgets.md":59961,"./CLA.md":81897,"./CODE_OF_CONDUCT.md":10455,"./CONTRIBUTING.md":17491,"./SECURITY.md":86697,"./SUPPORT.md":29960};function a(e){var n=o(e);return t(n)}function o(e){if(!t.o(i,e)){var n=new Error("Cannot find module '"+e+"'");throw n.code="MODULE_NOT_FOUND",n}return i[e]}a.keys=function(){return Object.keys(i)},a.resolve=o,e.exports=a,a.id=62462},65532:(e,n,t)=>{"use strict";t.d(n,{A:()=>s});var i=t(71354),a=t.n(i),o=t(76314),r=t.n(o)()(a());r.push([e.id,".ansi-green-fg {\n    color: #859900;\n}\n\n.ansi-yellow-fg {\n    color: #b58900;\n}\n\n.ansi-red-fg {\n    color: #dc322f;\n}","",{version:3,sources:["webpack://./src/console/logs.css"],names:[],mappings:"AAAA;IACI,cAAc;AAClB;;AAEA;IACI,cAAc;AAClB;;AAEA;IACI,cAAc;AAClB",sourcesContent:[".ansi-green-fg {\n    color: #859900;\n}\n\n.ansi-yellow-fg {\n    color: #b58900;\n}\n\n.ansi-red-fg {\n    color: #dc322f;\n}"],sourceRoot:""}]);const s=r},95108:(e,n,t)=>{"use strict";t.d(n,{A:()=>s});var i=t(71354),a=t.n(i),o=t(76314),r=t.n(o)()(a());r.push([e.id,".sAsBQANQ3Me7cNoYFofV {\n    animation: wqtMRC0Gh_lYSGrBN8xi 30s infinite linear;\n}\n\n@keyframes wqtMRC0Gh_lYSGrBN8xi {\n    from {\n        transform: rotate(0deg);\n    }\n\n    to {\n        transform: rotate(359deg);\n    }\n}","",{version:3,sources:["webpack://./src/home/home.css"],names:[],mappings:"AAAA;IACI,mDAAuC;AAC3C;;AAEA;IACI;QACI,uBAAuB;IAC3B;;IAEA;QACI,yBAAyB;IAC7B;AACJ",sourcesContent:[".rotate {\n    animation: rotation 30s infinite linear;\n}\n\n@keyframes rotation {\n    from {\n        transform: rotate(0deg);\n    }\n\n    to {\n        transform: rotate(359deg);\n    }\n}"],sourceRoot:""}]),r.locals={rotate:"sAsBQANQ3Me7cNoYFofV",rotation:"wqtMRC0Gh_lYSGrBN8xi"};const s=r},66777:(e,n,t)=>{"use strict";t.d(n,{A:()=>m});var i=t(71354),a=t.n(i),o=t(76314),r=t.n(o),s=t(4417),l=t.n(s),c=new URL(t(56367),t.b),d=new URL(t(96846),t.b),h=r()(a()),u=l()(c),p=l()(d);h.push([e.id,`html,\nbody {\n    margin: 0;\n    height: 100%;\n}\n\n@font-face {\n    font-family: 'VisbyCF';\n    src: local('VisbyCF'), url(${u}) format('opentype');\n}\n\n@font-face {\n    font-family: 'VisbyCFBold';\n    src: local('VisbyCF'), url(${p}) format('opentype');\n}`,"",{version:3,sources:["webpack://./src/theme/styles.css"],names:[],mappings:"AAAA;;IAEI,SAAS;IACT,YAAY;AAChB;;AAEA;IACI,sBAAsB;IACtB,iFAA0E;AAC9E;;AAEA;IACI,0BAA0B;IAC1B,iFAAuE;AAC3E",sourcesContent:["html,\nbody {\n    margin: 0;\n    height: 100%;\n}\n\n@font-face {\n    font-family: 'VisbyCF';\n    src: local('VisbyCF'), url(./fonts/VisbyCF-Regular.otf) format('opentype');\n}\n\n@font-face {\n    font-family: 'VisbyCFBold';\n    src: local('VisbyCF'), url(./fonts/VisbyCF-Bold.otf) format('opentype');\n}"],sourceRoot:""}]),h.locals={};const m=h},43193:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="## Tidbyt for Developers\n\n[Tidbyt](https://tidbyt.com) is a retro display from the future 😎. It's a connected, smart display that shows weather, stocks, sports, and a whole lot more.\n\n![HelloWorld](img/hello_world.png)\n\n### Getting Started\n\nOne of the best parts about Tidbyt is that it's an open platform that you can\nbuild on, publish apps for, and integrate with your own scripts:\n\n* [Build your own pixel-based apps](../02_build/01_build_for_tidbyt.md) to display\n  on the Tidbyt.\n* Deploy and run your apps\n  * [Publish your app to the world](../04_publish/01_community_apps.md)\n  * [Push to API](../03_integrate/01_pushing_apps.md)\n  * [Private App Hosting](../02_build/16_private_apps.md)\n* [Integrate with Tidbyt's API](../03_integrate/02_building_integrations.md) to connect your Tidbyt to existing systems and workflows.\n\n\n#### Engage with the community\n\n* Join other Tidbyt developers on [Discord](https://discord.gg/r45MXG4kZc) and [Discuss](https://discuss.tidbyt.com/c/developers/8).\n* Get inspired by [checking out all the apps the community has built](https://tidbyt.com/pages/apps).\n"},49444:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i='# Build for Tidbyt \n\nTo build apps for Tidbyt, use [Pixlet](./02_installing_pixlet.md). Apps developed with\nPixlet can be served in a browser or pushed to a physical Tidbyt device.\n\n![Example of a Tidbyt](img/tidbyt_1.png)\n\n\n## Requirements\n* You\'ve installed [Pixlet](./02_installing_pixlet.md).\n* You are familiar with using a terminal.\n\n## Hello, World!\n\nPixlet applets are written in a simple, Python-like language called\nStarlark. Here\'s the venerable Hello World program:\n\n```starlark\nload("render.star", "render")\n\ndef main():\n    return render.Root(\n        child = render.Text("Hello, World!")\n    )\n```\n\nCopy the code above and save it as `hello_world.star`. Run it with the\n`pixlet serve` command:\n\n```console\npixlet serve hello_world.star\n```\n\nYou can view the result by navigating to [http://localhost:8080][3]:\n\n![](img/hello_world-pixlet.png)\n\n[3]: http://localhost:8080\n\n### Push to a Tidbyt\n\nIf you have a Tidbyt, `pixlet` can push apps directly to it:\n\n```console\n# render the bitcoin example\npixlet render examples/bitcoin.star\n\n# login to your Tidbyt account\npixlet login\n\n# list available Tidbyt devices\npixlet devices\n\n# push to your favorite Tidbyt\npixlet push <YOUR DEVICE ID> examples/bitcoin.webp\n```\n\nTo get the ID for a device, run `pixlet devices`. Alternatively, you can\nopen the settings for the device in the Tidbyt app on your phone, and tap **Get API key**.\n\n### How it works\n\nPixlet scripts are written in a simple, Python-like language called\n[Starlark](https://github.com/google/starlark-go/). The scripts can\nretrieve data over HTTP, transform it and use a collection of\n_Widgets_ to describe how the data should be presented visually.\n\nThe Pixlet CLI runs these scripts on your computer (Mac, Windows or Linux) and renders the result as a WebP\nor GIF animation. You can view the animation in your browser, save\nit, or even push it to a Tidbyt device with `pixlet push`.\n\nNote: Scripts do not run on Tidbyt devices, only rendered WebP or GIF animations are sent to it.\n\n## What\'s next?\n\n* Read the [in-depth tutorial on building a more advanced app](./15_crypto-tracker.md).\n* See our [best practices for authoring apps](./05_authoring_apps.md).\n* Check out the references for the [**widgets**](../06_reference/widgets.md)\n  and [**modules**](../06_reference/modules.md) you can use in.\n* Learn about [fonts you can use in Pixlet apps](./07_fonts_in_pixlet.md).\n\n### Publish your app\n\nOnce you\'ve got an app that\'s looking spiffy, you can\n[publish and share it with the community](../04_publish/01_community_apps.md) or [deploy it as a private app](./16_private_apps.md)\n'},61732:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="# Installing Pixlet\n\nTo use Pixlet, one first has to install the CLI tool.\n\n## Install on macOS\n\nFirst, install [Homebrew](https://brew.sh/) on your computer. Then, in your terminal, run the following:\n\n```\nbrew install tidbyt/tidbyt/pixlet\n```\n\n## Install on Linux\n\nDownload the `pixlet` binary from [the latest release][1] and move it into your `PATH`. A complete example looks like the following:\n\n```bash\n# Download the archive.\ncurl -LO https://github.com/tidbyt/pixlet/releases/download/v0.34.0/pixlet_0.34.0_linux_amd64.tar.gz\n\n# Unpack the archive.\ntar -xvf pixlet_0.34.0_linux_amd64.tar.gz\n\n# Ensure the binary is executable.\nchmod +x ./pixlet\n\n# Move the binary into your path.\nsudo mv pixlet /usr/local/bin/pixlet\n```\n\n## Install on Windows\n\nFirst, install a file archiver that can support `tar.gz` archives if you don't already have one. [NanaZip](https://apps.microsoft.com/store/detail/nanazip/9N8G7TSCL18R) works great if you don't know where to start. Once installed, Download the Windows `pixlet` binary from [the latest release][1] on GitHub.\n\nOpen the file with NanaZip and double click on the archive to see the contents. Then, click extract:\n![windows NanaZip extract](img/windows_extract.png)\n\nNavigate to `This PC` -> `Local Disk` -> `Program Files` and create a folder named Pixlet. Copy the extracted contents to this folder:\n![windows pixlet folder](img/windows_pixlet_folder.png)\n\nGo to `Settings` and search for `environment variables` and select `Edit the system environment variables`:\n![windows env 01](img/windows_env_01.png)\n\nClick `Environment Variables`:\n![windows env 02](img/windows_env_02.png)\n\nUnder `User space variables`, select `Path` and select `Edit`:\n![windows env 03](img/windows_env_03.png)\n\nClick `New` and browse to the newly created Pixlet folder and click ok:\n![windows env 04](img/windows_env_04.png)\n\nOpen a new instance of PowerShell and run `pixlet version`. If all went well, you should see the following:\n![windows env 05](img/windows_env_05.png)\n\n[1]: https://github.com/tidbyt/pixlet/releases/latest\n"},64557:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="# Advanced Installation\nThis guide is for users who wish to install Pixlet from source 🤓. If you're new here, check out [installing pixlet](./02_installing_pixlet.md) for a standard installation.\n\n## Build from source\nThis is for users looking to build Pixlet from source on macOS, Linux, or other Unix like environment. If you're trying to build for windows, check out the [windows build instructions](#windows-build-instructions).\n\n### Prerequisites\n\n- Having [go installed].\n- Having [node installed].\n- Having [libwebp installed].\n\n### Steps\n- Clone the repository:\n\t```console\n\tgit clone https://github.com/tidbyt/pixlet\n\t```\n- Cd into the repository:\n\t```console\n\tcd pixlet\n\t```\n- Build the frontend:\n\t```console\n\tnpm install\n\tnpm run build\n\t```\n- Build the binary:\n\t```console\n\tmake build\n\t```\n- After that you will have the binary `/pixlet`, which you should copy to your path.\n\n## Windows build instructions\nBuilding Pixlet (on Windows)\n\n### Prerequisites\n\n- Having [MSYS2 installed].\n- Having [node installed].\n\n### Steps\n- Start the [MINGW64 environment].\n- Install dependencies:\n\t```console\n\tpacman -S git\n\tpacman -S mingw-w64-x86_64-go\n\tpacman -S mingw-w64-x86_64-toolchain\n\tpacman -S mingw-w64-x86_64-libwebp\n\t```\n- Add `node` and `npm` to your path:\n\t```console\n\texport PATH=$PATH:/c/Program\\ Files/nodejs\n\t```\n- Clone the repository:\n\t```console\n\tgit clone https://github.com/tidbyt/pixlet\n\t```\n- Cd into the repository:\n\t```console\n\tcd pixlet\n\t```\n- Build the frontend:\n\t```console\n\tnpm install\n\tnpm run build\n\t```\n- Build the binary:\n\t```console\n\tmake build\n\t```\n- After that you will have the binary `/pixlet.exe`, which you should copy to your path.\n\n[node installed]: https://nodejs.org/en/download/\n[MSYS2 installed]: https://www.msys2.org/#installation\n[MINGW64 environment]: https://www.msys2.org/docs/environments/\n\n[go installed]: https://golang.org/dl/\n[node installed]: https://nodejs.org/en/download/\n[libwebp installed]: https://developers.google.com/speed/webp/download\n\n[1]: https://github.com/tidbyt/pixlet/releases/latest"},37387:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i='# Authoring Apps\n\nThis guide provides best practices on how to build apps to integrate well with\nthe Tidbyt ecosystem.\n\n## Architecture\nPixlet is heavily influenced by the way Tidbyt devices work. The Tidbyt displays tiny 64x32 animations and images. It keeps a local cache of the apps that are installed on it.\n\nEach Tidbyt regularly sends heartbeats to the Tidbyt cloud, announcing what it has cached. The Tidbyt cloud decides which app needs to be rendered next, and executes the appropriate Starlark script. It encodes the result as a [WebP](https://developers.google.com/speed/webp) image, and sends it back to the device.\n\nTo mimic how we host apps internally, `pixlet render` executes the Starlark script and `pixlet push` pushes the resulting WebP to your Tidbyt.\n\n## Config\nWhen running an app, Pixlet passes a `config` object to the app\'s `main()`:\n\n```starlark\ndef main(config):\n    who = config.get("who")\n    print("Hello, %s" % who)\n```\n\nThe `config` object contains values that are useful for your app. You can set the actual values by:\n\n1. Passing URL query parameters when using `pixlet serve`.\n2. Setting command-line arguments via `pixlet render`.\n\nWhen apps are published to the [Tidbyt Community repo][3], users can install and configure them with the Tidbyt smartphone app. [Define a schema for your app][4] to enable this.\n\nYour app should always be able to render, even if a config value isn\'t provided. Provide defaults for every config field, or check if the value is `None`. This will ensure the app behaves as expected even if config was not provided.\n\nFor example, the following ensures there will always be a value for `who`:\n\n```starlark\nDEFAULT_WHO = "world"\n\ndef main(config):\n    who = config.get("who", DEFAULT_WHO)\n    print("Hello, %s" % who)\n```\n\nThe `config` object also has helpers to convert config values into specific types:\n\n```starlark\nconfig.str("foo") # returns a string, or None if not found\nconfig.bool("foo") # returns a boolean (True or False), or None if not found\n```\n\n## Caching\n\nMany apps retrieve data from external services and APIs. It\'s\nimportant both to be mindful of the request rates hitting these\nservices, and of the possibility of bad internet weather causing some\nrequests to fail. Caching plays an important role here.\n\nFor the majority of apps, it\'s sufficient to rely on the built-in\ncache functionality of the HTTP module. Simply pass in `ttl_seconds`\nwhen making a requests, and the HTTP response will be cached\naccordingly. This allows subsequent requests (until the TTL has\nexpired) to be served quickly, without hammering the upstream\nAPI.\n\n## Secrets\n\nMany apps need secret values like API keys. When publishing your app to the [Tidbyt community repo][3], encrypt sensitive values so that only the Tidbyt cloud servers can decrypt them.\n\nTo encrypt values, use the `pixlet encrypt` command. For example:\n\n```shell\n# replace "googletraffic" with the ID of your app (as per your manifest.yaml)\n$ pixlet encrypt googletraffic top_secret_google_api_key_123456\n"AV6+...."  # encrypted value\n```\n\nUse the `secret.decrypt()` function in your app to decrypt this value:\n\n```starlark\nload("secret.star", "secret")\n\ndef main(config):\n    api_key = secret.decrypt("AV6+...") or config.get("dev_api_key")\n```\n\nWhen you run `pixlet` locally, `secret.decrypt` will always return `None`. When your app runs in the Tidbyt cloud, `secret.decrypt` will return the string that you passed to `pixlet encrypt`.\n\n\n## Fail\nThe [`fail()`][1] function will immediately end the execution of your app and return an error. It should be used incredibly sparingly, and only in cases that are _permanent_ failures. \n\nFor example, if your app receives an error from an external API, try these options before `fail()`:\n\n1. Return a cached response.\n2. Display a useful message or fallback data.\n3. [`print()`][2] an error message.\n3. Handle the error in a way that makes sense for your app.\n\n[1]: https://github.com/bazelbuild/starlark/blob/master/spec.md#fail\n[2]: https://github.com/bazelbuild/starlark/blob/master/spec.md#print\n[3]: https://github.com/tidbyt/community\n[4]: ../06_reference/schema.md\n\n## Performance profiling\n\nSome apps may take a long time to render, particularly if they produce a long and complex animation. You can use `pixlet profile` to identify how to optimize the app\'s performance. Most apps will not need this kind of optimization.\n\n```shell\n$ pixlet profile path_to_your_app.star\n```\n\nWhen you profile your app, it will print a list of the functions which consume the most CPU time. Improving these will have the biggest impact on overall run time.'},76200:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="# Fonts in Pixlet\n\nPixlet offers a couple of different fonts for rendering text. Which\none to use depends on the information being presented and the amount\nof space available when rendering. Pixlet's `Text` Widget attempts to\ndraw the font on the baseline, i.e. offset upwards by the font's\ndescent. And if that sentence made no sense to you, read then next\nsection. =)\n\n## Typography and Unicode refresher\n\nOur most important Unicode block is Basic Latin (a.k.a. ASCII). We\nalso need at least the Latin-1 Supplement block (a.k.a. ISO 8859,\n\"Latin-1\") to be able to render symbols like Ñ, Ä and Ö. These matter\na lot when displaying names of people, locations, etc.\n\nThe definitions in this graphic are helpful:\n\n![Typography line terms](img/Typography_Line_Terms.png)\n\nIn addition to these, a glyph's _advance_ is the distance between its\n\"origin point\", i.e. the leftmost point of the baseline, and the\nfollowing glyph.\n\nA _cap height_ of 6 and a _descent_ of 1 is sufficient to fit both\nupper and lower case A-Z, as well as the most common special\ncharacters. From fiddling with fonts a bit, this seems to be the\nminimum.\n\nTo cover Latin-1 Supplement, we need more space. At least one\nadditional pixel in the _ascent_ for characters with diacritics to be\nlegible.\n\n## The fonts\n\nNote that all of these are free or public domain fonts created by\nothers. Attribution is given for each below.\n\n### tb-8\n\n![tb-8 example](img/tb-8.gif)\n\nA modified version of 5x8. This font has variable advance (i.e. it's\nnot mono-spaced) and slightly tweaked glyphs for improved\nlegibility. All digits are monospace with advance 5.\n\nLike 5x8, this covers Basic Latin and Latin-1 Supplement, plus some\nother latin glyphs.\n\nAll digits in tb-8 are monospaced 5x6, so rendering them with a\nbaseline offset of -1 and a height of 6 is perfectly fine and renders\nthe full glyphs without cropping.\n\nCommon numerical symbols ('+', '-', '/', '*', '=', '%', '.') also fit\nin height 6 with offset -1. These are however all variable-width. Note\nthat ',' has descent 1 and won't fit in this case.\n\nCurrency symbols require full height in the general case, but euro\nsign '€' and dollar sign '$' have no descent and fit in 7 pixels.\n\n- Advance: 2-6\n- Height: 8\n- Cap height: 6\n- Ascent: 7\n- Descent: 1\n\n### Dina_r400-6\nBy [Jørgen Ibsen](https://www.dcmembers.com/jibsen/download/61/)\n\n![Dina_r400-6 example](img/Dina_r400-6.gif)\n\nCovers Basic Latin and Latin-1 Supplement, but nothing beyond\nthat. 256 code points.\n\n- Advance: 6\n- Height: 10\n- Cap height: 6\n- Ascent: 8\n- Descent: 2\n\n### 5x8\nBy [Markus Kuhn](http://www.cl.cam.ac.uk/~mgk25/).\n\n![5x8 example](img/5x8.gif)\n\nCovers Basic Latin, Latin-1 Supplement, a ton of other Latin code\nblocks. 1426 code points in total.\n\n- Advance: 5\n- Height: 8\n- Cap height: 6\n- Ascent: 7\n- Descent: 1\n\n### 6x13\nBy [Markus Kuhn](http://www.cl.cam.ac.uk/~mgk25/).\n\n![6x16 example](img/6x13.gif)\n\nCovers Basic Latin, Latin1- Supplement, and a bazillion other glyphs,\nincluding the runic code block. 4121 code points in total.\n\n- Advance: 6\n- Height: 13\n- Cap height: 9\n- Ascent: 11\n- Descent: 2\n\n### 10x20\nBy [Markus Kuhn](http://www.cl.cam.ac.uk/~mgk25/).\n\n![10x20 example](img/10x20.gif)\n\nCovers Basic Latin, Latin1- Supplement, and a bazillion other glyphs,\nincluding the runic code block. 4121 code points in total.\n\n- Advance: 10\n- Height: 20\n- Cap height: 13\n- Ascent: 16\n- Descent: 4\n\n### tom-thumb\nBy [Robey Pointer](https://robey.lag.net/2010/01/23/tiny-monospace-font.html)\n\n![tom-thumb example](img/tom-thumb.gif)\n\nA very tiny, monospace, bitmap font. It's a 4x6 font with 3x5 usable pixels.\nThis font is great for a really tiny font that also supports upper and lower\ncased characters.\n\n- Advance: 4\n- Height: 6\n- Cap height: 4\n- Ascent: 5\n- Descent: 1\n\n### CG-pixel-3x5-mono\nBy [Ilmari Karonen](https://vyznev.net/)\n\n![CG-pixel-3x5-mono example](img/CG-pixel-3x5-mono.gif)\n\nThis font is a true 3x5 font which only occupies 5 pixels on a display. Check\nout the 4x5 version if you have the width to spare.\n\n- Advance: 4\n- Height: 5\n- Cap height: 4\n- Ascent: 5\n- Descent: 0\n\n### CG-pixel-4x5-mono\nBy [Ilmari Karonen](https://vyznev.net/)\n\n![CG-pixel-4x5-mono example](img/CG-pixel-4x5-mono.gif)\n\nThis font is a true 4x5 font which only occupies 5 pixels on a display. Check\nout the 3x5 version if you are also constrained on width.\n\n- Advance: 5\n- Height: 5\n- Cap height: 4\n- Ascent: 5\n- Descent: 0"},61421:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i='# A Clock App\n\nThis applet accepts a `timezone` parameter and produces a two frame\nanimation displaying the current time with a blinking \':\' separator\nbetween the hour and minute components.\n\n```starlark\nload("render.star", "render")\nload("time.star", "time")\n\ndef main(config):\n    timezone = config.get("timezone") or "America/New_York"\n    now = time.now().in_location(timezone)\n\n    return render.Root(\n        delay = 500,\n        child = render.Box(\n            child = render.Animation(\n                children = [\n                    render.Text(\n                        content = now.format("3:04 PM"),\n                        font = "6x13",\n                    ),\n                    render.Text(\n                        content = now.format("3 04 PM"),\n                        font = "6x13",\n                    ),\n                ],\n            ),\n        ),\n    )\n```\n\nHere\'s the resulting image:\n\n![](img/clock.gif)'},8596:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i='# A Crypto Tracker\n\nThis article walks you through how to build a simple Bitcoin tracker\nusing Pixlet. It looks pretty great on a\n[Tidbyt](http://www.tidbyt.com/) display, although we\'re admittedly\nbiased.\n\n## Getting Bitcoin data\n\nTo get closer to a truly useful Pixlet app, we\'ll be pulling in some\nBitcoin data. CoinDesk\'s [Bitcoin Price Index\nAPI](https://www.coindesk.com/coindesk-api) is free to use and\nrequires no authentication. We\'ll use Starlib\'s [http\nmodule](https://github.com/qri-io/starlib/tree/master/http) to\nretrieve the data.\n\nPixlet includes several modules from the\n[Starlib](https://github.com/qri-io/starlib) library. This is sort of\na standard library for Starlark, and it\'s very handy when building\nanything but the simplest app.\n\n```starlark\nload("render.star", "render")\nload("http.star", "http")\n\nCOINDESK_PRICE_URL = "https://api.coindesk.com/v1/bpi/currentprice.json"\n\ndef main():\n    rep = http.get(COINDESK_PRICE_URL)\n    if rep.status_code != 200:\n        fail("Coindesk request failed with status %d", rep.status_code)\n\n    rate = rep.json()["bpi"]["USD"]["rate_float"]\n\n    return render.Root(\n        child = render.Text("BTC: %d USD" % rate)\n    )\n```\n\nIf the HTTP request doesn\'t return the expected status code (200), we\ncall `fail()` to halt execution of the script. Starlark provides a few\nother helpful built-ins that you can read about in the [starlark-go\nlanguage\ndefinition](https://github.com/google/starlark-go/blob/master/doc/spec.md). Another\nbuilt-in worth mentioning is `print()`, which of course is invaluable\nin debugging your Pixlet scripts.\n\n![](img/tutorial_2.gif)\n\nVoilà. A perfectly functional Bitcoin price tracker.\n\n## Adding an icon\n\nTo make our app a bit snazzier, we headed over to\n[Pixilart](https://www.pixilart.com/) and drew this simple Bitcoin\nicon:\n\n![](img/tutorial_btcicon.png)\n\nPixlet allows us to embed graphics in our scripts through the `Image`\nwidget. We\'ll use Starlib\'s `encoding/base64` module to embed the\nimage in our source code. Finally, to display both the price string\nand the icon simultanesouly, we\'ll use the `Row` Widget to have them\nlaid out side by side.\n\n```starlark\nload("render.star", "render")\nload("http.star", "http")\nload("encoding/base64.star", "base64")\n\nCOINDESK_PRICE_URL = "https://api.coindesk.com/v1/bpi/currentprice.json"\n\n# Load Bitcoin icon from base64 encoded data\nBTC_ICON = base64.decode("""\niVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAAAlklEQVQ4T2NkwAH+H2T/jy7FaP+\nTEZtyDEG4Zi0TTPXXzoDF0A1DMQRsADbN6MZdO4NiENwQbAbERh1lWLzMmgFGo5iFZBDYEFwuwG\nsISCPUIKyGgDRjAyBXYXMNIz5XgDQga8TpLboYgux8DO/AwoUuLiEqTLBFMcmxQ7V0gssgklIsL\nAYozjsoBoE45OZi5DRBSnkCAMLhlPBiQGHlAAAAAElFTkSuQmCC\n""")\n\ndef main():\n    rep = http.get(COINDESK_PRICE_URL)\n    if rep.status_code != 200:\n        fail("CoinDesk request failed with status %d", rep.status_code)\n\n    rate = rep.json()["bpi"]["USD"]["rate_float"]\n\n    return render.Root(\n        child = render.Row( # Row lays out its children horizontally\n                children = [\n                    render.Image(src=BTC_ICON),\n                    render.Text("$%d" % rate),\n                ],\n        )\n    )\n```\n\n![](img/tutorial_3.gif)\n\nThis clearly leaves something to be desired as far as layout is\nconcerned, but the individual elements (the icon and the price) aren\'t\ntoo shabby!\n\n## Beautification\n\nBy default, `Row` will pack its children as closely together as it\npossibly can. That\'s often a useful behaviour, but in this case\nperhaps not so much. We can instruct `Row` to use as much horizontal\nspace as possible by passing `expanded=True`, and then use the\n`main_align` and `cross_align` parameters to adjust how the children\nare spaced out. For details on these parameters, check out the full\n[Widget reference](../06_reference/widgets.md).\n\nWe\'ll also place the `Row` itself in a `Box` to ensure that it\'s\nplaced in the vertical center of the screen. `Box` actually centers\nhorizontally as well, but since our `Row` is `expanded` that won\'t\nmatter.\n\n```starlark\nload("render.star", "render")\nload("http.star", "http")\nload("encoding/base64.star", "base64")\n\nCOINDESK_PRICE_URL = "https://api.coindesk.com/v1/bpi/currentprice.json"\n\nBTC_ICON = base64.decode("""\niVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAAAlklEQVQ4T2NkwAH+H2T/jy7FaP+\nTEZtyDEG4Zi0TTPXXzoDF0A1DMQRsADbN6MZdO4NiENwQbAbERh1lWLzMmgFGo5iFZBDYEFwuwG\nsISCPUIKyGgDRjAyBXYXMNIz5XgDQga8TpLboYgux8DO/AwoUuLiEqTLBFMcmxQ7V0gssgklIsL\nAYozjsoBoE45OZi5DRBSnkCAMLhlPBiQGHlAAAAAElFTkSuQmCC\n""")\n\ndef main():\n    rep = http.get(COINDESK_PRICE_URL)\n    if rep.status_code != 200:\n        fail("Coindesk request failed with status %d", rep.status_code)\n\n    rate = rep.json()["bpi"]["USD"]["rate_float"]\n\n    return render.Root(\n        child = render.Box( # This Box exists to provide vertical centering\n            render.Row(\n                expanded=True, # Use as much horizontal space as possible\n                main_align="space_evenly", # Controls horizontal alignment\n                cross_align="center", # Controls vertical alignment\n                children = [\n                    render.Image(src=BTC_ICON),\n                    render.Text("$%d" % rate),\n                ],\n            ),\n        ),\n    )\n```\n\nDont\' worry if all this alignment stuff feels a bit confusing at\nfirst. It\'ll be a lot clearer when you\'ve had a chance to play around\nwith it.\n\n![](img/tutorial_4.gif)\n\nNow that\'s a Bitcoin tracker.\n\n## Caching\n\nFinally, let\'s make sure we\'re not spamming CoinDesk with more\nrequests than what\'s absolutely necessary. The simplest way to do this\nis to rely on the HTTP module\'s built-in cache functionality, by adding\n`ttl_seconds` to the `http.get()` call. This instructs the module to\ncache the response for a given period of time.\n\nA special header will be set on the response to indicate if it was\nserved from cache or straight from the API. While we\'re using it in\nthis example to illustrate the cache behavior, it\'s not something\ndevelopers normally need to care about.\n\n```starlark\nload("render.star", "render")\nload("http.star", "http")\nload("encoding/base64.star", "base64")\n\nCOINDESK_PRICE_URL = "https://api.coindesk.com/v1/bpi/currentprice.json"\n\nBTC_ICON = base64.decode("""\niVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAAAlklEQVQ4T2NkwAH+H2T/jy7FaP+\nTEZtyDEG4Zi0TTPXXzoDF0A1DMQRsADbN6MZdO4NiENwQbAbERh1lWLzMmgFGo5iFZBDYEFwuwG\nsISCPUIKyGgDRjAyBXYXMNIz5XgDQga8TpLboYgux8DO/AwoUuLiEqTLBFMcmxQ7V0gssgklIsL\nAYozjsoBoE45OZi5DRBSnkCAMLhlPBiQGHlAAAAAElFTkSuQmCC\n""")\n\ndef main():\n    rep = http.get(COINDESK_PRICE_URL, ttl_seconds = 240) # cache for 4 minutes\n    if rep.status_code != 200:\n        fail("Coindesk request failed with status %d", rep.status_code)\n    rate = rep.json()["bpi"]["USD"]["rate_float"]\n\n    # for development purposes: check if result was served from cache or not\n    if rep.headers.get("Tidbyt-Cache-Status") == "HIT":\n        print("Hit! Displaying cached data.")\n    else:\n        print("Miss! Calling CoinDesk API.")\n\n    return render.Root(\n        child = render.Box(\n            render.Row(\n                expanded=True,\n                main_align="space_evenly",\n                cross_align="center",\n                children = [\n                    render.Image(src=BTC_ICON),\n                    render.Text("$%d" % rate),\n                ],\n            ),\n        ),\n    )\n```\n\nPixlet\'s in-memory cache only really kicks in when running pixlet in\nits "server mode" (via `pixlet serve <script>`). The resulting WebP\nimages are of course identical to what we saw before, but as we\nrepeately reload our browser (pointed at `http://localhost:8080/`), we\nsee the following output from the `print()` statements:\n\n```console\n$ ./pixlet serve tutorial.star\nlistening on tcp/8080\n[tutorial.star] Miss! Calling CoinDesk API.\n[tutorial.star] Hit! Displaying cached data.\n[tutorial.star] Hit! Displaying cached data.\n```\n\nThat\'s the cache working as intended. We\'re passing `ttl_seconds=240`\nto `http.get()`, so if we were to wait 4 minutes and then reload,\nwe\'d see a cache miss as the old record has expired.\n\n## What\'s next?\n\nTake a look at the guide on [authoring apps](./02_authoring_apps.md), the [Widget reference](../06_reference/widgets.md), and start hacking!\n'},76889:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="# Private Apps\n\nPrivate app hosting is now available for Tidbyt Plus and [Tidbyt for Teams](https://discuss.tidbyt.com/t/introducing-tidbyt-for-teams/5391) subscribers! Creating a new app, tailored to your needs, is quick and easy. While completely hosted in Tidbyt’s cloud, your apps are restricted to yourself, or members of your team. Unlike our community apps, private apps does not require code review from the Tidbyt Team.\n\nTo sign up for Tidbyt Plus, open the Tidbyt app on your phone and navigate to Settings -> Developer and click 'Deploy a Private App'.\n\n![PrivateApps](img/private-apps.png) \n\nPrivate apps will be available to install through the Tidbyt phone app under the \"Your Private Apps\" section. \n\n## Create an app\nTo create an app in the current working directory, run the following:\n\n```\npixlet private create\n```\n\nIf you're not yet subscribed to Tidbyt Plus, you will receive an error message with a link for signing up!\n\nWith Tidbyt for Teams, you can also create an organization-wide app. To find your org ID, check the `Developer` tab on the Tidbyt for Teams portal.\n\n```\npixlet private create --org {{ your_org_id }}\n```\n\n## Deploy your app\n\nMost of the time, if an app works locally, it'll work as a private app. Just run the upload command (in the same directory as the app was created) to deploy:\n\n```\npixlet private upload\n```\n\nFor more fine grained control of individual versions of your app, check out the other private app commands:\n\n```\npixlet private --help\n```\n"},96960:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="# Pushing Apps\n\nLow resolution applications are of course wonderful in their own\nright, but they're even better when you've pushed them to your Tidbyt!\nIn this chapter, we'll cover how to do that (and more) using the\nTidbyt API.\n\n## Pixlet Push\n\nLet's say you've [built](../02_build/15_crypto_tracker.md) a beautiful bitcoin\ntracker located in `examples/bitcoin.star`. You can easily render this\nto a webp image using pixlet:\n\n```\npixlet render examples/bitcoin.star\n```\n\nTo get the resulting webp displayed on your Tidbyt, you need two\npieces of information: your _Device ID_ and your _API Token_. Both of\nthese can be found in the Tidbyt smartphone app under Settings >\nGeneral > Get API Key. The Device ID uniquely identifies your device,\nand the API Token demonstrates that you are authorized to control the\ndevice.\n\n**NOTE*:* Anyone who has access to your API Token will be able to\ncontrol your device, so be careful sharing it!\n\nTo \"push\" the Bitcoin graphic to your Tidbyt, run:\n\n```\npixlet push \"<DEVICE ID>\" examples/bitcoin.webp\n```\n\nRun `pixlet devices` if you don't know the device ID of your device.\nIf all goes well, you should see the Bitcoin tracker appear on your Tidbyt:\n\n![Tidbyt device displaying a Bitcoin tracker](img/tidbyt_2.jpg)\n\nAfter a couple of seconds, your Tidbyt will go back to it's regular\nrotation of apps on display.\n\n## Apps and Installations\n\nTidbyt comes with a ton of apps out of the box, and you've likely\nadded a number of them to your Tidbyt already. Each time an app is\nadded, an _\"installation\"_ object is created. This is essentially a\nrecord in Tidbyt's database saying \"this app is to be run for this\ndevice, using these configuration options\". The device will rotate\nbetween displaying installations one at a time.\n\nWhen pushing a graphic, you can instruct Pixlet to create an\ninstallation for you:\n\n```\npixlet push --installation-id bitcoin \"<DEVICE ID>\" examples/bitcoin.webp\n```\n\nThis means the graphic will enter the regular rotation of apps, and\nbecome visible among them in the Tidbyt iOS/Android app. In the\nscreenshot below, you'll see the pushed bitcoin installation on the\nright hand side.\n\n![A pushed installation alongside a regular installation in the Tidbyt smartphone app.](img/integrate_pushed_installation.png)\n\nKeep in mind though, the graphic associated with the installation will\nonly change if you push a new one. If you really want to stay up to\nspeed on the price of Bitcoin, you'll have to either keep pushing the\ngraphic, or look into [publishing your\napp](../04_publish/02_publishing_apps.md). =)"},81090:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i='# Building Integrations\n\nBehind the scenes, the `pixlet push` command reaches out to Tidbyt\'s\nservers via the Tidbyt API. But pushing graphics isn\'t all the API is\ngood for. For instance, try the following in your terminal (requires\nyou have `curl` installed):\n\n```\ncurl "https://api.tidbyt.com/v0/apps"\n```\n\nYou should see a long list of all the available Tidbyt apps. It\'ll\nlook something like this:\n\n```\n{\n  "apps": [\n    {\n      "id": "nationaltoday",\n      "name": "NationalToday",\n      "description": "Displays today\'s holidays from NationalToday."\n    },\n    {\n      "id": "date-progress",\n      "name": "Date Progress",\n      "description": "Shows todays date as colorful progressbars, you can show the progress of the current day, month and year."\n    },\n...\n```\n\nThere are several endpoints available in the API, and you can read\nabout them all in the [API Reference](api). Most of them require passing\nin an API Token, so here\'s an example of how that works.\n\n```\ncurl -H "Authorization: Bearer <API Token HERE>" https://api.tidbyt.com/v0/devices/<Device ID HERE>\n```\n\nIn return, you should get a json object with information about your device. It\'ll look something like this:\n\n```\n{\n  "id": "<Device ID>",\n  "displayName": "My Tidbyt",\n  "brightness": 20,\n  "autoDim": false\n}\n```\n\nThe key component of that command line is the `-H` flag. Make sure to\ninclude it when performing requests to endpoints that require\nauthentication!\n\nThat\'s pretty much all there\'s too it. Now go forth and build a thing!\n'},78608:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="# Zapier Quickstart\nTidbyt has a Zapier integration in Public Beta 🎉. This quickstart guide will \nget you up and running in a few minutes. If you have any feedback for the\nprocess or our integration, let us know in\n[the comments on Discuss](https://discuss.tidbyt.com/t/zapier-integration/50/15).\n\n**Disclaimer**: We are offering this a Beta feature right now, it’s available\nand free for anyone to use. Availability of this feature might change in the\nfuture as we learn more about how it performs and how it’s being used.\n\n## Setup\nTo get started, add Zapier to your Tidbyt using the Tidbyt mobile app. Don't\nworry about setting any of the values, Zapier will take care of that in a later\nstep.\n\n![zapier starlark](img/zapier_starlark.jpg)\n\n## Create a Zap\nOnce the Zapier app has been setup on your Tidbyt, head over to\n[Zapier](https://zapier.com)'s website and create a new Zap. Select a trigger of\nyour choice, for this quickstart, we'll use Slack with the `New Mention` event\ntype.\n\n![zapier slack](img/zapier_slack.png)\n\nOnce your trigger test has succeeded, add the Tidbyt action and select the\n`Send Notification` event type. This event will push updates to the Zapier app\non your Tidbyt with details about you latest Slack mention.\n\n![zapier send notification](img/zapier_send_notification.png)\n\nLogin to your Tidbyt account and continue to setup your notification action.\nSelect your Tidbyt from the dropdown and the Zapier installation you installed\non your Tidbyt during the Setup step above.\n\n![zapier action setup](img/zapier_action_setup.png)\n\nOnce selected, populate the Heading, Subheading, and Body text for your\nnotification. These fields will appear on your Tidbyt as following:\n\n![zapier](img/zapier01.gif)\n\nUnder notification type, select Slack to use the Slack logo and\ncolor scheme on your Tidbyt. It will now display like so:\n\n![zapier slack](img/zapier02.gif)\n\nWe found these options to work nicely for slack:\n![zapier notification options](img/zapier_notification_options.png)\n\nOnce configured, test your action and take a look at your Tidbyt! If all goes\nwell, you should see your latest Slack message appear on your Tidbyt 😎.\n![zapier test action](img/zapier_test_action.png)\n\nTo wrap up, publish your action so that any new Slack mention will update the\nZapier app on your Tidbyt with the latest mention.\n\n![zapier publish](img/zapier_publish.png)\n\n\n## Feedback Wanted\nHave any feedback for us? Let us know in\n[the comments on Discuss](https://discuss.tidbyt.com/t/zapier-integration/50/15)\nso we can improve on our Zapier integration."},89014:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="# Community Apps\n\nDid you know that the vast majority of Tidbyt apps are contributed by\nother users and community members? When you browse the Tidbyt\niOS/Android app for new content to add to your Tidbyt, you'll notice\nthat plenty of them have an attribution given like in the example\nbelow. These are all community contributed apps.\n\n![A community contributed app as seen in Tidbyt's Android app](img/publish_attribution_phase_pf_moon.png)\n\n\n## How to contribute\n\nThe community apps can be found in our public github repository over\nat\n[github.com/tidbyt/community/](https://github.com/tidbyt/community/). It's\nall Free and Open Source Software, so you're welcome to borrow ideas,\ncode and design from other apps as you see fit. The community repo is\na great place to learn more about how to write code for your own\nTidbyt.\n\nShould you decide to share what you've developed - and we certainly\nencourage you to - then the community repo is where it happens.\n\n### The process\n\nTo get a new app published, you need to submit a Pull Request for it\nto be merged into the main branch of the community repo. This requires\nsome reviewing from Tidbyt employees (and often other community\ndevelopers) to make sure it's up to snuff.\n\nOnce a new app is merged, it will be publicly available to everyone via search.\nTidbyt employees will manually categorize apps on the explore page. Which apps\nmake it into the explore page is an editorial decision by our team. We do take\nsuggestions, though ultimately how we editorialize apps is up to the discretion\nof the Tidbyt team.\n\nFor the nitty gritty on how to get a new app published, check out\n[Publishing Apps](./02_publishing_apps.md)\n\n### How to pass a review\n\nDuring PR reviews, we'll be looking to make sure that the app is\nworking as intended, doesn't cause any harm and is at least somewhat\nuseful. But don't worry too much about the useful part; we've plenty\nof room for fun and silly apps too!\n\nApps added to this repo will be available to everyone. We love niche\nuse cases and encourage them. But if the app is only for you, the\nauthor, then we likely will not be able to support it. Your app\ndoesn't have to be popular, but there in theory should be more users\nthan just you.\n\nHere's what we're usually looking for when reviewing a PR:\n\n- Does the app work as intended?\n- Can we expect the app to work reliably over time?\n- Is the app handling user data responsibly?\n- Is the app caching in an appropriate manner?\n- If an external API is being used, is the app taking care to keep\n  request rates at a reasonable level?\n\nAnd of course, it goes without saying that we're not going to merge\nhateful, mean-spirited or otherwise inappropriate content.\n\n## Supporting your app\n\nAt the end of the day, Tidbyt employees will be the ones who will have\nto resolve production issues and respond to support emails. This means\na few things:\n\nApps need to use a stable API:\n- An API hosted on your home network simply won't do\n- Any failures will surface in our monitoring tools and alert our oncalls\n\nApps published should be stable:\n- If there are bugs, we will make changes quickly and will likely not wait for your review\n- If they are unresolvable, we may have to pull the app from our inventory until we get ahold of you\n\nWe want you, the contributor, to own the product direction of the apps\nyou contribute. If others want to contribute features or\nmodifications, we encourage it! However, we will want your input on\nthe pull request and will wait a week or so to hear back from you\nbefore we merge the change. If you're MIA and there is strong interest\nin the change, we will merge it and won't wait up on you forever. See\nmodifying apps for more.\n"},13577:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="# Publishing Apps\nSo pumped you're here and want to publish an app! If you haven't done so already, check out our [code of conduct](../05_engage/02_code_of_conduct.md) and the overview on [community apps](./01_community_apps.md) to get a better sense of what you're getting yourself into. You'll also want to check out the guide on [authoring apps](../02_build/05_authoring_apps.md) to get a better sense of how everything works together.\n\nOne final note before we hop in - you may want to check out the [schema docs](../06_reference/schema.md) if you haven't already. Schema allows you to display options inside of the Tidbyt mobile app so the user can configure your starlark applet.\n\n## Quick Start\nFork and clone the [Tidbyt community repo](https://github.com/tidbyt/community) to your local machine, and then run the following from the local folder to generate everything you need!\n```\npixlet create\n```\n\n> Note: the codegen tool is a bit picky. This is because these strings show up in the Tidbyt mobile app and we want to ensure the UX works as expected.\n\nOnce created, edit `apps/{{appname}}/{{app_name}}.star` with your source code.\n\nWhen you're ready to publish, run the following to ensure your app is ready:\n```\npixlet check apps/{{appname}}/{{app_name}}.star\n```\n\n## Detailed Instructions\n\n### 1. Fork the Tibyt Community repo on Github\n\n- Community apps are published by making a Pull Request to the community repo here: https://github.com/tidbyt/community\n- Start by forking the repo into your Github account.\n- After forking you may want to checkout to a new branch to avoid any headaches, and to not have to merge off the main branch of your forked repo.\n\n### 2. Clone the community repo to your local machine\n\n### 3. Create your app\n\n- Run `pixlet create` via the terminal\n\nThis should be run from the 'community' repo folder on your local machine.\nYou will be prompted for the relevant information about your app and the required files and folders will be generated.\n\n```\n$ pixlet create\nName (what do you want to call your app?): Tides\nSummary (what's the short and sweet of what this app does?): Tide charts\nDescription (what's the long form of what this app does?): Daily tide charts for your location.\nAuthor (your name or your Github handle): Mark Spicer\n```\n\nPlease note:\n- **Name:** The App Name can contain spaces but should not have any numbers\n- **Summary:** This should be a VERY brief summary of what the app does. (27 characters or less!)\n- **Description:** This is a longer description of what the app does.\n\n#### Example App\nIn this example, the fields map as follows:\n- **Name**: Fuzzy Clock\n- **Summary**: Human readable time\n- **Description**: Display the time in a groovy, human-readable way.\n- **Author**: Max Timkovich\n\n![example](img/example.png)\n\n![details](img/example_details.png)\n\n\n #### Run your App\n\n Preview your App in your browser at http://localhost:8080/ by running:\n\n```\npixlet serve apps/{{appname}}/{{app_name}}.star\n```\n\n#### Generate a Screenshot\n\nYou can generate an enlarged screen render by entering:\n\n```\npixlet render apps/{{appname}}/{{app_name}}.star --gif --magnify 10\n```\n\n### 4. Making a PR\n\nBefore submitting your app, run `pixlet check apps/{{appname}}/{{app_name}}.star` to check your code for errors.\n\nWhen you go to make a PR, give us a little background on what your app does. In addition, include a render from the following command so we can ooh-ahh 😍:\n```\npixlet render apps/{{appname}}/{{app_name}}.star --gif --magnify 10\n```\n\n\n\n\n\n\n"},14081:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="# Modifying Apps\nHave a feature you want in an existing app? Want to change the way an existing app works? This guide is for you! There're two things you should know:\n- We believe that code speaks\n    - This means we will prioritize a pull request over a feature request.\n- Original contributors own the product direction\n    - The original contributor's name is on the app, so we'll want their feedback before we merge the change.\n\nSo what does this all mean? If you want to modify or extend an existing app, make a pull request! We'll ask the original author to take a look and get their feedback before we merge it."},43623:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="# Advanced features\n\nTo write really great apps, it's helpful to understand how Tidbyt\ndevices function, and how they interact with the backend (where\ncommunity apps run.) There are a few advanced features that can\ninfluence certain aspects of these interactions, which we'll cover\nhere.\n\n## Device-side caching\n\nTidbyt devices maintain a cache of the most recently received graphic\nfor each of its installed apps. This serves several purposes. First of\nall, it allows the device to continue to display graphics during\nintermittent network failures, including when the device is forced to\nreconnect to the backend. Second, it eliminates the need to re-ship\ngraphics that have already reached the device, reducing network\nusage.\n\nThis mode of operation does come with a significant drawback: if new\ngraphics are unable to reach a device, the device will continue to\ndisplay older graphics even when these are out of date. An\nillustrative example of this being problematic is the clock app. If\nsome sort of glitch is preventing up-to-date graphics to reach a\ndevice, the clock will effectively be running behind.\n\nTo counter this, Tidbyt apps can optionally specify a `max_age` on\ntheir `Root` widget. When present, this field instructs Tidbyt devices\nto discard the graphic when a certain amount of time has\npassed. During normal operation, the backend will ship out replacement\ngraphics before this happens, but when that fails it is in some cases\nbetter to display nothing at all, than to display stale data that the\nuser will assume is correct.\n\n## App cycle speed\n**Note:** `show_full_animation` only works when the app is deployed to Tidbyts servers.\nPlease see [Publishing Apps](../04_publish/02_publishing_apps.md) or\n[Private App Hosting](../02_build/16_private_apps.md).\n\nMost users have multiple apps installed on their Tidbyts. By default,\neach will be displayed for about 15 seconds, although this _app cycle\nspeed_ is user configurable. For apps that generate static, single\nframe graphics, this is straightforward: the graphic is displayed for\nexactly as long as the user has requestd. For apps that generate\nanimations, things get a little bit more tricky.\n\nIf an animation fits within the allotted time window, it will be\ndisplayed as many times as possible, without truncating the\nanimation. For instance, if an animation is 7 seconds long, and the\napp cycle speed allows for 15 seconds per app, then the animation will\nbe displayed twice for a total of 14 seconds. While a single second\nremains of the time window, using it to display a small piece of the\nanimation a third time will typically result in a jarring experience\nfor the user. We don't want that.\n\nIf an animation exceeds the time window, it will be truncated to\nfit. This gives the user a predictable experience, where they know\nroughly how long it'll take for the next app to appear. It also\nprevents buggy apps from unintentially hijacking the display for long\nperiods of time. In some cases, however, this behavior is not ideal.\n\nFor instance, an app that displays quotes isn't all that useful if the\nquotes get truncated halfway through. While one can argue that shorter\nquotes should be used, that isn't always a reasonable solution. For\nsuch cases, the `show_full_animation` field on the `Root` object can\nbe used to request that the device's app cycle speed is ignored, and\nthat the animation is shown in full. If the user is bothered by the\nlonger-than-normal app duration, they'll simply have to uninstall the\napp.\n\nIt can be tempting to throw this setting on all sorts of apps, but we\nwould encourage developers to use some restraint. If the app can be\nredesigned to fit all its data in a shorter animation, then that may\nbe preferable. If not, then `show_full_animation` may be the way to\ngo.\n"},51966:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="# Frequently Asked Questions\n\n## Why is the formatter so opinionated?\nWe know the linter can be annoying. First off, we're sorry it's annoying! But it's in place for good reasons. On the technical front, Starlark is a language with syntactically significant whitespace. That means if the indentation is incorrect, it could change the meaning of your code 🙀. On the practical side, Tidbyt engineers often need to make minor modifications to apps in the Community repo. Our editors format Starlark automatically on save using the [Bazel plugin](https://marketplace.visualstudio.com/items?itemName=BazelBuild.vscode-bazel) for VSCode, which means one small change could auto format your entire app and look like a much bigger change!\n\nThe good news is you can fix formatting errors automatically! To automatically fix format issues, run the following:\n```\npixlet format\n```\n\n## When will my app be available in the Tidbyt mobile app?\nWhen new apps are merged in the community repo, it gets released to all users immediately using a [CI process](https://github.com/tidbyt/community/actions/workflows/main.yml). New apps get announced using the #new-apps channel on Discord.\n\nIf you're not sure where your app is in the release process, feel free to ping `@TIDBYT` on Discord!"},36578:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="# Community\nWelcome to the Tidbyt community! Join other Tidbyt developers on [Discord](https://discord.gg/r45MXG4kZc) and [Discuss](https://discuss.tidbyt.com/c/developers/8). \n\n## Discord\nNeed help installing Pixlet? Have a question about how a widget works? Ask in the `#developers` channel on [Discord](https://discord.gg/r45MXG4kZc). If you've never used Discord, have no fear! It's a instant messaging platform - so if you've used Slack or Facebook Messenger, you should feel right at home.\n![](img/discord.png)\n\n\n## Discuss\nGot a feature request? Want to make an announcement? Head over to [Discuss](https://discuss.tidbyt.com/c/developers/8) to start the conversation. Discuss is a forum where users can make posts and comment on existing posts. \n![](img/discuss.png)\n"},54870:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, religion, or sexual identity\nand orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n* Demonstrating empathy and kindness toward other people\n* Being respectful of differing opinions, viewpoints, and experiences\n* Giving and gracefully accepting constructive feedback\n* Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n* Focusing on what is best not just for us as individuals, but for the\n  overall community\n\nExamples of unacceptable behavior include:\n\n* The use of sexualized language or imagery, and sexual attention or\n  advances of any kind\n* Trolling, insulting or derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or email\n  address, without their explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\ncommunity@tidbyt.com.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series\nof actions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or\npermanent ban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior,  harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within\nthe community.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.0, available at\nhttps://www.contributor-covenant.org/version/2/0/code_of_conduct.html.\n\nCommunity Impact Guidelines were inspired by [Mozilla's code of conduct\nenforcement ladder](https://github.com/mozilla/diversity).\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see the FAQ at\nhttps://www.contributor-covenant.org/faq. Translations are available at\nhttps://www.contributor-covenant.org/translations."},66706:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i='\x3c!-- Docs generated by runtime/gen. DO NOT EDIT. --\x3e\n\n# Animations!\n\nPixlet supports a few animation primitives. These are used to animate\nwidgets from frame to frame.\n\nAll animations allow specifying an easing curve. This can either be one\nof the built-in "linear", "ease_in", "ease_out" or "ease_in_out" curves,\na custom cubic bézier curve in the form "cubic-bezier(a, b, c, d)" or a\ncustom easing function.\n\n**Warning**: The animation module is in a state of flux. Especially\n`Transformation` and related classes are likely to change in the near\nterm. Please be on the lookout for bugs, issues and potential\nimprovements!\n\n\n## AnimatedPositioned\nAnimate a widget from start to end coordinates.\n\n**DEPRECATED**: Please use `animation.Transformation` instead.\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `child` | `Widget` | Widget to animate | **Y** |\n| `duration` | `int` | Duration of animation in frames | **Y** |\n| `curve` | `str / function` | Easing curve to use, default is \'linear\' | **Y** |\n| `x_start` | `int` | Horizontal start coordinate | N |\n| `x_end` | `int` | Horizontal end coordinate | N |\n| `y_start` | `int` | Vertical start coordinate | N |\n| `y_end` | `int` | Vertical end coordinate | N |\n| `delay` | `int` | Delay before animation in frames | N |\n| `hold` | `int` | Delay after animation in frames | N |\n\n\n\n## Keyframe\nA keyframe defining specific point in time in the animation.\n\nThe keyframe _percentage_ can is expressed as a floating point value between `0.0` and `1.0`.\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `percentage` | `float` | Percentage of the time at which this keyframe occurs through the animation. | **Y** |\n| `transforms` | `[Transform]` | List of transforms at this keyframe to interpolate to or from. | **Y** |\n| `curve` | `str / function` | Easing curve to use, default is \'linear\' | N |\n\n\n\n## Origin\nAn relative anchor point to use for scaling and rotation transforms.\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `x` | `float` | Horizontal anchor point | **Y** |\n| `y` | `float` | Vertical anchor point | **Y** |\n\n\n\n## Rotate\nTransform by rotating by a given angle in degrees.\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `angle` | `float / int` | Angle to rotate by in degrees | **Y** |\n\n\n\n## Scale\nTransform by scaling by a given factor.\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `x` | `float / int` | Horizontal scale factor | **Y** |\n| `y` | `float / int` | Vertical scale factor | **Y** |\n\n\n\n## Transformation\nTransformation makes it possible to animate a child widget by\ntransitioning between transforms which are applied to the child wiget.\n\nIt supports animating translation, scale and rotation of its child.\n\nIf you have used CSS transforms and animations before, some of the\nfollowing concepts will be familiar to you.\n\nKeyframes define a list of transforms to apply at a specific point in\ntime, which is given as a percentage of the total animation duration.\n\nA keyframe is created via `animation.Keyframe(percentage, transforms, curve)`.\n\nThe `percentage` specifies its point in time and can be expressed as\na floating point number in the range `0.0` to `1.0`.\n\nIn case a keyframe at percentage 0% or 100% is missing, a default\nkeyframe without transforms and with a "linear" easing curve is inserted.\n\nAs the animation progresses, transforms defined by the previous and\nnext keyframe will be interpolated to determine the transform to apply\nat the current frame.\n\nThe `duration` and `delay` of the animation are expressed as a number\nof frames.\n\nBy default a transform `origin` of `animation.Origin(0.5, 0.5)` is used,\nwhich defines the anchor point for scaling and rotation to be exactly the\ncenter of the child widget. A different `origin` can be specified by\nproviding a custom `animation.Origin`.\n\nThe animation `direction` defaults to `normal`, playing the animation\nforwards. Other possible values are `reverse` to play it backwards,\n`alternate` to play it forwards, then backwards or `alternate-reverse`\nto play it backwards, then forwards.\n\nThe animation `fill_mode` defaults to `forwards`, and controls which\ntransforms will be applied to the child widget after the animation\nfinishes. A value of `forwards` will retain the transforms of the last\nkeyframe, while a value of `backwards` will rever to the transforms\nof the first keyframe.\n\nWhen translating the child widget on the X- or Y-axis, it often is\ndesireable to round to even integers, which can be controlled via\n`rounding`, which defaults to `round`. Possible values are `round` to\nround to the nearest integer, `floor` to round down, `ceil` to round\nup or `none` to not perform any rounding. Rounding only is applied for\ntranslation transforms, but not to scaling or rotation transforms.\n\nIf `wait_for_child` is set to `True`, the animation will finish and\nthen wait for all child frames to play before restarting. If it is set\nto `False`, it will not wait.\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `child` | `Widget` | Widget to animate | **Y** |\n| `keyframes` | `[Keyframe]` | List of animation keyframes | **Y** |\n| `duration` | `int` | Duration of animation (in frames) | **Y** |\n| `delay` | `int` | Duration to wait before animation (in frames) | N |\n| `width` | `int` | Width of the animation canvas | N |\n| `height` | `int` | Height of the animation canvas | N |\n| `origin` | `Origin` | Origin for transforms, default is \'50%, 50%\' | N |\n| `direction` | `str` | Direction of the animation, default is \'normal\' | N |\n| `fill_mode` | `str` | Fill mode of the animation, default is \'forwards\' | N |\n| `rounding` | `str` | Rounding to use for interpolated translation coordinates (not used for scale and rotate), default is \'round\' | N |\n| `wait_for_child` | `bool` | Wait for all child frames to play after finishing | N |\n\n#### Example\n```\nanimation.Transformation(\n  child = render.Box(render.Circle(diameter = 6, color = "#0f0")),\n  duration = 100,\n  delay = 0,\n  origin = animation.Origin(0.5, 0.5),\n  direction = "alternate",\n  fill_mode = "forwards",\n  keyframes = [\n    animation.Keyframe(\n      percentage = 0.0,\n      transforms = [animation.Rotate(0), animation.Translate(-10, 0), animation.Rotate(0)],\n      curve = "ease_in_out",\n    ),\n    animation.Keyframe(\n      percentage = 1.0,\n      transforms = [animation.Rotate(360), animation.Translate(-10, 0), animation.Rotate(-360)],\n    ),\n  ],\n),\n```\n![](img/widget_Transformation_0.gif)\n\n\n## Translate\nTransform by translating by a given offset.\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `x` | `float / int` | Horizontal offset | **Y** |\n| `y` | `float / int` | Vertical offset | **Y** |\n\n\n\n'},76481:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="# Creating GIFs for Tidbyt\n\nBy using Pixlet's [image widget](./widgets.md), images and GIFs can easily be displayed on pixel constrained displays. \n\nHowever, when creating GIFs for use on Tidbyt, there are a few requirements to keep in mind for the best result.\n\n## Design GIFs to be 64x32 pixels from the start\nTidbyt's display is 64x32 pixels. If there is a GIF that’s larger than 64x32 pixels, it has to be scaled down. In practice, we’ve found that images scaled down to this resolution don’t look as crisp as when images are designed for 64x32 from the beginning. So if you’re creating GIFs for the Tidbyt, make sure they’re 64x32.\n\n## Finished GIF is 128KB or less\nWe’re limited by the number of bytes we can send to the Tidbyt and the Tidbyt is constrained by how many bytes it can store locally. To get around this, we limit the size of the GIF to 128 Kilobytes and if it’s larger than this after downsizing to 64x32 pixels, we drop frames until it fits the size requirements. This means if you want your GIF to look great on the Tidbyt, make sure it’s 128KB or less before adding it through the mobile app or with Pixlet.\n\n## GIF is 15 seconds in length or loops cleanly if less then 15 seconds.\nThe length of time the GIF loops should be around 15 seconds. The timings for applet cycles are 15, 10, 7.5, and 5 seconds depending on the setting in the mobile app. If your GIF is less then 15 seconds, ensure it loops cleanly to avoid an interrupt."},33573:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i='# Module reference\n\nPixlet scripts have access to a couple of modules that can be very\nhelpful in developing applets. To make use of a module, use the `load`\nstatement.\n\nThe example below would load the `render.star` Starlark module,\nextract the `render` identifier and make it available to the script\nas the symbol `render`.\n\n```starlark\nload("render.star", "render")\n```\n\nIt\'s also possible to assign the identifiers to a different symbol. In\nthis example, the `render` module is made available to the script as\nthe symbol `r` instead of `render`:\n\n```starlark\nload("render.star", r = "render")\n```\n\n## Starlib modules\n\nPixlet offers a subset of the modules provided by the [Starlib\nproject](https://github.com/qri-io/starlib). For documentation of the\nindividual modules, please refer to the Starlib documentation.\n\n| Module | Description |\n| --- | --- |\n| [`bsoup.star`](https://github.com/qri-io/starlib/blob/master/bsoup) | Beautiful Soup-like functions for HTML |\n| [`compress/gzip.star`](https://github.com/qri-io/starlib/blob/master/compress/gzip) | gzip decompressing |\n| [`compress/zipfile.star`](https://github.com/qri-io/starlib/blob/master/zipfile) | zip decompressing |\n| [`encoding/base64.star`](https://github.com/qri-io/starlib/tree/master/encoding/base64) | Base 64 encoding and decoding |\n| [`encoding/csv.star`](https://github.com/qri-io/starlib/tree/master/encoding/csv) | CSV decoding |\n| [`encoding/json.star`](https://github.com/qri-io/starlib/tree/master/encoding/json) | JSON encoding and decoding |\n| [`hash.star`](https://github.com/qri-io/starlib/tree/master/hash) | MD5, SHA1, SHA256 hash generation  |\n| [`html.star`](https://github.com/qri-io/starlib/tree/master/html) | jQuery-like functions for HTML  |\n| [`math.star`](https://github.com/qri-io/starlib/tree/master/math) | Mathematical functions and constants |\n| [`re.star`](https://github.com/qri-io/starlib/tree/master/re) | Regular expressions |\n| [`time.star`](https://github.com/qri-io/starlib/tree/master/time) | Time operations |\n\n## Starlib HTTP\n\nPixlet also includes a version of the Starlib HTTP module, which has\nbeen modified to handle caching. It\'s very important to keep outgoing\nrequest rates at reasonable levels, and for this reason the HTTP\nclient has been extended to accept a parameter `ttl_seconds` to\ncontrol for how long HTTP responses should be cached.\n\n| Module | Description |\n| --- | --- |\n| [`http.star`](https://github.com/qri-io/starlib/tree/master/http) | HTTP client _with caching_ |\n\nExample:\n\n```starlark\nload("http.star", "http")\ndef get_data(url):\n    res = http.get(url, ttl_seconds=3600) # cache for 1 hour\n    if res.status_code != 200:\n        fail("GET %s failed with status %d: %s", url, res.status_code, res.body())\n    return res.json()\n```\n\n## Pixlet module: Cache\n\nIn addition to the Starlib modules, Pixlet offers a cache\nmodule. Since the HTTP module comes with caching built-in, 95% of apps\nwon\'t need the cache module, but it\'s there for those that do.\n\n| Function | Description |\n| --- | --- |\n| `set(key, value, ttl_seconds=60)` | Writes a key-value pair to the cache, with expiration as a TTL. |\n| `get(key)` | Retrieves a value by its key. Returns `None` if `key` doesn\'t exist or has expired. |\n\nKeys and values must all be string. Serialization of non-string data\nis the developer\'s responsibility.\n\n**NOTE*:* The cache is unique _per app_ and not _per installation_. All installations of your app will share the same cache. This is a common source of bugs!\n\nExample:\n\n```starlark\nload("cache.star", "cache")\ndef get_counter():\n    i = cache.get("counter")\n    if i == None:\n        i = 0\n    cache.set("counter", str(i + 1), ttl_seconds=3600)\n    return i + 1\n...\n```\n\n## Pixlet module: HMAC\n\nThis module implements the HMAC algorithm as described by [RFC 2104](https://datatracker.ietf.org/doc/html/rfc2104.html).\n\n| Function | Description |\n| --- | --- |\n| `md5(key, string)` | Returns md5 hash of a string using the provided key |\n| `sha1(key, string)` | Returns sha1 hash of a string using the provided key |\n| `sha256(key, string)` | Returns sha256 hash of a string using the provided key |\n\nExample:\n\n```starlark\nload("hmac.star", "hmac")\n\nsum = hmac.md5("secret", "hello world!")\nprint(sum)\n# Output: 0a0461e10e89506d7c31a145663bed93\n```\n\n## Pixlet module: Humanize\n\nThe `humanize` module has formatters for units to human friendly sizes. \n\n| Function | Description |\n| --- | --- |\n| `time(date)` | Lets you take a `time.Time` and spit it out in relative terms. For example, `12 seconds ago` or `3 days from now`. |\n| `relative_time(date1, date2, label1?, label2?)` | Formats a time into a relative string. It takes two `time.Time`s and two labels. In addition to the generic time delta string (e.g. 5 minutes), the labels are used applied so that the label corresponding to the smaller time is applied. |\n| `time_format(format, date?)` | Takes a [Java SimpleDateFormat](https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html) and returns a [Go layout string](https://programming.guide/go/format-parse-string-time-date-example.html). If you pass it a `date`, it will apply the format using the converted layout string and return the formatted date. |\n| `day_of_week(date)` | Returns an integer corresponding to the day of the week, where 0 = Sunday, 6 = Saturday. |\n| `bytes(size, iec?)` | Lets you take numbers like `82854982` and convert them to useful strings like, `83 MB`. You can optionally format using IEC sizes like, `83 MiB`. |\n| `parse_bytes(formatted_size)` | Lets you take strings like `83 MB` and convert them to the number of bytes it represents like, `82854982`. |\n| `comma(num)` | Lets you take numbers like `123456` or `123456.78` and convert them to comma-separated numbers like `123,456` or `123,456.78`. |\n| `float(format, num)` | Returns a formatted number as string with options. Examples: given n = 12345.6789:  `#,###.##` => `12,345.67`, `#,###.` => `12,345`|\n| `int(format, num)` | Returns a formatted number as string with options. Examples: given n = 12345: `#,###.` => `12,345`|\n| `ordinal(num)` | Lets you take numbers like `1` or `2` and convert them to a rank/ordinal format strings like, `1st` or `2nd`. |\n| `ftoa(num, digits?)` | Converts a float to a string with no trailing zeros. |\n| `plural(quantity, singular, plural?)` | Formats an integer and a string into a single pluralized string. The simple English rules of regular pluralization will be used if the plural form is an empty string (i.e. not explicitly given).. |\n| `plural_word(quantity, singular, plural?)` | Builds the plural form of an English word. The simple English rules of regular pluralization will be used if the plural form is an empty string (i.e. not explicitly given). |\n| `word_series(words, conjunction)` | Converts a list of words into a word series in English. It returns a string containing all the given words separated by commas, the coordinating conjunction, and a serial comma, as appropriate. |\n| `oxford_word_series(words, conjunction)` | Converts a list of words into a word series in English, using an [Oxford comma](https://en.wikipedia.org/wiki/Serial_comma). It returns a string containing all the given words separated by commas, the coordinating conjunction, and a serial comma, as appropriate. |\n| `url_encode(str)` | Escapes the string so it can be safely placed inside a URL query. |\n| `url_decode(str)` | The inverse of `url_encode`. Converts each 3-byte encoded substring of the form "%AB" into the hex-decoded byte 0xAB |\n\nExample:\n\nSee [examples/humanize.star](https://github.com/tidbyt/pixlet/blob/dc0f876089bb44a28653eba46e8182805944b782/examples/humanize.star) for an example.\n\n## Pixlet module: XPath\n\nThe xpath module lets you extract data from XML documents using\n[XPath](https://en.wikipedia.org/wiki/XPath) queries.\n\n| Function | Description |\n| --- | --- |\n| `loads(doc)` | Parses an XML document and returns an xpath object|\n\nOn an xpath object, the following methods are available:\n\n| Method | Description |\n| --- | --- |\n| `query(path)` | Retrieves text of the first tag matching the path |\n| `query_all(path)` | Retrieves text of all tags matching the path |\n| `query_node(path)` | Retrieves the first tag matching the path as an xpath object |\n| `query_all_nodes(path)` | Retrieves all tags matching the path as xpath objects |\n\nThe `query_node` and `query_all_nodes` methods allow you to recursively query the XML document, which can be useful if you need to query several tags that are nested underneath some parent tag.\n\nExample:\n\n```starlark\nload("xpath.star", "xpath")\n\ndoc = """\n<foo>\n    <bar>bar</bar>\n    <bar>baz</bar>\n</foo>\n"""\n\ndef get_bars():\n    x = xpath.loads(doc)\n    return x.query_all("/foo/bar")\n\ndef also_get_bars():\n    x = xpath.loads(doc)\n    foo = x.query_node("/foo")\n    return foo.query_all("/bar")\n...\n```\n\n\n## Pixlet module: Render\n\nThe `render.star` module is where Pixlet\'s Widgets live. All of them\nare documented in a fair bit of detail in the [widget\ndocumentation](./widgets.md).\n\nExample:\n\n```starlark\nload("render.star", r="render")\ndef main():\n    return r.Root(child=r.Box(width=12, height=14, color="#ff0"))\n```\n\n## Pixlet module: Schema\n\nThe schema module provides configuration options for your app. See the [schema documentation](./schema.md) for more details.\n\nExample:\n\nSee [examples/schema_hello_world.star](https://github.com/tidbyt/pixlet/blob/dc0f876089bb44a28653eba46e8182805944b782/examples/schema_hello_world.star) for an example.\n\n## Pixlet module: Secret\n\nThe secret module can decrypt values that were encrypted with `pixlet encrypt`.\n\n| Function | Description |\n| --- | --- |\n| `decrypt(value)` | Decrypts and returns the value when running in Tidbyt cloud. Returns `None` when running locally. Decryption will fail if the ID of the app doesn\'t match the ID that was passed to `pixlet encrypt`.  |\n\nExample:\n```starlark\nload("secret.star", "secret")\n\nENCRYPTED_API_KEY = "AV6+..." . # from `pixlet encyrpt`\n\ndef main(config):\n    api_key = secret.decrypt(ENCRYPTED_API_KEY) or config.get("dev_api_key")\n```\n\n## Pixlet module: Sunrise\n\nThe `sunrise` module calculates sunrise and sunset times for a given set of GPS coordinates and timestamp. \n\n| Function | Description |\n| --- | --- |\n| `sunrise(lat, lng, date)` | Calculates the sunrise time for a given location and date. |\n| `sunset(lat, lng, date)` | Calculates the sunset time for a given location and date. |\n| `elevation(lat, lng, time)` | Calculates the elevation of the sun above the horizon for a given location and point in time. |\n| `elevation_time(lat, lng, elev, date)` | Calculates the two times at which the sun was at the given elevation above the horizon for a given location and date. Returns None if the sun never reached the given elevation. |\n\nExample:\n\nSee [examples/sunrise.star](https://github.com/tidbyt/pixlet/blob/dc0f876089bb44a28653eba46e8182805944b782/examples/sunrise.star) for an example.\n\n## Pixlet module: Random\n\nThe `random` module provides a pseudorandom number generator for pixlet. The generator is automatically seeded on each execution. The seed itself changes every 15 seconds, making apps deterministic over that same time window. This behavior enables more effective caching of execution results on Tidbyt servers. Developer can reseed via `random.seed` if needed.\n\n| Function | Description |\n| --- | --- |\n| `seed(s)` | Seeds the generator.|\n| `number(min, max)` | Returns a random number between the min and max. The min has to be 0 or greater. The min has to be less than the max. |\n\nExample:\n```starlark\nload("random.star", "random")\n\ndef main(config):\n    num = random.number(0, 100)\n    if num > 50:\n        print("You win!")\n    else:\n        print("Better luck next time!")\n```\n\n## Pixlet module: QRCode\n\nThe `qrcode` module provides a QR code generator for pixlet!\n\n| Function | Description |\n| --- | --- |\n| `generate(url, size, color?, background?)` | Returns a QR code as an image that can be passed into the image widget. |\n\nSizing works as follows:\n- `small`: 21x21 pixels\n- `medium`: 25x25 pixels\n- `large`: 29x29 pixels\n\nNote: we\'re working with some of the smallest possible QR codes in this module, so the amount of data that can be used for the URL is extremely limited.\n\nExample:\n```starlark\nload("cache.star", "cache")\nload("encoding/base64.star", "base64")\nload("render.star", "render")\nload("qrcode.star", "qrcode")\n\ndef main(config):\n    url = "https://tidbyt.com?utm_source=pixlet_example"\n\n    data = cache.get(url)\n    if data == None:\n        code = qrcode.generate(\n            url = url,\n            size = "large",\n            color = "#fff",\n            background = "#000",\n        )\n        cache.set(url, base64.encode(code), ttl_seconds = 3600)\n    else:\n        code = base64.decode(data)\n\n    return render.Root(\n        child = render.Padding(\n            child = render.Image(src = code),\n            pad = 1,\n        ),\n    )\n```\n'},2501:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i='# Schema\nSchema provides structure for configuring apps. We use schema inside of the Tidbyt mobile app to allow configuring starlark applications and store the values inside of our database.\n\nIn order to supply fields to the mobile app, we call `get_schema()`. When a user saves the installation, we store the results in our database. Every time we render the app, we pass the values into the `config` key/value at the provided identifier.\n\n> Note: Schema is for configuring apps submitted to [Community Apps](https://github.com/tidbyt/community). We\'re working on adding tighter integration into Pixlet so that pixlet commands make better use of schema.\n\n## Quick Start\nLet\'s add a toggle and a text input to our hello world example. Here it is before we add schema:\n```starlark\nload("render.star", "render")\n\ndef main():\n    return render.Root(\n        child = render.Text("Hello, World!"),\n    )\n```\n\nThis is a quick start, so let\'s start with the code and we\'ll break it down:\n\n```starlark\nload("render.star", "render")\nload("schema.star", "schema")\n\nDEFAULT_WHO = "World"\n\ndef main(config):\n    message = "Hello, %s!" % config.str("who", DEFAULT_WHO)\n\n    if config.bool("small"):\n        msg = render.Text(message, font = "CG-pixel-3x5-mono")\n    else:\n        msg = render.Text(message)\n\n    return render.Root(\n        child = msg,\n    )\n\ndef get_schema():\n    return schema.Schema(\n        version = "1",\n        fields = [\n            schema.Text(\n                id = "who",\n                name = "Who?",\n                desc = "Who to say hello to.",\n                icon = "user",\n            ),\n            schema.Toggle(\n                id = "small",\n                name = "Display small text",\n                desc = "A toggle to display smaller text.",\n                icon = "compress",\n                default = False,\n            ),\n        ],\n    )\n```\n\nThe big change here is the `get_schema` method. This is the method we will call before rendering your app when running inside of our [Community Apps](https://github.com/tidbyt/community) repo. A quick note - we don\'t call this method using Pixlet at this time.\n\nThe `get_schema` method returns a `schema.Schema` object that contains _fields_. See below for a complete breakdown of what fields are available. In our example, we use a `Toggle` and a `Text` field.\n\nNext up should be more familiar. We\'re now passing `config` into `main()`. This is the same for current pixlet scripts that take `config` today. In [Community Apps](https://github.com/tidbyt/community), we will populate the config hashmap with values configured from the mobile app.\n\nConfiguration values can be set when using `pixlet render` by specifying `id=value`. The hello world example may be rendered with different configs as follows:\n```\npixlet render schema_hello_world.star who="Tidbyt" small=True\n```\n\n## Icons\nEach schema field takes an `icon` value. We use the free icons from [Font Awesome](https://fontawesome.com/v6/search?s=solid%2Cbrands) at version 6.1.1 with the names camel cased. For example [users-cog](https://fontawesome.com/v6/icons/users-cog?style=solid&s=solid) should be `usersCog` in the `icon` value. When submitting to the community repo, the icon names are validated against this [icon map](https://github.com/tidbyt/pixlet/blob/main/icons/icons.go).\n\n## Dynamic Fields\nPixlet offers two types of fields: basic fields like `Toggle` or `Text` and dynamic fields that take a `handler` method like `LocationBased` or `Typeahead`. For dynamic fields, the `handler` will get called with user inputs. What the handler returns is specific to the field.\n\n## Fields\nThese are the current fields we support through schema today. Note that any addition of a field will require changes in our mobile app before we can truly support them.\n\n### Color\n\n![color example](img/schema/color/color.gif)\n> [Example App](https://github.com/tidbyt/pixlet/blob/9eb20267914955a763f01962a9ce8bb9c99d34c8/docs/schema/color/example.star)\n\nColor provides a color picker. It is provided in `config` as a hex color string with a `#` prefix. The value is ready to use in widgets, like `render.Box()`.\n\n```starlark\ndef get_schema():\n    return schema.Schema(\n        version = "1",\n        fields = [\n            schema.Color(\n                id = "color",\n                name = "Color",\n                desc = "Color of the screen.",\n                icon = "brush",\n                default = "#7AB0FF",\n            ),\n        ],\n    )\n```\n\nYou can also provide an optional `palette` parameter to guide your users towards reasonable color options:\n```starlark\ndef get_schema():\n    return schema.Schema(\n        version = "1",\n        fields = [\n            schema.Color(\n                id = "color",\n                name = "Color",\n                desc = "Color of the screen.",\n                icon = "brush",\n                default = "#7AB0FF",\n                palette = [\n                    "#7AB0FF",\n                    "#BFEDC4",\n                    "#78DECC",\n                    "#DBB5FF",\n                ],\n            ),\n        ],\n    )\n```\n\n### Datetime\n![datetime example](img/schema/datetime/datetime.gif)\n> [Example App](https://github.com/tidbyt/pixlet/blob/dc0f876089bb44a28653eba46e8182805944b782/docs/schema/datetime/example.star)\n\nDatetime provides a picker for a date and time. It is provided in `config` as a string that is parsable by `time.parse_time()`.\n\n```starlark\nschema.DateTime(\n    id = "event_time",\n    name = "Event Time",\n    desc = "The time of the event.",\n    icon = "gear",\n)\n```\n\n### Dropdown\n![dropdown example](img/schema/dropdown/dropdown.gif)\n> [Example App](https://github.com/tidbyt/pixlet/blob/dc0f876089bb44a28653eba46e8182805944b782/docs/schema/dropdown/example.star)\n\nA dropdown provides a selection from a list of options. Options are a key/value pair where the display is the text displayed in the mobile app and the value is what is returned in `config` to the starlark app.\n\nOptions:\n```starlark\noptions = [\n    schema.Option(\n        display = "Pink",\n        value = "#FF94FF",\n    ),\n    schema.Option(\n        display = "Mustard",\n        value = "#FFD10D",\n    ),\n]\n```\n\nDropdown:\n```starlark\nschema.Dropdown(\n    id = "color",\n    name = "Text Color",\n    desc = "The color of text to be displayed.",\n    icon = "brush",\n    default = options[0].value,\n    options = options,\n)\n```\n\n### Generated\n> [Example App](https://github.com/tidbyt/pixlet/blob/dc0f876089bb44a28653eba46e8182805944b782/docs/schema/generated/example.star)\n\nThe generated field allows for a schema field to generate additional schema\nfields 🤯. User beware - this field is both not user friendly and our tooling\nlikely has a fair number of bugs. The benefit though is the ability to ask the\nuser for additional fields depending on their input.\n\n\nIn this example, `source` is the `id` of the field that will be passed to the\n`handler`. So if there is a text field with `id = pet`, the value of the pet\ntext field will be passed to `more_options`:\n```starlark\nschema.Generated(\n    id = "generated",\n    source = "pet",\n    handler = more_options,\n)\n```\n\nNote - the value that is passed to the handler is dependent on the source field\ntype. A handler might look as follows:\n\n```starlark\ndef more_options(pet):\n    if pet == "dog":\n        return [\n            schema.Toggle(\n                id = "leash",\n                name = "Leash",\n                desc = "A toggle to enable a dog leash.",\n                icon = "gear",\n                default = False,\n            ),\n        ]\n    elif pet == "cat":\n        return [\n            schema.Toggle(\n                id = "litter-box",\n                name = "Litter Box",\n                desc = "A toggle to enable a litter box.",\n                icon = "gear",\n                default = False,\n            ),\n        ]\n    else:\n        return []\n```\n\n### Location\n![location example](img/schema/location/location.gif)\n> [Example App](https://github.com/tidbyt/pixlet/blob/dc0f876089bb44a28653eba46e8182805944b782/docs/schema/location/example.star)\n\nA location field provides a location selection option inside of the mobile app. It\'s populated with the devices location. Note - if you\'re adding location to your app and want to call external APIs with this data, we will ask you to truncate the location to avoid leaking location data to third-parties.\n\n```starlark\nschema.Location(\n    id = "location",\n    name = "Location",\n    desc = "Location for which to display time.",\n    icon = "locationDot",\n)\n```\n\nWhen you get location using `config.get("location")`, we will return the location in the following format:\n```json\n{\n\t"lat": "40.6781784",\n\t"lng": "-73.9441579",\n\t"description": "Brooklyn, NY, USA",\n\t"locality": "Brooklyn",\n\t"place_id": "ChIJCSF8lBZEwokRhngABHRcdoI",\n\t"timezone": "America/New_York"\n}\n```\n\n### LocationBased\n![locationbased example](img/schema/locationbased/locationbased.gif)\n> [Example App](https://github.com/tidbyt/pixlet/blob/dc0f876089bb44a28653eba46e8182805944b782/docs/schema/locationbased/example.star)\n\nA `LocationBased` field provides a list of `Option` objects to the user by calling a handler method with the user provided location. This field can be used to populate a list of options based on the location provided by the user.\n\n```starlark\nschema.LocationBased(\n    id = "station",\n    name = "Train Station",\n    desc = "A list of train stations based on a location.",\n    icon = "train",\n    handler = get_stations,\n)\n```\n\nA handler for `LocationBased` is provided a location object:\n```json\n{\n\t"lat": "40.6781784",\n\t"lng": "-73.9441579",\n\t"description": "Brooklyn, NY, USA",\n\t"locality": "Brooklyn",\n\t"place_id": "ChIJCSF8lBZEwokRhngABHRcdoI",\n\t"timezone": "America/New_York"\n}\n```\n\nThe handler needs to return a list of `Option` objects where the display is value is what the user will see and the value is what will be provided to your app:\n```starlark\ndef get_stations(location):\n    loc = json.decode(location)\n\n    return [\n        schema.Option(\n            display = "Grand Central",\n            value = "grand_central",\n        ),\n    ]\n```\n\nThe value provided to `config.get()` is a JSON string with display and values provided:\n```json\n{"display": "Grand Central", "value": "grand_central"}\n```\n\n### OAuth2\n![oauth2 example](img/schema/oauth2/oauth2.gif)\n> [Example App](https://github.com/tidbyt/pixlet/blob/dc0f876089bb44a28653eba46e8182805944b782/docs/schema/oauth2/example.star)\n\nThe `OAuth2` field provides mechanism to authenticate a user via an OAuth2 compatible API. \n\n```starlark\nschema.OAuth2(\n    id = "auth",\n    name = "GitHub",\n    desc = "Connect your GitHub account.",\n    icon = "github",\n    handler = oauth_handler,\n    client_id = "your-client-id",\n    authorization_endpoint = "https://github.com/login/oauth/authorize",\n    scopes = [\n        "read:user",\n    ],\n)\n```\n\nThe handler for `OAuth2` looks as follows:\n```starlark\ndef oauth_handler(params):\n    params = json.decode(params)\n\t# handle oauth2 flow (see Example App)\n\treturn "access-token"\n```\n\nParams is a JSON encoded string:\n```json\n{"code": "your-code", "grant_type": "authorization_code", "client_id": "your-client-id", "redirect_uri": "https://appauth.tidbyt.com/your-app-id"}\n```\n\nWhen configuring your OAuth2 app with the third-party provider, the authorization callback URL should be as follows:\n```\nhttps://appauth.tidbyt.com/{{ your_app_id }}\n```\n\n### PhotoSelect\n![photoselect example](img/schema/photoselect/photoselect.gif)\n> [Example App](https://github.com/tidbyt/pixlet/blob/dc0f876089bb44a28653eba46e8182805944b782/docs/schema/photoselect/example.star)\n\nThe `PhotoSelect` field provides a photo picker to the user. The selected image will be cropped to 64x32 pixels and be available through `config` as a base64 encoded string.\n\n```starlark\nschema.PhotoSelect(\n    id = "photo",\n    name = "Add Photo",\n    desc = "A photo to display.",\n    icon = "gear",\n)\n```\n\nYou can use the provided image as follows in your app:\n```starlark\nimg = base64.decode(config.get("photo"))\nrender.Image(img)\n```\n\n### Text\n![text example](img/schema/text/text.gif)\n> [Example App](https://github.com/tidbyt/pixlet/blob/dc0f876089bb44a28653eba46e8182805944b782/docs/schema/text/example.star)\n\nThe `Text` field provides a text entry box for a string entered by the user.\n\n```starlark\nschema.Text(\n    id = "msg",\n    name = "Message",\n    desc = "A message to display.",\n    icon = "gear",\n    default = "Hello",\n)\n```\n\n### Toggle\n![toggle example](img/schema/toggle/toggle.gif)\n> [Example App](https://github.com/tidbyt/pixlet/blob/dc0f876089bb44a28653eba46e8182805944b782/docs/schema/toggle/example.star)\n\nA toggle provides an on/off switch for your app. The values returned in `config` are either `True` or `False`. Remember to use `config.bool()` to ensure the results are cast to a boolean.\n\n```starlark\nschema.Toggle(\n    id = "party_mode",\n    name = "Party Mode",\n    desc = "A toggle to enable party mode.",\n    icon = "gear",\n    default = False,\n)\n```\n\nRemember to request the value as a bool when getting the value from `config`:\n```\nconfig.bool("party_mode", False)\n```\n\n### Typeahead\n![typeahead example](img/schema/typeahead/typeahead.gif)\n> [Example App](https://github.com/tidbyt/pixlet/blob/dc0f876089bb44a28653eba46e8182805944b782/docs/schema/typeahead/example.star)\n\nThe `Typeahead` field provides a list of options based on user input. \n\n```starlark\nschema.Typeahead(\n    id = "search",\n    name = "Search",\n    desc = "A list of items that match search.",\n    icon = "gear",\n    handler = search,\n)\n```\n\nA handler for `Typeahead` takes the search string as a parameter to the function and returns a list of `Option` objects:\n```starlark\ndef search(pattern):\n    if pattern.startswith("a"):\n        return [\n            schema.Option(\n                display = "Apple",\n                value = "apple",\n            )\n\t\t]\n\n\treturn []\n```\n\nThe value provided to `config.get()` is a JSON string with display and values provided:\n```json\n{"display": "Apple", "value": "apple"}\n```\n'},59961:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i='# Widgets!\n\nPixlet comes with a number of built-in _Widgets_. These are used to\ndescribe how data should be laid out, presented and finally rendered\nto an image file.\n\nThe easiest way to get started is probably to take a look at some of\nthe [examples](https://github.com/tidbyt/pixlet/tree/main/examples), and then refer to the detailed Widget\ndocumentation (this document) when the need arises.\n\nA quick note about colors.  When specifying colors, use a CSS-like\nhexdecimal color specification.  Pixlet supports `#rgb`, `#rrggbb`,\n`#rgba`, and `#rrggbbaa` color specifications.\n\nFor animated widgets like Marquee, you can also call `frame_count()`\nto work out how many frames are required to display the whole\nanimation. You can also call `size()` on dynamically-sized widgets\nlike Text to get the width and height.\n\n## Animation\nAnimations turns a list of children into an animation, where each\nchild is a frame.\n\nFIXME: Behavior when children themselves are animated is a bit\nweird. Think and fix.\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `children` | `[Widget]` | Children to use as frames in the animation | N |\n\n#### Example\n```\nrender.Animation(\n     children=[\n          render.Box(width=10, height=10, color="#300"),\n          render.Box(width=12, height=12, color="#500"),\n          render.Box(width=14, height=14, color="#700"),\n          render.Box(width=16, height=16, color="#900"),\n          render.Box(width=18, height=18, color="#b00"),\n     ],\n)\n```\n![](img/widget_Animation_0.gif)\n\n\n## Box\nA Box is a rectangular widget that can hold a child widget.\n\nBoxes are transparent unless `color` is provided. They expand to\nfill all available space, unless `width` and/or `height` is\nprovided. Boxes can have a `child`, which will be centered in the\nbox, and the child can be padded (via `padding`).\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `child` | `Widget` | Child to center inside box | N |\n| `width` | `int` | Limits Box width | N |\n| `height` | `int` | Limits Box height | N |\n| `padding` | `int` | Padding around the child widget | N |\n| `color` | `color` | Background color | N |\n\n#### Example\n```\nrender.Box(\n     color="#00f",\n     child=render.Box(\n          width=20,\n          height=10,\n          color="#f00",\n     )\n)\n```\n![](img/widget_Box_0.gif)\n\n\n## Circle\nCircle draws a circle with the given `diameter` and `color`. If a\n`child` widget is provided, it is drawn in the center of the\ncircle.\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `color` | `color` | Fill color | **Y** |\n| `diameter` | `int` | Diameter of the circle | **Y** |\n| `child` | `Widget` | Widget to place in the center of the circle | N |\n\n#### Example\n```\nrender.Circle(\n     color="#666",\n     diameter=30,\n     child=render.Circle(color="#0ff", diameter=10),\n)\n```\n![](img/widget_Circle_0.gif)\n\n\n## Column\nColumn lays out and draws its children vertically (in a column).\n\nBy default, a Column is as small as possible, while still holding\nall its children. However, if `expanded` is set, the Column will\nfill all available space vertically. The width of a Column is\nalways that of its widest child.\n\nAlignment along the vertical main axis is controlled by passing\none of the following `main_align` values:\n- `"start"`: place children at the beginning of the column\n- `"end"`: place children at the end of the column\n- `"center"`: place children in the middle of the column\n- `"space_between"`: place equal space between children\n- `"space_evenly"`: equal space between children and before/after first/last child\n- `"space_around"`: equal space between children, and half of that before/after first/last child\n\nAlignment along the horizontal cross axis is controlled by passing\none of the following `cross_align` values:\n- `"start"`: place children at the left\n- `"end"`: place children at the right\n- `"center"`: place children in the center\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `children` | `[Widget]` | Child widgets to lay out | **Y** |\n| `main_align` | `str` | Alignment along vertical main axis | N |\n| `cross_align` | `str` | Alignment along horizontal cross axis | N |\n| `expanded` | `bool` | Column should expand to fill all available vertical space | N |\n\n#### Example\n```\nrender.Column(\n     children=[\n          render.Box(width=10, height=8, color="#a00"),\n          render.Box(width=14, height=6, color="#0a0"),\n          render.Box(width=16, height=4, color="#00a"),\n     ],\n)\n```\n![](img/widget_Column_0.gif)\n#### Example\n```\nrender.Column(\n     expanded=True,\n     main_align="space_around",\n     cross_align="center",\n     children=[\n          render.Box(width=10, height=8, color="#a00"),\n          render.Box(width=14, height=6, color="#0a0"),\n          render.Box(width=16, height=4, color="#00a"),\n     ],\n)\n```\n![](img/widget_Column_1.gif)\n\n\n## Image\nImage renders the binary image data passed via `src`. Supported\nformats include PNG, JPEG and GIF.\n\nIf `width` or `height` are set, the image will be scaled\naccordingly, with nearest neighbor interpolation. Otherwise the\nimage\'s original dimensions are used.\n\nIf the image data encodes an animated GIF, the Image instance will\nalso be animated. Frame delay (in milliseconds) can be read from\nthe `delay` attribute.\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `src` | `str` | Binary image data | **Y** |\n| `width` | `int` | Scale image to this width | N |\n| `height` | `int` | Scale image to this height | N |\n| `delay` | `int` | (Read-only) Frame delay in ms, for animated GIFs | N |\n\n\n\n## Marquee\nMarquee scrolls its child horizontally or vertically.\n\nThe `scroll_direction` will be \'horizontal\' and will scroll from right\nto left if left empty, if specified as \'vertical\' the Marquee will\nscroll from bottom to top.\n\nIn horizontal mode the height of the Marquee will be that of its child,\nbut its `width` must be specified explicitly. In vertical mode the width\nwill be that of its child but the `height` must be specified explicitly.\n\nIf the child\'s width fits fully, it will not scroll.\n\nThe `offset_start` and `offset_end` parameters control the position\nof the child in the beginning and the end of the animation.\n\nAlignment for a child that fits fully along the horizontal/vertical axis is controlled by passing\none of the following `align` values:\n- `"start"`: place child at the left/top\n- `"end"`: place child at the right/bottom\n- `"center"`: place child at the center\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `child` | `Widget` | Widget to potentially scroll | **Y** |\n| `width` | `int` | Width of the Marquee, required for horizontal | N |\n| `height` | `int` | Height of the Marquee, required for vertical | N |\n| `offset_start` | `int` | Position of child at beginning of animation | N |\n| `offset_end` | `int` | Position of child at end of animation | N |\n| `scroll_direction` | `str` | Direction to scroll, \'vertical\' or \'horizontal\', default is horizontal | N |\n| `align` | `str` | alignment when contents fit on screen, \'start\', \'center\' or \'end\', default is start | N |\n\n#### Example\n```\nrender.Marquee(\n     width=64,\n     child=render.Text("this won\'t fit in 64 pixels"),\n     offset_start=5,\n     offset_end=32,\n)\n```\n![](img/widget_Marquee_0.gif)\n\n\n## Padding\nPadding places padding around its child.\n\nIf the `pad` attribute is a single integer, that amount of padding\nwill be placed on all sides of the child. If it\'s a 4-tuple `(left,\ntop, right, bottom)`, then padding will be placed on the sides\naccordingly.\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `child` | `Widget` | The Widget to place padding around | **Y** |\n| `pad` | `int / (int, int, int, int)` | Padding around the child | N |\n| `expanded` | `bool` | This is a confusing parameter | N |\n| `color` | `color` | Background color | N |\n\n\n\n## PieChart\nPieChart draws a circular pie chart of size `diameter`. It takes two\narguments for the data: parallel lists `colors` and `weights` representing\nthe shading and relative sizes of each data entry.\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `colors` | `[color]` | List of color hex codes | **Y** |\n| `weights` | `[float]` | List of numbers corresponding to the relative size of each color | **Y** |\n| `diameter` | `int` | Diameter of the circle | **Y** |\n\n#### Example\n```\nrender.PieChart(\n     colors = [ "#fff", "#0f0", "#00f" ],\n     weights  = [ 180, 135, 45 ],\n     diameter = 30,\n)\n```\n![](img/widget_PieChart_0.gif)\n\n\n## Plot\nPlot is a widget that draws a data series.\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `data` | `[(float, float)]` | A list of 2-tuples of numbers | **Y** |\n| `width` | `int` | Limits Plot width | **Y** |\n| `height` | `int` | Limits Plot height | **Y** |\n| `color` | `color` | Line color, default is \'#fff\' | N |\n| `color_inverted` | `color` | Line color for Y-values below 0 | N |\n| `x_lim` | `(float, float)` | Limit X-axis to a range | N |\n| `y_lim` | `(float, float)` | Limit Y-axis to a range | N |\n| `fill` | `bool` | Paint surface between line and X-axis | N |\n| `chart_type` | `str` | Specifies the type of chart to render, "scatter" or "line", default is "line" | N |\n| `fill_color` | `color` | Fill color for Y-values above 0 | N |\n| `fill_color_inverted` | `color` | Fill color for Y-values below 0 | N |\n\n#### Example\n```\nrender.Plot(\n  data = [\n    (0, 3.35),\n    (1, 2.15),\n    (2, 2.37),\n    (3, -0.31),\n    (4, -3.53),\n    (5, 1.31),\n    (6, -1.3),\n    (7, 4.60),\n    (8, 3.33),\n    (9, 5.92),\n  ],\n  width = 64,\n  height = 32,\n  color = "#0f0",\n  color_inverted = "#f00",\n  x_lim = (0, 9),\n  y_lim = (-5, 7),\n  fill = True,\n),\n```\n![](img/widget_Plot_0.gif)\n\n\n## Root\nEvery Widget tree has a Root.\n\nThe child widget, and all its descendants, will be drawn on a 64x32\ncanvas. Root places its child in the upper left corner of the\ncanvas.\n\nIf the tree contains animated widgets, the resulting animation will\nrun with _delay_ milliseconds per frame.\n\nIf the tree holds time sensitive information which must never be\ndisplayed past a certain point in time, pass _MaxAge_ to specify\nan expiration time in seconds. Display devices use this to avoid\ndisplaying stale data in the event of e.g. connectivity issues.\n\n**NOTE*:* If you only want your app to display when there is data (e.g. for alerts) you can use `return []` rather than `return render.Root`. This will cause your app to not display in your app rotation.\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `child` | `Widget` | Widget to render | **Y** |\n| `delay` | `int` | Frame delay in milliseconds | N |\n| `max_age` | `int` | Expiration time in seconds | N |\n| `show_full_animation` | `bool` | Request animation is shown in full, regardless of app cycle speed | N |\n\n\n\n## Row\nRow lays out and draws its children horizontally (in a row).\n\nBy default, a Row is as small as possible, while still holding all\nits children. However, if `expanded` is set, the Row will fill all\navailable space horizontally. The height of a Row is always that of\nits tallest child.\n\nAlignment along the horizontal main axis is controlled by passing\none of the following `main_align` values:\n- `"start"`: place children at the beginning of the row\n- `"end"`: place children at the end of the row\n- `"center"`: place children in the middle of the row\n- `"space_between"`: place equal space between children\n- `"space_evenly"`: equal space between children and before/after first/last child\n- `"space_around"`: equal space between children, and half of that before/after first/last child\n\nAlignment along the vertical cross axis is controlled by passing\none of the following `cross_align` values:\n- `"start"`: place children at the top\n- `"end"`: place children at the bottom\n- `"center"`: place children at the center\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `children` | `[Widget]` | Child widgets to lay out | **Y** |\n| `main_align` | `str` | Alignment along horizontal main axis | N |\n| `cross_align` | `str` | Alignment along vertical cross axis | N |\n| `expanded` | `bool` | Row should expand to fill all available horizontal space | N |\n\n#### Example\n```\nrender.Row(\n     children=[\n          render.Box(width=10, height=8, color="#a00"),\n          render.Box(width=14, height=6, color="#0a0"),\n          render.Box(width=16, height=4, color="#00a"),\n     ],\n)\n```\n![](img/widget_Row_0.gif)\n#### Example\n```\nrender.Row(\n     expanded=True,\n     main_align="space_between",\n     cross_align="end",\n     children=[\n          render.Box(width=10, height=8, color="#a00"),\n          render.Box(width=14, height=6, color="#0a0"),\n          render.Box(width=16, height=4, color="#00a"),\n     ],\n)\n```\n![](img/widget_Row_1.gif)\n\n\n## Sequence\nSequence renders a list of child widgets in sequence.\n\nEach child widget is rendered for the duration of its\nframe count, then the next child widget in the list will\nbe rendered and so on.\n\nIt comes in quite useful when chaining animations.\nIf you want to know more about that, go check\nout the [animation](../06_reference/animation.md) documentation.\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `children` | `[Widget]` | List of child widgets | **Y** |\n\n#### Example\n```\nrender.Sequence(\n  children = [\n    animation.Transformation(...),\n    animation.Transformation(...),\n    ...\n  ],\n),\n```\n\n\n## Stack\nStack draws its children on top of each other.\n\nJust like a stack of pancakes, except with Widgets instead of\npancakes. The Stack will be given a width and height sufficient to\nfit all its children.\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `children` | `[Widget]` | Widgets to stack | **Y** |\n\n#### Example\n```\nrender.Stack(\n     children=[\n          render.Box(width=50, height=25, color="#911"),\n          render.Text("hello there"),\n          render.Box(width=4, height=32, color="#119"),\n     ],\n)\n```\n![](img/widget_Stack_0.gif)\n\n\n## Text\nText draws a string of text on a single line.\n\nBy default, the text will use the "tb-8" font, but other fonts can\nbe chosen via the `font` attribute. The `height` and `offset`\nparameters allow fine tuning of the vertical layout of the\nstring. Take a look at the [font documentation](../02_build/07_fonts_in_pixlet.md) for more\ninformation.\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `content` | `str` | The text string to draw | **Y** |\n| `font` | `str` | Desired font face | N |\n| `height` | `int` | Limits height of the area on which text is drawn | N |\n| `offset` | `int` | Shifts position of text vertically. | N |\n| `color` | `color` | Desired font color | N |\n\n#### Example\n```\nrender.Text(content="Tidbyt!", color="#099")\n```\n![](img/widget_Text_0.gif)\n\n\n## WrappedText\nWrappedText draws multi-line text.\n\nThe optional `width` and `height` parameters limit the drawing\narea. If not set, WrappedText will use as much vertical and\nhorizontal space as possible to fit the text.\n\nAlignment of the text is controlled by passing one of the following `align` values:\n- `"left"`: align text to the left\n- `"center"`: align text in the center\n- `"right"`: align text to the right\n\n#### Attributes\n| Name | Type | Description | Required |\n| --- | --- | --- | --- |\n| `content` | `str` | The text string to draw | **Y** |\n| `font` | `str` | Desired font face | N |\n| `height` | `int` | Limits height of the area on which text may be drawn | N |\n| `width` | `int` | Limits width of the area on which text may be drawn | N |\n| `linespacing` | `int` | Controls spacing between lines | N |\n| `color` | `color` | Desired font color | N |\n| `align` | `str` | Text Alignment | N |\n\n#### Example\n```\nrender.WrappedText(\n      content="this is a multi-line text string",\n      width=50,\n      color="#fa0",\n)\n```\n![](img/widget_WrappedText_0.gif)\n\n\n'},81897:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i='# Tidbyt Individual Contributor License Agreement\n\nTo clarify the intellectual property license granted with Contributions from\nany person or entity, Tidbyt, Inc. ("Tidbyt") must have a \nmust have on file a signed Contributor License Agreement ("CLA")\nfrom each Contributor, indicating agreement with the license\nterms below. This agreement is for your protection as a Contributor\nas well as the protection of Tidbyt. It does not\nchange your rights to use your own Contributions for any other purpose.\n\nYou accept and agree to the following terms and conditions for Your\nContributions (present and future) that you submit to Tidbyt. Except\nfor the license granted herein to Tidbyt and recipients of\nsoftware distributed by Tidbyt, You reserve all right, title,\nand interest in and to Your Contributions.\n\n1. Definitions.\n     \n   "You" (or "Your") shall mean the copyright owner or legal entity\n   authorized by the copyright owner that is making this Agreement\n   with Tidbyt. For legal entities, the entity making a\n   Contribution and all other entities that control, are controlled\n   by, or are under common control with that entity are considered to\n   be a single Contributor. For the purposes of this definition,\n   "control" means (i) the power, direct or indirect, to cause the\n   direction or management of such entity, whether by contract or\n   otherwise, or (ii) ownership of fifty percent (50%) or more of the\n   outstanding shares, or (iii) beneficial ownership of such entity.\n   \n   "Contribution" shall mean any original work of authorship,\n   including any modifications or additions to an existing work, that\n   is intentionally submitted by You to Tidbyt for inclusion\n   in, or documentation of, any of the products owned or managed by\n   Tidbyt (the "Work"). For the purposes of this definition,\n   "submitted" means any form of electronic, verbal, or written\n   communication sent to Tidbyt or its representatives,\n   including but not limited to communication on electronic mailing\n   lists, source code control systems, and issue tracking systems that\n   are managed by, or on behalf of, Tidbyt for the purpose of\n   discussing and improving the Work, but excluding communication that\n   is conspicuously marked or otherwise designated in writing by You\n   as "Not a Contribution."\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n   this Agreement, You hereby grant to Tidbyt and to\n   recipients of software distributed by Tidbyt a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   copyright license to reproduce, prepare derivative works of,\n   publicly display, publicly perform, sublicense, and distribute Your\n   Contributions and such derivative works.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n   this Agreement, You hereby grant to Tidbyt and to\n   recipients of software distributed by Tidbyt a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   (except as stated in this section) patent license to make, have\n   made, use, offer to sell, sell, import, and otherwise transfer the\n   Work, where such license applies only to those patent claims\n   licensable by You that are necessarily infringed by Your\n   Contribution(s) alone or by combination of Your Contribution(s)\n   with the Work to which such Contribution(s) was submitted. If any\n   entity institutes patent litigation against You or any other entity\n   (including a cross-claim or counterclaim in a lawsuit) alleging\n   that your Contribution, or the Work to which you have contributed,\n   constitutes direct or contributory patent infringement, then any\n   patent licenses granted to that entity under this Agreement for\n   that Contribution or Work shall terminate as of the date such\n   litigation is filed.\n\n4. You represent that you are legally entitled to grant the above\n   license. If your employer(s) has rights to intellectual property\n   that you create that includes your Contributions, you represent\n   that you have received permission to make Contributions on behalf\n   of that employer, that your employer has waived such rights for\n   your Contributions to Tidbyt, or that your employer has\n   executed a separate Corporate CLA with Tidbyt.\n\n5. You represent that each of Your Contributions is Your original\n   creation (see section 7 for submissions on behalf of others). You\n   represent that Your Contribution submissions include complete\n   details of any third-party license or other restriction (including,\n   but not limited to, related patents and trademarks) of which you\n   are personally aware and which are associated with any part of Your\n   Contributions.\n\n6. You are not expected to provide support for Your Contributions,\n   except to the extent You desire to provide support. You may provide\n   support for free, for a fee, or not at all. Unless required by\n   applicable law or agreed to in writing, You provide Your\n   Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS\n   OF ANY KIND, either express or implied, including, without\n   limitation, any warranties or conditions of TITLE, NON-\n   INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.\n\n7. Should You wish to submit work that is not Your original creation,\n   You may submit it to Tidbyt separately from any\n   Contribution, identifying the complete details of its source and of\n   any license or other restriction (including, but not limited to,\n   related patents, trademarks, and license agreements) of which you\n   are personally aware, and conspicuously marking the work as\n   "Submitted on behalf of a third-party: [named here]".\n\n8. You agree to notify Tidbyt of any facts or circumstances of\n   which you become aware that would make these representations\n   inaccurate in any respect.\n'},10455:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, religion, or sexual identity\nand orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n* Demonstrating empathy and kindness toward other people\n* Being respectful of differing opinions, viewpoints, and experiences\n* Giving and gracefully accepting constructive feedback\n* Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n* Focusing on what is best not just for us as individuals, but for the\n  overall community\n\nExamples of unacceptable behavior include:\n\n* The use of sexualized language or imagery, and sexual attention or\n  advances of any kind\n* Trolling, insulting or derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or email\n  address, without their explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\ncommunity@tidbyt.com.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series\nof actions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or\npermanent ban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior,  harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within\nthe community.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.0, available at\nhttps://www.contributor-covenant.org/version/2/0/code_of_conduct.html.\n\nCommunity Impact Guidelines were inspired by [Mozilla's code of conduct\nenforcement ladder](https://github.com/mozilla/diversity).\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see the FAQ at\nhttps://www.contributor-covenant.org/faq. Translations are available at\nhttps://www.contributor-covenant.org/translations."},17491:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="This project and everyone participating in it is governed by the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to community@tidbyt.com via email.\n\nIn addition, we have a [Contributor License Agreement](CLA.md) that you'll be asked to sign a part of the pull request process through an automated tool. This agreement offers protections to both you, the contributor and us, Tidbyt, Inc. It is based on the [Apache Software Foundation's CLAs](https://www.apache.org/licenses/contributor-agreements.html).\n\n\nOK! Now that we're past the boring part, check out our [README on how to contribute various changes](../README.md).\n"},86697:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="# Security\nWe take security **very seriously** here at Tidbyt. If you discover a security issue with any of the code maintained in this library or elsewhere at Tidbyt, please reach out to security@tidbyt.com via email and we'll get back to you quickly. If the issue is severe, please continue to email us every 24 hours until you get a response."},29960:(e,n,t)=>{"use strict";t.r(n),t.d(n,{default:()=>i});const i="# Support\nLooking for help on how to get started beyond the documentation in this repo? Create a discussion post on the [Tidbyt Forum](https://discuss.tidbyt.com/c/developers/) and a member of our team or the broader community will get back to you."},47593:(e,n,t)=>{"use strict";var i=t(96540),a=t(5338),o=t(69733),r=t(30493),s=(0,r.Z0)({name:"test",initialState:0,reducers:{increment:function(e,n){return e+n.payload}}});const l=(0,r.U1)({reducer:{posts:s.reducer}});var c=t(37107),d=t(37875),h=t(66188),u=t(74572),p=(t(79891),t(4294),t(60408),t(50550),t(83478)),m={base03:"#002b36",base02:"#073642",base01:"#586e75",base00:"#657b83",base0:"#839496",base1:"#93a1a1",base2:"#eee8d5",base3:"#fdf6e3",yellow:"#b58900",orange:"#cb4b16",red:"#dc322f",magenta:"#d33682",violet:"#6c71c4",blue:"#268bd2",cyan:"#2aa198",green:"#859900"},f=(0,p.A)({palette:{mode:"light",primary:{main:m.cyan},secondary:{main:m.yellow},text:{primary:m.base1,secondary:m.base0},background:{default:m.base03},divider:m.base01},components:{MuiSvgIcon:{defaultProps:{htmlColor:m.base1}}},typography:{fontFamily:["Barlow","sans-serif"].join(","),h1:{fontFamily:'"VisbyCFBold"',fontSize:"4.5rem"},h2:{fontFamily:'"VisbyCFBold"',fontSize:"3.2rem"},h3:{fontFamily:'"VisbyCFBold"',fontSize:"2.4rem"},h4:{fontFamily:'"VisbyCFBold"',fontSize:"1.3rem"},h5:{fontFamily:'"VisbyCFBold"',fontSize:"1.3rem"},h6:{fontFamily:'"VisbyCFBold"',fontSize:"1.3rem"},body2:{fontSize:"1.3rem"}}}),g=t(85072),b=t.n(g),y=t(97825),A=t.n(y),w=t(77659),v=t.n(w),x=t(55056),T=t.n(x),k=t(10540),I=t.n(k),C=t(41113),E=t.n(C),D=t(66777),B={};function M(e){var n=e.children;return c.Yv.add(h.X7I,d.Cvc),i.createElement(u.A,{theme:f},n)}B.styleTagTransform=E(),B.setAttributes=T(),B.insert=v().bind(null,"head"),B.domAPI=A(),B.insertStyleElement=I(),b()(D.A,B),D.A&&D.A.locals&&D.A.locals;var N=t(47767),P=t(84976),S=t(44675),_=t(71335),R=t(62274),F=t(43294),U=t(8532),z=t(11641),Z=t(69067),q=t(11848),Y=t(89828),G=function(){return G=Object.assign||function(e){for(var n,t=1,i=arguments.length;t<i;t++)for(var a in n=arguments[t])Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a]);return e},G.apply(this,arguments)},H=240,O=(0,q.Ay)(Z.A,{shouldForwardProp:function(e){return"open"!==e}})((function(e){var n=e.theme,t=e.open;return G({flexGrow:1,padding:n.spacing(3),transition:n.transitions.create("margin",{easing:n.transitions.easing.sharp,duration:n.transitions.duration.leavingScreen})},t&&{transition:n.transitions.create("margin",{easing:n.transitions.easing.easeOut,duration:n.transitions.duration.enteringScreen}),marginLeft:"".concat(H,"px")})}));function W(e){var n=e.open,t=e.children,a=(0,S.A)();return(0,_.A)(a.breakpoints.up("sm"))?i.createElement(O,{open:n},t):i.createElement(Z.A,{sx:{flexGrow:1,padding:a.spacing(3)}},t)}var j=function(){return j=Object.assign||function(e){for(var n,t=1,i=arguments.length;t<i;t++)for(var a in n=arguments[t])Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a]);return e},j.apply(this,arguments)},L=(0,q.Ay)(Y.A,{shouldForwardProp:function(e){return"open"!==e}})((function(e){var n=e.theme,t=e.open;return j({transition:n.transitions.create(["margin","width"],{easing:n.transitions.easing.sharp,duration:n.transitions.duration.leavingScreen})},t&&{width:"calc(100% - ".concat(H,"px)"),marginLeft:"".concat(H,"px"),transition:n.transitions.create(["margin","width"],{easing:n.transitions.easing.easeOut,duration:n.transitions.duration.enteringScreen})})}));function Q(e){var n=e.children,t=e.open,a=(0,S.A)();return(0,_.A)(a.breakpoints.up("sm"))?i.createElement(L,{position:"fixed",open:t,elevation:0,sx:{zIndex:function(e){return e.zIndex.drawer+1},backgroundColor:m.base03}},n):i.createElement(Y.A,{position:"fixed",sx:{backgroundColor:m.base03},elevation:0},n)}var V=function(){return V=Object.assign||function(e){for(var n,t=1,i=arguments.length;t<i;t++)for(var a in n=arguments[t])Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a]);return e},V.apply(this,arguments)};function X(e){return i.createElement("svg",V({"data-name":"logo",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 215.01 32.01"},e),i.createElement("path",{style:{fill:e.color},d:"M76.77 27.9h2.36c4.94 0 6.59-3.8 6.59-12.56 0-7.75-1.64-11.16-6.55-11.16h-2.4ZM71.76 0h7.92c7.95 0 11.18 5.24 11.18 15.29 0 10.83-3 16.72-11.64 16.72h-7.46ZM119.75 28.08h3.72c3.17 0 5-1.74 5-5.54 0-3.64-1.65-5.64-5.6-5.64h-3.08ZM122.82 13c3.72 0 4.84-1.52 4.84-4.51S126.11 4 123.11 4h-3.36v9Zm-7.95-13h9.27c5.3 0 8.31 3 8.31 8 0 4.12-2 6.05-3.78 6.71 2.32.9 4.75 3 4.75 7.89 0 6-3.79 9.4-9.44 9.4h-9.11ZM161.75 32V20.39a2.13 2.13 0 0 0-.21-1L153.45 0H159c1.93 5.15 4.43 11.79 5.38 15.09 1.16-3.64 3.68-10.19 5.45-15.09h5.25l-8.18 19.48a2.56 2.56 0 0 0-.17 1V32Z"}),i.createElement("path",{style:{fill:e.color},d:"M0 0v4.37l6.94.01-.11 27.59 5.09.04V4.37h6.94V0H0zM41.47 0h4.98v32.01h-4.98zM196.15 0v4.37h6.94v27.64h4.98V4.38l6.94-.01V0h-18.86z"}))}var K=function(){return K=Object.assign||function(e){for(var n,t=1,i=arguments.length;t<i;t++)for(var a in n=arguments[t])Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a]);return e},K.apply(this,arguments)};function J(e){var n=e.open,t=e.handleOpen,a=(0,S.A)(),o={mr:2};return(0,_.A)(a.breakpoints.up("sm"))&&(o=K(K({},o),n&&{display:"none"})),i.createElement(Q,{open:n},i.createElement(U.A,null,i.createElement(z.A,{size:"large",edge:"start",color:"inherit","aria-label":"open drawer",onClick:t,sx:o},i.createElement(R.A,null)),i.createElement(Z.A,{sx:{flexGrow:1}}),i.createElement(P.N_,{to:"/"},i.createElement(Z.A,{sx:{display:{xs:"flex",md:"flex"},height:"16px"}},i.createElement(X,{color:m.base1,height:"16px"}))),i.createElement(Z.A,{sx:{flexGrow:1}}),i.createElement(z.A,{size:"large",edge:"end",href:"https://github.com/tidbyt"},i.createElement(F.A,null))))}var $=t(41333),ee=t(23088),ne=t(55487),te=t(88613),ie=t(82041),ae=t(86798);function oe(e){var n=e.children;return i.createElement(ae.A,null,n)}var re=t(33198),se=t(60538),le=t(64137);function ce(e){var n=e.children;return i.createElement(re.A,{sx:{marginTop:4,borderRadius:2},component:se.A},i.createElement(le.A,null,n))}var de=t(14774);function he(e){var n=e.children;return e.isHeader?i.createElement(de.A,{sx:{fontWeight:"500",color:"#000"}},n):i.createElement(de.A,{sx:{color:"#000"}},n)}var ue=t(96627);function pe(e){var n=e.children;return i.createElement(ue.A,null,n)}var me=t(43884);function fe(e){var n=e.children;return i.createElement(me.A,null,n)}var ge=t(58027),be=t(14073),ye=t(67725);function Ae(e){var n=e.inline,t=e.className,a=e.children,o=e.code;if(n)return i.createElement(Z.A,{component:"code",sx:{fontWeight:"500",paddingLeft:"0.3rem",paddingRight:"0.3rem",fontFamily:"monospace"}},a);var r="python",s=/language-(\w+)/.exec(t||"");return s&&(r=s[1]),"starlark"===r.toLowerCase()&&(r="python"),o||(o=String(a).replace(/\n$/,"")),i.createElement(Z.A,{sx:{minWidth:"100%"}},i.createElement(se.A,{sx:{borderRadius:2,backgroundColor:m.base03}},i.createElement(be.A,{mt:4,mb:0,variant:"body2"},i.createElement(ge.A,{customStyle:{background:"none"},children:o,style:ye.Wy,language:r}))))}var we=t(15001),ve=function(){return ve=Object.assign||function(e){for(var n,t=1,i=arguments.length;t<i;t++)for(var a in n=arguments[t])Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a]);return e},ve.apply(this,arguments)},xe=function(e,n){var t={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&n.indexOf(i)<0&&(t[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var a=0;for(i=Object.getOwnPropertySymbols(e);a<i.length;a++)n.indexOf(i[a])<0&&Object.prototype.propertyIsEnumerable.call(e,i[a])&&(t[i[a]]=e[i[a]])}return t};function Te(e){var n=e.href,t=e.children,a=xe(e,["href","children"]);return n.startsWith("http")||n.startsWith("#")||n.startsWith("mailto")?i.createElement(we.A,ve({href:n},a),t):i.createElement(we.A,ve({component:P.N_,to:n},a),t)}function ke(e){var n=e.level,t=e.children,a=e.id,o="h".concat(n),r=a?i.createElement(Te,{href:"#".concat(a),mt:3,mb:0,underline:"hover",mr:1},i.createElement("span",null,"#")):null;return i.createElement(Z.A,{sx:{display:"flex",alignItems:"center"}},r,i.createElement(be.A,{mt:3,mb:0,variant:o,id:a},t))}var Ie=t(8239);function Ce(e){var n=e.src,t=e.alt;return e.title,e.children,i.createElement(Z.A,{sx:{flexGrow:1}},i.createElement(Ie.Ay,{container:!0},i.createElement(Ie.Ay,{item:!0,xs:12,md:8},i.createElement(se.A,{sx:{borderRadius:2,marginTop:4,maxWidth:"100%",height:"auto"},component:"img",alt:t,src:n}))))}var Ee=t(49799);function De(e){var n=e.children;return i.createElement(Ee.A,{dense:!0},n)}var Be=t(44090),Me=t(53369);function Ne(e){var n=e.index,t=e.ordered,a=e.children;return t?i.createElement(Be.Ay,{key:n},i.createElement(be.A,{component:"span",variant:"body2"},i.createElement("strong",{style:{paddingRight:10}},"".concat(n+1,".")),a)):i.createElement(Be.Ay,{sx:{display:"block"},key:n},i.createElement(be.A,{component:"span",variant:"body2"},i.createElement(Me.A,{sx:{fontSize:10,color:"#000",paddingRight:1}}),a))}function Pe(e){var n=e.children;return i.createElement(be.A,{mt:4,mb:0,variant:"body2"},n)}var Se=t(62462);function _e(e){var n=e.split("/");return{name:Fe(n[n.length-1].replace(".md","")),url:Re(e),path:e,source:Se(e).default}}function Re(e){var n=e.replace(".md","").replace("../","").replace("./","").replace(/\d\d_/g,"").replace(/_/g,"-");return"/docs/".concat(n)}function Fe(e){var n=e.split("/");return ze(n[n.length-1].replace(".md","").replace(/\d\d_/g,"").replace(/_/g," "))}function Ue(e){return ze(e.replace(/\d\d_/g,"").replace(/_/g," "))}function ze(e){if(e.toUpperCase()===e)return e;for(var n=e.toLowerCase().split(" "),t=0;t<n.length;t++)n[t]=n[t].charAt(0).toUpperCase()+n[t].slice(1);return n.join(" ")}var Ze=t(60356);function qe(){return i.createElement(Z.A,{sx:{flexGrow:1,marginTop:4,marginBottom:2}},i.createElement(Ze.A,null))}function Ye(e){var n=e.source,t=(0,N.zy)();return(0,i.useEffect)((function(){if(t.hash){var e=t.hash.substring(1),n=document.getElementById(e);n&&(n.scrollIntoView({behavior:"auto"}),window.scrollBy(0,-80))}}),[]),i.createElement($.$,{children:n,transformLinkUri:function(e){return e.startsWith("http")||e.startsWith("#")||e.startsWith("mailto")?e:Re(function(e,n){var t=n.replace("/docs/","").split("/");if(e.startsWith("./")&&t.length>1){var i=t.slice(0,t.length-1).join("/");return e.replace("./","".concat(i,"/"))}return e}(e,t.pathname))},transformImageUri:function(e){return"/static/".concat(e)},remarkPlugins:[ee.A,te.A],rehypePlugins:[ne.A,ie.A],components:{code:Ae,p:Pe,h1:ke,h2:ke,h3:ke,h4:ke,h5:ke,h6:ke,a:Te,td:he,th:he,tr:oe,table:ce,thead:pe,tbody:fe,ol:De,ul:De,li:Ne,img:Ce,hr:qe}})}var Ge=t(8451),He=t(61317),Oe=t(37211),We=t(44545),je=t(48158);function Le(e){var n,t=e.title,a=e.docs,o=e.handleClose;return i.createElement(i.Fragment,null,i.createElement(Ee.A,{subheader:i.createElement(je.A,{sx:{backgroundColor:m.base03},component:"div",id:"nested-list-subheader"},Ue(t))},(n=[],a.forEach((function(e){return n.push(i.createElement(P.N_,{key:e.path,style:{color:"inherit",textDecoration:"inherit"},to:e.url},i.createElement(Be.Ay,{disablePadding:!0},i.createElement(Oe.A,{onClick:o},i.createElement(We.A,{primary:e.name})))))})),"Integrate"===Ue(t)&&n.push(i.createElement(P.N_,{key:"/docs/api",style:{color:"inherit",textDecoration:"inherit"},to:"/docs/api"},i.createElement(Be.Ay,{disablePadding:!0},i.createElement(Oe.A,{onClick:o},i.createElement(We.A,{primary:"API Operations"}))))),n)),i.createElement(Ze.A,null))}var Qe=function(){return Qe=Object.assign||function(e){for(var n,t=1,i=arguments.length;t<i;t++)for(var a in n=arguments[t])Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a]);return e},Qe.apply(this,arguments)},Ve=(0,q.Ay)("div")((function(e){var n=e.theme;return Qe(Qe({display:"flex",alignItems:"center",padding:n.spacing(0,1)},n.mixins.toolbar),{justifyContent:"flex-end"})}));function Xe(e){var n=e.open,t=(e.handleOpen,e.handleClose),a=(0,S.A)(),o=(0,_.A)(a.breakpoints.up("sm")),r=function(){var e=new Map;return Se.keys().forEach((function(n){var t=n.split("/");t.length>2&&(e.has(t[1])||e.set(t[1],new Array),e.get(t[1]).push(_e(n)))})),e}(),s="temporary";o&&(s="persistent");var l=t;return o&&(l=function(){}),i.createElement(He.Ay,{sx:{width:H,"& .MuiDrawer-paper":{width:H}},variant:s,anchor:"left",open:n,onClose:l,PaperProps:{sx:{backgroundColor:m.base03}}},i.createElement(Ve,null,i.createElement(z.A,{onClick:t},i.createElement(Ge.A,null))),i.createElement(Ze.A,null),function(e){var n=[];return r.forEach((function(t,a){return n.push(i.createElement(Le,{key:a,title:a,docs:t,handleClose:e}))})),n}(l))}var Ke=t(3339);function Je(e){var n=e.source,t=e.children,a=(0,S.A)(),o=(0,_.A)(a.breakpoints.up("sm")),r=(0,i.useState)(o),s=r[0],l=r[1],c=function(){l(!0)};return i.createElement(Z.A,{sx:{flexGrow:1}},i.createElement(J,{open:s,handleOpen:c}),i.createElement(Xe,{open:s,handleOpen:c,handleClose:function(){l(!1)}}),i.createElement(U.A,null),i.createElement(W,{open:s},i.createElement(Ke.A,{maxWidth:"md"},i.createElement(Ye,{source:n}),t)),i.createElement(Z.A,{height:"80px"}))}var $e=t(81597),en=t(47620),nn=t(80242),tn=t(3517);function an(e){var n=e.heading,t=e.desc,a=e.href,o=e.icon;return i.createElement(P.N_,{style:{color:"inherit",textDecoration:"inherit"},to:a},i.createElement(Z.A,{sx:{border:"2px solid ".concat(m.base02),borderRadius:"12px",padding:"28px",transition:"border 100ms ease-out",":hover":{border:"2px solid ".concat(m.cyan)},":hover > div > div > h2":{textDecoration:"underline ".concat(m.cyan)}}},i.createElement(Ie.Ay,{container:!0,spacing:0},i.createElement(Ie.Ay,{sx:{justifyContent:"center",display:"flex",alignItems:"center"},item:!0,xs:2},o),i.createElement(Ie.Ay,{item:!0,xs:10,display:{xs:"none",md:"block"}},i.createElement(be.A,{sx:{color:m.base1},variant:"h2"},n)),i.createElement(Ie.Ay,{item:!0,xs:10,display:{xs:"block",md:"none"}},i.createElement(be.A,{sx:{color:m.base1},variant:"h3"},n)),i.createElement(Ie.Ay,{item:!0,xs:2}),i.createElement(Ie.Ay,{item:!0,xs:10},i.createElement(be.A,{sx:{color:m.cyan}},t)))))}var on=t(95108),rn={};rn.styleTagTransform=E(),rn.setAttributes=T(),rn.insert=v().bind(null,"head"),rn.domAPI=A(),rn.insertStyleElement=I(),b()(on.A,rn);const sn=on.A&&on.A.locals?on.A.locals:void 0;var ln=function(){return ln=Object.assign||function(e){for(var n,t=1,i=arguments.length;t<i;t++)for(var a in n=arguments[t])Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a]);return e},ln.apply(this,arguments)};function cn(e){return i.createElement("svg",ln({"data-name":"round-logo",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 69.46 69.46"},e),i.createElement("path",{d:"M34.73 69.46A34.73 34.73 0 1 0 0 34.73a34.73 34.73 0 0 0 34.73 34.73"}),i.createElement("path",{style:{fill:"#e0b0ff"},d:"M31.43 37.21h6.61v19.93h-6.61z"}),i.createElement("path",{style:{fill:"#7d8af7"},d:"M31.43 20.46h6.61v16.75h-6.61z"}),i.createElement("path",{style:{fill:"#ffb5f5"},d:"M38.04 14.65h9.21v5.81h-9.21z"}),i.createElement("path",{style:{fill:"#78decc"},d:"M22.22 14.65h15.82v5.81H22.22z"}))}var dn=function(){return dn=Object.assign||function(e){for(var n,t=1,i=arguments.length;t<i;t++)for(var a in n=arguments[t])Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a]);return e},dn.apply(this,arguments)};function hn(e){return i.createElement("svg",dn({"data-name":"rotate-text",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 112.33 112.14"},e),i.createElement("path",{style:{fill:e.color},d:"m58.18 1.73-1.53-.08.25-1.6 4.86.25-.26 1.6-1.56-.17-.85 5.5-1.75-.09ZM62.42 2.31l1.72.22-1.2 5.09-1.72-.22Zm.43-1.86 1.72.22-.34 1.46-1.71-.22ZM64.22 5.41a2.83 2.83 0 0 1 3.27-2.35 1.67 1.67 0 0 1 1.25.87h.06l.77-2.28 1.69.37-2.25 6.78-1.67-.36.16-.46h-.07a2.1 2.1 0 0 1-1.58.26 2.21 2.21 0 0 1-1.63-2.83Zm2.47 1.43a1.25 1.25 0 0 0 1.52-1 .94.94 0 0 0-.76-1.21 1.26 1.26 0 0 0-1.52 1 1 1 0 0 0 .76 1.21ZM71.63 9.15h-.05l-.22.45-1.63-.59 3.09-6.43 1.63.58-1 2.16a2.4 2.4 0 0 1 1.65 0 2.15 2.15 0 0 1 1.24 2.91 2.84 2.84 0 0 1-3.48 2 2 2 0 0 1-1.23-1.08Zm1.34-.52a1.24 1.24 0 0 0 1.67-.82.91.91 0 0 0-.57-1.27 1.27 1.27 0 0 0-1.68.82.93.93 0 0 0 .58 1.27ZM76.82 11.63l.83-5.27 1.57.78-.63 3.23 2.75-2.16 1.6.79-6.43 4.73-1.53-.76ZM82.07 12.57l1.27-1.66-.67-.42.84-1.08.67.42.83-1 1.46.92-.83 1 .94.59-.85 1.08-.93-.59-1.14 1.46c-.15.19-.22.5.2.76a2.07 2.07 0 0 0 .46.2l-.82 1a1.61 1.61 0 0 1-1.07-.33 1.44 1.44 0 0 1-.36-2.35ZM87.8 14.78a1 1 0 0 1 1.37-.15 1 1 0 0 1-1.22 1.52 1 1 0 0 1-.15-1.37ZM95.17 15.84l1.93 2.05a3.17 3.17 0 0 1-.26 4.56 3.82 3.82 0 0 1-5.36-.17l-2-2.1Zm-2.46 5.33a1.93 1.93 0 0 0 2.83 0 1.52 1.52 0 0 0 .19-2.29l-.68-.72-3 2.32ZM96.07 23.73a2.88 2.88 0 0 1 4.06.63c.8 1.09.92 2.87-1.38 3.82l-2.09-2.86a1.2 1.2 0 0 0 .2 1.34 2.19 2.19 0 0 0 1 .77l-.28 1a2.91 2.91 0 0 1-2-1.19 2.39 2.39 0 0 1 .49-3.51Zm2.83 2.58a.89.89 0 0 0 0-1.21 1.14 1.14 0 0 0-1.22-.47ZM101.86 26.98l.87 1.53-2.32 2.33 3.52-.24.89 1.55-5.87.23-.8-1.4ZM104.08 35.73a1 1 0 1 1-.54 1.27 1 1 0 0 1 .54-1.27ZM108.67 41.66l-.4-1.48 1.6-.25 1.26 4.69-1.61.24-.4-1.5-5.45.86-.45-1.7ZM109.34 45.89l.31 1.71-5.21.4-.31-1.7Zm1.9-.15.32 1.7-1.5.12-.31-1.69ZM106.98 48.57a2.85 2.85 0 0 1 3.24 2.4 1.73 1.73 0 0 1-.46 1.46v.06h2.41l.16 1.72-7.14-.07-.16-1.73h.49v-.07a2.18 2.18 0 0 1-.72-1.43 2.21 2.21 0 0 1 2.18-2.34Zm-.64 2.79a1.27 1.27 0 0 0 1.44 1.15 1 1 0 0 0 .92-1.1 1.25 1.25 0 0 0-1.36-1.14 1 1 0 0 0-1 1.09ZM105.67 56.79v-.06l-.48-.07.05-1.73 7.07.95v1.73l-2.38-.33v.06a2.36 2.36 0 0 1 .54 1.56 2.14 2.14 0 0 1-2.42 2.06 2.83 2.83 0 0 1-3-2.7 2 2 0 0 1 .62-1.47Zm.91 1.11a1.25 1.25 0 0 0 1.3 1.34.92.92 0 0 0 1-.94 1.26 1.26 0 0 0-1.29-1.34.93.93 0 0 0-1.01.94ZM104.92 62.46l5.26-.85-.25 1.74-3.26.41 2.91 2-.24 1.74-6.48-4.69.24-1.69ZM105.64 67.73l2 .73.2-.77 1.28.47-.19.76 1.25.46-.42 1.68-1.26-.46-.28 1.13-1.29-.47.27-1.07-1.74-.63c-.22-.09-.54-.06-.66.42a1.76 1.76 0 0 0 0 .5l-1.23-.46a1.58 1.58 0 0 1 0-1.12 1.43 1.43 0 0 1 2.07-1.17ZM105.34 73.88a1 1 0 1 1-1.25.56 1 1 0 0 1 1.25-.56ZM106.55 81.24l-1.35 2.49a3.18 3.18 0 0 1-4.42 1.14 3.81 3.81 0 0 1-1.44-5.14l1.39-2.53Zm-5.82-.72a1.92 1.92 0 0 0 .89 2.68 1.52 1.52 0 0 0 2.24-.51l.48-.87-3.13-2.16ZM99.28 84.52a2.89 2.89 0 0 1 .65 4.06c-.8 1.09-2.45 1.75-4.06-.15l2.08-2.86a1.23 1.23 0 0 0-1.22.6 2.15 2.15 0 0 0-.39 1.18h-1a2.94 2.94 0 0 1 .51-2.29 2.4 2.4 0 0 1 3.43-.54ZM97.69 88a.89.89 0 0 0 1.15-.37 1.15 1.15 0 0 0 .07-1.31ZM98 91l-1.19 1.3-2.93-1.49 1.31 3.27-1.2 1.32-2-5.51 1.07-1.16ZM90.41 95.79a1 1 0 0 1-.07 1.36 1 1 0 0 1-1.37-.11 1 1 0 1 1 1.49-1.25ZM86.13 101.99l1.29-.84.73 1.45-4.08 2.64-.73-1.45 1.31-.85-2.51-4.92 1.48-1ZM82.34 103.97l-1.52.83-2-4.84 1.52-.82Zm.74 1.77-1.53.82-.57-1.38 1.51-.82ZM79.02 102.52a2.85 2.85 0 0 1-1.28 3.82 1.71 1.71 0 0 1-1.53 0h-.05l.7 2.29-1.59.69-2.12-6.82 1.59-.68.13.47h.07a2.12 2.12 0 0 1 1.13-1.14 2.22 2.22 0 0 1 2.95 1.37Zm-2.84.27a1.26 1.26 0 0 0-.64 1.72 1 1 0 0 0 1.32.54 1.26 1.26 0 0 0 .65-1.71 1 1 0 0 0-1.33-.55ZM70.82 103.8h.06l-.08-.49 1.67-.48 1.25 7-1.67.48-.41-2.37a2.46 2.46 0 0 1-1.32 1 2.15 2.15 0 0 1-2.71-1.68 2.84 2.84 0 0 1 1.67-3.64 2 2 0 0 1 1.54.18Zm-.77 1.21a1.24 1.24 0 0 0-.88 1.64.91.91 0 0 0 1.2.7 1.26 1.26 0 0 0 .89-1.64.92.92 0 0 0-1.21-.7ZM65.19 104.82l2.41 4.77-1.74.28-1.38-3-1 3.38-1.76.29 2.5-7.62 1.68-.27ZM60.34 107.13l-.09 2.11.79-.05v1.36l-.79.05-.06 1.34-1.73.11.06-1.34-1.1.07.06-1.37 1.1-.06.07-1.85c0-.24-.11-.54-.6-.51a1.76 1.76 0 0 0-.5.12l.07-1.32a1.68 1.68 0 0 1 1.06-.36 1.44 1.44 0 0 1 1.66 1.7ZM54.44 108.73a1 1 0 0 1-1 .93 1 1 0 1 1 1-.93ZM47.84 112.14l-2.77-.52a3.18 3.18 0 0 1-2.45-3.89 3.8 3.8 0 0 1 4.45-3l2.83.54Zm-1.12-5.75a1.92 1.92 0 0 0-2.28 1.67 1.52 1.52 0 0 0 1.18 2l1 .19 1.08-3.65ZM42.45 106.24a2.9 2.9 0 0 1-3.66 1.87c-1.28-.42-2.43-1.79-1.12-3.91l3.37 1.1a1.22 1.22 0 0 0-1-1 2.19 2.19 0 0 0-1.25 0l-.37-1a3 3 0 0 1 2.33-.22 2.41 2.41 0 0 1 1.7 3.16Zm-3.8-.44a.89.89 0 0 0 .71 1 1.12 1.12 0 0 0 1.26-.34ZM35.91 107.03l-1.6-.73.52-3.25-2.72 2.25-1.62-.73 4.62-3.62 1.47.66ZM29 101.25a1 1 0 1 1-1.64-1 1 1 0 1 1 1.64 1ZM21.8 99.09l1.19 1-1.15 1.14-3.76-3.08 1.16-1.13 1.2 1 3.9-3.93 1.36 1.11ZM17.34 97.3l-1.25-1.2 1.14-1 1.24 1.19Zm1.45-1.24-1.24-1.2 4-3.38 1.19 1.25ZM19.13 92.48a2.83 2.83 0 0 1-4 0 1.68 1.68 0 0 1-.48-1.44v-.05l-2 1.38-1.14-1.3 5.83-4.17 1.14 1.3-.41.28a2.19 2.19 0 0 1 1.06 4Zm-1.14-2.61a1.25 1.25 0 0 0-1.83-.09.94.94 0 0 0-.11 1.42 1.25 1.25 0 0 0 1.82.1.94.94 0 0 0 .12-1.43ZM15.34 85.07l.44-.23 1 1.43-6.27 3.46-1-1.44 2.13-1.12v-.05a2.31 2.31 0 0 1-1.3-.98 2.15 2.15 0 0 1 .75-3.1 2.83 2.83 0 0 1 4 .46 2 2 0 0 1 .25 1.57Zm-1.36-.34a1.24 1.24 0 0 0-1.83-.33.91.91 0 0 0-.29 1.33 1.25 1.25 0 0 0 1.83.34.92.92 0 0 0 .29-1.34ZM12.66 80.02l-3.79 3.76-.81-1.56 2.42-2.23-3.53.09-.82-1.58h8l.79 1.52ZM8.98 76.16l-2 .57.29.73-1.31.37-.29-.73-1.33.36-.64-1.61 1.29-.36-.4-1 1.31-.37.41 1 1.78-.5c.23-.06.47-.27.29-.73a2 2 0 0 0-.26-.43l1.27-.35a1.64 1.64 0 0 1 .67.9 1.44 1.44 0 0 1-1.08 2.15ZM5.67 70.98a1 1 0 0 1-1.19-.68 1 1 0 1 1 1.19.68ZM.34 65.73 0 62.94a3.17 3.17 0 0 1 2.94-3.48 3.81 3.81 0 0 1 4.22 3.32l.34 2.86Zm5.14-2.82a1.91 1.91 0 0 0-2.28-1.66 1.52 1.52 0 0 0-1.52 1.72l.12 1 3.8-.08ZM4.34 58.79a2.87 2.87 0 0 1-2.86-2.94c0-1.35 1-2.85 3.41-2.22l-.06 3.54a1.22 1.22 0 0 0 .65-1.19 2.13 2.13 0 0 0-.36-1.25l.83-.64a2.92 2.92 0 0 1 .89 2.17 2.39 2.39 0 0 1-2.5 2.53Zm-.7-3.76a.89.89 0 0 0-.72 1 1.13 1.13 0 0 0 .69 1.11ZM1.59 52.84l.2-1.75 3.24-.51-2.97-1.85.2-1.76 4.86 3.28-.18 1.55ZM4.94 44.5a1 1 0 0 1-.7-1.18 1 1 0 0 1 1.89.48 1 1 0 0 1-1.19.7ZM4.79 36.96l-.56 1.42-1.43-.75 1.77-4.52 1.43.76-.57 1.45 4.91 2.53-.64 1.64ZM5.09 32.14l.76-1.56 1.27.79-.78 1.54Zm1.63 1 .76-1.56 4.44 2.76-.75 1.55ZM10.23 32.41a2.84 2.84 0 0 1-1.19-3.85 1.69 1.69 0 0 1 1.23-.9v-.05l-1.91-1.45.89-1.49 5.71 4.29-.89 1.48-.39-.3v.06a2.14 2.14 0 0 1-.26 1.58 2.21 2.21 0 0 1-3.19.63Zm2.11-1.88a1.26 1.26 0 0 0-.44-1.8 1 1 0 0 0-1.39.33 1.26 1.26 0 0 0 .47 1.77 1 1 0 0 0 1.36-.3ZM16.14 26.57v.05l.35.35-1.15 1.36-5.13-5L11.34 22l1.7 1.73v-.05a2.32 2.32 0 0 1 .49-1.58 2.15 2.15 0 0 1 3.18-.22 2.84 2.84 0 0 1 .82 3.85 2 2 0 0 1-1.39.84Zm-.07-1.43a1.26 1.26 0 0 0-.25-1.85.92.92 0 0 0-1.39.14 1.26 1.26 0 0 0 .24 1.85.94.94 0 0 0 1.4-.14ZM20.12 22.44 15.34 20l1.27-1.27 2.87 1.62-1.14-3.32 1.22-1.3 2.45 7.62-1.21 1.22ZM22.67 17.73l-1.17-1.75-.61.5-.75-1.14.6-.5-.73-1.11 1.33-1.09.74 1.09.84-.7.76 1.14-.84.7 1 1.53c.13.21.4.37.78.06a2.27 2.27 0 0 0 .34-.38l.71 1.1a1.56 1.56 0 0 1-.64.91 1.43 1.43 0 0 1-2.36-.36ZM26.58 13a1 1 0 0 1 1.63-1.06A1 1 0 1 1 26.58 13ZM29.92 6.34l2.54-1.18a3.16 3.16 0 0 1 4.24 1.69 3.81 3.81 0 0 1-1.85 5l-2.61 1.24Zm4.27 4a1.92 1.92 0 0 0 .86-2.68 1.51 1.51 0 0 0-2.1-.93l-.9.42 1.29 3.58ZM37.73 7.98a2.89 2.89 0 0 1 1.88-3.65c1.29-.41 3 0 3.19 2.52l-3.38 1.08a1.23 1.23 0 0 0 1.34.23 2.12 2.12 0 0 0 1-.7l.87.58a2.88 2.88 0 0 1-1.76 1.54 2.4 2.4 0 0 1-3.14-1.6Zm3.34-1.86a.89.89 0 0 0-1.15-.39 1.15 1.15 0 0 0-.83 1ZM42.6 3.52l1.74-.35 1.48 2.94.87-3.38 1.74-.35-1.64 5.63-1.58.32ZM51.58 4.17a1 1 0 1 1 1.93-.13 1 1 0 1 1-1.93.13Z"}))}function un(){var e=(0,i.useState)(!1),n=e[0],t=e[1],a=function(){t(!0)};return i.createElement(Z.A,{sx:{flexGrow:1,backgroundColor:m.base03}},i.createElement(J,{open:n,handleOpen:a}),i.createElement(Xe,{open:n,handleOpen:a,handleClose:function(){t(!1)}}),i.createElement(Z.A,{display:"flex",justifyContent:"center",alignItems:"center",minHeight:"100vh"},i.createElement(W,{disabled:!0},i.createElement(Ke.A,{sx:{mt:4}},i.createElement(U.A,null),i.createElement(Ie.Ay,{container:!0,spacing:4},i.createElement(Ie.Ay,{sx:{justifyContent:"center",display:"flex",alignItems:"center",m:2},item:!0,xs:12},i.createElement(Z.A,{sx:{zIndex:1,position:"absolute"}},i.createElement(cn,{width:"180px"})),i.createElement(Z.A,{className:sn.rotate},i.createElement(hn,{color:m.base01,width:"264px"}))),i.createElement(Ie.Ay,{item:!0,xs:12,md:6},i.createElement(an,{href:"/docs/build/build-for-tidbyt",heading:"Build",desc:"Build an app for your Tidbyt",icon:i.createElement($e.A,{sx:{fontSize:48}})})),i.createElement(Ie.Ay,{item:!0,xs:12,md:6},i.createElement(an,{href:"/docs/publish/community-apps",heading:"Publish",desc:"Publish your app for all Tidbyt users",icon:i.createElement(nn.A,{sx:{fontSize:48}})})),i.createElement(Ie.Ay,{item:!0,xs:12,md:6},i.createElement(an,{href:"/docs/integrate/pushing-apps",heading:"Integrate",desc:"Integrate with the Tidbyt API",icon:i.createElement(tn.A,{sx:{fontSize:48}})})),i.createElement(Ie.Ay,{item:!0,xs:12,md:6},i.createElement(an,{href:"/docs/engage/community",heading:"Engage",desc:"Learn from the Tidbyt Community",icon:i.createElement(en.A,{sx:{fontSize:48}})})),i.createElement(Ie.Ay,{item:!0,xs:12,display:{xs:"block",md:"none"}},i.createElement(Z.A,{height:"80px"})))))))}var pn=t(39287);function mn(){return i.createElement(pn.A,{url:"https://api.tidbyt.com/swagger.json",tryItOutEnabled:!0})}function fn(){var e=(0,N.zy)().pathname;return(0,i.useEffect)((function(){window.scrollTo(0,0)}),[e]),null}t(38871);const gn="data:image/webp;base64,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";function bn(){return i.createElement(Z.A,{sx:{flexGrow:1}},i.createElement(Ie.Ay,{container:!0},i.createElement(Ie.Ay,{item:!0,xs:12},i.createElement(se.A,{sx:{borderRadius:2,marginTop:4,maxWidth:"100%",height:"auto"},component:"img",alt:"not found",src:gn}))))}var yn=t(86990),An=t(77728),wn=t.n(An),vn=t(65532),xn={};function Tn(e){var n=e.output,t=(0,i.useRef)(null);(0,i.useEffect)((function(){var e=t.current;e.scrollTop=e.scrollHeight})),n||(n="Please connect your Tidbyt");var a=wn().ansiToHtml(n,{use_classes:!0});return i.createElement(Z.A,{sx:{minWidth:"100%"}},i.createElement(se.A,{sx:{borderRadius:2,backgroundColor:m.base03,padding:2}},i.createElement(be.A,{ref:t,style:{whiteSpace:"pre",overflowX:"auto",overflowY:"scroll",marginTop:0,height:"60vh"},mt:4,mb:0,variant:"body2",dangerouslySetInnerHTML:{__html:a}})))}xn.styleTagTransform=E(),xn.setAttributes=T(),xn.insert=v().bind(null,"head"),xn.domAPI=A(),xn.insertStyleElement=I(),b()(vn.A,xn),vn.A&&vn.A.locals&&vn.A.locals;var kn=function(e,n,t,i){return new(t||(t=Promise))((function(a,o){function r(e){try{l(i.next(e))}catch(e){o(e)}}function s(e){try{l(i.throw(e))}catch(e){o(e)}}function l(e){var n;e.done?a(e.value):(n=e.value,n instanceof t?n:new t((function(e){e(n)}))).then(r,s)}l((i=i.apply(e,n||[])).next())}))},In=function(e,n){var t,i,a,o,r={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]};return o={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function s(s){return function(l){return function(s){if(t)throw new TypeError("Generator is already executing.");for(;o&&(o=0,s[0]&&(r=0)),r;)try{if(t=1,i&&(a=2&s[0]?i.return:s[0]?i.throw||((a=i.return)&&a.call(i),0):i.next)&&!(a=a.call(i,s[1])).done)return a;switch(i=0,a&&(s=[2&s[0],a.value]),s[0]){case 0:case 1:a=s;break;case 4:return r.label++,{value:s[1],done:!1};case 5:r.label++,i=s[1],s=[0];continue;case 7:s=r.ops.pop(),r.trys.pop();continue;default:if(!((a=(a=r.trys).length>0&&a[a.length-1])||6!==s[0]&&2!==s[0])){r=0;continue}if(3===s[0]&&(!a||s[1]>a[0]&&s[1]<a[3])){r.label=s[1];break}if(6===s[0]&&r.label<a[1]){r.label=a[1],a=s;break}if(a&&r.label<a[2]){r.label=a[2],r.ops.push(s);break}a[2]&&r.ops.pop(),r.trys.pop();continue}s=n.call(e,r)}catch(e){s=[6,e],i=0}finally{t=a=0}if(5&s[0])throw s[1];return{value:s[0]?s[1]:void 0,done:!0}}([s,l])}}};function Cn(){var e=(0,i.useRef)(""),n=(0,i.useState)(""),t=(n[0],n[1]),a=(0,i.useState)((function(){return"serial"in navigator}))[0],o=(0,i.useState)("closed"),r=o[0],s=o[1],l=(0,i.useRef)(null),c=(0,i.useRef)(null),d=(0,i.useRef)(Promise.resolve());function h(){e.current="",t("")}function u(e){return kn(this,void 0,void 0,(function(){return In(this,(function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,e.open({baudRate:115200})];case 1:return n.sent(),l.current=e,s("open"),[3,3];case 2:return n.sent(),s("closed"),console.error("Could not open port"),[3,3];case 3:return[2]}}))}))}function p(){return kn(this,void 0,void 0,(function(){var e;return In(this,(function(n){switch(n.label){case 0:if(!a||"closed"!==r)return[3,5];h(),s("opening"),e=[{usbVendorId:4292,usbProductId:6e4}],n.label=1;case 1:return n.trys.push([1,4,,5]),[4,navigator.serial.requestPort({filters:e})];case 2:return[4,u(n.sent())];case 3:return n.sent(),[2,!0];case 4:return n.sent(),s("closed"),console.error("User did not select port"),[3,5];case 5:return[2,!1]}}))}))}function m(){var e;return kn(this,void 0,void 0,(function(){var n;return In(this,(function(t){switch(t.label){case 0:return a&&"open"===r&&(n=l.current)?(s("closing"),null===(e=c.current)||void 0===e||e.cancel(),[4,d.current]):[3,3];case 1:return t.sent(),c.current=null,[4,n.close()];case 2:t.sent(),l.current=null,s("closed"),t.label=3;case 3:return[2]}}))}))}function f(){return kn(this,void 0,void 0,(function(){return In(this,(function(e){switch(e.label){case 0:return[4,d.current];case 1:return e.sent(),c.current=null,d.current=Promise.resolve(),l.current=null,s("closed"),[2]}}))}))}(0,i.useEffect)((function(){var n,i=l.current;if("open"===r&&i){var a={current:!1};return null===(n=c.current)||void 0===n||n.cancel(),d.current.then((function(){a.current||(c.current=null,d.current=function(n){return kn(this,void 0,void 0,(function(){var i,a,o,r,s;return In(this,(function(l){switch(l.label){case 0:if(!n.readable)return[3,9];i=new TextDecoderStream,a=n.readable.pipeTo(i.writable),c.current=i.readable.getReader(),l.label=1;case 1:l.trys.push([1,5,6,7]),l.label=2;case 2:return[4,c.current.read()];case 3:return o=l.sent(),r=o.value,o.done?[3,4]:(d=r,e.current=e.current+d,t(d),[3,2]);case 4:return[3,7];case 5:return s=l.sent(),console.error(s),[3,7];case 6:return c.current.releaseLock(),[7];case 7:return[4,a.catch((function(){}))];case 8:l.sent(),l.label=9;case 9:return[2]}var d}))}))}(i))})),navigator.serial.addEventListener("disconnect",f),function(){a.current=!0,navigator.serial.removeEventListener("disconnect",f)}}}),[r]);var g=null;switch(r){case"closed":g=i.createElement(yn.A,{variant:"contained",onClick:function(){return p()}},"Connect");break;case"closing":g=i.createElement(yn.A,{disabled:!0,variant:"contained",onClick:function(){return p()}},"Connect");break;case"open":g=i.createElement(yn.A,{variant:"contained",onClick:function(){return m()}},"Disconnect");break;case"opening":g=i.createElement(yn.A,{disabled:!0,variant:"contained",onClick:function(){return m()}},"Disconnect")}var b=null;return"closed"===r&&""!==e.current&&(b=i.createElement(yn.A,{sx:{marginLeft:2},variant:"outlined",onClick:function(){return n=(new Date).getTime(),t=document.createElement("a"),i=new Blob([e.current],{type:"text/plain"}),t.href=URL.createObjectURL(i),t.download="tidbyt-diagnostics-".concat(n,".txt"),document.body.appendChild(t),void t.click();var n,t,i}},"Download")),i.createElement(Ie.Ay,{container:!0},i.createElement(Ie.Ay,{item:!0,xs:12},g,i.createElement(yn.A,{sx:{marginLeft:2},variant:"outlined",onClick:function(){return h()}},"Reset"),b),i.createElement(Ie.Ay,{item:!0,xs:12,mt:2},i.createElement(Tn,{output:e.current})))}function En(){return i.createElement(P.Kd,null,i.createElement(fn,null),i.createElement(N.BV,null,i.createElement(N.qh,{path:"/",element:i.createElement(un,null)}),i.createElement(N.qh,{path:"/console",element:i.createElement(Je,null,i.createElement(Cn,null))}),i.createElement(N.qh,{path:"/docs/api",element:i.createElement(Je,null,i.createElement(mn,null))}),(n=[],(e=[],Se.keys().forEach((function(n){e.push(_e(n))})),e).forEach((function(e){n.push(i.createElement(N.qh,{key:e.path,path:e.url,element:i.createElement(Je,{source:e.source})}))})),n),i.createElement(N.qh,{path:"/docs",element:i.createElement(N.C5,{to:"/docs/overview/getting-started"})}),i.createElement(N.qh,{path:"/docs/overview",element:i.createElement(N.C5,{to:"/docs/overview/getting-started"})}),i.createElement(N.qh,{path:"/docs/build",element:i.createElement(N.C5,{to:"/docs/build/build-for-tidbyt"})}),i.createElement(N.qh,{path:"/docs/integrate",element:i.createElement(N.C5,{to:"/docs/integrate/pushing-apps"})}),i.createElement(N.qh,{path:"/docs/publish",element:i.createElement(N.C5,{to:"/docs/publish/community-apps"})}),i.createElement(N.qh,{path:"/docs/engage",element:i.createElement(N.C5,{to:"/docs/engage/community"})}),i.createElement(N.qh,{path:"/docs/tidbyt-api",element:i.createElement(N.C5,{to:"/docs/api"})}),i.createElement(N.qh,{path:"*",element:i.createElement(Je,null,i.createElement(bn,null))})));var e,n}var Dn=document.getElementById("app");(0,a.H)(Dn).render(i.createElement((function(){return i.createElement(o.Kq,{store:l},i.createElement(M,null,i.createElement(En,null)))}),null))},95712:e=>{"use strict";e.exports="data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAAAAAD/4QMxaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzExMSA3OS4xNTgzMjUsIDIwMTUvMDkvMTAtMDE6MTA6MjAgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE1IChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkIxMjI0OTczNjdCMzExRTZCMkJDRTI0MDgxMDAyMTcxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkIxMjI0OTc0NjdCMzExRTZCMkJDRTI0MDgxMDAyMTcxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QjEyMjQ5NzE2N0IzMTFFNkIyQkNFMjQwODEwMDIxNzEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QjEyMjQ5NzI2N0IzMTFFNkIyQkNFMjQwODEwMDIxNzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAbGhopHSlBJiZBQi8vL0JHPz4+P0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHAR0pKTQmND8oKD9HPzU/R0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0f/wAARCAAIAAgDASIAAhEBAxEB/8QAWQABAQAAAAAAAAAAAAAAAAAAAAYBAQEAAAAAAAAAAAAAAAAAAAIEEAEBAAMBAAAAAAAAAAAAAAABADECA0ERAAEDBQAAAAAAAAAAAAAAAAARITFBUWESIv/aAAwDAQACEQMRAD8AoOnTV1QTD7JJshP3vSM3P//Z"},35744:e=>{"use strict";e.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTRDOTY4N0U2N0VFMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTRDOTY4N0Q2N0VFMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3NjY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3NzY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsBS+GMAAAAjSURBVHjaYvz//z8DLsD4gcGXiYEAGBIKGBne//fFpwAgwAB98AaF2pjlUQAAAABJRU5ErkJggg=="},99090:e=>{"use strict";e.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzY3MkJEN0U2N0M1MTFFNkIyQkNFMjQwODEwMDIxNzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzY3MkJEN0Y2N0M1MTFFNkIyQkNFMjQwODEwMDIxNzEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3QzY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3RDY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pve6J3kAAAAzSURBVHjaYvz//z8D0UDsMwMjSRoYP5Gq4SPNbRjVMEQ1fCRDg+in/6+J1AJUxsgAEGAA31BAJMS0GYEAAAAASUVORK5CYII="},5015:e=>{"use strict";e.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODYyRjhERDU2N0YyMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODYyRjhERDQ2N0YyMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3QTY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3QjY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvCS01IAAABMSURBVHjaYmR4/5+BFPBfAMFm/MBgx8RAGWCn1AAmSg34Q6kBDKMGMDCwICeMIemF/5QawEipAWwUhwEjMDvbAWlWkvVBwu8vQIABAEwBCph8U6c0AAAAAElFTkSuQmCC"},95234:e=>{"use strict";e.exports='data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M13.418 7.859a.695.695 0 0 1 .978 0 .68.68 0 0 1 0 .969l-3.908 3.83a.697.697 0 0 1-.979 0l-3.908-3.83a.68.68 0 0 1 0-.969.695.695 0 0 1 .978 0L10 11l3.418-3.141z"/></svg>'},7779:e=>{"use strict";e.exports='data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="10" height="8" viewBox="3 7 10 8"><path fill="%2341474E" fill-rule="evenodd" d="M6.333 15 3 11.667l1.333-1.334 2 2L11.667 7 13 8.333z"/></svg>'},12153:e=>{"use strict";e.exports='data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="15" aria-hidden="true"><path fill="%23fff" fill-rule="evenodd" d="M4 12h4v1H4v-1zm5-6H4v1h5V6zm2 3V7l-3 3 3 3v-2h5V9h-5zM6.5 8H4v1h2.5V8zM4 11h2.5v-1H4v1zm9 1h1v2c-.02.28-.11.52-.3.7-.19.18-.42.28-.7.3H3c-.55 0-1-.45-1-1V3c0-.55.45-1 1-1h3c0-1.11.89-2 2-2 1.11 0 2 .89 2 2h3c.55 0 1 .45 1 1v5h-1V5H3v9h10v-2zM4 4h8c0-.55-.45-1-1-1h-1c-.55 0-1-.45-1-1s-.45-1-1-1-1 .45-1 1-.45 1-1 1H5c-.55 0-1 .45-1 1z"/></svg>'},25294:e=>{"use strict";e.exports='data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>'},96846:(e,n,t)=>{"use strict";e.exports=t.p+"c09f12b6ca448e39dafb.otf"},56367:(e,n,t)=>{"use strict";e.exports=t.p+"90fa0184fe76d08f53b6.otf"},42634:()=>{}},a={};function o(e){var n=a[e];if(void 0!==n)return n.exports;var t=a[e]={id:e,loaded:!1,exports:{}};return i[e].call(t.exports,t,t.exports,o),t.loaded=!0,t.exports}o.m=i,e=[],o.O=(n,t,i,a)=>{if(!t){var r=1/0;for(d=0;d<e.length;d++){for(var[t,i,a]=e[d],s=!0,l=0;l<t.length;l++)(!1&a||r>=a)&&Object.keys(o.O).every((e=>o.O[e](t[l])))?t.splice(l--,1):(s=!1,a<r&&(r=a));if(s){e.splice(d--,1);var c=i();void 0!==c&&(n=c)}}return n}a=a||0;for(var d=e.length;d>0&&e[d-1][2]>a;d--)e[d]=e[d-1];e[d]=[t,i,a]},o.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return o.d(n,{a:n}),n},t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,o.t=function(e,i){if(1&i&&(e=this(e)),8&i)return e;if("object"==typeof e&&e){if(4&i&&e.__esModule)return e;if(16&i&&"function"==typeof e.then)return e}var a=Object.create(null);o.r(a);var r={};n=n||[null,t({}),t([]),t(t)];for(var s=2&i&&e;"object"==typeof s&&!~n.indexOf(s);s=t(s))Object.getOwnPropertyNames(s).forEach((n=>r[n]=()=>e[n]));return r.default=()=>e,o.d(a,r),a},o.d=(e,n)=>{for(var t in n)o.o(n,t)&&!o.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),o.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),o.p="/static/",(()=>{o.b=document.baseURI||self.location.href;var e={792:0};o.O.j=n=>0===e[n];var n=(n,t)=>{var i,a,[r,s,l]=t,c=0;if(r.some((n=>0!==e[n]))){for(i in s)o.o(s,i)&&(o.m[i]=s[i]);if(l)var d=l(o)}for(n&&n(t);c<r.length;c++)a=r[c],o.o(e,a)&&e[a]&&e[a][0](),e[a]=0;return o.O(d)},t=self.webpackChunktidbyt_dev=self.webpackChunktidbyt_dev||[];t.forEach(n.bind(null,0)),t.push=n.bind(null,t.push.bind(t))})(),o.nc=void 0;var r=o.O(void 0,[121],(()=>o(47593)));r=o.O(r)})();
//# sourceMappingURL=main.23232c3be2498f546941.js.map