<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[8779] sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks: WordCamp Blocks: File and folder reorganization</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="http://meta.trac.wordpress.org/changeset/8779">8779</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"http://meta.trac.wordpress.org/changeset/8779","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>coreymckrill</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2019-05-10 22:24:19 +0000 (Fri, 10 May 2019)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>WordCamp Blocks: File and folder reorganization

This moves things around so that the files and folders more closely match
the structure used by Gutenberg and other modern JS projects. It also
reorganizes many of the PHP files so that it's easier to correlate them with
their JS counterparts.

Additionally:

* Simplifies the names of child components within blocks, where block name
  prefixes aren't really necessary.
* Eliminates the usage of default exports, in favor of having explicit names
  for every export.
  See https://blog.neufund.org/why-we-have-banned-default-exports-and-you-should-do-the-same-d51fdc2cf2ad</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksblocksphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/blocks.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockswebpackconfigjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/webpack.config.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/build/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksbuildblocksmincss">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/build/blocks.min.css</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksbuildblocksminjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/build/blocks.min.js</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblocksorganizersphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/organizers.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblockssessionsphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/sessions.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblocksspeakersphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/speakers.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblockssponsorsphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/sponsors.php</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludescomponentsblockcontentphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/block-content.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludescomponentsfeaturedimagephp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/featured-image.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludescomponentspostlistphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/post-list.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesdefinitionsphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/definitions.php</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/utilities/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesutilitiescontentphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/utilities/content.php</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/</li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksindexjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/index.js</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizersblockcontentjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/block-content.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizersblockcontrolsjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/block-controls.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizerscontentselectjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/content-select.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizerseditjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/edit.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizersindexjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/index.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizersinspectorcontrolsjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/inspector-controls.js</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionsblockcontentjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/block-content.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionsblockcontrolsjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/block-controls.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionscontentselectjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/content-select.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionseditjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/edit.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionsindexjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/index.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionsinspectorcontrolsjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/inspector-controls.js</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakersblockcontentjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/block-content.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakersblockcontentscss">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/block-content.scss</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakersblockcontrolsjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/block-controls.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakerscontentselectjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/content-select.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakerseditjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/edit.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakersindexjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/index.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakersinspectorcontrolsjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/inspector-controls.js</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorsblockcontentjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/block-content.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorsblockcontrolsjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/block-controls.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorscontentselectjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/content-select.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorseditjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/edit.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorsindexjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/index.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorsinspectorcontrolsjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/inspector-controls.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks.js</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/</li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-content/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsblockcontentindexjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-content/index.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsblockcontentstylescss">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-content/style.scss</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-controls/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsblockcontrolsindexjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-controls/index.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsblockcontrolsstylescss">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-controls/style.scss</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsimageavatarjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/avatar.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsimagefeaturedimagejs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/featured-image.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsimagefeaturedimagescss">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/featured-image.scss</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsimageindexjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/index.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsimageinspectorcontrolsjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/inspector-controls.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsimageinspectorcontrolsscss">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/inspector-controls.scss</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsimagestylescss">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/style.scss</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/item-select/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsitemselectindexjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/item-select/index.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsitemselectoptionjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/item-select/option.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsitemselectstylescss">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/item-select/style.scss</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentspostlistindexjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/index.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentspostlistinspectorcontrolsjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/inspector-controls.js</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentspostliststylescss">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/style.scss</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentspostlisttoolbarjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/toolbar.js</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/data/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcedataindexjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/data/index.js</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/i18n/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcei18nindexjs">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/i18n/index.js</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewsorganizerphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/organizer.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewssessionphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/session.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewsspeakerphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/speaker.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewssponsorphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/sponsor.php</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/assets/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesorganizersphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/organizers.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludessessionsphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/sessions.php</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/shared/</li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesspeakersphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/speakers.php</a></li>
<li><a href="#sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludessponsorsphp">sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/sponsors.php</a></li>
<li>sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/view/</li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksblocksphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/blocks.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/blocks.php      2019-05-10 20:20:52 UTC (rev 8778)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/blocks.php        2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,5 +1,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><span class="cx" style="display: block; padding: 0 10px"> namespace WordCamp\Blocks;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> defined( 'WPINC' ) || die();
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> define( __NAMESPACE__ . '\PLUGIN_DIR', \plugin_dir_path( __FILE__ ) );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -10,20 +11,29 @@
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @return void
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function load() {
-       require_once PLUGIN_DIR . 'includes/shared/content.php';
-       require_once PLUGIN_DIR . 'includes/shared/definitions.php';
-       require_once PLUGIN_DIR . 'includes/shared/featured-image.php';
-       require_once PLUGIN_DIR . 'includes/shared/post-list.php';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function load_includes() {
+       $includes_dir = PLUGIN_DIR . 'includes/';
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        require_once PLUGIN_DIR . 'includes/organizers.php';
-       require_once PLUGIN_DIR . 'includes/sessions.php';
-       require_once PLUGIN_DIR . 'includes/speakers.php';
-       require_once PLUGIN_DIR . 'includes/sponsors.php';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ require_once $includes_dir . 'definitions.php';
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        // Utilities.
+       require_once $includes_dir . 'utilities/content.php';
+
+       // Components.
+       require_once $includes_dir . 'components/block-content.php';
+       require_once $includes_dir . 'components/featured-image.php';
+       require_once $includes_dir . 'components/post-list.php';
+
+       // Blocks.
+       require_once $includes_dir . 'blocks/organizers.php';
+       require_once $includes_dir . 'blocks/sessions.php';
+       require_once $includes_dir . 'blocks/speakers.php';
+       require_once $includes_dir . 'blocks/sponsors.php';
+
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-add_action( 'plugins_loaded', __NAMESPACE__ . '\load' );
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+add_action( 'plugins_loaded', __NAMESPACE__ . '\load_includes' );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px">  * Add block categories for custom blocks.
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -52,14 +62,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> function register_assets() {
</span><span class="cx" style="display: block; padding: 0 10px">        wp_register_style(
</span><span class="cx" style="display: block; padding: 0 10px">                'wordcamp-blocks',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                PLUGIN_URL . 'assets/blocks.min.css',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         PLUGIN_URL . 'build/blocks.min.css',
</ins><span class="cx" style="display: block; padding: 0 10px">                 [],
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                filemtime( PLUGIN_DIR . 'assets/blocks.min.css' )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         filemtime( PLUGIN_DIR . 'build/blocks.min.css' )
</ins><span class="cx" style="display: block; padding: 0 10px">         );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        wp_register_script(
</span><span class="cx" style="display: block; padding: 0 10px">                'wordcamp-blocks',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                PLUGIN_URL . 'assets/blocks.min.js',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         PLUGIN_URL . 'build/blocks.min.js',
</ins><span class="cx" style="display: block; padding: 0 10px">                 array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'lodash',
</span><span class="cx" style="display: block; padding: 0 10px">                        'wp-api-fetch',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -73,7 +83,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        'wp-i18n',
</span><span class="cx" style="display: block; padding: 0 10px">                        'wp-url',
</span><span class="cx" style="display: block; padding: 0 10px">                ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                filemtime( PLUGIN_DIR . 'assets/blocks.min.js' ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         filemtime( PLUGIN_DIR . 'build/blocks.min.js' ),
</ins><span class="cx" style="display: block; padding: 0 10px">                 false
</span><span class="cx" style="display: block; padding: 0 10px">        );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksbuildblocksmincss"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/build/blocks.min.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/build/blocks.min.css                            (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/build/blocks.min.css      2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,140 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.wordcamp-clearfix::after {
+  content: "";
+  display: table;
+  clear: both; }
+
+.wordcamp-post-list.wordcamp-post-list {
+  list-style: none; }
+
+.wordcamp-post-list .wordcamp-post-list-item {
+  margin: 0 0 1em 0; }
+  .layout-list .wordcamp-post-list .wordcamp-post-list-item {
+    margin-bottom: 1em; }
+    .layout-list .wordcamp-post-list .wordcamp-post-list-item:last-child {
+      margin-bottom: 0; }
+
+@media (min-width: 400px) {
+  .wordcamp-post-list.layout-grid {
+    display: grid;
+    grid-template-columns: repeat(2, 1fr);
+    grid-column-gap: 1em;
+    grid-row-gap: 1em;
+    /* Ensure columns maintain equal widths. */
+    /* https://stackoverflow.com/a/43312314 */
+    min-height: 0;
+    min-width: 0; }
+    .wordcamp-post-list.layout-grid .wordcamp-post-list-item {
+      overflow: hidden;
+      min-width: 0; } }
+
+@media (min-width: 600px) {
+  .wordcamp-post-list.layout-grid.grid-columns-3 {
+    grid-template-columns: repeat(3, 1fr); } }
+
+@media (min-width: 800px) {
+  .wordcamp-post-list.layout-grid.grid-columns-4 {
+    grid-template-columns: repeat(4, 1fr); } }
+
+.wordcamp-block-edit-mode-option {
+  flex-basis: 100%;
+  padding: 0.5em; }
+
+.wordcamp-block-edit-placeholder .components-placeholder__fieldset {
+  /*
+        * By default the fieldset has a `z-index` of `1`, and `.editor-block-list__insertion-point` has a value of
+        * `6`, so the `Add Block` button will stack on top of things like an expanded `ItemSelect` list. This
+        * corrects that.
+        */
+  z-index: 7; }
+
+.wordcamp-item-select-inner {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  text-align: left; }
+
+.wordcamp-item-select-select {
+  flex-grow: 2;
+  margin-right: 1em; }
+  .rtl .wordcamp-item-select-select {
+    margin-left: 1em;
+    margin-right: 0; }
+  .wordcamp-item-select-select input[type="text"]:focus {
+    box-shadow: none; }
+
+.wordcamp-item-select-option {
+  display: flex;
+  align-items: center; }
+
+.wordcamp-item-select-option-avatar,
+.wordcamp-item-select-option-icon-container {
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  flex: 0 0 24px;
+  height: 24px;
+  background-color: #f3f3f4; }
+
+.wordcamp-item-select-option-label {
+  margin: 0 0.5em;
+  white-space: normal; }
+
+.wordcamp-item-select-option-label-count {
+  font-size: 0.6em;
+  display: inline-block;
+  border-radius: 50%;
+  background-color: #f3f3f4;
+  width: 2.2em;
+  height: 2.2em;
+  margin: 0 0.5em;
+  text-align: center;
+  line-height: 2.2em;
+  vertical-align: text-top; }
+
+.wordcamp-item-select {
+  width: 100%; }
+
+.wordcamp-image-container.align-left {
+  float: left;
+  margin-right: 1em; }
+
+.wordcamp-image-container.align-center {
+  margin-left: auto;
+  margin-right: auto;
+  text-align: center; }
+
+.wordcamp-image-container.align-right {
+  float: right;
+  margin-left: 1em; }
+
+img.wordcamp-featured-image {
+  max-width: 100%;
+  max-height: 100%; }
+
+.wordcamp-image-size-preset-buttons {
+  display: flex;
+  justify-content: space-between; }
+
+.edit-post-settings-sidebar__panel-block .components-panel__body .wordcamp-image-size-range {
+  margin-top: 1em; }
+
+.wordcamp-block-content-none {
+  margin: 1em 0;
+  text-align: center; }
+  .wordcamp-block-content-none .components-spinner {
+    float: none; }
+
+.wordcamp-item-meta {
+  margin: 0 0 1.5em; }
+
+.wordcamp-speaker-sessions-list.wordcamp-speaker-sessions-list {
+  list-style: none;
+  margin: 0; }
+
+.wordcamp-speaker-session-link,
+.wordcamp-speaker-session-info {
+  display: block; }
+
+.wordcamp-speaker-session-info {
+  font-style: italic; }
+
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksbuildblocksminjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/build/blocks.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/build/blocks.min.js                             (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/build/blocks.min.js       2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,12 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?functio
 n(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=55)}([function(e,t){e.exports=React},function(e,t){e.exports=lodash},function(e,t){e.exports=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}e.exports=function(e,t,r){return t&&n(e.prototype,t),r&&n(e,r),e}},function(e,t,n){var r=n(30),o=n(8);e.exports=function(e,t){return!t||"object"!==r(t)&&"function"!=typeof t?o(e):t}},function(e,t){function n(t){return e.exports=n=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)},n(t)}e.exports=n},function(e,t,n){var r=n(31);e.exports=
 function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&r(e,t)}},function(e,t,n){var r;
+/*!
+  Copyright (c) 2017 Jed Watson.
+  Licensed under the MIT License (MIT), see
+  http://jedwatson.github.io/classnames
+*/
+/*!
+  Copyright (c) 2017 Jed Watson.
+  Licensed under the MIT License (MIT), see
+  http://jedwatson.github.io/classnames
+*/
+!function(){"use strict";var n={}.hasOwnProperty;function o(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var i=typeof r;if("string"===i||"number"===i)e.push(r);else if(Array.isArray(r)&&r.length){var a=o.apply(null,r);a&&e.push(a)}else if("object"===i)for(var s in r)n.call(r,s)&&r[s]&&e.push(s)}}return e.join(" ")}e.exports?(o.default=o,e.exports=o):void 0===(r=function(){return o}.apply(t,[]))||(e.exports=r)}()},function(e,t){e.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}},function(e,t){function n(){return e.exports=n=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},n.apply(this,arguments)}e.exports=n},function(e,t,n){"use strict";(function(e){n.d(t,&
 quot;b",function(){return a}),n.d(t,"a",function(){return s});var r=n(29),o=void 0!==e?e:{},i=Object(r.a)(o),a=(i.flush,i.hydrate,i.cx,i.merge,i.getRegisteredStyles,i.injectGlobal),s=(i.keyframes,i.css);i.sheet,i.caches}).call(this,n(20))},function(e,t){e.exports=ReactDOM},function(e,t,n){e.exports=n(39)()},function(e,t,n){var r=n(17),o=n(34),i=n(18);e.exports=function(e,t){return r(e)||o(e,t)||i()}},function(e,t,n){var r=n(33);e.exports=function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},o=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(o=o.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),o.forEach(function(t){r(e,t,n[t])})}return e}},function(e,t,n){var r=n(35),o=n(19),i=n(36);e.exports=function(e){return r(e)||o(e)||i()}},function(e,t,n){"use strict";var r=s(n(43)),o=s(n(48)),i=s(n(24)),a=s(n(21));function s(e){ret
 urn e&&e.__esModule?e:{default:e}}e.exports={Transition:a.default,TransitionGroup:i.default,ReplaceTransition:o.default,CSSTransition:r.default}},function(e,t){e.exports=function(e){if(Array.isArray(e))return e}},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}},function(e,t){e.exports=function(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}},function(e,t){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){"use strict";t.__esModule=!0,t.default=t.EXITING=t.ENTERED=t.ENTERING=t.EXITED=t.UNMOUNTED=void 0;var r=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=Object.defineProperty&&O
 bject.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,n):{};r.get||r.set?Object.defineProperty(t,n,r):t[n]=e[n]}return t.default=e,t}(n(12)),o=s(n(0)),i=s(n(11)),a=n(22);n(23);function s(e){return e&&e.__esModule?e:{default:e}}var u="unmounted";t.UNMOUNTED=u;var l="exited";t.EXITED=l;var c="entering";t.ENTERING=c;var p="entered";t.ENTERED=p;t.EXITING="exiting";var d=function(e){function t(t,n){var r;r=e.call(this,t,n)||this;var o,i=n.transitionGroup,a=i&&!i.isMounting?t.enter:t.appear;return r.appearStatus=null,t.in?a?(o=l,r.appearStatus=c):o=p:o=t.unmountOnExit||t.mountOnEnter?u:l,r.state={status:o},r.nextCallback=null,r}!function(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}(t,e);var n=t.prototype;return n.getChildContext=function(){return{transitionGroup:null}},t.getDerivedStateFromProps=function(e,t){return e.in&&t.status===u?{status:l}:null},n.componentDid
 Mount=function(){this.updateStatus(!0,this.appearStatus)},n.componentDidUpdate=function(e){var t=null;if(e!==this.props){var n=this.state.status;this.props.in?n!==c&&n!==p&&(t=c):n!==c&&n!==p||(t="exiting")}this.updateStatus(!1,t)},n.componentWillUnmount=function(){this.cancelNextCallback()},n.getTimeouts=function(){var e,t,n,r=this.props.timeout;return e=t=n=r,null!=r&&"number"!=typeof r&&(e=r.exit,t=r.enter,n=void 0!==r.appear?r.appear:t),{exit:e,enter:t,appear:n}},n.updateStatus=function(e,t){if(void 0===e&&(e=!1),null!==t){this.cancelNextCallback();var n=i.default.findDOMNode(this);t===c?this.performEnter(n,e):this.performExit(n)}else this.props.unmountOnExit&&this.state.status===l&&this.setState({status:u})},n.performEnter=function(e,t){var n=this,r=this.props.enter,o=this.context.transitionGroup?this.context.transitionGroup.isMounting:t,i=this.getTimeouts(),a=o?i.appear:i.enter;t||r?(this.props
 .onEnter(e,o),this.safeSetState({status:c},function(){n.props.onEntering(e,o),n.onTransitionEnd(e,a,function(){n.safeSetState({status:p},function(){n.props.onEntered(e,o)})})})):this.safeSetState({status:p},function(){n.props.onEntered(e)})},n.performExit=function(e){var t=this,n=this.props.exit,r=this.getTimeouts();n?(this.props.onExit(e),this.safeSetState({status:"exiting"},function(){t.props.onExiting(e),t.onTransitionEnd(e,r.exit,function(){t.safeSetState({status:l},function(){t.props.onExited(e)})})})):this.safeSetState({status:l},function(){t.props.onExited(e)})},n.cancelNextCallback=function(){null!==this.nextCallback&&(this.nextCallback.cancel(),this.nextCallback=null)},n.safeSetState=function(e,t){t=this.setNextCallback(t),this.setState(e,t)},n.setNextCallback=function(e){var t=this,n=!0;return this.nextCallback=function(r){n&&(n=!1,t.nextCallback=null,e(r))},this.nextCallback.cancel=function(){n=!1},this.nextCallback},n.onTransitionEnd=function(e,
 t,n){this.setNextCallback(n);var r=null==t&&!this.props.addEndListener;e&&!r?(this.props.addEndListener&&this.props.addEndListener(e,this.nextCallback),null!=t&&setTimeout(this.nextCallback,t)):setTimeout(this.nextCallback,0)},n.render=function(){var e=this.state.status;if(e===u)return null;var t=this.props,n=t.children,r=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(t,["children"]);if(delete r.in,delete r.mountOnEnter,delete r.unmountOnExit,delete r.appear,delete r.enter,delete r.exit,delete r.timeout,delete r.addEndListener,delete r.onEnter,delete r.onEntering,delete r.onEntered,delete r.onExit,delete r.onExiting,delete r.onExited,"function"==typeof n)return n(e,r);var i=o.default.Children.only(n);return o.default.cloneElement(i,r)},t}(o.default.Component);function f(){}d.contextTypes={transitionGroup:r.object},d.childContextTypes={transi
 tionGroup:function(){}},d.propTypes={},d.defaultProps={in:!1,mountOnEnter:!1,unmountOnExit:!1,appear:!1,enter:!0,exit:!0,onEnter:f,onEntering:f,onEntered:f,onExit:f,onExiting:f,onExited:f},d.UNMOUNTED=0,d.EXITED=1,d.ENTERING=2,d.ENTERED=3,d.EXITING=4;var m=(0,a.polyfill)(d);t.default=m},function(e,t,n){"use strict";function r(){var e=this.constructor.getDerivedStateFromProps(this.props,this.state);null!==e&&void 0!==e&&this.setState(e)}function o(e){this.setState(function(t){var n=this.constructor.getDerivedStateFromProps(e,t);return null!==n&&void 0!==n?n:null}.bind(this))}function i(e,t){try{var n=this.props,r=this.state;this.props=e,this.state=t,this.__reactInternalSnapshotFlag=!0,this.__reactInternalSnapshot=this.getSnapshotBeforeUpdate(n,r)}finally{this.props=n,this.state=r}}function a(e){var t=e.prototype;if(!t||!t.isReactComponent)throw new Error("Can only polyfill class components");if("function"!=typeof e.getDerivedState
 FromProps&&"function"!=typeof t.getSnapshotBeforeUpdate)return e;var n=null,a=null,s=null;if("function"==typeof t.componentWillMount?n="componentWillMount":"function"==typeof t.UNSAFE_componentWillMount&&(n="UNSAFE_componentWillMount"),"function"==typeof t.componentWillReceiveProps?a="componentWillReceiveProps":"function"==typeof t.UNSAFE_componentWillReceiveProps&&(a="UNSAFE_componentWillReceiveProps"),"function"==typeof t.componentWillUpdate?s="componentWillUpdate":"function"==typeof t.UNSAFE_componentWillUpdate&&(s="UNSAFE_componentWillUpdate"),null!==n||null!==a||null!==s){var u=e.displayName||e.name,l="function"==typeof e.getDerivedStateFromProps?"getDerivedStateFromProps()":"getSnapshotBeforeUpdate()";throw Error("Unsafe legacy lifecycles will not be called for components using new c
 omponent APIs.\n\n"+u+" uses "+l+" but also contains the following legacy lifecycles:"+(null!==n?"\n  "+n:"")+(null!==a?"\n  "+a:"")+(null!==s?"\n  "+s:"")+"\n\nThe above lifecycles should be removed. Learn more about this warning here:\nhttps://fb.me/react-async-component-lifecycle-hooks")}if("function"==typeof e.getDerivedStateFromProps&&(t.componentWillMount=r,t.componentWillReceiveProps=o),"function"==typeof t.getSnapshotBeforeUpdate){if("function"!=typeof t.componentDidUpdate)throw new Error("Cannot polyfill getSnapshotBeforeUpdate() for components that do not define componentDidUpdate() on the prototype");t.componentWillUpdate=i;var c=t.componentDidUpdate;t.componentDidUpdate=function(e,t,n){var r=this.__reactInternalSnapshotFlag?this.__reactInternalSnapshot:n;c.call(this,e,t,r)}}return e}n.r(t),n.d(t,"polyfill",function(){ret
 urn a}),r.__suppressDeprecationWarning=!0,o.__suppressDeprecationWarning=!0,i.__suppressDeprecationWarning=!0},function(e,t,n){"use strict";t.__esModule=!0,t.classNamesShape=t.timeoutsShape=void 0;!function(e){e&&e.__esModule}(n(12));t.timeoutsShape=null;t.classNamesShape=null},function(e,t,n){"use strict";t.__esModule=!0,t.default=void 0;var r=s(n(12)),o=s(n(0)),i=n(22),a=n(49);function s(e){return e&&e.__esModule?e:{default:e}}function u(){return(u=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function l(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}var c=Object.values||function(e){return Object.keys(e).map(function(t){return e[t]})},p=function(e){function t(t,n){var r,o=(r=e.call(this,t,n)||this).handleExited.bind(l(l(r)))
 ;return r.state={handleExited:o,firstRender:!0},r}!function(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}(t,e);var n=t.prototype;return n.getChildContext=function(){return{transitionGroup:{isMounting:!this.appeared}}},n.componentDidMount=function(){this.appeared=!0,this.mounted=!0},n.componentWillUnmount=function(){this.mounted=!1},t.getDerivedStateFromProps=function(e,t){var n=t.children,r=t.handleExited;return{children:t.firstRender?(0,a.getInitialChildMapping)(e,r):(0,a.getNextChildMapping)(e,n,r),firstRender:!1}},n.handleExited=function(e,t){var n=(0,a.getChildMapping)(this.props.children);e.key in n||(e.props.onExited&&e.props.onExited(t),this.mounted&&this.setState(function(t){var n=u({},t.children);return delete n[e.key],{children:n}}))},n.render=function(){var e=this.props,t=e.component,n=e.childFactory,r=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||
 (o[n]=e[n]);return o}(e,["component","childFactory"]),i=c(this.state.children).map(n);return delete r.appear,delete r.enter,delete r.exit,null===t?i:o.default.createElement(t,r,i)},t}(o.default.Component);p.childContextTypes={transitionGroup:r.default.object.isRequired},p.propTypes={},p.defaultProps={component:"div",childFactory:function(e){return e}};var d=(0,i.polyfill)(p);t.default=d,e.exports=t.default},function(e,t,n){e.exports=function(){"use strict";return function(e){function t(t){if(t)try{e(t+"}")}catch(e){}}return function(n,r,o,i,a,s,u,l,c,p){switch(n){case 1:if(0===c&&64===r.charCodeAt(0))return e(r+";"),"";break;case 2:if(0===l)return r+"/*|*/";break;case 3:switch(l){case 102:case 112:return e(o[0]+r),"";default:return r+(0===p?"/*|*/":"")}case-2:r.split("/*|*/}").forEach(t)}}}}()},function(e,t,n){(function(t){for(var r=n(41),o="undefined&
 quot;==typeof window?t:window,i=["moz","webkit"],a="AnimationFrame",s=o["request"+a],u=o["cancel"+a]||o["cancelRequest"+a],l=0;!s&&l<i.length;l++)s=o[i[l]+"Request"+a],u=o[i[l]+"Cancel"+a]||o[i[l]+"CancelRequest"+a];if(!s||!u){var c=0,p=0,d=[];s=function(e){if(0===d.length){var t=r(),n=Math.max(0,1e3/60-(t-c));c=n+t,setTimeout(function(){var e=d.slice(0);d.length=0;for(var t=0;t<e.length;t++)if(!e[t].cancelled)try{e[t].callback(c)}catch(e){setTimeout(function(){throw e},0)}},Math.round(n))}return d.push({handle:++p,callback:e,cancelled:!1}),p},u=function(e){for(var t=0;t<d.length;t++)d[t].handle===e&&(d[t].cancelled=!0)}}e.exports=function(e){return s.call(o,e)},e.exports.cancel=function(){u.apply(o,arguments)},e.exports.polyfill=function(e){e||(e=o),e.requestAnimationFrame=s,e.cancelAnimationFrame=u}}).call(this,n(20))},function(e,t,n){"use strict";Object.def
 ineProperty(t,"__esModule",{value:!0});var r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},o=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),i=n(0),a=u(i),s=u(n(12));function u(e){return e&&e.__esModule?e:{default:e}}var l={position:"absolute",top:0,left:0,visibility:"hidden",height:0,overflow:"scroll",whiteSpace:"pre"},c=["extraWidth","injectStyles","inputClassName","inputRef","inputStyle","minWidth","onAutosize","placeholderIsMinWidth"],p=function(e,t){t.style.fontSize=e.fontSize,t.style.fontF
 amily=e.fontFamily,t.style.fontWeight=e.fontWeight,t.style.fontStyle=e.fontStyle,t.style.letterSpacing=e.letterSpacing,t.style.textTransform=e.textTransform},d=!("undefined"==typeof window||!window.navigator)&&/MSIE |Trident\/|Edge\//.test(window.navigator.userAgent),f=function(){return d?"_"+Math.random().toString(36).substr(2,12):void 0},m=function(e){function t(e){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);var n=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return n.inputRef=function(e){n.input=e,"function"==typeof n.props.inputRef&&n.props.inputRef(e)},n.placeHolderSizerRef=function(e){n.placeHolderSizer=e},n.sizerRef=function(e){n.sizer=e},n.state={inputWi
 dth:e.minWidth,inputId:e.id||f()},n}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,i.Component),o(t,[{key:"componentDidMount",value:function(){this.mounted=!0,this.copyInputStyles(),this.updateInputWidth()}},{key:"componentWillReceiveProps",value:function(e){var t=e.id;t!==this.props.id&&this.setState({inputId:t||f()})}},{key:"componentDidUpdate",value:function(e,t){t.inputWidth!==this.state.inputWidth&&"function"==typeof this.props.onAutosize&&this.props.onAutosize(this.state.inputWidth),this.updateInputWidth()}},{key:"componentWillUnmount",value:function(){this.mounted=!1}},{key:"copyInput
 Styles",value:function(){if(this.mounted&&window.getComputedStyle){var e=this.input&&window.getComputedStyle(this.input);e&&(p(e,this.sizer),this.placeHolderSizer&&p(e,this.placeHolderSizer))}}},{key:"updateInputWidth",value:function(){if(this.mounted&&this.sizer&&void 0!==this.sizer.scrollWidth){var e=void 0;e=this.props.placeholder&&(!this.props.value||this.props.value&&this.props.placeholderIsMinWidth)?Math.max(this.sizer.scrollWidth,this.placeHolderSizer.scrollWidth)+2:this.sizer.scrollWidth+2,(e+="number"===this.props.type&&void 0===this.props.extraWidth?16:parseInt(this.props.extraWidth)||0)<this.props.minWidth&&(e=this.props.minWidth),e!==this.state.inputWidth&&this.setState({inputWidth:e})}}},{key:"getInput",value:function(){return this.input}},{key:"focus",value:function(){this.input.focus()}},{key:"blur",value:function(){this.inp
 ut.blur()}},{key:"select",value:function(){this.input.select()}},{key:"renderStyles",value:function(){var e=this.props.injectStyles;return d&&e?a.default.createElement("style",{dangerouslySetInnerHTML:{__html:"input#"+this.state.inputId+"::-ms-clear {display: none;}"}}):null}},{key:"render",value:function(){var e=[this.props.defaultValue,this.props.value,""].reduce(function(e,t){return null!==e&&void 0!==e?e:t}),t=r({},this.props.style);t.display||(t.display="inline-block");var n=r({boxSizing:"content-box",width:this.state.inputWidth+"px"},this.props.inputStyle),o=function(e,t){var n={};for(var r in e)t.indexOf(r)>=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}(this.props,[]);return function(e){c.forEach(function(t){return delete e[t]})}(o),o.className=this.props.inputClassName,o.id=this.state.inputId,o.style=n,a.default.createElement(&q
 uot;div",{className:this.props.className,style:t},this.renderStyles(),a.default.createElement("input",r({},o,{ref:this.inputRef})),a.default.createElement("div",{ref:this.sizerRef,style:l},e),this.props.placeholder?a.default.createElement("div",{ref:this.placeHolderSizerRef,style:l},this.props.placeholder):null)}}]),t}();m.propTypes={className:s.default.string,defaultValue:s.default.any,extraWidth:s.default.oneOfType([s.default.number,s.default.string]),id:s.default.string,injectStyles:s.default.bool,inputClassName:s.default.string,inputRef:s.default.func,inputStyle:s.default.object,minWidth:s.default.oneOfType([s.default.number,s.default.string]),onAutosize:s.default.func,onChange:s.default.func,placeholder:s.default.string,placeholderIsMinWidth:s.default.bool,style:s.default.object,value:s.default.any},m.defaultProps={minWidth:1,injectStyles:!0},t.default=m},function(e,t,n){var r=n(17),o=n(19),i=n(18);e.exports=function(e){return r(e)||o(e)||i()}
 },function(e,t,n){"use strict";var r=function(e){var t={};return function(n){return void 0===t[n]&&(t[n]=e(n)),t[n]}},o={animationIterationCount:1,borderImageOutset:1,borderImageSlice:1,borderImageWidth:1,boxFlex:1,boxFlexGroup:1,boxOrdinalGroup:1,columnCount:1,columns:1,flex:1,flexGrow:1,flexPositive:1,flexShrink:1,flexNegative:1,flexOrder:1,gridRow:1,gridRowEnd:1,gridRowSpan:1,gridRowStart:1,gridColumn:1,gridColumnEnd:1,gridColumnSpan:1,gridColumnStart:1,fontWeight:1,lineHeight:1,opacity:1,order:1,orphans:1,tabSize:1,widows:1,zIndex:1,zoom:1,WebkitLineClamp:1,fillOpacity:1,floodOpacity:1,stopOpacity:1,strokeDasharray:1,strokeDashoffset:1,strokeMiterlimit:1,strokeOpacity:1,strokeWidth:1};var i=function(e){for(var t,n=e.length,r=n^n,o=0;n>=4;)t=1540483477*(65535&(t=255&e.charCodeAt(o)|(255&e.charCodeAt(++o))<<8|(255&e.charCodeAt(++o))<<16|(255&e.charCodeAt(++o))<<24))+((1540483477*(t>>>16)&65535)<<16),r=15
 40483477*(65535&r)+((1540483477*(r>>>16)&65535)<<16)^(t=1540483477*(65535&(t^=t>>>24))+((1540483477*(t>>>16)&65535)<<16)),n-=4,++o;switch(n){case 3:r^=(255&e.charCodeAt(o+2))<<16;case 2:r^=(255&e.charCodeAt(o+1))<<8;case 1:r=1540483477*(65535&(r^=255&e.charCodeAt(o)))+((1540483477*(r>>>16)&65535)<<16)}return r=1540483477*(65535&(r^=r>>>13))+((1540483477*(r>>>16)&65535)<<16),((r^=r>>>15)>>>0).toString(36)};var a=function(e){function t(e,t,r){var o=t.trim().split(m);t=o;var i=o.length,a=e.length;switch(a){case 0:case 1:var s=0;for(e=0===a?"":e[0]+" ";s<i;++s)t[s]=n(e,t[s],r).trim();break;default:var u=s=0;for(t=[];s<i;++s)for(var l=0;l<a;++l)t[u++]=n(e[l]+" ",o[s],r).trim()}return t}function n(e,t,n){var r=t.charCodeAt(0);switch(33>r&&(r=(t=t.trim()).charCodeAt(0)),r){case 38:return t.r
 eplace(h,"$1"+e.trim());case 58:return e.trim()+t.replace(h,"$1"+e.trim());default:if(0<1*n&&0<t.indexOf("\f"))return t.replace(h,(58===e.charCodeAt(0)?"":"$1")+e.trim())}return e+t}function r(e,t,n,i){var a=e+";",s=2*t+3*n+4*i;if(944===s){e=a.indexOf(":",9)+1;var u=a.substring(e,a.length-1).trim();return u=a.substring(0,e).trim()+u+";",1===j||2===j&&o(u,1)?"-webkit-"+u+u:u}if(0===j||2===j&&!o(a,1))return a;switch(s){case 1015:return 97===a.charCodeAt(10)?"-webkit-"+a+a:a;case 951:return 116===a.charCodeAt(3)?"-webkit-"+a+a:a;case 963:return 110===a.charCodeAt(5)?"-webkit-"+a+a:a;case 1009:if(100!==a.charCodeAt(4))break;case 969:case 942:return"-webkit-"+a+a;case 978:return"-webkit-"+a+"-moz-"+a+a;case 1019:case 983:return"-webkit-"+a+"-moz-"+a+"-ms-"+a+a;case 883:if(45===a.ch
 arCodeAt(8))return"-webkit-"+a+a;if(0<a.indexOf("image-set(",11))return a.replace(S,"$1-webkit-$2")+a;break;case 932:if(45===a.charCodeAt(4))switch(a.charCodeAt(5)){case 103:return"-webkit-box-"+a.replace("-grow","")+"-webkit-"+a+"-ms-"+a.replace("grow","positive")+a;case 115:return"-webkit-"+a+"-ms-"+a.replace("shrink","negative")+a;case 98:return"-webkit-"+a+"-ms-"+a.replace("basis","preferred-size")+a}return"-webkit-"+a+"-ms-"+a+a;case 964:return"-webkit-"+a+"-ms-flex-"+a+a;case 1023:if(99!==a.charCodeAt(8))break;return"-webkit-box-pack"+(u=a.substring(a.indexOf(":",15)).replace("flex-","").replace("space-between","justify"))+"-webkit-"+a+"-ms-flex-pack"+u+a;case 1005:return d.test(
 a)?a.replace(p,":-webkit-")+a.replace(p,":-moz-")+a:a;case 1e3:switch(t=(u=a.substring(13).trim()).indexOf("-")+1,u.charCodeAt(0)+u.charCodeAt(t)){case 226:u=a.replace(E,"tb");break;case 232:u=a.replace(E,"tb-rl");break;case 220:u=a.replace(E,"lr");break;default:return a}return"-webkit-"+a+"-ms-"+u+a;case 1017:if(-1===a.indexOf("sticky",9))break;case 975:switch(t=(a=e).length-10,s=(u=(33===a.charCodeAt(t)?a.substring(0,t):a).substring(e.indexOf(":",7)+1).trim()).charCodeAt(0)+(0|u.charCodeAt(7))){case 203:if(111>u.charCodeAt(8))break;case 115:a=a.replace(u,"-webkit-"+u)+";"+a;break;case 207:case 102:a=a.replace(u,"-webkit-"+(102<s?"inline-":"")+"box")+";"+a.replace(u,"-webkit-"+u)+";"+a.replace(u,"-ms-"+u+"box")+";"+a}return a+";";case 938:if(45===a.c
 harCodeAt(5))switch(a.charCodeAt(6)){case 105:return"-webkit-"+a+"-webkit-box-"+(u=a.replace("-items",""))+"-ms-flex-"+u+a;case 115:return"-webkit-"+a+"-ms-flex-item-"+a.replace(O,"")+a;default:return"-webkit-"+a+"-ms-flex-line-pack"+a.replace("align-content","").replace(O,"")+a}break;case 973:case 989:if(45!==a.charCodeAt(3)||122===a.charCodeAt(4))break;case 931:case 953:if(!0===k.test(e))return 115===(u=e.substring(e.indexOf(":")+1)).charCodeAt(0)?r(e.replace("stretch","fill-available"),t,n,i).replace(":fill-available",":stretch"):a.replace(u,"-webkit-"+u)+a.replace(u,"-moz-"+u.replace("fill-",""))+a;break;case 962:if(a="-webkit-"+a+(102===a.charCodeAt(5)?"-ms-"+a:"")+a,211===n+i&&105===a.charCodeAt(13)&&0<a.indexOf(
 "transform",10))return a.substring(0,a.indexOf(";",27)+1).replace(f,"$1-webkit-$2")+a}return a}function o(e,t){var n=e.indexOf(1===t?":":"{"),r=e.substring(0,3!==t?n:10);return n=e.substring(n+1,e.length-1),P(2!==t?r:r.replace(C,"$1"),n,t)}function i(e,t){var n=r(t,t.charCodeAt(0),t.charCodeAt(1),t.charCodeAt(2));return n!==t+";"?n.replace(w," or ($1)").substring(4):"("+t+")"}function a(e,t,n,r,o,i,a,s,l,c){for(var p,d=0,f=t;d<N;++d)switch(p=D[d].call(u,e,f,n,r,o,i,a,s,l,c)){case void 0:case!1:case!0:case null:break;default:f=p}if(f!==t)return f}function s(e){return void 0!==(e=e.prefix)&&(P=null,e?"function"!=typeof e?j=1:(j=2,P=e):j=0),s}function u(e,n){var s=e;if(33>s.charCodeAt(0)&&(s=s.trim()),s=[s],0<N){var u=a(-1,n,s,s,x,A,0,0,0,0);void 0!==u&&"string"==typeof u&&(n=u)}var p=function e(n,s,u,p,d){for(var f,m,h,E,w,O=0
 ,C=0,k=0,S=0,D=0,P=0,T=h=f=0,I=0,M=0,V=0,R=0,B=u.length,z=B-1,U="",W="",H="",G="";I<B;){if(m=u.charCodeAt(I),I===z&&0!==C+S+k+O&&(0!==C&&(m=47===C?10:47),S=k=O=0,B++,z++),0===C+S+k+O){if(I===z&&(0<M&&(U=U.replace(c,"")),0<U.trim().length)){switch(m){case 32:case 9:case 59:case 13:case 10:break;default:U+=u.charAt(I)}m=59}switch(m){case 123:for(f=(U=U.trim()).charCodeAt(0),h=1,R=++I;I<B;){switch(m=u.charCodeAt(I)){case 123:h++;break;case 125:h--;break;case 47:switch(m=u.charCodeAt(I+1)){case 42:case 47:e:{for(T=I+1;T<z;++T)switch(u.charCodeAt(T)){case 47:if(42===m&&42===u.charCodeAt(T-1)&&I+2!==T){I=T+1;break e}break;case 10:if(47===m){I=T+1;break e}}I=T}}break;case 91:m++;case 40:m++;case 34:case 39:for(;I++<z&&u.charCodeAt(I)!==m;);}if(0===h)break;I++}switch(h=u.substring(R,I),0===f&&(f=(U=U.replace(l,"").trim()).charCodeAt(0)),f){cas
 e 64:switch(0<M&&(U=U.replace(c,"")),m=U.charCodeAt(1)){case 100:case 109:case 115:case 45:M=s;break;default:M=F}if(R=(h=e(s,M,h,m,d+1)).length,0<N&&(w=a(3,h,M=t(F,U,V),s,x,A,R,m,d,p),U=M.join(""),void 0!==w&&0===(R=(h=w.trim()).length)&&(m=0,h="")),0<R)switch(m){case 115:U=U.replace(y,i);case 100:case 109:case 45:h=U+"{"+h+"}";break;case 107:h=(U=U.replace(g,"$1 $2"))+"{"+h+"}",h=1===j||2===j&&o("@"+h,3)?"@-webkit-"+h+"@"+h:"@"+h;break;default:h=U+h,112===p&&(W+=h,h="")}else h="";break;default:h=e(s,t(s,U,V),h,p,d+1)}H+=h,h=V=M=T=f=0,U="",m=u.charCodeAt(++I);break;case 125:case 59:if(1<(R=(U=(0<M?U.replace(c,""):U).trim()).length))switch(0===T&&(f=U.charCodeAt(0),45===f||96<f&&123>f)&&(R=(U=U.replace(" ",":")).len
 gth),0<N&&void 0!==(w=a(1,U,s,n,x,A,W.length,p,d,p))&&0===(R=(U=w.trim()).length)&&(U="\0\0"),f=U.charCodeAt(0),m=U.charCodeAt(1),f){case 0:break;case 64:if(105===m||99===m){G+=U+u.charAt(I);break}default:58!==U.charCodeAt(R-1)&&(W+=r(U,f,m,U.charCodeAt(2)))}V=M=T=f=0,U="",m=u.charCodeAt(++I)}}switch(m){case 13:case 10:47===C?C=0:0===1+f&&107!==p&&0<U.length&&(M=1,U+="\0"),0<N*L&&a(0,U,s,n,x,A,W.length,p,d,p),A=1,x++;break;case 59:case 125:if(0===C+S+k+O){A++;break}default:switch(A++,E=u.charAt(I),m){case 9:case 32:if(0===S+O+C)switch(D){case 44:case 58:case 9:case 32:E="";break;default:32!==m&&(E=" ")}break;case 0:E="\\0";break;case 12:E="\\f";break;case 11:E="\\v";break;case 38:0===S+C+O&&(M=V=1,E="\f"+E);break;case 108:if(0===S+C+O+_&&0<T)switch(I-T){case 2:112===D&&58===u.charCodeAt(I
 -3)&&(_=D);case 8:111===P&&(_=P)}break;case 58:0===S+C+O&&(T=I);break;case 44:0===C+k+S+O&&(M=1,E+="\r");break;case 34:case 39:0===C&&(S=S===m?0:0===S?m:S);break;case 91:0===S+C+k&&O++;break;case 93:0===S+C+k&&O--;break;case 41:0===S+C+O&&k--;break;case 40:if(0===S+C+O){if(0===f)switch(2*D+3*P){case 533:break;default:f=1}k++}break;case 64:0===C+k+S+O+T+h&&(h=1);break;case 42:case 47:if(!(0<S+O+k))switch(C){case 0:switch(2*m+3*u.charCodeAt(I+1)){case 235:C=47;break;case 220:R=I,C=42}break;case 42:47===m&&42===D&&R+2!==I&&(33===u.charCodeAt(R+2)&&(W+=u.substring(R,I+1)),E="",C=0)}}0===C&&(U+=E)}P=D,D=m,I++}if(0<(R=W.length)){if(M=s,0<N&&void 0!==(w=a(2,W,M,n,x,A,R,p,d,p))&&0===(W=w).length)return G+W+H;if(W=M.join(",")+"{"+W+"}",0!=j*_){switch(2!==j||o(W,2)||(_=0),_){case 111:W=W.replace(v,":-moz
 -$1")+W;break;case 112:W=W.replace(b,"::-webkit-input-$1")+W.replace(b,"::-moz-$1")+W.replace(b,":-ms-input-$1")+W}_=0}}return G+W+H}(F,s,n,0,0);return 0<N&&void 0!==(u=a(-2,p,s,s,x,A,p.length,0,0,0))&&(p=u),_=0,A=x=1,p}var l=/^\0+/g,c=/[\0\r\f]/g,p=/: */g,d=/zoo|gra/,f=/([,: ])(transform)/g,m=/,\r+?/g,h=/([\t\r\n ])*\f?&/g,g=/@(k\w+)\s*(\S*)\s*/,b=/::(place)/g,v=/:(read-only)/g,E=/[svh]\w+-[tblr]{2}/,y=/\(\s*(.*)\s*\)/g,w=/([\s\S]*?);/g,O=/-self|flex-/g,C=/[^]*?(:[rp][el]a[\w-]+)[^]*/,k=/stretch|:\s*\w+\-(?:conte|avail)/,S=/([^-])(image-set\()/,A=1,x=1,_=0,j=1,F=[],D=[],N=0,P=null,L=0;return u.use=function e(t){switch(t){case void 0:case null:N=D.length=0;break;default:switch(t.constructor){case Array:for(var n=0,r=t.length;n<r;++n)e(t[n]);break;case Function:D[N++]=t;break;case Boolean:L=0|!!t}}return e},u.set=s,void 0!==e&&s(e),u},s=n(25),u=n.n(s),l=/[A-Z]|^ms/g,c=r(function(e){return e.replace(l,"-$&&q
 uot;).toLowerCase()}),p=function(e,t){return null==t||"boolean"==typeof t?"":1===o[e]||45===e.charCodeAt(1)||isNaN(t)||0===t?t:t+"px"},d=function e(t){for(var n=t.length,r=0,o="";r<n;r++){var i=t[r];if(null!=i){var a=void 0;switch(typeof i){case"boolean":break;case"function":0,a=e([i()]);break;case"object":if(Array.isArray(i))a=e(i);else for(var s in a="",i)i[s]&&s&&(a&&(a+=" "),a+=s);break;default:a=i}a&&(o&&(o+=" "),o+=a)}}return o},f="undefined"!=typeof document;function m(e){var t=document.createElement("style");return t.setAttribute("data-emotion",e.key||""),void 0!==e.nonce&&t.setAttribute("nonce",e.nonce),t.appendChild(document.createTextNode("")),(void 0!==e.container?e.container:document.head).appendChild(t),t}var h=function(){function e(e){this.isSpeedy=!0,this.tags
 =[],this.ctr=0,this.opts=e}var t=e.prototype;return t.inject=function(){if(this.injected)throw new Error("already injected!");this.tags[0]=m(this.opts),this.injected=!0},t.speedy=function(e){if(0!==this.ctr)throw new Error("cannot change speedy now");this.isSpeedy=!!e},t.insert=function(e,t){if(this.isSpeedy){var n=function(e){if(e.sheet)return e.sheet;for(var t=0;t<document.styleSheets.length;t++)if(document.styleSheets[t].ownerNode===e)return document.styleSheets[t]}(this.tags[this.tags.length-1]);try{n.insertRule(e,n.cssRules.length)}catch(e){0}}else{var r=m(this.opts);this.tags.push(r),r.appendChild(document.createTextNode(e+(t||"")))}this.ctr++,this.ctr%65e3==0&&this.tags.push(m(this.opts))},t.flush=function(){this.tags.forEach(function(e){return e.parentNode.removeChild(e)}),this.tags=[],this.ctr=0,this.injected=!1},e}();t.a=function(e,t){if(void 0!==e.__SECRET_EMOTION__)return e.__SECRET_EMOTION__;void 0===t&&(t={});var n,r,o=t
 .key||"css",s=u()(function(e){n+=e,f&&m.insert(e,b)});void 0!==t.prefix&&(r={prefix:t.prefix});var l={registered:{},inserted:{},nonce:t.nonce,key:o},m=new h(t);f&&m.inject();var g=new a(r);g.use(t.stylisPlugins)(s);var b="";function v(e,t){if(null==e)return"";switch(typeof e){case"boolean":return"";case"function":if(void 0!==e.__emotion_styles){var n=e.toString();return n}return v.call(this,void 0===this?e():e(this.mergedProps,this.context),t);case"object":return function(e){if(w.has(e))return w.get(e);var t="";return Array.isArray(e)?e.forEach(function(e){t+=v.call(this,e,!1)},this):Object.keys(e).forEach(function(n){"object"!=typeof e[n]?void 0!==l.registered[e[n]]?t+=n+"{"+l.registered[e[n]]+"}":t+=c(n)+":"+p(n,e[n])+";":Array.isArray(e[n])&&"string"==typeof e[n][0]&&void 0===l.registered[e[n][0]]?e[n].
 forEach(function(e){t+=c(n)+":"+p(n,e)+";"}):t+=n+"{"+v.call(this,e[n],!1)+"}"},this),w.set(e,t),t}.call(this,e);default:var r=l.registered[e];return!1===t&&void 0!==r?r:e}}var E,y,w=new WeakMap,O=/label:\s*([^\s;\n{]+)\s*;/g,C=function(e){var t=!0,n="",r="";null==e||void 0===e.raw?(t=!1,n+=v.call(this,e,!1)):n+=e[0];for(var o=arguments.length,a=new Array(o>1?o-1:0),s=1;s<o;s++)a[s-1]=arguments[s];return a.forEach(function(r,o){n+=v.call(this,r,46===n.charCodeAt(n.length-1)),!0===t&&void 0!==e[o+1]&&(n+=e[o+1])},this),y=n,n=n.replace(O,function(e,t){return r+="-"+t,""}),E=function(e,t){return i(e+t)+t}(n,r),n};function k(e,t){void 0===l.inserted[E]&&(n="",g(e,t),l.inserted[E]=n)}var S=function(){var e=C.apply(this,arguments),t=o+"-"+E;return void 0===l.registered[t]&&(l.registered[t]=y),k("."+t,e),t};function A(e,t){var n="&
 quot;;return t.split(" ").forEach(function(t){void 0!==l.registered[t]?e.push(t):n+=t+" "}),n}function x(e,t){var n=[],r=A(n,e);return n.length<2?e:r+S(n,t)}function _(e){l.inserted[e]=!0}if(f){var j=document.querySelectorAll("[data-emotion-"+o+"]");Array.prototype.forEach.call(j,function(e){m.tags[0].parentNode.insertBefore(e,m.tags[0]),e.getAttribute("data-emotion-"+o).split(" ").forEach(_)})}var F={flush:function(){f&&(m.flush(),m.inject()),l.inserted={},l.registered={}},hydrate:function(e){e.forEach(_)},cx:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return x(d(t))},merge:x,getRegisteredStyles:A,injectGlobal:function(){k("",C.apply(this,arguments))},keyframes:function(){var e=C.apply(this,arguments),t="animation-"+E;return k("","@keyframes "+t+"{"+e+"}"),t},css:S,sheet:m,caches:l};return e.__SECRET_EMOTION__=F
 ,F}},function(e,t){function n(e){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function r(t){return"function"==typeof Symbol&&"symbol"===n(Symbol.iterator)?e.exports=r=function(e){return n(e)}:e.exports=r=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":n(e)},r(t)}e.exports=r},function(e,t){function n(t,r){return e.exports=n=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},n(t,r)}e.exports=n},function(e,t,n){},function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}},function(e,t){e.exports=function(e,t){var n=[],r=!0,o=!1,i=v
 oid 0;try{for(var a,s=e[Symbol.iterator]();!(r=(a=s.next()).done)&&(n.push(a.value),!t||n.length!==t);r=!0);}catch(e){o=!0,i=e}finally{try{r||null==s.return||s.return()}finally{if(o)throw i}}return n}},function(e,t){e.exports=function(e){if(Array.isArray(e)){for(var t=0,n=new Array(e.length);t<e.length;t++)n[t]=e[t];return n}}},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}},function(e,t,n){},function(e,t,n){},function(e,t,n){"use strict";var r=n(40);function o(){}e.exports=function(){function e(e,t,n,o,i,a){if(a!==r){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,i
 nstanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t};return n.checkPropTypes=o,n.PropTypes=n,n}},function(e,t,n){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},function(e,t,n){(function(t){(function(){var n,r,o,i,a,s;"undefined"!=typeof performance&&null!==performance&&performance.now?e.exports=function(){return performance.now()}:void 0!==t&&null!==t&&t.hrtime?(e.exports=function(){return(n()-a)/1e6},r=t.hrtime,i=(n=function(){var e;return 1e9*(e=r())[0]+e[1]})(),s=1e9*t.uptime(),a=i-s):Date.now?(e.exports=function(){return Date.now()-o},o=Date.now()):(e.exports=function(){return(new Date).getTime()-o},o=(new Date).getTime())}).call(this)}).call(this,n(42))},function(e,t){var n,r,o=e.exports={};function i(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function s(e){if(n===setTimeout)return set
 Timeout(e,0);if((n===i||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:i}catch(e){n=i}try{r="function"==typeof clearTimeout?clearTimeout:a}catch(e){r=a}}();var u,l=[],c=!1,p=-1;function d(){c&&u&&(c=!1,u.length?l=u.concat(l):p=-1,l.length&&f())}function f(){if(!c){var e=s(d);c=!0;for(var t=l.length;t;){for(u=l,l=[];++p<t;)u&&u[p].run();p=-1,t=l.length}u=null,c=!1,function(e){if(r===clearTimeout)return clearTimeout(e);if((r===a||!r)&&clearTimeout)return r=clearTimeout,clearTimeout(e);try{r(e)}catch(t){try{return r.call(null,e)}catch(t){return r.call(this,e)}}}(e)}}function m(e,t){this.fun=e,this.array=t}function h(){}o.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];l.push
 (new m(e,t)),1!==l.length||c||s(f)},m.prototype.run=function(){this.fun.apply(null,this.array)},o.title="browser",o.browser=!0,o.env={},o.argv=[],o.version="",o.versions={},o.on=h,o.addListener=h,o.once=h,o.off=h,o.removeListener=h,o.removeAllListeners=h,o.emit=h,o.prependListener=h,o.prependOnceListener=h,o.listeners=function(e){return[]},o.binding=function(e){throw new Error("process.binding is not supported")},o.cwd=function(){return"/"},o.chdir=function(e){throw new Error("process.chdir is not supported")},o.umask=function(){return 0}},function(e,t,n){"use strict";t.__esModule=!0,t.default=void 0;!function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,n):{};r.get||r.set?Object.defineProperty(t,n,r):t[n]=e[n]}t.default=e}(n(12));var r=s(n(44)),o=s
 (n(47)),i=s(n(0)),a=s(n(21));n(23);function s(e){return e&&e.__esModule?e:{default:e}}function u(){return(u=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}var l=function(e,t){return e&&t&&t.split(" ").forEach(function(t){return(0,r.default)(e,t)})},c=function(e,t){return e&&t&&t.split(" ").forEach(function(t){return(0,o.default)(e,t)})},p=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(t=e.call.apply(e,[this].concat(r))||this).onEnter=function(e,n){var r=t.getClassNames(n?"appear":"enter").className;t.removeClasses(e,"exit"),l(e,r),t.props.onEnter&&t.props.onEnter(e,n)},t.onEntering=function(e,n){var r=t.getClassNames(n?"appear":"enter").activeClassName;t.reflo
 wAndAddClass(e,r),t.props.onEntering&&t.props.onEntering(e,n)},t.onEntered=function(e,n){var r=t.getClassNames("enter").doneClassName;t.removeClasses(e,n?"appear":"enter"),l(e,r),t.props.onEntered&&t.props.onEntered(e,n)},t.onExit=function(e){var n=t.getClassNames("exit").className;t.removeClasses(e,"appear"),t.removeClasses(e,"enter"),l(e,n),t.props.onExit&&t.props.onExit(e)},t.onExiting=function(e){var n=t.getClassNames("exit").activeClassName;t.reflowAndAddClass(e,n),t.props.onExiting&&t.props.onExiting(e)},t.onExited=function(e){var n=t.getClassNames("exit").doneClassName;t.removeClasses(e,"exit"),l(e,n),t.props.onExited&&t.props.onExited(e)},t.getClassNames=function(e){var n=t.props.classNames,r="string"!=typeof n?n[e]:n+"-"+e;return{className:r,activeClassName:"string"!=typeof n?n[e+"Active"]:r+"-active&q
 uot;,doneClassName:"string"!=typeof n?n[e+"Done"]:r+"-done"}},t}!function(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}(t,e);var n=t.prototype;return n.removeClasses=function(e,t){var n=this.getClassNames(t),r=n.className,o=n.activeClassName,i=n.doneClassName;r&&c(e,r),o&&c(e,o),i&&c(e,i)},n.reflowAndAddClass=function(e,t){t&&(e&&e.scrollTop,l(e,t))},n.render=function(){var e=u({},this.props);return delete e.classNames,i.default.createElement(a.default,u({},e,{onEnter:this.onEnter,onEntered:this.onEntered,onEntering:this.onEntering,onExit:this.onExit,onExiting:this.onExiting,onExited:this.onExited}))},t}(i.default.Component);p.propTypes={};var d=p;t.default=d,e.exports=t.default},function(e,t,n){"use strict";var r=n(45);t.__esModule=!0,t.default=function(e,t){e.classList?e.classList.add(t):(0,o.default)(e,t)||("string"==typeof e.className?e.className=e.cla
 ssName+" "+t:e.setAttribute("class",(e.className&&e.className.baseVal||"")+" "+t))};var o=r(n(46));e.exports=t.default},function(e,t){e.exports=function(e){return e&&e.__esModule?e:{default:e}}},function(e,t,n){"use strict";t.__esModule=!0,t.default=function(e,t){return e.classList?!!t&&e.classList.contains(t):-1!==(" "+(e.className.baseVal||e.className)+" ").indexOf(" "+t+" ")},e.exports=t.default},function(e,t,n){"use strict";function r(e,t){return e.replace(new RegExp("(^|\\s)"+t+"(?:\\s|$)","g"),"$1").replace(/\s+/g," ").replace(/^\s*|\s*$/g,"")}e.exports=function(e,t){e.classList?e.classList.remove(t):"string"==typeof e.className?e.className=r(e.className,t):e.setAttribute("class",r(e.className&&e.className.baseVal||"",t))}},function(e,t,n){"use strict&qu
 ot;;t.__esModule=!0,t.default=void 0;a(n(12));var r=a(n(0)),o=n(11),i=a(n(24));function a(e){return e&&e.__esModule?e:{default:e}}var s=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return(t=e.call.apply(e,[this].concat(r))||this).handleEnter=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.handleLifecycle("onEnter",0,n)},t.handleEntering=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.handleLifecycle("onEntering",0,n)},t.handleEntered=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.handleLifecycle("onEntered",0,n)},t.handleExit=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.handleLifecycle("onExit",1,n)},t.handleExiting=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arg
 uments[r];return t.handleLifecycle("onExiting",1,n)},t.handleExited=function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return t.handleLifecycle("onExited",1,n)},t}!function(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}(t,e);var n=t.prototype;return n.handleLifecycle=function(e,t,n){var i,a=this.props.children,s=r.default.Children.toArray(a)[t];s.props[e]&&(i=s.props)[e].apply(i,n),this.props[e]&&this.props[e]((0,o.findDOMNode)(this))},n.render=function(){var e=this.props,t=e.children,n=e.in,o=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,["children","in"]),a=r.default.Children.toArray(t),s=a[0],u=a[1];return delete o.onEnter,delete o.onEntering,delete o.onEntered,delete o.onExit,delete o.onExiting,delete o.onExited,r.default.createElement(i.default,o,n?r.default
 .cloneElement(s,{key:"first",onEnter:this.handleEnter,onEntering:this.handleEntering,onEntered:this.handleEntered}):r.default.cloneElement(u,{key:"second",onEnter:this.handleExit,onEntering:this.handleExiting,onEntered:this.handleExited}))},t}(r.default.Component);s.propTypes={};var u=s;t.default=u,e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0,t.getChildMapping=o,t.mergeChildMappings=i,t.getInitialChildMapping=function(e,t){return o(e.children,function(n){return(0,r.cloneElement)(n,{onExited:t.bind(null,n),in:!0,appear:a(n,"appear",e),enter:a(n,"enter",e),exit:a(n,"exit",e)})})},t.getNextChildMapping=function(e,t,n){var s=o(e.children),u=i(t,s);return Object.keys(u).forEach(function(o){var i=u[o];if((0,r.isValidElement)(i)){var l=o in t,c=o in s,p=t[o],d=(0,r.isValidElement)(p)&&!p.props.in;!c||l&&!d?c||!l||d?c&&l&&(0,r.isValidElement)(p)&&(u[o]=(0,r.cloneElement)(
 i,{onExited:n.bind(null,i),in:p.props.in,exit:a(i,"exit",e),enter:a(i,"enter",e)})):u[o]=(0,r.cloneElement)(i,{in:!1}):u[o]=(0,r.cloneElement)(i,{onExited:n.bind(null,i),in:!0,exit:a(i,"exit",e),enter:a(i,"enter",e)})}}),u};var r=n(0);function o(e,t){var n=Object.create(null);return e&&r.Children.map(e,function(e){return e}).forEach(function(e){n[e.key]=function(e){return t&&(0,r.isValidElement)(e)?t(e):e}(e)}),n}function i(e,t){function n(n){return n in t?t[n]:e[n]}e=e||{},t=t||{};var r,o=Object.create(null),i=[];for(var a in e)a in t?i.length&&(o[a]=i,i=[]):i.push(a);var s={};for(var u in t){if(o[u])for(r=0;r<o[u].length;r++){var l=o[u][r];s[o[u][r]]=n(l)}s[u]=n(u)}for(r=0;r<i.length;r++)s[i[r]]=n(i[r]);return s}function a(e,t,n){return null!=n[t]?n[t]:e.props[t]}},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){"use strict";n.r(t);var r={};n.r(
 r),n.d(r,"NAME",function(){return Lr}),n.d(r,"LABEL",function(){return Tr}),n.d(r,"ICON",function(){return Ir}),n.d(r,"SETTINGS",function(){return Mr});var o={};n.r(o),n.d(o,"NAME",function(){return Co}),n.d(o,"LABEL",function(){return ko}),n.d(o,"ICON",function(){return So}),n.d(o,"SETTINGS",function(){return Ao});var i={};n.r(i),n.d(i,"NAME",function(){return pi}),n.d(i,"LABEL",function(){return di}),n.d(i,"ICON",function(){return fi}),n.d(i,"SETTINGS",function(){return mi});var a={};n.r(a),n.d(a,"NAME",function(){return Hi}),n.d(a,"LABEL",function(){return Gi}),n.d(a,"ICON",function(){return $i}),n.d(a,"SETTINGS",function(){return qi});var s=n(9),u=n.n(s),l=n(2),c=n.n(l),p=n(3),d=n.n(p),f=n(4),m=n.n(f),h=n(5),g=n.n(h),b=n(6),v=n.n(b);var E=n(0),y=n.n(E),w=n(1);var O=n(11);var C=Object(E.createContext)();C.Provider,C.Consum
 er,new Set(["string","boolean","number"]),new Set(["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"]),new Set(["allowfullscreen","allowpaymentrequest","allowusermedia","async","autofocus","autoplay","checked","controls","default","defer","disabled","formnovalidate","hidden","ismap","itemscope","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","selected","typemustmatch"]),new Set(["autocapitalize","
 autocomplete","charset","contenteditable","crossorigin","decoding","dir","draggable","enctype","formenctype","formmethod","http-equiv","inputmode","kind","method","preload","scope","shape","spellcheck","translate","type","wrap"]),new Set(["animation","animationIterationCount","baselineShift","borderImageOutset","borderImageSlice","borderImageWidth","columnCount","cx","cy","fillOpacity","flexGrow","flexShrink","floodOpacity","fontWeight","gridColumnEnd","gridColumnStart","gridRowEnd","gridRowStart","lineHeight","opacity","order","orphans","r","rx"
 ,"ry","shapeImageThreshold","stopOpacity","strokeDasharray","strokeDashoffset","strokeMiterlimit","strokeOpacity","strokeWidth","tabSize","widows","x","y","zIndex","zoom"]);var k=n(7),S=n.n(k),A=(n(32),wp.components),x=A.PanelBody,_=(A.PanelRow,A.RangeControl),j=wp.element,F=j.Component,D=j.Fragment,N=wp.i18n.__;function P(e){var t=e.grid_columns,n=e.schema,r=e.setAttributes,o=n.default,i=void 0===o?2:o,a=n.maximum,s=void 0===a?4:a,u=n.minimum,l=void 0===u?4:u;return Object(E.createElement)(_,{label:N("Grid Columns","wordcamporg"),value:Number(t),min:l,max:s,initialPosition:i,onChange:function(e){return r({grid_columns:e})}})}var L=function(e){function t(){return c()(this,t),m()(this,g()(t).apply(this,arguments))}return v()(t,e),d()(t,[{key:"render",value:function(){var e=this.props,t=e.attributes,n=e.setAttributes,
 r=e.blockData,o=t.layout,i=t.grid_columns,a=r.schema;return Object(E.createElement)(D,null,"grid"===o&&Object(E.createElement)(x,{title:N("Grid Layout","wordcamporg"),initialOpen:!0},Object(E.createElement)(P,{grid_columns:i,schema:a.grid_columns||{},setAttributes:n})))}}]),t}(F),T=wp.components.Toolbar,I=wp.editor.BlockControls;function M(e){var t=e.layout,n=e.options,r=e.setAttributes,o=n.map(function(e){var n="".concat(e.value,"-view"),o=t===e.value;return{icon:n,title:e.label,isActive:o,onClick:function(){r({layout:e.value})}}});return Object(E.createElement)(I,null,Object(E.createElement)(T,{controls:o}))}var V=function(e){function t(){return c()(this,t),m()(this,g()(t).apply(this,arguments))}return v()(t,e),d()(t,[{key:"render",value:function(){var e=this.props,t=e.attributes,n=e.className,r=e.children,o=void 0===r?[]:r,i=t.align,a=t.grid_columns,s=t.layout,u=["wordcamp-block","wordcamp-post-lis
 t","layout-"+s,n];return"grid"===s&&u.push("grid-columns-"+Number(a)),i&&u.push("align"+i),Object(E.createElement)("ul",{className:S()(u)},o.map(function(e){return Object(E.createElement)("li",{key:e.key,className:S()("wordcamp-post-list-item","wordcamp-clearfix")},e)}))}}]),t}(wp.element.Component),R=n(14),B=n.n(R),z=n(13),U=n.n(z),W=n(15),H=n.n(W),G=wp.apiFetch,$=wp.data,q=$.registerStore,Y=$.select,X=$.dispatch,K={},Z=function(e,t){var n=Array.isArray;if(!n(e))return e;var r=H()(e);if(t.hasOwnProperty("filter")&&n(t.filter)&&t.filter.forEach(function(e){var t=e.fieldName,o=e.fieldValue;n(o)||(o=[o]),r=r.filter(function(e){if(!e.hasOwnProperty(t))return!1;var r=n(e[t])?e[t]:[e[t]];return Object(w.intersection)(o,r).length>0})}),t.hasOwnProperty("sort")){var o=Object(w.split)(t.sort,"_",2),i=U()(o,2),a=i[0],s=i[1];"title"===
 a&&r.length&&r[0].title.hasOwnProperty("rendered")&&(a="title.rendered"),r=Object(w.orderBy)(r,[a],[s])}return r};q("wordcamp",{selectors:{getEntities:function(e,t,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},o=B()({},{per_page:-1},r);return Y("core").getEntityRecords(t,n,o)},getSiteSettings:function(e){return e.hasOwnProperty("siteSettings")?e.siteSettings:(X("wordcamp").fetchSiteSettings(),null)}},actions:{fetchSiteSettings:function(){return{type:"FETCH_SETTINGS"}},setSiteSettings:function(e){return{type:"SET_SETTINGS",settings:e}}},reducer:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:K,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case"FETCH_SETTINGS":if(e.loadingSettings)break;G({path:"/wp/v2/settings"}).then(function(e){X("wordcamp").setSiteSettings(e)}),e.loading
 Settings=!0;break;case"SET_SETTINGS":e.siteSettings=t.settings,e.loadingSettings=!1}return e}});n(37);var J=wp.components.Placeholder,Q=wp.element.Fragment;function ee(e){var t=e.className,n=e.label,r=e.icon,o=e.content,i=e.placeholderChildren,a=["wordcamp-block-edit-placeholder","wordcamp-block-edit-placeholder-specific-mode",t];return Object(E.createElement)(Q,null,o,Object(E.createElement)(J,{className:S()(a),label:n,icon:r},i))}var te=n(8),ne=n.n(te),re=function(e,t){return e.length===t.length&&e.every(function(e,n){return function(e,t){return e===t}(e,t[n])})};var oe=function(e,t){var n;void 0===t&&(t=re);var r,o=[],i=!1;return function(){for(var a=arguments.length,s=new Array(a),u=0;u<a;u++)s[u]=arguments[u];return i&&n===this&&t(s,o)?r:(r=e.apply(this,s),i=!0,n=this,o=s,r)}},ie=n(10),ae=n(12),se=n.n(ae),ue=n(26),le=n.n(ue),ce=n(27),pe=n.n(ce),de=n(16);function fe(e){return(fe="function"==typeof Symbol&
 amp;&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function me(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function he(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function ge(e,t,n){return t&&he(e.prototype,t),n&&he(e,n),e}function be(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function ve(){return(ve=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function Ee(e){for(var t=1;t<arguments.len
 gth;t++){var n=null!=arguments[t]?arguments[t]:{},r=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){be(e,t,n[t])})}return e}function ye(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&Oe(e,t)}function we(e){return(we=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function Oe(e,t){return(Oe=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function Ce(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Ob
 ject.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function ke(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function Se(e,t){return!t||"object"!=typeof t&&"function"!=typeof t?ke(e):t}function Ae(e){return function(e){if(Array.isArray(e)){for(var t=0,n=new Array(e.length);t<e.length;t++)n[t]=e[t];return n}}(e)||function(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}()}var xe=function(){};function _e(e,t){return t?"-"===t[0]?e+t:e+"__"+t:e}var je=function(e){return Array.isArray(e)?e.filter(Boolean):"object"===fe(e)&&null!==e
 ?[e]:[]};function Fe(e){return[document.documentElement,document.body,window].indexOf(e)>-1}function De(e){return Fe(e)?window.pageYOffset:e.scrollTop}function Ne(e,t){Fe(e)?window.scrollTo(0,t):e.scrollTop=t}function Pe(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:200,r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:xe,o=De(e),i=t-o,a=10,s=0;!function t(){var u=function(e,t,n,r){return n*((e=e/r-1)*e*e+1)+t}(s+=a,o,i,n);Ne(e,u),s<n?le()(t):r(e)}()}function Le(){try{return document.createEvent("TouchEvent"),!0}catch(e){return!1}}function Te(e){var t=e.maxHeight,n=e.menuEl,r=e.minHeight,o=e.placement,i=e.shouldScroll,a=e.isFixedPosition,s=e.theme.spacing,u=function(e){var t=getComputedStyle(e),n="absolute"===t.position,r=/(auto|scroll)/,o=document.documentElement;if("fixed"===t.position)return o;for(var i=e;i=i.parentElement;)if(t=getComputedStyle(i),(!n||"static"!==t.position)&&r
 .test(t.overflow+t.overflowY+t.overflowX))return i;return o}(n),l={placement:"bottom",maxHeight:t};if(!n||!n.offsetParent)return l;var c=u.getBoundingClientRect().height,p=n.getBoundingClientRect(),d=p.bottom,f=p.height,m=p.top,h=n.offsetParent.getBoundingClientRect().top,g=window.innerHeight,b=De(u),v=parseInt(getComputedStyle(n).marginBottom,10),E=parseInt(getComputedStyle(n).marginTop,10),y=h-E,w=g-m,O=y+b,C=c-b-m,k=d-g+b+v,S=b+m-E;switch(o){case"auto":case"bottom":if(w>=f)return{placement:"bottom",maxHeight:t};if(C>=f&&!a)return i&&Pe(u,k,160),{placement:"bottom",maxHeight:t};if(!a&&C>=r||a&&w>=r)return i&&Pe(u,k,160),{placement:"bottom",maxHeight:a?w-v:C-v};if("auto"===o||a){var A=t,x=a?y:O;return x>=r&&(A=Math.min(x-v-s.controlHeight,t)),{placement:"top",maxHeight:A}}if("bottom"===o)return Ne(u,k),{placement:"bottom"
 ,maxHeight:t};break;case"top":if(y>=f)return{placement:"top",maxHeight:t};if(O>=f&&!a)return i&&Pe(u,S,160),{placement:"top",maxHeight:t};if(!a&&O>=r||a&&y>=r){var _=t;return(!a&&O>=r||a&&y>=r)&&(_=a?y-E:O-E),i&&Pe(u,S,160),{placement:"top",maxHeight:_}}return{placement:"bottom",maxHeight:t};default:throw new Error('Invalid placement provided "'.concat(o,'".'))}return l}var Ie=function(e){return"auto"===e?"bottom":e},Me=function(e){function t(){var e,n;me(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return be(ke(ke(n=Se(this,(e=we(t)).call.apply(e,[this].concat(o))))),"state",{maxHeight:n.props.maxMenuHeight,placement:null}),be(ke(ke(n)),"getPlacement",function(e){var t=n.props,r=t.minMenuHeight,o=t.maxMenuHeight,i=t.menuPlacement,a=t.menuPosition,s=t.menuShouldScrol
 lIntoView,u=t.theme,l=n.context.getPortalPlacement;if(e){var c="fixed"===a,p=Te({maxHeight:o,menuEl:e,minHeight:r,placement:i,shouldScroll:s&&!c,isFixedPosition:c,theme:u});l&&l(p),n.setState(p)}}),be(ke(ke(n)),"getUpdatedProps",function(){var e=n.props.menuPlacement,t=n.state.placement||Ie(e);return Ee({},n.props,{placement:t,maxHeight:n.state.maxHeight})}),n}return ye(t,E["Component"]),ge(t,[{key:"render",value:function(){return(0,this.props.children)({ref:this.getPlacement,placerProps:this.getUpdatedProps()})}}]),t}();be(Me,"contextTypes",{getPortalPlacement:se.a.func});var Ve=function(e){var t=e.theme,n=t.spacing.baseUnit;return{color:t.colors.neutral40,padding:"".concat(2*n,"px ").concat(3*n,"px"),textAlign:"center"}},Re=Ve,Be=Ve,ze=function(e){var t=e.children,n=e.className,r=e.cx,o=e.getStyles,i=e.innerProps;return y.a.createElement("div",ve({className:r(Object(
 ie.a)(o("noOptionsMessage",e)),{"menu-notice":!0,"menu-notice--no-options":!0},n)},i),t)};ze.defaultProps={children:"No options"};var Ue=function(e){var t=e.children,n=e.className,r=e.cx,o=e.getStyles,i=e.innerProps;return y.a.createElement("div",ve({className:r(Object(ie.a)(o("loadingMessage",e)),{"menu-notice":!0,"menu-notice--loading":!0},n)},i),t)};Ue.defaultProps={children:"Loading..."};var We=function(e){function t(){var e,n;me(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return be(ke(ke(n=Se(this,(e=we(t)).call.apply(e,[this].concat(o))))),"state",{placement:null}),be(ke(ke(n)),"getPortalPlacement",function(e){var t=e.placement;t!==Ie(n.props.menuPlacement)&&n.setState({placement:t})}),n}return ye(t,E["Component"]),ge(t,[{key:"getChildContext",value:function(){return{getPortalPlacement:this.getPortalPla
 cement}}},{key:"render",value:function(){var e=this.props,t=e.appendTo,n=e.children,r=e.controlElement,o=e.menuPlacement,i=e.menuPosition,a=e.getStyles,s="fixed"===i;if(!t&&!s||!r)return null;var u=this.state.placement||Ie(o),l=function(e){var t=e.getBoundingClientRect();return{bottom:t.bottom,height:t.height,left:t.left,right:t.right,top:t.top,width:t.width}}(r),c=s?0:window.pageYOffset,p={offset:l[u]+c,position:i,rect:l},d=y.a.createElement("div",{className:Object(ie.a)(a("menuPortal",p))},n);return t?Object(O.createPortal)(d,t):d}}]),t}();be(We,"childContextTypes",{getPortalPlacement:se.a.func});var He=Array.isArray,Ge=Object.keys,$e=Object.prototype.hasOwnProperty;function qe(e,t){try{return function e(t,n){if(t===n)return!0;if(t&&n&&"object"==fe(t)&&"object"==fe(n)){var r,o,i,a=He(t),s=He(n);if(a&&s){if((o=t.length)!=n.length)return!1;for(r=o;0!=r--;)if(!e(t[r],n[r]))re
 turn!1;return!0}if(a!=s)return!1;var u=t instanceof Date,l=n instanceof Date;if(u!=l)return!1;if(u&&l)return t.getTime()==n.getTime();var c=t instanceof RegExp,p=n instanceof RegExp;if(c!=p)return!1;if(c&&p)return t.toString()==n.toString();var d=Ge(t);if((o=d.length)!==Ge(n).length)return!1;for(r=o;0!=r--;)if(!$e.call(n,d[r]))return!1;for(r=o;0!=r--;)if(!("_owner"===(i=d[r])&&t.$$typeof||e(t[i],n[i])))return!1;return!0}return t!=t&&n!=n}(e,t)}catch(e){if(e.message&&e.message.match(/stack|recursion/i))return console.warn("Warning: react-fast-compare does not handle circular references.",e.name,e.message),!1;throw e}}var Ye=[{base:"A",letters:/[\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F]/g},{base:"AA",letters:/[\uA732]/g},{base:"AE",let
 ters:/[\u00C6\u01FC\u01E2]/g},{base:"AO",letters:/[\uA734]/g},{base:"AU",letters:/[\uA736]/g},{base:"AV",letters:/[\uA738\uA73A]/g},{base:"AY",letters:/[\uA73C]/g},{base:"B",letters:/[\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181]/g},{base:"C",letters:/[\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E]/g},{base:"D",letters:/[\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779]/g},{base:"DZ",letters:/[\u01F1\u01C4]/g},{base:"Dz",letters:/[\u01F2\u01C5]/g},{base:"E",letters:/[\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E]/g},{base:"F",letters:/[\u0046\u24BB\uFF26\u1E1E\u0191\uA77B]/g},{base:"G",letters:/[\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4
 \u0193\uA7A0\uA77D\uA77E]/g},{base:"H",letters:/[\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D]/g},{base:"I",letters:/[\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197]/g},{base:"J",letters:/[\u004A\u24BF\uFF2A\u0134\u0248]/g},{base:"K",letters:/[\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2]/g},{base:"L",letters:/[\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780]/g},{base:"LJ",letters:/[\u01C7]/g},{base:"Lj",letters:/[\u01C8]/g},{base:"M",letters:/[\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C]/g},{base:"N",letters:/[\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4]/g},{base:"NJ",letters:/[\u01CA]/g},{base:"Nj",letter
 s:/[\u01CB]/g},{base:"O",letters:/[\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C]/g},{base:"OI",letters:/[\u01A2]/g},{base:"OO",letters:/[\uA74E]/g},{base:"OU",letters:/[\u0222]/g},{base:"P",letters:/[\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754]/g},{base:"Q",letters:/[\u0051\u24C6\uFF31\uA756\uA758\u024A]/g},{base:"R",letters:/[\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782]/g},{base:"S",letters:/[\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784]/g},{base:"T",letters:/[\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786]/g
 },{base:"TZ",letters:/[\uA728]/g},{base:"U",letters:/[\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244]/g},{base:"V",letters:/[\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245]/g},{base:"VY",letters:/[\uA760]/g},{base:"W",letters:/[\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72]/g},{base:"X",letters:/[\u0058\u24CD\uFF38\u1E8A\u1E8C]/g},{base:"Y",letters:/[\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE]/g},{base:"Z",letters:/[\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762]/g},{base:"a",letters:/[\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01C
 E\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250]/g},{base:"aa",letters:/[\uA733]/g},{base:"ae",letters:/[\u00E6\u01FD\u01E3]/g},{base:"ao",letters:/[\uA735]/g},{base:"au",letters:/[\uA737]/g},{base:"av",letters:/[\uA739\uA73B]/g},{base:"ay",letters:/[\uA73D]/g},{base:"b",letters:/[\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253]/g},{base:"c",letters:/[\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184]/g},{base:"d",letters:/[\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A]/g},{base:"dz",letters:/[\u01F3\u01C6]/g},{base:"e",letters:/[\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD]/g},{base:"f",letters:/[\u0066\u24D5\uFF46\u1E1F\u0192\uA77C]/g},{base:
 "g",letters:/[\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F]/g},{base:"h",letters:/[\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265]/g},{base:"hv",letters:/[\u0195]/g},{base:"i",letters:/[\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131]/g},{base:"j",letters:/[\u006A\u24D9\uFF4A\u0135\u01F0\u0249]/g},{base:"k",letters:/[\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3]/g},{base:"l",letters:/[\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747]/g},{base:"lj",letters:/[\u01C9]/g},{base:"m",letters:/[\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F]/g},{base:"n",letters:/[\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u
 1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5]/g},{base:"nj",letters:/[\u01CC]/g},{base:"o",letters:/[\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275]/g},{base:"oi",letters:/[\u01A3]/g},{base:"ou",letters:/[\u0223]/g},{base:"oo",letters:/[\uA74F]/g},{base:"p",letters:/[\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755]/g},{base:"q",letters:/[\u0071\u24E0\uFF51\u024B\uA757\uA759]/g},{base:"r",letters:/[\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783]/g},{base:"s",letters:/[\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B]/g},{base:"t",letters:/[\u0074\u24E3\uF
 F54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787]/g},{base:"tz",letters:/[\uA729]/g},{base:"u",letters:/[\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289]/g},{base:"v",letters:/[\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C]/g},{base:"vy",letters:/[\uA761]/g},{base:"w",letters:/[\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73]/g},{base:"x",letters:/[\u0078\u24E7\uFF58\u1E8B\u1E8D]/g},{base:"y",letters:/[\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF]/g},{base:"z",letters:/[\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763]/g}],Xe=function(e){for(var t=0;t<Ye.length;t++)e=e.replace(Ye[t].letters,Ye[t].base);retu
 rn e},Ke=function(e){return e.replace(/^\s+|\s+$/g,"")},Ze=function(e){return"".concat(e.label," ").concat(e.value)},Je=function(e){return y.a.createElement("span",ve({className:Object(ie.a)({zIndex:9999,border:0,clip:"rect(1px, 1px, 1px, 1px)",height:1,width:1,position:"absolute",overflow:"hidden",padding:0,whiteSpace:"nowrap",backgroundColor:"red",color:"blue"})},e))},Qe=function(e){function t(){return me(this,t),Se(this,we(t).apply(this,arguments))}return ye(t,E["Component"]),ge(t,[{key:"render",value:function(){var e=this.props,t=(e.in,e.out,e.onExited,e.appear,e.enter,e.exit,e.innerRef),n=(e.emotion,Ce(e,["in","out","onExited","appear","enter","exit","innerRef","emotion"]));return y.a.createElement("input",ve({ref:t},n,{className:Object(ie.a)({background:0,border:0,fontSi
 ze:"inherit",outline:0,padding:0,width:1,color:"transparent",left:-100,opacity:0,position:"relative",transform:"scale(0)"})}))}}]),t}(),et=function(e){function t(){return me(this,t),Se(this,we(t).apply(this,arguments))}return ye(t,E["Component"]),ge(t,[{key:"componentDidMount",value:function(){this.props.innerRef(Object(O.findDOMNode)(this))}},{key:"componentWillUnmount",value:function(){this.props.innerRef(null)}},{key:"render",value:function(){return this.props.children}}]),t}(),tt=["boxSizing","height","overflow","paddingRight","position"],nt={boxSizing:"border-box",overflow:"hidden",position:"relative",height:"100%"};function rt(e){e.preventDefault()}function ot(e){e.stopPropagation()}function it(){var e=this.scrollTop,t=this.scrollHeight,n=e+this.offsetHeight;0===e?this.scrollTop=1:n===t&&(this.scrollTo
 p=e-1)}function at(){return"ontouchstart"in window||navigator.maxTouchPoints}var st=!("undefined"==typeof window||!window.document||!window.document.createElement),ut=0,lt=function(e){function t(){var e,n;me(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return be(ke(ke(n=Se(this,(e=we(t)).call.apply(e,[this].concat(o))))),"originalStyles",{}),be(ke(ke(n)),"listenerOptions",{capture:!1,passive:!1}),n}return ye(t,E["Component"]),ge(t,[{key:"componentDidMount",value:function(){var e=this;if(st){var t=this.props,n=t.accountForScrollbars,r=t.touchScrollTarget,o=document.body,i=o&&o.style;if(n&&tt.forEach(function(t){var n=i&&i[t];e.originalStyles[t]=n}),n&&ut<1){var a=parseInt(this.originalStyles.paddingRight,10)||0,s=document.body?document.body.clientWidth:0,u=window.innerWidth-s+a||0;Object.keys(nt).forEach(function(e){var t=nt[e];i&&(i[e]=t)}),i&a
 mp;&(i.paddingRight="".concat(u,"px"))}o&&at()&&(o.addEventListener("touchmove",rt,this.listenerOptions),r&&(r.addEventListener("touchstart",it,this.listenerOptions),r.addEventListener("touchmove",ot,this.listenerOptions))),ut+=1}}},{key:"componentWillUnmount",value:function(){var e=this;if(st){var t=this.props,n=t.accountForScrollbars,r=t.touchScrollTarget,o=document.body,i=o&&o.style;ut=Math.max(ut-1,0),n&&ut<1&&tt.forEach(function(t){var n=e.originalStyles[t];i&&(i[t]=n)}),o&&at()&&(o.removeEventListener("touchmove",rt,this.listenerOptions),r&&(r.removeEventListener("touchstart",it,this.listenerOptions),r.removeEventListener("touchmove",ot,this.listenerOptions)))}}},{key:"render",value:function(){return null}}]),t}();be(lt,"defaultProps",{accountForScrollbars:!0});var ct=function(e){fun
 ction t(){var e,n;me(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return be(ke(ke(n=Se(this,(e=we(t)).call.apply(e,[this].concat(o))))),"state",{touchScrollTarget:null}),be(ke(ke(n)),"getScrollTarget",function(e){e!==n.state.touchScrollTarget&&n.setState({touchScrollTarget:e})}),be(ke(ke(n)),"blurSelectInput",function(){document.activeElement&&document.activeElement.blur()}),n}return ye(t,E["PureComponent"]),ge(t,[{key:"render",value:function(){var e=this.props,t=e.children,n=e.isEnabled,r=this.state.touchScrollTarget;return n?y.a.createElement("div",null,y.a.createElement("div",{onClick:this.blurSelectInput,className:Object(ie.a)({position:"fixed",left:0,bottom:0,right:0,top:0})}),y.a.createElement(et,{innerRef:this.getScrollTarget},t),r?y.a.createElement(lt,{touchScrollTarget:r}):null):t}}]),t}(),pt=function(e){function t(){var e,n;me(this,t);for(va
 r r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return be(ke(ke(n=Se(this,(e=we(t)).call.apply(e,[this].concat(o))))),"isBottom",!1),be(ke(ke(n)),"isTop",!1),be(ke(ke(n)),"scrollTarget",void 0),be(ke(ke(n)),"touchStart",void 0),be(ke(ke(n)),"cancelScroll",function(e){e.preventDefault(),e.stopPropagation()}),be(ke(ke(n)),"handleEventDelta",function(e,t){var r=n.props,o=r.onBottomArrive,i=r.onBottomLeave,a=r.onTopArrive,s=r.onTopLeave,u=n.scrollTarget,l=u.scrollTop,c=u.scrollHeight,p=u.clientHeight,d=n.scrollTarget,f=t>0,m=c-p-l,h=!1;m>t&&n.isBottom&&(i&&i(e),n.isBottom=!1),f&&n.isTop&&(s&&s(e),n.isTop=!1),f&&t>m?(o&&!n.isBottom&&o(e),d.scrollTop=c,h=!0,n.isBottom=!0):!f&&-t>l&&(a&&!n.isTop&&a(e),d.scrollTop=0,h=!0,n.isTop=!0),h&&n.cancelScroll(e)}),be(ke(ke(n)),"onWheel",f
 unction(e){n.handleEventDelta(e,e.deltaY)}),be(ke(ke(n)),"onTouchStart",function(e){n.touchStart=e.changedTouches[0].clientY}),be(ke(ke(n)),"onTouchMove",function(e){var t=n.touchStart-e.changedTouches[0].clientY;n.handleEventDelta(e,t)}),be(ke(ke(n)),"getScrollTarget",function(e){n.scrollTarget=e}),n}return ye(t,E["Component"]),ge(t,[{key:"componentDidMount",value:function(){this.startListening(this.scrollTarget)}},{key:"componentWillUnmount",value:function(){this.stopListening(this.scrollTarget)}},{key:"startListening",value:function(e){e&&(e.scrollHeight<=e.clientHeight||("function"==typeof e.addEventListener&&e.addEventListener("wheel",this.onWheel,!1),"function"==typeof e.addEventListener&&e.addEventListener("touchstart",this.onTouchStart,!1),"function"==typeof e.addEventListener&&e.addEventListener("touchmove",this
 .onTouchMove,!1)))}},{key:"stopListening",value:function(e){e.scrollHeight<=e.clientHeight||("function"==typeof e.removeEventListener&&e.removeEventListener("wheel",this.onWheel,!1),"function"==typeof e.removeEventListener&&e.removeEventListener("touchstart",this.onTouchStart,!1),"function"==typeof e.removeEventListener&&e.removeEventListener("touchmove",this.onTouchMove,!1))}},{key:"render",value:function(){return y.a.createElement(et,{innerRef:this.getScrollTarget},this.props.children)}}]),t}(),dt=function(e){function t(){return me(this,t),Se(this,we(t).apply(this,arguments))}return ye(t,E["Component"]),ge(t,[{key:"render",value:function(){var e=this.props,t=e.isEnabled,n=Ce(e,["isEnabled"]);return t?y.a.createElement(pt,n):this.props.children}}]),t}();be(dt,"defaultProps",{isEnabled:!0});var ft=function(e){var t=arguments.length>1&a
 mp;&void 0!==arguments[1]?arguments[1]:{},n=t.isSearchable,r=t.isMulti,o=t.label,i=t.isDisabled;switch(e){case"menu":return"Use Up and Down to choose options".concat(i?"":", press Enter to select the currently focused option",", press Escape to exit the menu, press Tab to select the option and exit the menu.");case"input":return"".concat(o||"Select"," is focused ").concat(n?",type to refine list":"",", press Down to open the menu, ").concat(r?" press left to focus selected values":"");case"value":return"Use left and right to toggle between focused values, press Backspace to remove the currently focused value"}},mt=function(e,t){var n=t.value,r=t.isDisabled;if(n)switch(e){case"deselect-option":case"pop-value":case"remove-value":return"option ".concat(n,", deselected.");case
 "select-option":return"option ".concat(n,r?" is disabled. Select another option.":", selected.")}},ht=function(e){return!!e.isDisabled},gt=function(e){function t(){return me(this,t),Se(this,we(t).apply(this,arguments))}return ye(t,E["Component"]),ge(t,[{key:"render",value:function(){var e=this.props,t=e.children,n=e.className,r=e.cx,o=e.isMulti,i=e.getStyles,a=e.hasValue;return y.a.createElement("div",{className:r(Object(ie.a)(i("valueContainer",this.props)),{"value-container":!0,"value-container--is-multi":o,"value-container--has-value":a},n)},t)}}]),t}(),bt=function(e){var t=e.size,n=Ce(e,["size"]);return y.a.createElement("svg",ve({height:t,width:t,viewBox:"0 0 20 20","aria-hidden":"true",focusable:"false",className:Object(ie.a)({display:"inline-block",fill:"currentColor",lineHeight:1,stroke:&
 quot;currentColor",strokeWidth:0})},n))},vt=function(e){return y.a.createElement(bt,ve({size:20},e),y.a.createElement("path",{d:"M14.348 14.849c-0.469 0.469-1.229 0.469-1.697 0l-2.651-3.030-2.651 3.029c-0.469 0.469-1.229 0.469-1.697 0-0.469-0.469-0.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-0.469-0.469-0.469-1.228 0-1.697s1.228-0.469 1.697 0l2.652 3.031 2.651-3.031c0.469-0.469 1.228-0.469 1.697 0s0.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c0.469 0.469 0.469 1.229 0 1.698z"}))},Et=function(e){return y.a.createElement(bt,ve({size:20},e),y.a.createElement("path",{d:"M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"}))},yt=function(e){var t=e.isFocused,n=e.theme,r=n.spacing.baseUnit,o=n.colors;return{color:t?o.neutral6
 0:o.neutral20,display:"flex",padding:2*r,transition:"color 150ms",":hover":{color:t?o.neutral80:o.neutral40}}},wt=yt,Ot=yt,Ct=!1,kt=function(e){var t=e.color,n=e.delay,r=e.offset;return y.a.createElement("span",{className:Object(ie.a)({animationDuration:"1s",animationDelay:"".concat(n,"ms"),animationIterationCount:"infinite",animationName:"react-select-loading-indicator",animationTimingFunction:"ease-in-out",backgroundColor:t,borderRadius:"1em",display:"inline-block",marginLeft:r?"1em":null,height:"1em",verticalAlign:"top",width:"1em"})})},St=function(e){var t=e.className,n=e.cx,r=e.getStyles,o=e.innerProps,i=e.isFocused,a=e.isRtl,s=e.theme.colors,u=i?s.neutral80:s.neutral20;return Ct||(Object(ie.b)("@keyframes ","react-select-loading-indicator","{0%,80%,100%{opacity:0;}40%{opacity:1;}};"),Ct=!0)
 ,y.a.createElement("div",ve({},o,{className:n(Object(ie.a)(r("loadingIndicator",e)),{indicator:!0,"loading-indicator":!0},t)}),y.a.createElement(kt,{color:u,delay:0,offset:a}),y.a.createElement(kt,{color:u,delay:160,offset:!0}),y.a.createElement(kt,{color:u,delay:320,offset:!a}))};St.defaultProps={size:4};var At=function(e){var t=e.children,n=e.innerProps;return y.a.createElement("div",n,t)},xt=At,_t=At,jt=function(e){function t(){return me(this,t),Se(this,we(t).apply(this,arguments))}return ye(t,E["Component"]),ge(t,[{key:"render",value:function(){var e=this.props,t=e.children,n=e.innerProps;return y.a.createElement("div",n,t||y.a.createElement(vt,{size:14}))}}]),t}(),Ft=function(e){function t(){return me(this,t),Se(this,we(t).apply(this,arguments))}return ye(t,E["Component"]),ge(t,[{key:"render",value:function(){var e=this.props,t=e.children,n=e.className,r=e.components,o=e.cx,i=e.data,a=e.ge
 tStyles,s=e.innerProps,u=e.isDisabled,l=e.removeProps,c=e.selectProps,p=r.Container,d=r.Label,f=r.Remove,m=Ee({className:o(Object(ie.a)(a("multiValue",this.props)),{"multi-value":!0,"multi-value--is-disabled":u},n)},s),h={className:o(Object(ie.a)(a("multiValueLabel",this.props)),{"multi-value__label":!0},n)},g=Ee({className:o(Object(ie.a)(a("multiValueRemove",this.props)),{"multi-value__remove":!0},n)},l);return y.a.createElement(p,{data:i,innerProps:m,selectProps:c},y.a.createElement(d,{data:i,innerProps:h,selectProps:c},t),y.a.createElement(f,{data:i,innerProps:g,selectProps:c}))}}]),t}();be(Ft,"defaultProps",{cropWithEllipsis:!0});var Dt={ClearIndicator:function(e){var t=e.children,n=e.className,r=e.cx,o=e.getStyles,i=e.innerProps;return y.a.createElement("div",ve({},i,{className:r(Object(ie.a)(o("clearIndicator",e)),{indicator:!0,"clear-indicator":!0},n)}),t||y.a.createE
 lement(vt,null))},Control:function(e){var t=e.children,n=e.cx,r=e.getStyles,o=e.className,i=e.isDisabled,a=e.isFocused,s=e.innerRef,u=e.innerProps,l=e.menuIsOpen;return y.a.createElement("div",ve({ref:s,className:n(Object(ie.a)(r("control",e)),{control:!0,"control--is-disabled":i,"control--is-focused":a,"control--menu-is-open":l},o)},u),t)},DropdownIndicator:function(e){var t=e.children,n=e.className,r=e.cx,o=e.getStyles,i=e.innerProps;return y.a.createElement("div",ve({},i,{className:r(Object(ie.a)(o("dropdownIndicator",e)),{indicator:!0,"dropdown-indicator":!0},n)}),t||y.a.createElement(Et,null))},DownChevron:Et,CrossIcon:vt,Group:function(e){var t=e.children,n=e.className,r=e.cx,o=e.getStyles,i=e.Heading,a=e.headingProps,s=e.label,u=e.theme,l=e.selectProps;return y.a.createElement("div",{className:r(Object(ie.a)(o("group",e)),{group:!0},n)},y.a.createElement(i,ve({},a,{selectProps:
 l,theme:u,getStyles:o,cx:r}),s),y.a.createElement("div",null,t))},GroupHeading:function(e){var t=e.className,n=e.cx,r=e.getStyles,o=e.theme,i=(e.selectProps,Ce(e,["className","cx","getStyles","theme","selectProps"]));return y.a.createElement("div",ve({className:n(Object(ie.a)(r("groupHeading",Ee({theme:o},i))),{"group-heading":!0},t)},i))},IndicatorsContainer:function(e){var t=e.children,n=e.className,r=e.cx,o=e.getStyles;return y.a.createElement("div",{className:r(Object(ie.a)(o("indicatorsContainer",e)),{indicators:!0},n)},t)},IndicatorSeparator:function(e){var t=e.className,n=e.cx,r=e.getStyles,o=e.innerProps;return y.a.createElement("span",ve({},o,{className:n(Object(ie.a)(r("indicatorSeparator",e)),{"indicator-separator":!0},t)}))},Input:function(e){var t=e.className,n=e.cx,r=e.getStyles,o=e.innerRef,i=e.isHidden,a=e.isDisabled,s=e.theme,u=
 (e.selectProps,Ce(e,["className","cx","getStyles","innerRef","isHidden","isDisabled","theme","selectProps"]));return y.a.createElement("div",{className:Object(ie.a)(r("input",Ee({theme:s},u)))},y.a.createElement(pe.a,ve({className:n(null,{input:!0},t),inputRef:o,inputStyle:function(e){return{background:0,border:0,fontSize:"inherit",opacity:e?0:1,outline:0,padding:0,color:"inherit"}}(i),disabled:a},u)))},LoadingIndicator:St,Menu:function(e){var t=e.children,n=e.className,r=e.cx,o=e.getStyles,i=e.innerRef,a=e.innerProps,s=r(Object(ie.a)(o("menu",e)),{menu:!0},n);return y.a.createElement("div",ve({className:s},a,{ref:i}),t)},MenuList:function(e){var t=e.children,n=e.className,r=e.cx,o=e.getStyles,i=e.isMulti,a=e.innerRef;return y.a.createElement("div",{className:r(Object(ie.a)(o("menuList",e)),{"menu-list":!0,"men
 u-list--is-multi":i},n),ref:a},t)},MenuPortal:We,LoadingMessage:Ue,NoOptionsMessage:ze,MultiValue:Ft,MultiValueContainer:xt,MultiValueLabel:_t,MultiValueRemove:jt,Option:function(e){var t=e.children,n=e.className,r=e.cx,o=e.getStyles,i=e.isDisabled,a=e.isFocused,s=e.isSelected,u=e.innerRef,l=e.innerProps;return y.a.createElement("div",ve({ref:u,className:r(Object(ie.a)(o("option",e)),{option:!0,"option--is-disabled":i,"option--is-focused":a,"option--is-selected":s},n)},l),t)},Placeholder:function(e){var t=e.children,n=e.className,r=e.cx,o=e.getStyles,i=e.innerProps;return y.a.createElement("div",ve({className:r(Object(ie.a)(o("placeholder",e)),{placeholder:!0},n)},i),t)},SelectContainer:function(e){var t=e.children,n=e.className,r=e.cx,o=e.getStyles,i=e.innerProps,a=e.isDisabled,s=e.isRtl;return y.a.createElement("div",ve({className:r(Object(ie.a)(o("container",e)),{"--is-disabled&quo
 t;:a,"--is-rtl":s},n)},i),t)},SingleValue:function(e){var t=e.children,n=e.className,r=e.cx,o=e.getStyles,i=e.isDisabled,a=e.innerProps;return y.a.createElement("div",ve({className:r(Object(ie.a)(o("singleValue",e)),{"single-value":!0,"single-value--is-disabled":i},n)},a),t)},ValueContainer:gt},Nt=function(e){return Ee({},Dt,e.components)},Pt={clearIndicator:Ot,container:function(e){var t=e.isDisabled;return{direction:e.isRtl?"rtl":null,pointerEvents:t?"none":null,position:"relative"}},control:function(e){var t=e.isDisabled,n=e.isFocused,r=e.theme,o=r.colors,i=r.borderRadius,a=r.spacing;return{alignItems:"center",backgroundColor:t?o.neutral5:o.neutral0,borderColor:t?o.neutral10:n?o.primary:o.neutral20,borderRadius:i,borderStyle:"solid",borderWidth:1,boxShadow:n?"0 0 0 1px ".concat(o.primary):null,cursor:"default",display:"flex",flexWrap:"wrap",j
 ustifyContent:"space-between",minHeight:a.controlHeight,outline:"0 !important",position:"relative",transition:"all 100ms","&:hover":{borderColor:n?o.primary:o.neutral30}}},dropdownIndicator:wt,group:function(e){var t=e.theme.spacing;return{paddingBottom:2*t.baseUnit,paddingTop:2*t.baseUnit}},groupHeading:function(e){var t=e.theme.spacing;return{color:"#999",cursor:"default",display:"block",fontSize:"75%",fontWeight:"500",marginBottom:"0.25em",paddingLeft:3*t.baseUnit,paddingRight:3*t.baseUnit,textTransform:"uppercase"}},indicatorsContainer:function(){return{alignItems:"center",alignSelf:"stretch",display:"flex",flexShrink:0}},indicatorSeparator:function(e){var t=e.isDisabled,n=e.theme,r=n.spacing.baseUnit,o=n.colors;return{alignSelf:"stretch",backgroundColor:t?o.neutral10:o.neutral20,marginBottom:2*r,marginTop:2*r,width:1
 }},input:function(e){var t=e.isDisabled,n=e.theme,r=n.spacing,o=n.colors;return{margin:r.baseUnit/2,paddingBottom:r.baseUnit/2,paddingTop:r.baseUnit/2,visibility:t?"hidden":"visible",color:o.neutral80}},loadingIndicator:function(e){var t=e.isFocused,n=e.size,r=e.theme,o=r.colors,i=r.spacing.baseUnit;return{color:t?o.neutral60:o.neutral20,display:"flex",padding:2*i,transition:"color 150ms",alignSelf:"center",fontSize:n,lineHeight:1,marginRight:n,textAlign:"center",verticalAlign:"middle"}},loadingMessage:Be,menu:function(e){var t,n=e.placement,r=e.theme,o=r.borderRadius,i=r.spacing,a=r.colors;return be(t={},function(e){return e?{bottom:"top",top:"bottom"}[e]:"bottom"}(n),"100%"),be(t,"backgroundColor",a.neutral0),be(t,"borderRadius",o),be(t,"boxShadow","0 0 0 1px hsla(0, 0%, 0%, 0.1), 0 4px 11px hsla(0, 0%, 0%, 0.1)"),be(t,"marginBo
 ttom",i.menuGutter),be(t,"marginTop",i.menuGutter),be(t,"position","absolute"),be(t,"width","100%"),be(t,"zIndex",1),t},menuList:function(e){var t=e.maxHeight,n=e.theme.spacing.baseUnit;return{maxHeight:t,overflowY:"auto",paddingBottom:n,paddingTop:n,position:"relative",WebkitOverflowScrolling:"touch"}},menuPortal:function(e){var t=e.rect,n=e.offset,r=e.position;return{left:t.left,position:r,top:n,width:t.width,zIndex:1}},multiValue:function(e){var t=e.theme,n=t.spacing,r=t.borderRadius;return{backgroundColor:t.colors.neutral10,borderRadius:r/2,display:"flex",margin:n.baseUnit/2,minWidth:0}},multiValueLabel:function(e){var t=e.theme,n=t.borderRadius,r=t.colors,o=e.cropWithEllipsis;return{borderRadius:n/2,color:r.neutral80,fontSize:"85%",overflow:"hidden",padding:3,paddingLeft:6,textOverflow:o?"ellipsis":null,whiteSpace:"nowrap"}},multiValue
 Remove:function(e){var t=e.theme,n=t.spacing,r=t.borderRadius,o=t.colors;return{alignItems:"center",borderRadius:r/2,backgroundColor:e.isFocused&&o.dangerLight,display:"flex",paddingLeft:n.baseUnit,paddingRight:n.baseUnit,":hover":{backgroundColor:o.dangerLight,color:o.danger}}},noOptionsMessage:Re,option:function(e){var t=e.isDisabled,n=e.isFocused,r=e.isSelected,o=e.theme,i=o.spacing,a=o.colors;return{backgroundColor:r?a.primary:n?a.primary25:"transparent",color:t?a.neutral20:r?a.neutral0:"inherit",cursor:"default",display:"block",fontSize:"inherit",padding:"".concat(2*i.baseUnit,"px ").concat(3*i.baseUnit,"px"),width:"100%",userSelect:"none",WebkitTapHighlightColor:"rgba(0, 0, 0, 0)",":active":{backgroundColor:r?a.primary:a.primary50}}},placeholder:function(e){var t=e.theme,n=t.spacing;return{color:t.colors.neutral50,marginL
 eft:n.baseUnit/2,marginRight:n.baseUnit/2,position:"absolute",top:"50%",transform:"translateY(-50%)"}},singleValue:function(e){var t=e.isDisabled,n=e.theme,r=n.spacing,o=n.colors;return{color:t?o.neutral40:o.neutral80,marginLeft:r.baseUnit/2,marginRight:r.baseUnit/2,maxWidth:"calc(100% - ".concat(2*r.baseUnit,"px)"),overflow:"hidden",position:"absolute",textOverflow:"ellipsis",whiteSpace:"nowrap",top:"50%",transform:"translateY(-50%)"}},valueContainer:function(e){var t=e.theme.spacing;return{alignItems:"center",display:"flex",flex:1,flexWrap:"wrap",padding:"".concat(t.baseUnit/2,"px ").concat(2*t.baseUnit,"px"),WebkitOverflowScrolling:"touch",position:"relative",overflow:"hidden"}}};var Lt={borderRadius:4,colors:{primary:"#2684FF",primary75:"#4C9AFF",primary50:"
 #B2D4FF",primary25:"#DEEBFF",danger:"#DE350B",dangerLight:"#FFBDAD",neutral0:"hsl(0, 0%, 100%)",neutral5:"hsl(0, 0%, 95%)",neutral10:"hsl(0, 0%, 90%)",neutral20:"hsl(0, 0%, 80%)",neutral30:"hsl(0, 0%, 70%)",neutral40:"hsl(0, 0%, 60%)",neutral50:"hsl(0, 0%, 50%)",neutral60:"hsl(0, 0%, 40%)",neutral70:"hsl(0, 0%, 30%)",neutral80:"hsl(0, 0%, 20%)",neutral90:"hsl(0, 0%, 10%)"},spacing:{baseUnit:4,controlHeight:38,menuGutter:8}},Tt={backspaceRemovesValue:!0,blurInputOnSelect:Le(),captureMenuScroll:!Le(),closeMenuOnSelect:!0,closeMenuOnScroll:!1,components:{},controlShouldRenderValue:!0,escapeClearsValue:!1,filterOption:function(e){return function(t,n){var r=Ee({ignoreCase:!0,ignoreAccents:!0,stringify:Ze,trim:!0,matchFrom:"any"},e),o=r.ignoreCase,i=r.ignoreAccents,a=r.stringify,s=r.trim,u=r.matchFrom,l=s?Ke(n):n,c=s?Ke(a(t)):a(t);retur
 n o&&(l=l.toLowerCase(),c=c.toLowerCase()),i&&(l=Xe(l),c=Xe(c)),"start"===u?c.substr(0,l.length)===l:c.indexOf(l)>-1}}(),formatGroupLabel:function(e){return e.label},getOptionLabel:function(e){return e.label},getOptionValue:function(e){return e.value},isDisabled:!1,isLoading:!1,isMulti:!1,isRtl:!1,isSearchable:!0,isOptionDisabled:ht,loadingMessage:function(){return"Loading..."},maxMenuHeight:300,minMenuHeight:140,menuIsOpen:!1,menuPlacement:"bottom",menuPosition:"absolute",menuShouldBlockScroll:!1,menuShouldScrollIntoView:!function(){try{return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)}catch(e){return!1}}(),noOptionsMessage:function(){return"No options"},openMenuOnFocus:!1,openMenuOnClick:!0,options:[],pageSize:5,placeholder:"Select...",screenReaderStatus:function(e){var t=e.count;return"".concat(t," result").concat(1!==t?"s":&q
 uot;"," available")},styles:{},tabIndex:"0",tabSelectsValue:!0},It=1,Mt=function(e){function t(e){var n;me(this,t),be(ke(ke(n=Se(this,we(t).call(this,e)))),"state",{ariaLiveSelection:"",ariaLiveContext:"",focusedOption:null,focusedValue:null,inputIsHidden:!1,isFocused:!1,isComposing:!1,menuOptions:{render:[],focusable:[]},selectValue:[]}),be(ke(ke(n)),"blockOptionHover",!1),be(ke(ke(n)),"clearFocusValueOnUpdate",!1),be(ke(ke(n)),"commonProps",void 0),be(ke(ke(n)),"components",void 0),be(ke(ke(n)),"hasGroups",!1),be(ke(ke(n)),"initialTouchX",0),be(ke(ke(n)),"initialTouchY",0),be(ke(ke(n)),"inputIsHiddenAfterUpdate",void 0),be(ke(ke(n)),"instancePrefix",""),be(ke(ke(n)),"openAfterFocus",!1),be(ke(ke(n)),"scrollToFocusedOptionOnUpdate",!1),be(ke(ke(n)),"userIsDragging",void 0),be(ke(ke(n)),"controlR
 ef",null),be(ke(ke(n)),"getControlRef",function(e){n.controlRef=e}),be(ke(ke(n)),"focusedOptionRef",null),be(ke(ke(n)),"getFocusedOptionRef",function(e){n.focusedOptionRef=e}),be(ke(ke(n)),"menuListRef",null),be(ke(ke(n)),"getMenuListRef",function(e){n.menuListRef=e}),be(ke(ke(n)),"inputRef",null),be(ke(ke(n)),"getInputRef",function(e){n.inputRef=e}),be(ke(ke(n)),"cacheComponents",function(e){n.components=Nt({components:e})}),be(ke(ke(n)),"focus",n.focusInput),be(ke(ke(n)),"blur",n.blurInput),be(ke(ke(n)),"onChange",function(e,t){var r=n.props;(0,r.onChange)(e,Ee({},t,{name:r.name}))}),be(ke(ke(n)),"setValue",function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"set-value",r=arguments.length>2?arguments[2]:void 0,o=n.props,i=o.closeMenuOnSelect,a=o.isMulti;n.onInputChange("",{action:"set-value"}),
 i&&(n.inputIsHiddenAfterUpdate=!a,n.onMenuClose()),n.clearFocusValueOnUpdate=!0,n.onChange(e,{action:t,option:r})}),be(ke(ke(n)),"selectOption",function(e){var t=n.props,r=t.blurInputOnSelect,o=t.isMulti,i=n.state.selectValue;if(o)if(n.isOptionSelected(e,i)){var a=n.getOptionValue(e);n.setValue(i.filter(function(e){return n.getOptionValue(e)!==a}),"deselect-option",e),n.announceAriaLiveSelection({event:"deselect-option",context:{value:n.getOptionLabel(e)}})}else n.isOptionDisabled(e,i)?n.announceAriaLiveSelection({event:"select-option",context:{value:n.getOptionLabel(e),isDisabled:!0}}):(n.setValue([].concat(Ae(i),[e]),"select-option",e),n.announceAriaLiveSelection({event:"select-option",context:{value:n.getOptionLabel(e)}}));else n.isOptionDisabled(e,i)?n.announceAriaLiveSelection({event:"select-option",context:{value:n.getOptionLabel(e),isDisabled:!0}}):(n.setValue(e,"select-option"),n.announce
 AriaLiveSelection({event:"select-option",context:{value:n.getOptionLabel(e)}}));r&&n.blurInput()}),be(ke(ke(n)),"removeValue",function(e){var t=n.state.selectValue,r=n.getOptionValue(e);n.onChange(t.filter(function(e){return n.getOptionValue(e)!==r}),{action:"remove-value",removedValue:e}),n.announceAriaLiveSelection({event:"remove-value",context:{value:e?n.getOptionLabel(e):""}}),n.focusInput()}),be(ke(ke(n)),"clearValue",function(){var e=n.props.isMulti;n.onChange(e?[]:null,{action:"clear"})}),be(ke(ke(n)),"popValue",function(){var e=n.state.selectValue,t=e[e.length-1];n.announceAriaLiveSelection({event:"pop-value",context:{value:t?n.getOptionLabel(t):""}}),n.onChange(e.slice(0,e.length-1),{action:"pop-value",removedValue:t})}),be(ke(ke(n)),"getOptionLabel",function(e){return n.props.getOptionLabel(e)}),be(ke(ke(n)),"getOptionValue",function(e){
 return n.props.getOptionValue(e)}),be(ke(ke(n)),"getStyles",function(e,t){var r=Pt[e](t);r.boxSizing="border-box";var o=n.props.styles[e];return o?o(r,t):r}),be(ke(ke(n)),"getElementId",function(e){return"".concat(n.instancePrefix,"-").concat(e)}),be(ke(ke(n)),"getActiveDescendentId",function(){var e=n.props.menuIsOpen,t=n.state,r=t.menuOptions,o=t.focusedOption;if(o&&e){var i=r.focusable.indexOf(o),a=r.render[i];return a&&a.key}}),be(ke(ke(n)),"announceAriaLiveSelection",function(e){var t=e.event,r=e.context;n.setState({ariaLiveSelection:mt(t,r)})}),be(ke(ke(n)),"announceAriaLiveContext",function(e){var t=e.event,r=e.context;n.setState({ariaLiveContext:ft(t,Ee({},r,{label:n.props["aria-label"]}))})}),be(ke(ke(n)),"onMenuMouseDown",function(e){0===e.button&&(e.stopPropagation(),e.preventDefault(),n.focusInput())}),be(ke(ke(n)),"onMenuMouseMove",functi
 on(e){n.blockOptionHover=!1}),be(ke(ke(n)),"onControlMouseDown",function(e){var t=n.props.openMenuOnClick;n.state.isFocused?n.props.menuIsOpen?"INPUT"!==e.target.tagName&&n.onMenuClose():t&&n.openMenu("first"):(t&&(n.openAfterFocus=!0),n.focusInput()),"INPUT"!==e.target.tagName&&e.preventDefault()}),be(ke(ke(n)),"onDropdownIndicatorMouseDown",function(e){if(!(e&&"mousedown"===e.type&&0!==e.button||n.props.isDisabled)){var t=n.props,r=t.isMulti,o=t.menuIsOpen;n.focusInput(),o?(n.inputIsHiddenAfterUpdate=!r,n.onMenuClose()):n.openMenu("first"),e.preventDefault(),e.stopPropagation()}}),be(ke(ke(n)),"onClearIndicatorMouseDown",function(e){e&&"mousedown"===e.type&&0!==e.button||(n.clearValue(),e.stopPropagation(),n.openAfterFocus=!1,setTimeout(function(){return n.focusInput()}))}),be(ke(ke(n)),"onScroll",function(e){"bool
 ean"==typeof n.props.closeMenuOnScroll?e.target instanceof HTMLElement&&Fe(e.target)&&n.props.onMenuClose():"function"==typeof n.props.closeMenuOnScroll&&n.props.closeMenuOnScroll(e)&&n.props.onMenuClose()}),be(ke(ke(n)),"onCompositionStart",function(){n.setState({isComposing:!0})}),be(ke(ke(n)),"onCompositionEnd",function(){n.setState({isComposing:!1})}),be(ke(ke(n)),"onTouchStart",function(e){var t=e.touches.item(0);t&&(n.initialTouchX=t.clientX,n.initialTouchY=t.clientY,n.userIsDragging=!1)}),be(ke(ke(n)),"onTouchMove",function(e){var t=e.touches.item(0);if(t){var r=Math.abs(t.clientX-n.initialTouchX),o=Math.abs(t.clientY-n.initialTouchY);n.userIsDragging=r>5||o>5}}),be(ke(ke(n)),"onTouchEnd",function(e){n.userIsDragging||(n.controlRef&&!n.controlRef.contains(e.target)&&n.menuListRef&&!n.menuListRef.contains(e.target)&&n.blurInput(),n.init
 ialTouchX=0,n.initialTouchY=0)}),be(ke(ke(n)),"onControlTouchEnd",function(e){n.userIsDragging||n.onControlMouseDown(e)}),be(ke(ke(n)),"onClearIndicatorTouchEnd",function(e){n.userIsDragging||n.onClearIndicatorMouseDown(e)}),be(ke(ke(n)),"onDropdownIndicatorTouchEnd",function(e){n.userIsDragging||n.onDropdownIndicatorMouseDown(e)}),be(ke(ke(n)),"handleInputChange",function(e){var t=e.currentTarget.value;n.inputIsHiddenAfterUpdate=!1,n.onInputChange(t,{action:"input-change"}),n.onMenuOpen()}),be(ke(ke(n)),"onInputFocus",function(e){var t=n.props,r=t.isSearchable,o=t.isMulti;n.props.onFocus&&n.props.onFocus(e),n.inputIsHiddenAfterUpdate=!1,n.announceAriaLiveContext({event:"input",context:{isSearchable:r,isMulti:o}}),n.setState({isFocused:!0}),(n.openAfterFocus||n.props.openMenuOnFocus)&&n.openMenu("first"),n.openAfterFocus=!1}),be(ke(ke(n)),"onInputBlur",function(e){n.menuListRef&
 amp;&n.menuListRef.contains(document.activeElement)?n.inputRef.focus():(n.props.onBlur&&n.props.onBlur(e),n.onInputChange("",{action:"input-blur"}),n.onMenuClose(),n.setState({focusedValue:null,isFocused:!1}))}),be(ke(ke(n)),"onOptionHover",function(e){n.blockOptionHover||n.state.focusedOption===e||n.setState({focusedOption:e})}),be(ke(ke(n)),"shouldHideSelectedOptions",function(){var e=n.props,t=e.hideSelectedOptions,r=e.isMulti;return void 0===t?r:t}),be(ke(ke(n)),"onKeyDown",function(e){var t=n.props,r=t.isMulti,o=t.backspaceRemovesValue,i=t.escapeClearsValue,a=t.inputValue,s=t.isClearable,u=t.isDisabled,l=t.menuIsOpen,c=t.onKeyDown,p=t.tabSelectsValue,d=t.openMenuOnFocus,f=n.state,m=f.isComposing,h=f.focusedOption,g=f.focusedValue,b=f.selectValue;if(!(u||"function"==typeof c&&(c(e),e.defaultPrevented))){switch(n.blockOptionHover=!0,e.key){case"ArrowLeft":if(!r||a)return;n.focusValue("p
 revious");break;case"ArrowRight":if(!r||a)return;n.focusValue("next");break;case"Delete":case"Backspace":if(a)return;if(g)n.removeValue(g);else{if(!o)return;r?n.popValue():s&&n.clearValue()}break;case"Tab":if(m)return;if(e.shiftKey||!l||!p||!h||d&&n.isOptionSelected(h,b))return;n.selectOption(h);break;case"Enter":if(l){if(!h)return;if(m)return;n.selectOption(h);break}return;case"Escape":l?(n.inputIsHiddenAfterUpdate=!1,n.onInputChange("",{action:"menu-close"}),n.onMenuClose()):s&&i&&n.clearValue();break;case" ":if(a)return;if(!l){n.openMenu("first");break}if(!h)return;n.selectOption(h);break;case"ArrowUp":l?n.focusOption("up"):n.openMenu("last");break;case"ArrowDown":l?n.focusOption("down"):n.openMenu("first");break;case"PageUp":if(!l)return;n.focusOption("pageup&q
 uot;);break;case"PageDown":if(!l)return;n.focusOption("pagedown");break;case"Home":if(!l)return;n.focusOption("first");break;case"End":if(!l)return;n.focusOption("last");break;default:return}e.preventDefault()}});var r=e.value;n.cacheComponents=oe(n.cacheComponents,qe).bind(ke(ke(n))),n.cacheComponents(e.components),n.instancePrefix="react-select-"+(n.props.instanceId||++It);var o=je(r),i=n.buildMenuOptions(e,o);return n.state.menuOptions=i,n.state.selectValue=o,n}return ye(t,E["Component"]),ge(t,[{key:"componentDidMount",value:function(){this.startListeningComposition(),this.startListeningToTouch(),this.props.closeMenuOnScroll&&document&&document.addEventListener&&document.addEventListener("scroll",this.onScroll,!0),this.props.autoFocus&&this.focusInput()}},{key:"componentWillReceiveProps",value:function(e){var t=this.props,n=t.options,r=t.va
 lue,o=t.inputValue;if(this.cacheComponents(e.components),e.value!==r||e.options!==n||e.inputValue!==o){var i=je(e.value),a=this.buildMenuOptions(e,i),s=this.getNextFocusedValue(i),u=this.getNextFocusedOption(a.focusable);this.setState({menuOptions:a,selectValue:i,focusedOption:u,focusedValue:s})}null!=this.inputIsHiddenAfterUpdate&&(this.setState({inputIsHidden:this.inputIsHiddenAfterUpdate}),delete this.inputIsHiddenAfterUpdate)}},{key:"componentDidUpdate",value:function(e){var t=this.props,n=t.isDisabled,r=t.menuIsOpen,o=this.state.isFocused;(o&&!n&&e.isDisabled||o&&r&&!e.menuIsOpen)&&this.focusInput(),this.menuListRef&&this.focusedOptionRef&&this.scrollToFocusedOptionOnUpdate&&function(e,t){var n=e.getBoundingClientRect(),r=t.getBoundingClientRect(),o=t.offsetHeight/3;r.bottom+o>n.bottom?Ne(e,Math.min(t.offsetTop+t.clientHeight-e.offsetHeight+o,e.scrollHeight)):r.top-o<n.top&&Ne(e,Math
 .max(t.offsetTop-o,0))}(this.menuListRef,this.focusedOptionRef),this.scrollToFocusedOptionOnUpdate=!1}},{key:"componentWillUnmount",value:function(){this.stopListeningComposition(),this.stopListeningToTouch(),document.removeEventListener("scroll",this.onScroll,!0)}},{key:"onMenuOpen",value:function(){this.props.onMenuOpen()}},{key:"onMenuClose",value:function(){var e=this.props,t=e.isSearchable,n=e.isMulti;this.announceAriaLiveContext({event:"input",context:{isSearchable:t,isMulti:n}}),this.onInputChange("",{action:"menu-close"}),this.props.onMenuClose()}},{key:"onInputChange",value:function(e,t){this.props.onInputChange(e,t)}},{key:"focusInput",value:function(){this.inputRef&&this.inputRef.focus()}},{key:"blurInput",value:function(){this.inputRef&&this.inputRef.blur()}},{key:"openMenu",value:function(e){var t=this.state,n=t.menuOptions,r=t.selectValue,o=t.is
 Focused,i=this.props.isMulti,a="first"===e?0:n.focusable.length-1;if(!i){var s=n.focusable.indexOf(r[0]);s>-1&&(a=s)}this.scrollToFocusedOptionOnUpdate=!(o&&this.menuListRef),this.inputIsHiddenAfterUpdate=!1,this.onMenuOpen(),this.setState({focusedValue:null,focusedOption:n.focusable[a]}),this.announceAriaLiveContext({event:"menu"})}},{key:"focusValue",value:function(e){var t=this.props,n=t.isMulti,r=t.isSearchable,o=this.state,i=o.selectValue,a=o.focusedValue;if(n){this.setState({focusedOption:null});var s=i.indexOf(a);a||(s=-1,this.announceAriaLiveContext({event:"value"}));var u=i.length-1,l=-1;if(i.length){switch(e){case"previous":l=0===s?0:-1===s?u:s-1;break;case"next":s>-1&&s<u&&(l=s+1)}-1===l&&this.announceAriaLiveContext({event:"input",context:{isSearchable:r,isMulti:n}}),this.setState({inputIsHidden:-1!==l,focusedValue:i[l]})}}}},{key:"focusOption"
 ,value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"first",t=this.props.pageSize,n=this.state,r=n.focusedOption,o=n.menuOptions.focusable;if(o.length){var i=0,a=o.indexOf(r);r||(a=-1,this.announceAriaLiveContext({event:"menu"})),"up"===e?i=a>0?a-1:o.length-1:"down"===e?i=(a+1)%o.length:"pageup"===e?(i=a-t)<0&&(i=0):"pagedown"===e?(i=a+t)>o.length-1&&(i=o.length-1):"last"===e&&(i=o.length-1),this.scrollToFocusedOptionOnUpdate=!0,this.setState({focusedOption:o[i],focusedValue:null}),this.announceAriaLiveContext({event:"menu",context:{isDisabled:ht(o[i])}})}}},{key:"getTheme",value:function(){return this.props.theme?"function"==typeof this.props.theme?this.props.theme(Lt):Ee({},Lt,this.props.theme):Lt}},{key:"getCommonProps",value:function(){var e=this.clearValue,t=this.getStyles,n=this.setValue,r=this.sele
 ctOption,o=this.props,i=o.classNamePrefix,a=o.isMulti,s=o.isRtl,u=o.options,l=this.state.selectValue,c=this.hasValue();return{cx:function(e,t,n,r){var o=[t,r];if(n&&e)for(var i in n)n.hasOwnProperty(i)&&n[i]&&o.push("".concat(_e(e,i)));return o.filter(function(e){return e}).map(function(e){return String(e).trim()}).join(" ")}.bind(null,i),clearValue:e,getStyles:t,getValue:function(){return l},hasValue:c,isMulti:a,isRtl:s,options:u,selectOption:r,setValue:n,selectProps:o,theme:this.getTheme()}}},{key:"getNextFocusedValue",value:function(e){if(this.clearFocusValueOnUpdate)return this.clearFocusValueOnUpdate=!1,null;var t=this.state,n=t.focusedValue,r=t.selectValue.indexOf(n);if(r>-1){if(e.indexOf(n)>-1)return n;if(r<e.length)return e[r]}return null}},{key:"getNextFocusedOption",value:function(e){var t=this.state.focusedOption;return t&&e.indexOf(t)>-1?t:e[0]}},{key:"hasValue",value:function()
 {return this.state.selectValue.length>0}},{key:"hasOptions",value:function(){return!!this.state.menuOptions.render.length}},{key:"countOptions",value:function(){return this.state.menuOptions.focusable.length}},{key:"isClearable",value:function(){var e=this.props,t=e.isClearable,n=e.isMulti;return void 0===t?n:t}},{key:"isOptionDisabled",value:function(e,t){return"function"==typeof this.props.isOptionDisabled&&this.props.isOptionDisabled(e,t)}},{key:"isOptionSelected",value:function(e,t){var n=this;if(t.indexOf(e)>-1)return!0;if("function"==typeof this.props.isOptionSelected)return this.props.isOptionSelected(e,t);var r=this.getOptionValue(e);return t.some(function(e){return n.getOptionValue(e)===r})}},{key:"filterOption",value:function(e,t){return!this.props.filterOption||this.props.filterOption(e,t)}},{key:"formatOptionLabel",value:function(e,t){if("function"==typeof th
 is.props.formatOptionLabel){var n=this.props.inputValue,r=this.state.selectValue;return this.props.formatOptionLabel(e,{context:t,inputValue:n,selectValue:r})}return this.getOptionLabel(e)}},{key:"formatGroupLabel",value:function(e){return this.props.formatGroupLabel(e)}},{key:"startListeningComposition",value:function(){document&&document.addEventListener&&(document.addEventListener("compositionstart",this.onCompositionStart,!1),document.addEventListener("compositionend",this.onCompositionEnd,!1))}},{key:"stopListeningComposition",value:function(){document&&document.removeEventListener&&(document.removeEventListener("compositionstart",this.onCompositionStart),document.removeEventListener("compositionend",this.onCompositionEnd))}},{key:"startListeningToTouch",value:function(){document&&document.addEventListener&&(document.addEventListener("touchstart&q
 uot;,this.onTouchStart,!1),document.addEventListener("touchmove",this.onTouchMove,!1),document.addEventListener("touchend",this.onTouchEnd,!1))}},{key:"stopListeningToTouch",value:function(){document&&document.removeEventListener&&(document.removeEventListener("touchstart",this.onTouchStart),document.removeEventListener("touchmove",this.onTouchMove),document.removeEventListener("touchend",this.onTouchEnd))}},{key:"buildMenuOptions",value:function(e,t){var n=this,r=e.inputValue,o=void 0===r?"":r,i=function(e,r){var i=n.isOptionDisabled(e,t),a=n.isOptionSelected(e,t),s=n.getOptionLabel(e),u=n.getOptionValue(e);if(!(n.shouldHideSelectedOptions()&&a||!n.filterOption({label:s,value:u,data:e},o))){var l=i?void 0:function(){return n.onOptionHover(e)},c=i?void 0:function(){return n.selectOption(e)},p="".concat(n.getElementId("option"),"-").concat(r);return{in
 nerProps:{id:p,onClick:c,onMouseMove:l,onMouseOver:l,tabIndex:-1},data:e,isDisabled:i,isSelected:a,key:p,label:s,type:"option",value:u}}};return e.options.reduce(function(e,t,r){if(t.options){n.hasGroups||(n.hasGroups=!0);var o=t.options.map(function(t,n){var o=i(t,"".concat(r,"-").concat(n));return o&&e.focusable.push(t),o}).filter(Boolean);if(o.length){var a="".concat(n.getElementId("group"),"-").concat(r);e.render.push({type:"group",key:a,data:t,options:o})}}else{var s=i(t,"".concat(r));s&&(e.render.push(s),e.focusable.push(t))}return e},{render:[],focusable:[]})}},{key:"constructAriaLiveMessage",value:function(){var e=this.state,t=e.ariaLiveContext,n=e.selectValue,r=e.focusedValue,o=e.focusedOption,i=this.props,a=i.options,s=i.menuIsOpen,u=i.inputValue,l=i.screenReaderStatus,c=r?function(e){var t=e.focusedValue,n=e.getOptionLabel,r=e.selectValue;return"value ".conc
 at(n(t)," focused, ").concat(r.indexOf(t)+1," of ").concat(r.length,".")}({focusedValue:r,getOptionLabel:this.getOptionLabel,selectValue:n}):"",p=o&&s?function(e){var t=e.focusedOption,n=e.getOptionLabel,r=e.options;return"option ".concat(n(t)," focused").concat(t.isDisabled?" disabled":"",", ").concat(r.indexOf(t)+1," of ").concat(r.length,".")}({focusedOption:o,getOptionLabel:this.getOptionLabel,options:a}):"",d=function(e){var t=e.inputValue,n=e.screenReaderMessage;return"".concat(n).concat(t?" for search term "+t:"",".")}({inputValue:u,screenReaderMessage:l({count:this.countOptions()})});return"".concat(c," ").concat(p," ").concat(d," ").concat(t)}},{key:"renderInput",value:function(){var e=this.props,t=e.isDisabled,n=e.isSearchable,r=e.inputId,o=e.inputValue,i=e.t
 abIndex,a=this.components.Input,s=this.state.inputIsHidden,u=r||this.getElementId("input");if(!n)return y.a.createElement(Qe,{id:u,innerRef:this.getInputRef,onBlur:this.onInputBlur,onChange:xe,onFocus:this.onInputFocus,readOnly:!0,disabled:t,tabIndex:i,value:""});var l={"aria-autocomplete":"list","aria-label":this.props["aria-label"],"aria-labelledby":this.props["aria-labelledby"]},c=this.commonProps,p=c.cx,d=c.theme,f=c.selectProps;return y.a.createElement(a,ve({autoCapitalize:"none",autoComplete:"off",autoCorrect:"off",cx:p,getStyles:this.getStyles,id:u,innerRef:this.getInputRef,isDisabled:t,isHidden:s,onBlur:this.onInputBlur,onChange:this.handleInputChange,onFocus:this.onInputFocus,selectProps:f,spellCheck:"false",tabIndex:i,theme:d,type:"text",value:o},l))}},{key:"renderPlaceholderOrValue",value:function(){var e=this,t=this.components,n=t.Mu
 ltiValue,r=t.MultiValueContainer,o=t.MultiValueLabel,i=t.MultiValueRemove,a=t.SingleValue,s=t.Placeholder,u=this.commonProps,l=this.props,c=l.controlShouldRenderValue,p=l.isDisabled,d=l.isMulti,f=l.inputValue,m=l.placeholder,h=this.state,g=h.selectValue,b=h.focusedValue,v=h.isFocused;if(!this.hasValue()||!c)return f?null:y.a.createElement(s,ve({},u,{key:"placeholder",isDisabled:p,isFocused:v}),m);if(d)return g.map(function(t){var a=t===b;return y.a.createElement(n,ve({},u,{components:{Container:r,Label:o,Remove:i},isFocused:a,isDisabled:p,key:e.getOptionValue(t),removeProps:{onClick:function(){return e.removeValue(t)},onTouchEnd:function(){return e.removeValue(t)},onMouseDown:function(e){e.preventDefault(),e.stopPropagation()}},data:t}),e.formatOptionLabel(t,"value"))});if(f)return null;var E=g[0];return y.a.createElement(a,ve({},u,{data:E,isDisabled:p}),this.formatOptionLabel(E,"value"))}},{key:"renderClearIndicator",value:function(){var e=th
 is.components.ClearIndicator,t=this.commonProps,n=this.props,r=n.isDisabled,o=n.isLoading,i=this.state.isFocused;if(!this.isClearable()||!e||r||!this.hasValue()||o)return null;var a={onMouseDown:this.onClearIndicatorMouseDown,onTouchEnd:this.onClearIndicatorTouchEnd,"aria-hidden":"true"};return y.a.createElement(e,ve({},t,{innerProps:a,isFocused:i}))}},{key:"renderLoadingIndicator",value:function(){var e=this.components.LoadingIndicator,t=this.commonProps,n=this.props,r=n.isDisabled,o=n.isLoading,i=this.state.isFocused;if(!e||!o)return null;return y.a.createElement(e,ve({},t,{innerProps:{"aria-hidden":"true"},isDisabled:r,isFocused:i}))}},{key:"renderIndicatorSeparator",value:function(){var e=this.components,t=e.DropdownIndicator,n=e.IndicatorSeparator;if(!t||!n)return null;var r=this.commonProps,o=this.props.isDisabled,i=this.state.isFocused;return y.a.createElement(n,ve({},r,{isDisabled:o,isFocused:i}))}},{key:"rende
 rDropdownIndicator",value:function(){var e=this.components.DropdownIndicator;if(!e)return null;var t=this.commonProps,n=this.props.isDisabled,r=this.state.isFocused,o={onMouseDown:this.onDropdownIndicatorMouseDown,onTouchEnd:this.onDropdownIndicatorTouchEnd,"aria-hidden":"true"};return y.a.createElement(e,ve({},t,{innerProps:o,isDisabled:n,isFocused:r}))}},{key:"renderMenu",value:function(){var e=this,t=this.components,n=t.Group,r=t.GroupHeading,o=t.Menu,i=t.MenuList,a=t.MenuPortal,s=t.LoadingMessage,u=t.NoOptionsMessage,l=t.Option,c=this.commonProps,p=this.state,d=p.focusedOption,f=p.menuOptions,m=this.props,h=m.captureMenuScroll,g=m.inputValue,b=m.isLoading,v=m.loadingMessage,E=m.minMenuHeight,w=m.maxMenuHeight,O=m.menuIsOpen,C=m.menuPlacement,k=m.menuPosition,S=m.menuPortalTarget,A=m.menuShouldBlockScroll,x=m.menuShouldScrollIntoView,_=m.noOptionsMessage,j=m.onMenuScrollToTop,F=m.onMenuScrollToBottom;if(!O)return null;var D,N=function(t){var n=d
 ===t.data;return t.innerRef=n?e.getFocusedOptionRef:void 0,y.a.createElement(l,ve({},c,t,{isFocused:n}),e.formatOptionLabel(t.data,"menu"))};if(this.hasOptions())D=f.render.map(function(t){if("group"===t.type){t.type;var o=Ce(t,["type"]),i="".concat(t.key,"-heading");return y.a.createElement(n,ve({},c,o,{Heading:r,headingProps:{id:i},label:e.formatGroupLabel(t.data)}),t.options.map(function(e){return N(e)}))}if("option"===t.type)return N(t)});else if(b){var P=v({inputValue:g});if(null===P)return null;D=y.a.createElement(s,c,P)}else{var L=_({inputValue:g});if(null===L)return null;D=y.a.createElement(u,c,L)}var T={minMenuHeight:E,maxMenuHeight:w,menuPlacement:C,menuPosition:k,menuShouldScrollIntoView:x},I=y.a.createElement(Me,ve({},c,T),function(t){var n=t.ref,r=t.placerProps,a=r.placement,s=r.maxHeight;return y.a.createElement(o,ve({},c,T,{innerRef:n,innerProps:{onMouseDown:e.onMenuMouseDown,onMouseMove:e.onMenuMouseMove},is
 Loading:b,placement:a}),y.a.createElement(dt,{isEnabled:h,onTopArrive:j,onBottomArrive:F},y.a.createElement(ct,{isEnabled:A},y.a.createElement(i,ve({},c,{innerRef:e.getMenuListRef,isLoading:b,maxHeight:s}),D))))});return S||"fixed"===k?y.a.createElement(a,ve({},c,{appendTo:S,controlElement:this.controlRef,menuPlacement:C,menuPosition:k}),I):I}},{key:"renderFormField",value:function(){var e=this,t=this.props,n=t.delimiter,r=t.isDisabled,o=t.isMulti,i=t.name,a=this.state.selectValue;if(i&&!r){if(o){if(n){var s=a.map(function(t){return e.getOptionValue(t)}).join(n);return y.a.createElement("input",{name:i,type:"hidden",value:s})}var u=a.length>0?a.map(function(t,n){return y.a.createElement("input",{key:"i-".concat(n),name:i,type:"hidden",value:e.getOptionValue(t)})}):y.a.createElement("input",{name:i,type:"hidden"});return y.a.createElement("div",null,u)}var l=a[0]?this.getOpt
 ionValue(a[0]):"";return y.a.createElement("input",{name:i,type:"hidden",value:l})}}},{key:"renderLiveRegion",value:function(){return this.state.isFocused?y.a.createElement(Je,{"aria-live":"assertive"},y.a.createElement("p",{id:"aria-selection-event"}," ",this.state.ariaLiveSelection),y.a.createElement("p",{id:"aria-context"}," ",this.constructAriaLiveMessage())):null}},{key:"render",value:function(){var e=this.components,t=e.Control,n=e.IndicatorsContainer,r=e.SelectContainer,o=e.ValueContainer,i=this.props,a=i.className,s=i.id,u=i.isDisabled,l=i.menuIsOpen,c=this.state.isFocused,p=this.commonProps=this.getCommonProps();return y.a.createElement(r,ve({},p,{className:a,innerProps:{id:s,onKeyDown:this.onKeyDown},isDisabled:u,isFocused:c}),this.renderLiveRegion(),y.a.createElement(t,ve({},p,{innerRef:this.getControlRef,innerProps:{onMouseDown:this.onContro
 lMouseDown,onTouchEnd:this.onControlTouchEnd},isDisabled:u,isFocused:c,menuIsOpen:l}),y.a.createElement(o,ve({},p,{isDisabled:u}),this.renderPlaceholderOrValue(),this.renderInput()),y.a.createElement(n,ve({},p,{isDisabled:u}),this.renderClearIndicator(),this.renderLoadingIndicator(),this.renderIndicatorSeparator(),this.renderDropdownIndicator())),this.renderMenu(),this.renderFormField())}}]),t}();be(Mt,"defaultProps",Tt);var Vt,Rt,Bt={defaultInputValue:"",defaultMenuIsOpen:!1,defaultValue:null},zt=function(e){var t,n;return n=t=function(t){function n(){var e,t;me(this,n);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return be(ke(ke(t=Se(this,(e=we(n)).call.apply(e,[this].concat(o))))),"select",void 0),be(ke(ke(t)),"state",{inputValue:void 0!==t.props.inputValue?t.props.inputValue:t.props.defaultInputValue,menuIsOpen:void 0!==t.props.menuIsOpen?t.props.menuIsOpen:t.props.defaultMenuIsOpen,value:void 0!==t.props.valu
 e?t.props.value:t.props.defaultValue}),be(ke(ke(t)),"onChange",function(e,n){t.callProp("onChange",e,n),t.setState({value:e})}),be(ke(ke(t)),"onInputChange",function(e,n){var r=t.callProp("onInputChange",e,n);t.setState({inputValue:void 0!==r?r:e})}),be(ke(ke(t)),"onMenuOpen",function(){t.callProp("onMenuOpen"),t.setState({menuIsOpen:!0})}),be(ke(ke(t)),"onMenuClose",function(){t.callProp("onMenuClose"),t.setState({menuIsOpen:!1})}),t}return ye(n,E["Component"]),ge(n,[{key:"focus",value:function(){this.select.focus()}},{key:"blur",value:function(){this.select.blur()}},{key:"getProp",value:function(e){return void 0!==this.props[e]?this.props[e]:this.state[e]}},{key:"callProp",value:function(e){if("function"==typeof this.props[e]){for(var t,n=arguments.length,r=new Array(n>1?n-1:0),o=1;o<n;o++)r[o-1]=arguments[o];return(t=this.props)[e].appl
 y(t,r)}}},{key:"render",value:function(){var t=this,n=this.props,r=(n.defaultInputValue,n.defaultMenuIsOpen,n.defaultValue,Ce(n,["defaultInputValue","defaultMenuIsOpen","defaultValue"]));return y.a.createElement(e,ve({},r,{ref:function(e){t.select=e},inputValue:this.getProp("inputValue"),menuIsOpen:this.getProp("menuIsOpen"),onChange:this.onChange,onInputChange:this.onInputChange,onMenuClose:this.onMenuClose,onMenuOpen:this.onMenuOpen,value:this.getProp("value")}))}}]),n}(),be(t,"defaultProps",Bt),n},Ut={cacheOptions:!1,defaultOptions:!1,filterOption:null},Wt=function(e){var t,n;return n=t=function(t){function n(e){var t;return me(this,n),be(ke(ke(t=Se(this,we(n).call(this)))),"select",void 0),be(ke(ke(t)),"lastRequest",void 0),be(ke(ke(t)),"mounted",!1),be(ke(ke(t)),"optionsCache",{}),be(ke(ke(t)),"handleInputChange",function(e,n){var r=t.props,o=r.cache
 Options,i=function(e,t,n){if(n){var r=n(e,t);if("string"==typeof r)return r}return e}(e,n,r.onInputChange);if(!i)return delete t.lastRequest,void t.setState({inputValue:"",loadedInputValue:"",loadedOptions:[],isLoading:!1,passEmptyOptions:!1});if(o&&t.optionsCache[i])t.setState({inputValue:i,loadedInputValue:i,loadedOptions:t.optionsCache[i],isLoading:!1,passEmptyOptions:!1});else{var a=t.lastRequest={};t.setState({inputValue:i,isLoading:!0,passEmptyOptions:!t.state.loadedInputValue},function(){t.loadOptions(i,function(e){t.mounted&&(e&&(t.optionsCache[i]=e),a===t.lastRequest&&(delete t.lastRequest,t.setState({isLoading:!1,loadedInputValue:i,loadedOptions:e||[],passEmptyOptions:!1})))})})}return i}),t.state={defaultOptions:Array.isArray(e.defaultOptions)?e.defaultOptions:void 0,inputValue:void 0!==e.inputValue?e.inputValue:"",isLoading:!0===e.defaultOptions,loadedOptions:[],passEmptyOptions:!1},t}return ye(n,E[&
 quot;Component"]),ge(n,[{key:"componentDidMount",value:function(){var e=this;this.mounted=!0;var t=this.props.defaultOptions,n=this.state.inputValue;!0===t&&this.loadOptions(n,function(t){if(e.mounted){var n=!!e.lastRequest;e.setState({defaultOptions:t||[],isLoading:n})}})}},{key:"componentWillReceiveProps",value:function(e){e.cacheOptions!==this.props.cacheOptions&&(this.optionsCache={}),e.defaultOptions!==this.props.defaultOptions&&this.setState({defaultOptions:Array.isArray(e.defaultOptions)?e.defaultOptions:void 0})}},{key:"componentWillUnmount",value:function(){this.mounted=!1}},{key:"focus",value:function(){this.select.focus()}},{key:"blur",value:function(){this.select.blur()}},{key:"loadOptions",value:function(e,t){var n=this.props.loadOptions;if(!n)return t();var r=n(e,t);r&&"function"==typeof r.then&&r.then(t,function(){return t()})}},{key:"render",va
 lue:function(){var t=this,n=this.props,r=(n.loadOptions,Ce(n,["loadOptions"])),o=this.state,i=o.defaultOptions,a=o.inputValue,s=o.isLoading,u=o.loadedInputValue,l=o.loadedOptions,c=o.passEmptyOptions?[]:a&&u?l:i||[];return y.a.createElement(e,ve({},r,{ref:function(e){t.select=e},options:c,isLoading:s,onInputChange:this.handleInputChange}))}}]),n}(),be(t,"defaultProps",Ut),n},Ht=(Wt(zt(Mt)),function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1?arguments[1]:void 0,n=String(e).toLowerCase(),r=String(t.value).toLowerCase(),o=String(t.label).toLowerCase();return r===n||o===n}),Gt=Ee({allowCreateWhileLoading:!1,createOptionPosition:"last"},{formatCreateLabel:function(e){return'Create "'.concat(e,'"')},isValidNewOption:function(e,t,n){return!(!e||t.some(function(t){return Ht(e,t)})||n.some(function(t){return Ht(e,t)}))},getNewOptionData:function(e,t){return{label:t,value:e,__is
 New__:!0}}}),$t=function(e){var t,n;return n=t=function(t){function n(e){var t;me(this,n),be(ke(ke(t=Se(this,we(n).call(this,e)))),"select",void 0),be(ke(ke(t)),"onChange",function(e,n){var r=t.props,o=r.getNewOptionData,i=r.inputValue,a=r.isMulti,s=r.onChange,u=r.onCreateOption,l=r.value;if("select-option"!==n.action)return s(e,n);var c=t.state.newOption,p=Array.isArray(e)?e:[e];if(p[p.length-1]!==c)s(e,n);else if(u)u(i);else{var d=o(i,i),f={action:"create-option"};s(a?[].concat(Ae(je(l)),[d]):d,f)}});var r=e.options||[];return t.state={newOption:void 0,options:r},t}return ye(n,E["Component"]),ge(n,[{key:"componentWillReceiveProps",value:function(e){var t=e.allowCreateWhileLoading,n=e.createOptionPosition,r=e.formatCreateLabel,o=e.getNewOptionData,i=e.inputValue,a=e.isLoading,s=e.isValidNewOption,u=e.value,l=e.options||[],c=this.state.newOption;c=s(i,je(u),l)?o(i,r(i)):void 0,this.setState({newOption:c,options:!t&&
 a||!c?l:"first"===n?[c].concat(Ae(l)):[].concat(Ae(l),[c])})}},{key:"focus",value:function(){this.select.focus()}},{key:"blur",value:function(){this.select.blur()}},{key:"render",value:function(){var t=this,n=ve({},this.props),r=this.state.options;return y.a.createElement(e,ve({},n,{ref:function(e){t.select=e},options:r,onChange:this.onChange}))}}]),n}(),be(t,"defaultProps",Gt),n},qt=(zt($t(Mt)),Wt(zt($t(Mt))),function(e){var t=e.component,n=e.duration,r=void 0===n?1:n,o=e.in,i=(e.onExited,Ce(e,["component","duration","in","onExited"])),a={entering:{opacity:0},entered:{opacity:1,transition:"opacity ".concat(r,"ms")},exiting:{opacity:0},exited:{opacity:0}};return y.a.createElement(de.Transition,{mountOnEnter:!0,unmountOnExit:!0,in:o,timeout:r},function(e){var n={style:Ee({},a[e])};return y.a.createElement(t,ve({innerProps:n},i))})}),Yt=260,Xt=function(e){function t(){var e,n;
 me(this,t);for(var r=arguments.length,o=new Array(r),i=0;i<r;i++)o[i]=arguments[i];return be(ke(ke(n=Se(this,(e=we(t)).call.apply(e,[this].concat(o))))),"duration",Yt),be(ke(ke(n)),"rafID",void 0),be(ke(ke(n)),"state",{width:"auto"}),be(ke(ke(n)),"transition",{exiting:{width:0,transition:"width ".concat(n.duration,"ms ease-out")},exited:{width:0}}),be(ke(ke(n)),"getWidth",function(e){e&&isNaN(n.state.width)&&(n.rafID=window.requestAnimationFrame(function(){var t=e.getBoundingClientRect().width;n.setState({width:t})}))}),be(ke(ke(n)),"getStyle",function(e){return{overflow:"hidden",whiteSpace:"nowrap",width:e}}),be(ke(ke(n)),"getTransition",function(e){return n.transition[e]}),n}return ye(t,E["Component"]),ge(t,[{key:"componentWillUnmount",value:function(){this.rafID&&window.cancelAnimationFrame(this.rafID)}},{key:"
 render",value:function(){var e=this,t=this.props,n=t.children,r=t.in,o=this.state.width;return y.a.createElement(de.Transition,{enter:!1,mountOnEnter:!0,unmountOnExit:!0,in:r,timeout:this.duration},function(t){var r=Ee({},e.getStyle(o),e.getTransition(t));return y.a.createElement("div",{ref:e.getWidth,style:r},n)})}}]),t}(),Kt=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=Nt({components:e}),n=t.Input,r=t.MultiValue,o=t.Placeholder,i=t.SingleValue,a=t.ValueContainer,s=Ce(t,["Input","MultiValue","Placeholder","SingleValue","ValueContainer"]);return Ee({Input:function(e){return function(t){t.in,t.onExited,t.appear,t.enter,t.exit;var n=Ce(t,["in","onExited","appear","enter","exit"]);return y.a.createElement(e,n)}}(n),MultiValue:function(e){return function(t){var n=t.in,r=t.onExited,o=Ce(t,["in","onExited"]);retur
 n y.a.createElement(Xt,{in:n,onExited:r},y.a.createElement(e,ve({cropWithEllipsis:n},o)))}}(r),Placeholder:function(e){return function(t){return y.a.createElement(qt,ve({component:e,duration:t.isMulti?Yt:1},t))}}(o),SingleValue:function(e){return function(t){return y.a.createElement(qt,ve({component:e},t))}}(i),ValueContainer:function(e){return function(t){return y.a.createElement(de.TransitionGroup,ve({component:e},t))}}(a)},s)},Zt=Kt(),Jt=(Zt.Input,Zt.MultiValue,Zt.Placeholder,Zt.SingleValue,Zt.ValueContainer,oe(Kt,qe),zt(Mt));n(38);function Qt(e){return[e]}function en(e){return!!e&&"object"==typeof e}function tn(){var e={clear:function(){e.head=null}};return e}function nn(e,t,n){var r;if(e.length!==t.length)return!1;for(r=n;r<e.length;r++)if(e[r]!==t[r])return!1;return!0}Vt={},Rt="undefined"!=typeof WeakMap;n(50);var rn=wp.components.Disabled,on=wp.i18n,an=on.__,sn=on._x,un=on.sprintf,ln=wp.url,cn=ln.addQueryArgs,pn=ln.isURL,dn=[{name:an("Small
 ","wordcamporg"),shortName:sn("S","size small","wordcamporg"),size:90,slug:"small"},{name:an("Regular","wordcamporg"),shortName:sn("M","size medium","wordcamporg"),size:150,slug:"regular"},{name:an("Large","wordcamporg"),shortName:sn("L","size large","wordcamporg"),size:300,slug:"large"},{name:an("Larger","wordcamporg"),shortName:sn("XL","size extra large","wordcamporg"),size:500,slug:"larger"}];function fn(e){var t=e.className,n=e.name,r=e.size,o=e.url,i=e.imageLink,a=function(e,t){return cn(e,{s:t})},s=Object(E.createElement)("img",{className:S()("avatar","avatar-"+r,"photo"),src:a(o,r),srcSet:a(o,2*r)+" 2x",alt:n?un(an("Avatar of %s","wordcamporg"),n):"",width:r,height:r
 });return pn(i)&&(s=Object(E.createElement)(rn,null,Object(E.createElement)("a",{href:i,className:S()("wordcamp-image-link","wordcamp-avatar-link")},s))),s=Object(E.createElement)("div",{className:S()("wordcamp-image-container","wordcamp-avatar-container",t)},s)}n(51);var mn=wp.components.Disabled,hn=wp.element.Component,gn=wp.i18n,bn=gn.__,vn=gn._x,En=wp.url.isURL,yn=[{name:bn("Small","wordcamporg"),shortName:vn("S","size small","wordcamporg"),size:150,slug:"small"},{name:bn("Regular","wordcamporg"),shortName:vn("M","size medium","wordcamporg"),size:300,slug:"regular"},{name:bn("Large","wordcamporg"),shortName:vn("L","size large","wordcamporg"),size:600,slug:"large"},{name:bn("Larger","wordcamporg"),shortName:vn("
 XL","size extra large","wordcamporg"),size:1024,slug:"larger"}],wn=function(e){function t(e){var n;c()(this,t),n=m()(this,g()(t).call(this,e));var r=e.imageData,o=r.media_details,i=void 0===o?{}:o,a=r.alt_text,s=void 0===a?"":a,u=n.constructor.getWidestImage(i);return n.state={image:u,alt:s},n}return v()(t,e),d()(t,[{key:"render",value:function(){var e=this.props,t=e.width,n=e.className,r=e.imageLink,o=this.state,i=o.image,a=o.alt,s=i.source_url,u=void 0===s?"":s;if(!u)return"";var l=this.constructor.getNewHeight(t,i),c=Object(E.createElement)("img",{className:S()("wordcamp-featured-image","wp-post-image"),src:u,alt:a,width:t,height:l});return En(r)&&(c=Object(E.createElement)(mn,null,Object(E.createElement)("a",{href:r,className:S()("wordcamp-image-link","wordcamp-featured-image-link")},c))),c=Object(E.createElement)("div",{classNa
 me:S()("wordcamp-image-container","wordcamp-featured-image-container",n)},c)}}],[{key:"getWidestImage",value:function(e){var t={},n=e.sizes,r=void 0===n?{}:n;if(r.hasOwnProperty("full")&&r.full.hasOwnProperty("source_url"))t=r.full;else if(Object.getOwnPropertyDescriptors(r).length>0){t=Object(w.sortBy)(r,"width").pop()}return t}},{key:"getNewHeight",value:function(e,t){var n=null,r=t.width,o=t.height;if(r&&o){var i=Number(o)/Number(r);n=Number.parseFloat(i*e).toFixed(1)}return n}}]),t}(hn),On=(n(52),wp.components),Cn=On.BaseControl,kn=On.Button,Sn=On.ButtonGroup,An=On.PanelBody,xn=On.PanelRow,_n=On.RangeControl,jn=On.ToggleControl,Fn=On.Toolbar,Dn=wp.element,Nn=Dn.Component,Pn=Dn.Fragment,Ln=wp.i18n.__,Tn=function(e){function t(e){var n;return c()(this,t),(n=m()(this,g()(t).call(this,e))).state={value:e.value,onChange:Object(w.debounce)(e.onChange,10)},n.onChange=n.onChange.bind(ne()(ne()(n))),
 n}return v()(t,e),d()(t,[{key:"onChange",value:function(e){this.setState({value:e}),this.state.onChange(e)}},{key:"render",value:function(){var e=this,t=this.props,n=t.className,r=t.label,o=t.help,i=t.sizePresets,a=void 0===i?[]:i,s=t.initialPosition,l=t.rangeProps,c=this.state.value;return Object(E.createElement)(Cn,{className:S()("wordcamp-image-size",n),label:r,help:o},Object(E.createElement)("div",{className:"wordcamp-image-size-preset-buttons"},a.length>0&&Object(E.createElement)(Sn,{"aria-label":r},a.map(function(t){var n=t.name,r=t.shortName,o=t.size,i=t.slug,a=c===o;return Object(E.createElement)(kn,{key:i,isLarge:!0,isPrimary:a,"aria-label":n,"aria-pressed":a,onClick:function(){return e.onChange(Number(o))}},r||n)})),Object(E.createElement)(kn,{className:"wordcamp-image-size-button-reset",isLarge:!0,isDefault:!0,onClick:function(){return e.onChange(Number(s))}},Ln("Rese
 t","wordcamporg"))),Object(E.createElement)(_n,u()({className:"wordcamp-image-size-range",value:c,initialPosition:s,onChange:this.onChange,beforeIcon:"format-image",afterIcon:"format-image","aria-label":r},l)))}}]),t}(Nn);function In(e){var t=e.className,n=e.label,r=e.help,o=e.value,i=e.onChange,a=e.alignOptions;return Object(E.createElement)(Cn,{className:S()("wordcamp-image-alignment",t),label:n,help:r},Object(E.createElement)(Fn,{controls:a.map(function(e){var t=o===e.value,n="align-".concat(e.value);return{title:e.label,icon:n,isActive:t,onClick:function(){i(e.value)}}})}))}var Mn=function(e){function t(){return c()(this,t),m()(this,g()(t).apply(this,arguments))}return v()(t,e),d()(t,[{key:"render",value:function(){var e=this.props,t=e.title,n=void 0===t?Ln("Image Settings","wordcamporg"):t,r=e.initialOpen,o=void 0===r||r,i=e.className,a=e.show,s=e.onChangeShow,u=e.size,l=e.o
 nChangeSize,c=e.sizeSchema,p=e.sizePresets,d=void 0===p?[]:p,f=e.align,m=e.onChangeAlign,h=e.alignOptions,g=void 0===h?[]:h;return Object(E.createElement)(An,{title:n,initialOpen:o,className:S()("wordcamp-image-inspector-panel",i)},Object(E.createElement)(jn,{label:Ln("Show images","wordcamporg"),checked:a,onChange:s}),a&&Object(E.createElement)(Pn,null,Object(E.createElement)(Tn,{label:Ln("Size","wordcamporg"),value:Number(u),initialPosition:Number(c.default),sizePresets:d,onChange:l,rangeProps:{min:Number(c.minimum),max:Number(c.maximum)}}),Object(E.createElement)(xn,null,Object(E.createElement)(In,{label:Ln("Alignment","wordcamporg"),value:f,onChange:m,alignOptions:g}))))}}]),t}(Nn),Vn=wp.components.Dashicon,Rn=wp.i18n.__,Bn=function(e,t){var n,r;function o(){n=Rt?new WeakMap:tn()}function i(){var n,o,i,a,s,u=arguments.length;for(a=new Array(u),i=0;i<u;i++)a[i]=arguments[i];for(s=t.apply(null,a),(n=r
 (s)).isUniqueByDependants||(n.lastDependants&&!nn(s,n.lastDependants,0)&&n.clear(),n.lastDependants=s),o=n.head;o;){if(nn(o.args,a,1))return o!==n.head&&(o.prev.next=o.next,o.next&&(o.next.prev=o.prev),o.next=n.head,o.prev=null,n.head.prev=o,n.head=o),o.val;o=o.next}return o={val:e.apply(null,a)},a[0]=null,o.args=a,n.head&&(n.head.prev=o,o.next=n.head),n.head=o,o.val}return t||(t=Qt),r=Rt?function(e){var t,r,o,i,a=n,s=!0;for(t=0;t<e.length;t++){if(!en(r=e[t])){s=!1;break}a.has(r)?a=a.get(r):(o=new WeakMap,a.set(r,o),a=o)}return a.has(Vt)||((i=tn()).isUniqueByDependants=s,a.set(Vt,i)),a.get(Vt)}:function(){return n},i.getDependants=t,i.clear=o,o(),i}(function(e){var t=[];return e.forEach(function(e){var n,r=e.entityType,o=e.type,i=e.label,a=e.items;switch(r){case"post":n="title.rendered";break;case"term":n="name"}if(Array.isArray(a)&&a.length){var s=Z(a,{sort:n+"_asc"});t.push(functio
 n(e,t,n,r){return{label:n,options:r=r.map(function(n){var r;switch(e){case"post":(r={label:n.title.rendered.trim()||Rn("(Untitled)","wordcamporg"),value:n.id,type:t}).avatar=Object(w.get)(n,"avatar_urls['24']",""),r.image=Object(w.get)(n,"_embedded['wp:featuredmedia'].media_details.sizes.thumbnail.source_url","");break;case"term":r={label:n.name||Rn("(Untitled)","wordcamporg"),value:n.id,type:t,count:n.count}}return r})}}(r,o,i,s))}}),t},function(e){var t=[];return e.forEach(function(e){var n=e.items;t.push(n)}),t});function zn(e,t){var n="",r=t.find(function(t){return e===t.value});return r.hasOwnProperty("label")&&(n=r.label),n}function Un(e){var t,n=e.avatar,r=e.icon,o=e.label,i=e.count;n?t=Object(E.createElement)(fn,{className:"wordcamp-item-select-option-avatar",name:o,size:24,url:n}):r&&(t=Object(E.createElement)("div",{cla
 ssName:"wordcamp-item-select-option-icon-container"},Object(E.createElement)(Vn,{className:"wordcamp-item-select-option-icon",icon:r,size:16})));var a=Object(E.createElement)("span",{className:"wordcamp-item-select-option-label"},o,void 0!==i&&Object(E.createElement)("span",{className:"wordcamp-item-select-option-label-count"},i));return Object(E.createElement)("div",{className:"wordcamp-item-select-option"},t,a)}var Wn=wp.components,Hn=Wn.BaseControl,Gn=Wn.Button,$n=wp.element.Component,qn=wp.i18n.__,Yn=function(e){function t(e){var n;return c()(this,t),(n=m()(this,g()(t).call(this,e))).state={selectedOptions:null},n.getNewAttributes=n.getNewAttributes.bind(ne()(ne()(n))),n}return v()(t,e),d()(t,[{key:"getNewAttributes",value:function(){var e=this.state.selectedOptions,t={};if(null===e)return t;var n=e.map(function(e){return e.value})||[];n.length?t={mode:e[0].type,item_ids:n}:t={mode:
 "",item_ids:[]};return t}},{key:"render",value:function(){var e=this,t=this.props,n=t.instanceId,r=t.className,o=t.label,i=t.help,a=t.submitLabel,s=t.onChange,l=t.selectProps,c=this.state.selectedOptions||this.props.value,p="wordcamp-item-select-control-".concat(n),d=B()({isMulti:!0,isOptionDisabled:this.constructor.isOptionDisabled,formatGroupLabel:this.constructor.formatGroupLabel},l);return Object(E.createElement)(Hn,{id:p,className:S()("wordcamp-item-select",r),label:o,help:i},Object(E.createElement)("div",{className:"wordcamp-item-select-inner"},Object(E.createElement)(Jt,u()({id:p,className:"wordcamp-item-select-select",value:c,"aria-label":o,onChange:function(t){e.setState({selectedOptions:t})}},d)),Object(E.createElement)(Gn,{className:"wordcamp-item-select-button",isLarge:!0,isDefault:!0,onClick:function(){return s(e.getNewAttributes())}},a||qn("Select","wordcamporg&quot
 ;))))}}],[{key:"isOptionDisabled",value:function(e,t){var n;return Array.isArray(t)&&t.length&&(n=t[0].type),n&&n!==e.type}},{key:"formatGroupLabel",value:function(e){return Object(E.createElement)("span",{className:"wordcamp-item-select-option-group-label"},e.label)}}]),t}($n),Xn=(n(53),wp.components),Kn=Xn.Disabled,Zn=Xn.Spinner,Jn=wp.element,Qn=Jn.Fragment,er=Jn.RawHTML,tr=wp.i18n.__;function nr(e){var t=e.loading;return Object(E.createElement)("div",{className:"wordcamp-block-content-none"},t?Object(E.createElement)(Zn,null):tr("No content found.","wordcamporg"))}function rr(e){var t=e.headingLevel,n=e.className,r=e.title,o=e.link,i="h3";[1,2,3,4,5,6].includes(t)&&(i="h"+t);var a=["wordcamp-item-title",n],s=r||tr("(Untitled)","wordcamporg");return Object(E.createElement)(i,{className:S()(a)},o&&Object(E.createEl
 ement)(Kn,null,Object(E.createElement)("a",{href:o},s)),!o&&Object(E.createElement)(Qn,null,s))}function or(e){var t=e.className,n=e.content,r=e.link,o=e.linkText,i=["wordcamp-item-content",t];return Object(E.createElement)("div",{className:S()(i)},Object(E.createElement)(Kn,null,Object(E.createElement)(er,{children:n}),r&&Object(E.createElement)(ir,{link:r,linkText:o})))}function ir(e){var t=e.className,n=e.link,r=e.linkText,o=["wordcamp-item-permalink",t];return Object(E.createElement)("p",{className:S()(o)},Object(E.createElement)("a",{href:n},r||tr("Read more","wordcamporg")))}var ar=function(e){function t(e){var n;return c()(this,t),(n=m()(this,g()(t).call(this,e))).getFilteredPosts=n.getFilteredPosts.bind(ne()(ne()(n))),n}return v()(t,e),d()(t,[{key:"getFilteredPosts",value:function(){var e=this.props,t=e.attributes,n=e.entities.wcb_organizer,r=t.mode,o=t.item_ids,i=t.sort
 ,a={};return Array.isArray(o)&&o.length>0&&(a.filter=[{fieldName:"wcb_organizer"===r?"id":"organizer_team",fieldValue:o}]),a.sort=i,Z(n,a)}},{key:"render",value:function(){var e=this.props.attributes,t=e.show_avatars,n=e.avatar_size,r=e.avatar_align,o=e.content,i=this.getFilteredPosts(),a=!Array.isArray(i),s=!a&&i.length>0;return a||!s?Object(E.createElement)(nr,{loading:a}):Object(E.createElement)(V,u()({},this.props,{className:"wordcamp-organizers-block"}),i.map(function(e){return Object(E.createElement)("div",{key:e.slug,className:S()("wordcamp-organizer","wordcamp-organizer-"+e.slug.trim())},Object(E.createElement)(rr,{className:"wordcamp-organizer-title",headingLevel:3,title:e.title.rendered.trim()}),t&&Object(E.createElement)(fn,{className:S()("align-"+r),name:e.title.rendered.trim()||"",size:n,url:e.avatar_urls[24]}),"none&qu
 ot;!==o&&Object(E.createElement)(or,{className:S()("wordcamp-organizer-content-"+o),content:"full"===o?e.content.rendered.trim():e.excerpt.rendered.trim()}))}))}}]),t}(wp.element.Component),sr=wp.element.Component,ur=wp.i18n.__,lr=function(e){function t(e){var n;return c()(this,t),(n=m()(this,g()(t).call(this,e))).buildSelectOptions=n.buildSelectOptions.bind(ne()(ne()(n))),n.getCurrentSelectValue=n.getCurrentSelectValue.bind(ne()(ne()(n))),n.isLoading=n.isLoading.bind(ne()(ne()(n))),n}return v()(t,e),d()(t,[{key:"buildSelectOptions",value:function(){var e=this.props.entities,t=e.wcb_organizer,n=e.wcb_organizer_team,r=[{entityType:"post",type:"wcb_organizer",label:ur("Organizers","wordcamporg"),items:t},{entityType:"term",type:"wcb_organizer_team",label:ur("Teams","wordcamporg"),items:n}];return Bn(r)}},{key:"getCurrentSelectValue",value:function(){var e=thi
 s.props.attributes,t=e.mode,n=e.item_ids,r=Object(w.flatMap)(this.buildSelectOptions(),function(e){return e.options}),o=[];return t&&n.length&&(o=r.filter(function(e){return t===e.type&&Object(w.includes)(n,e.value)})),o}},{key:"isLoading",value:function(){var e=this.props.entities;return!Object(w.every)(e,function(e){return Array.isArray(e)})}},{key:"render",value:function(){var e=this.props,t=e.label,n=e.setAttributes;return Object(E.createElement)(Yn,{className:"wordcamp-organizers-select",label:t,value:this.getCurrentSelectValue(),onChange:function(e){return n(e)},selectProps:{options:this.buildSelectOptions(),isLoading:this.isLoading(),formatOptionLabel:function(e){return Object(E.createElement)(Un,e)}}})}}]),t}(sr),cr=wp.components,pr=cr.Button,dr=cr.Placeholder,fr=wp.element.Component,mr=wp.i18n.__,hr=function(e){function t(){return c()(this,t),m()(this,g()(t).apply(this,arguments))}return v()(t,e),d()(t,[{key:"render
 ",value:function(){var e,t=this.props,n=t.icon,r=t.attributes,o=t.setAttributes,i=t.blockData,a=r.mode,s=i.options;switch(a){case"all":e=Object(E.createElement)(ar,this.props);break;case"wcb_organizer":case"wcb_organizer_team":e=Object(E.createElement)(ee,{label:zn(a,s.mode),icon:n,content:Object(E.createElement)(ar,this.props),placeholderChildren:Object(E.createElement)(lr,this.props)});break;default:e=Object(E.createElement)(dr,{className:S()("wordcamp-block-edit-placeholder","wordcamp-block-edit-placeholder-no-mode"),icon:n,label:Tr},Object(E.createElement)("div",{className:"wordcamp-block-edit-mode-option"},Object(E.createElement)(pr,{isDefault:!0,isLarge:!0,onClick:function(){o({mode:"all"})}},zn("all",s.mode))),Object(E.createElement)("div",{className:"wordcamp-block-edit-mode-option"},Object(E.createElement)(lr,u()({label:mr("Choose specific organizers or te
 ams","wordcamporg")},this.props))))}return e}}]),t}(fr),gr=wp.blockEditor.InspectorControls,br=wp.components,vr=br.PanelBody,Er=br.PanelRow,yr=br.SelectControl,wr=(br.ToggleControl,wp.element.Component),Or=wp.i18n.__,Cr={grid_columns:{default:2,minimum:2,maximum:4},avatar_size:{default:150,minimum:25,maximum:600}},kr={align:{},content:{},sort:{}},Sr=function(e){function t(){return c()(this,t),m()(this,g()(t).apply(this,arguments))}return v()(t,e),d()(t,[{key:"render",value:function(){var e=this.props,t=e.attributes,n=e.setAttributes,r=e.blockData,o=t.show_avatars,i=t.avatar_size,a=t.avatar_align,s=t.content,u=t.sort,l=r.schema,c=void 0===l?Cr:l,p=r.options,d=void 0===p?kr:p;return Object(E.createElement)(gr,null,Object(E.createElement)(L,this.props),Object(E.createElement)(Mn,{title:Or("Avatar Settings","wordcamporg"),show:o,onChangeShow:function(e){return n({show_avatars:e})},size:i,onChangeSize:function(e){return n({avatar_size:e})},siz
 eSchema:c.avatar_size,sizePresets:dn,align:a,onChangeAlign:function(e){return n({avatar_align:e})},alignOptions:d.align_image}),Object(E.createElement)(vr,{title:Or("Content Settings","wordcamporg"),initialOpen:!1},Object(E.createElement)(Er,null,Object(E.createElement)(yr,{label:Or("Biography Length","wordcamporg"),value:s,options:d.content,onChange:function(e){return n({content:e})}}))),Object(E.createElement)(vr,{title:Or("Sorting & Filtering","wordcamporg"),initialOpen:!1},Object(E.createElement)(Er,null,Object(E.createElement)(yr,{label:Or("Sort by","wordcamporg"),value:u,options:d.sort,onChange:function(e){return n({sort:e})}}))))}}]),t}(wr),Ar=wp.data.withSelect,xr=wp.element,_r=xr.Component,jr=xr.Fragment,Fr=window.WordCampBlocks.organizers||{},Dr=function(e){function t(){return c()(this,t),m()(this,g()(t).apply(this,arguments))}return v()(t,e),d()(t,[{key:"render",value:function(){
 var e=this.props,t=e.attributes,n=e.setAttributes,r=t.mode,o=t.layout,i=Fr.options.layout,a=void 0===i?{}:i;return Object(E.createElement)(jr,null,Object(E.createElement)(hr,u()({icon:Ir},this.props)),""!==r&&Object(E.createElement)(jr,null,Object(E.createElement)(Sr,this.props),Object(E.createElement)(M,{layout:o,options:a,setAttributes:n})))}}]),t}(_r),Nr=Ar(function(e){var t=e("wordcamp").getEntities,n={wcb_organizer:t("postType","wcb_organizer",{_embed:!0}),wcb_organizer_team:t("taxonomy","wcb_organizer_team")};return{blockData:Fr,entities:n}})(Dr),Pr=wp.i18n.__,Lr="wordcamp/organizers",Tr=Pr("Organizers","wordcamporg"),Ir="groups",Mr={title:Pr("Organizers","wordcamporg"),description:Pr("Add a list of organizers.","wordcamporg"),icon:Ir,category:"wordcamp",supports:{align:["wide","full"]},edit:Nr,save:fu
 nction(){return null}},Vr=n(28),Rr=n.n(Vr),Br=wp.i18n.__;function zr(e){return e.split(/(%[1-9]?\$?s)/)}function Ur(e,t){var n,r=0;return e.flatMap(function(e){var o=e.match(/^%([1-9])?\$?s$/);return Array.isArray(o)&&(o.length>1&&void 0!==o[1]?(n=Number(o[1])-1,void 0!==t[n]&&(e=t[n])):(e=t[r],r++)),e})}function Wr(e,t){return e.length?e.slice(1).reduce(function(e,n,r){var o="function"==typeof t?o(r):t;return e.concat([o,n])},[e[0]]):[]}var Hr=wp.element.Component,Gr=wp.i18n.__;function $r(e){var t=e.session,n=Object(w.get)(t,"_embedded.speakers",[]);n=n.map(function(e){if(e.hasOwnProperty("code"))return null;var t=e.link,n=e.title,r=void 0===n?{}:n;return r=r.rendered.trim()||Gr("Unnamed","wordcamporg"),t?Object(E.createElement)("a",{key:t,href:t},r):r});var r=Ur(zr(Gr("Presented by %s","wordcamporg")),[function(e){var t=[],n=Br(", ","wordcamporg"),r=Br(&q
 uot; and ","wordcamporg");if(!Array.isArray(e))return t;switch(e.length){case 0:break;case 1:t=e;break;case 2:t=Wr(e,r);break;default:var o=H()(e).reverse(),i=Rr()(o),a=i[0];t=Wr(i.slice(1),n).concat([n,r,a])}return t}(n)]);return Object(E.createElement)("div",{className:"wordcamp-item-meta wordcamp-session-speakers"},r)}function qr(e){var t,n=e.session,r=Object(w.get)(n,"_embedded['wp:term']",[]).flat();if(n.session_track.length){var o=r.filter(function(e){return"wcb_track"===e.taxonomy}),i=U()(o,1)[0];t=Ur(zr(Gr("%1$s at %2$s in %3$s","wordcamporg")),[n.session_date_time.date,n.session_date_time.time,Object(E.createElement)("span",{key:i.id,className:S()("wordcamp-session-track","wordcamp-session-track-"+i.slug.trim())},i.name.trim())])}else t=Ur(zr(Gr("%1$s at %2$s","wordcamporg")),[n.session_date_time.date,n.session_date_time.time]);return Object(E.createE
 lement)("div",{className:"wordcamp-session-time-location"},t)}function Yr(e){var t,n=e.session,r=Object(w.get)(n,"_embedded['wp:term']",[]).flat();if(n.session_category.length){var o=Gr(", ","wordcamporg");t=Wr(r.filter(function(e){return"wcb_session_category"===e.taxonomy}).map(function(e){return Object(E.createElement)("span",{key:e.slug,className:S()("wordcamp-session-category","wordcamp-session-category-"+e.slug)},e.name.trim())}),o)}return Object(E.createElement)("div",{className:"wordcamp-session-categories"},t)}var Xr=function(e){function t(e){var n;return c()(this,t),(n=m()(this,g()(t).call(this,e))).getFilteredPosts=n.getFilteredPosts.bind(ne()(ne()(n))),n}return v()(t,e),d()(t,[{key:"getFilteredPosts",value:function(){var e=this.props,t=e.attributes,n=e.entities.wcb_session,r=t.mode,o=t.item_ids,i=t.sort,a={};if(Array.isArray(o)&&o.length>0){va
 r s;switch(r){case"wcb_session":s="id";break;case"wcb_track":s="session_track";break;case"wcb_session_category":s="session_category"}a.filter=[{fieldName:s,fieldValue:o}]}"session_time"!==i&&(a.sort=i);var u=Z(n,a);return Array.isArray(u)&&"session_time"===i&&(u=u.sort(function(e,t){return Number(e.meta._wcpt_session_time)-Number(t.meta._wcpt_session_time)})),u}},{key:"render",value:function(){var e=this,t=this.props.attributes,n=t.show_speaker,r=t.show_images,o=t.image_align,i=t.featured_image_width,a=t.content,s=t.show_meta,l=t.show_category,c=this.getFilteredPosts(),p=!Array.isArray(c),d=!p&&c.length>0;return p||!d?Object(E.createElement)(nr,{loading:p}):Object(E.createElement)(V,u()({},this.props,{className:"wordcamp-sessions-block"}),c.map(function(t){return Object(E.createElement)("div",{key:t.slug,className:S()("wordcamp-session
 ","wordcamp-session-"+t.slug)},Object(E.createElement)(rr,{className:"wordcamp-session-title",headingLevel:3,title:t.title.rendered.trim(),link:t.link}),n&&e.constructor.hasSpeaker(t)&&Object(E.createElement)($r,{session:t}),r&&Object(E.createElement)(wn,{imageData:Object(w.get)(t,"_embedded.wp:featuredmedia[0]",{}),width:Number(i),className:S()("wordcamp-session-featured-image","align-"+o),imageLink:t.link}),"none"!==a&&Object(E.createElement)(or,{className:S()("wordcamp-session-content-"+a),content:"full"===a?t.content.rendered.trim():t.excerpt.rendered.trim()}),(s||l)&&Object(E.createElement)("div",{className:"wordcamp-item-meta wordcamp-session-details"},s&&Object(E.createElement)(qr,{session:t}),l&&Object(E.createElement)(Yr,{session:t})),"full"===a&&Object(E.createElement)(ir,{link:t.link,linkText:Gr(
 "Visit session page","wordcamporg"),className:"wordcamp-session-permalink"}))}))}}],[{key:"hasSpeaker",value:function(e){return Object(w.get)(e,"_embedded.speakers",[]).length>0}}]),t}(Hr),Kr=wp.element.Component,Zr=wp.i18n.__,Jr=function(e){function t(e){var n;return c()(this,t),(n=m()(this,g()(t).call(this,e))).buildSelectOptions=n.buildSelectOptions.bind(ne()(ne()(n))),n.getCurrentSelectValue=n.getCurrentSelectValue.bind(ne()(ne()(n))),n.isLoading=n.isLoading.bind(ne()(ne()(n))),n}return v()(t,e),d()(t,[{key:"buildSelectOptions",value:function(){var e=this.props.entities,t=e.wcb_session,n=e.wcb_track,r=e.wcb_session_category,o=[{entityType:"post",type:"wcb_session",label:Zr("Sessions","wordcamporg"),items:t},{entityType:"term",type:"wcb_track",label:Zr("Tracks","wordcamporg"),items:n},{entityType:"term",type:"wcb_session_cat
 egory",label:Zr("Session Categories","wordcamporg"),items:r}];return Bn(o)}},{key:"getCurrentSelectValue",value:function(){var e=this.props.attributes,t=e.mode,n=e.item_ids,r=Object(w.flatMap)(this.buildSelectOptions(),function(e){return e.options}),o=[];return t&&n.length&&(o=r.filter(function(e){return t===e.type&&Object(w.includes)(n,e.value)})),o}},{key:"isLoading",value:function(){var e=this.props.entities;return!Object(w.every)(e,function(e){return Array.isArray(e)})}},{key:"render",value:function(){var e=this.props,t=e.icon,n=e.label,r=e.setAttributes;return Object(E.createElement)(Yn,{className:"wordcamp-sessions-select",label:n,value:this.getCurrentSelectValue(),onChange:function(e){return r(e)},selectProps:{options:this.buildSelectOptions(),isLoading:this.isLoading(),formatOptionLabel:function(e){return Object(E.createElement)(Un,u()({icon:Object(w.includes)(["wcb_track",&quo
 t;wcb_session_category"],e.type)?t:null},e))}}})}}]),t}(Kr),Qr=wp.components,eo=Qr.Button,to=Qr.Placeholder,no=wp.element.Component,ro=wp.i18n.__,oo=function(e){function t(){return c()(this,t),m()(this,g()(t).apply(this,arguments))}return v()(t,e),d()(t,[{key:"render",value:function(){var e,t=this.props,n=t.icon,r=t.attributes,o=t.setAttributes,i=t.blockData,a=r.mode,s=i.options;switch(a){case"all":e=Object(E.createElement)(Xr,this.props);break;case"wcb_session":case"wcb_track":case"wcb_session_category":e=Object(E.createElement)(ee,{label:zn(a,s.mode),icon:n,content:Object(E.createElement)(Xr,this.props),placeholderChildren:Object(E.createElement)(Jr,this.props)});break;default:e=Object(E.createElement)(to,{className:S()("wordcamp-block-edit-placeholder","wordcamp-block-edit-placeholder-no-mode"),icon:n,label:ko},Object(E.createElement)("div",{className:"wordcamp-block-edit-mode-option"},
 Object(E.createElement)(eo,{isDefault:!0,isLarge:!0,onClick:function(){o({mode:"all"})}},zn("all",s.mode))),Object(E.createElement)("div",{className:"wordcamp-block-edit-mode-option"},Object(E.createElement)(Jr,u()({icon:n,label:ro("Choose specific sessions, tracks, or categories","wordcamporg")},this.props))))}return e}}]),t}(no),io=wp.blockEditor.InspectorControls,ao=wp.components,so=ao.PanelBody,uo=ao.PanelRow,lo=ao.SelectControl,co=ao.ToggleControl,po=wp.element.Component,fo=wp.i18n.__,mo=function(e){function t(){return c()(this,t),m()(this,g()(t).apply(this,arguments))}return v()(t,e),d()(t,[{key:"render",value:function(){var e=this.props,t=e.attributes,n=e.setAttributes,r=e.blockData,o=t.show_images,i=t.featured_image_width,a=t.image_align,s=t.show_speaker,u=t.content,l=t.show_meta,c=t.show_category,p=t.sort,d=r.schema,f=r.options;return Object(E.createElement)(io,null,Object(E.createElement)(L,this.props),O
 bject(E.createElement)(Mn,{title:fo("Featured Image Settings","wordcamporg"),show:o,onChangeShow:function(e){return n({show_images:e})},size:i,onChangeSize:function(e){return n({featured_image_width:e})},sizeSchema:d.featured_image_width,sizePresets:yn,align:a,onChangeAlign:function(e){return n({image_align:e})},alignOptions:f.align_image}),Object(E.createElement)(so,{title:fo("Content Settings","wordcamporg"),initialOpen:!0},Object(E.createElement)(uo,null,Object(E.createElement)(lo,{label:fo("Description","wordcamporg"),value:u||"full",options:f.content,onChange:function(e){return n({content:e})}})),Object(E.createElement)(uo,null,Object(E.createElement)(co,{label:fo("Details","wordcamporg"),help:fo("Show date, time, and track.","wordcamporg"),checked:void 0!==l&&l,onChange:function(e){return n({show_meta:e})}})),Object(E.createElement)(uo,null,Object(E.createEleme
 nt)(co,{label:fo("Categories","wordcamporg"),help:fo("Show session categories.","wordcamporg"),checked:void 0!==c&&c,onChange:function(e){return n({show_category:e})}})),Object(E.createElement)(uo,null,Object(E.createElement)(co,{label:fo("Speakers","wordcamporg"),help:fo("Show session speakers.","wordcamporg"),checked:void 0!==s&&s,onChange:function(e){return n({show_speaker:e})}}))),Object(E.createElement)(so,{title:fo("Sorting","wordcamporg")},Object(E.createElement)(uo,null,Object(E.createElement)(lo,{label:fo("Sort by","wordcamporg"),value:p,options:f.sort||"session_time",onChange:function(e){return n({sort:e})}}))))}}]),t}(po),ho=wp.data.withSelect,go=wp.element,bo=go.Component,vo=go.Fragment,Eo=window.WordCampBlocks.sessions||{},yo=function(e){function t(){return c()(this,t),m()(this,g()(t).apply(this,arguments))}return v()(t,e),d()
 (t,[{key:"render",value:function(){var e=this.props,t=e.attributes,n=e.setAttributes,r=t.mode,o=t.layout,i=Eo.options.layout,a=void 0===i?{}:i;return Object(E.createElement)(vo,null,Object(E.createElement)(oo,u()({icon:So},this.props)),r&&Object(E.createElement)(vo,null,Object(E.createElement)(mo,this.props),Object(E.createElement)(M,{layout:o,options:a,setAttributes:n})))}}]),t}(bo),wo=ho(function(e){var t=e("wordcamp").getEntities,n={wcb_session:t("postType","wcb_session",{_embed:!0,wc_meta_key:"_wcpt_session_type",wc_meta_value:"session"}),wcb_track:t("taxonomy","wcb_track"),wcb_session_category:t("taxonomy","wcb_session_category")};return{blockData:Eo,entities:n}})(yo),Oo=wp.i18n.__,Co="wordcamp/sessions",ko=Oo("Sessions","wordcamporg"),So="list-view",Ao={title:Oo("Sessions","wordcamporg"),description:Oo("Add
  a list of sessions.","wordcamporg"),icon:So,category:"wordcamp",supports:{align:["wide","full"]},edit:wo,save:function(){return null}},xo=(n(54),wp.components.Disabled),_o=wp.element,jo=_o.Component,Fo=_o.Fragment,Do=wp.i18n,No=Do.__,Po=Do._n,Lo=wp.escapeHtml.escapeAttribute;function To(e){var t=e.speaker,n=e.tracks,r=Object(w.get)(t,"_embedded.sessions",[]),o=Object(E.createElement)(Fo,null,null);return r.length&&(o=Object(E.createElement)("div",{className:S()("wordcamp-item-meta","wordcamp-speaker-sessions")},Object(E.createElement)("h4",{className:"wordcamp-speaker-sessions-heading"},Po("Session","Sessions",r.length,"wordcamporg")),Object(E.createElement)("ul",{className:"wordcamp-speaker-sessions-list"},r.map(function(e){return Object(E.createElement)("li",{key:Lo(e.slug),className:"wordcamp-speaker-ses
 sions-list-item"},Object(E.createElement)(xo,null,Object(E.createElement)("a",{className:"wordcamp-speaker-session-link",href:e.link},e.title.rendered.trim()||No("(Untitled)","wordcamporg")),Object(E.createElement)("span",{className:"wordcamp-speaker-session-info"},e.session_track.length&&Array.isArray(n)&&Ur(zr(No("%1$s at %2$s in %3$s","wordcamporg")),[e.session_date_time.date,e.session_date_time.time,Object(w.get)(n.find(function(t){var n=U()(e.session_track,1)[0];return parseInt(t.id)===n}),"name")]),(!e.session_track.length||!Array.isArray(n))&&Ur(zr(No("%1$s at %2$s","wordcamporg")),[e.session_date_time.date,e.session_date_time.time]))))})))),o}var Io=function(e){function t(e){var n;return c()(this,t),(n=m()(this,g()(t).call(this,e))).getFilteredPosts=n.getFilteredPosts.bind(ne()(ne()(n))),n}return v()(t,e),d()(t,[{key:"getFilteredPost
 s",value:function(){var e=this.props,t=e.attributes,n=e.entities.wcb_speaker,r=t.mode,o=t.item_ids,i=t.sort,a={};return Array.isArray(o)&&o.length>0&&(a.filter=[{fieldName:"wcb_speaker"===r?"id":"speaker_group",fieldValue:o}]),a.sort=i,Z(n,a)}},{key:"render",value:function(){var e=this.props,t=e.attributes,n=e.entities.wcb_track,r=t.show_avatars,o=t.avatar_size,i=t.avatar_align,a=t.content,s=t.show_session,l=this.getFilteredPosts(),c=!Array.isArray(l),p=!c&&l.length>0;return c||!p?Object(E.createElement)(nr,{loading:c}):Object(E.createElement)(V,u()({},this.props,{className:"wordcamp-speakers-block"}),l.map(function(e){return Object(E.createElement)("div",{key:e.slug,className:S()("wordcamp-speaker","wordcamp-speaker-"+e.slug)},Object(E.createElement)(rr,{className:"wordcamp-speaker-title",headingLevel:3,title:e.title.rendered.trim(),link:e.link}),r&&O
 bject(E.createElement)(fn,{className:S()("align-"+i),name:e.title.rendered.trim()||"",size:o,url:e.avatar_urls[24],imageLink:e.link}),"none"!==a&&Object(E.createElement)(or,{className:S()("wordcamp-speaker-content-"+a),content:"full"===a?e.content.rendered.trim():e.excerpt.rendered.trim()}),!0===s&&Object(E.createElement)(To,{speaker:e,tracks:n}),"full"===a&&Object(E.createElement)(ir,{link:e.link,linkText:No("Visit speaker page","wordcamporg")}))}))}}]),t}(jo),Mo=wp.element.Component,Vo=wp.i18n.__,Ro=function(e){function t(e){var n;return c()(this,t),(n=m()(this,g()(t).call(this,e))).buildSelectOptions=n.buildSelectOptions.bind(ne()(ne()(n))),n.getCurrentSelectValue=n.getCurrentSelectValue.bind(ne()(ne()(n))),n.isLoading=n.isLoading.bind(ne()(ne()(n))),n}return v()(t,e),d()(t,[{key:"buildSelectOptions",value:function(){var e=this.props.entities,t=e.wcb_speaker,n=e.wcb_s
 peaker_group,r=[{entityType:"post",type:"wcb_speaker",label:Vo("Speakers","wordcamporg"),items:t},{entityType:"term",type:"wcb_speaker_group",label:Vo("Groups","wordcamporg"),items:n}];return Bn(r)}},{key:"getCurrentSelectValue",value:function(){var e=this.props.attributes,t=e.mode,n=e.item_ids,r=Object(w.flatMap)(this.buildSelectOptions(),function(e){return e.options}),o=[];return t&&n.length&&(o=r.filter(function(e){return t===e.type&&Object(w.includes)(n,e.value)})),o}},{key:"isLoading",value:function(){var e=this.props.entities;return!Object(w.every)(e,function(e){return Array.isArray(e)})}},{key:"render",value:function(){var e=this.props,t=e.label,n=e.icon,r=e.setAttributes;return Object(E.createElement)(Yn,{className:"wordcamp-speakers-select",label:t,value:this.getCurrentSelectValue(),onChange:function(e){return r(e)},selectProps:{opt
 ions:this.buildSelectOptions(),isLoading:this.isLoading(),formatOptionLabel:function(e){return Object(E.createElement)(Un,u()({icon:"wcb_speaker_group"===e.type?n:null},e))}}})}}]),t}(Mo),Bo=wp.components,zo=Bo.Button,Uo=Bo.Placeholder,Wo=wp.element.Component,Ho=wp.i18n.__,Go=function(e){function t(){return c()(this,t),m()(this,g()(t).apply(this,arguments))}return v()(t,e),d()(t,[{key:"render",value:function(){var e,t=this.props,n=t.icon,r=t.attributes,o=t.setAttributes,i=t.blockData,a=r.mode,s=i.options;switch(a){case"all":e=Object(E.createElement)(Io,this.props);break;case"wcb_speaker":case"wcb_speaker_group":e=Object(E.createElement)(ee,{label:zn(a,s.mode),icon:n,content:Object(E.createElement)(Io,this.props),placeholderChildren:Object(E.createElement)(Ro,this.props)});break;default:e=Object(E.createElement)(Uo,{className:S()("wordcamp-block-edit-placeholder","wordcamp-block-edit-placeholder-no-mode"),icon:n,la
 bel:di},Object(E.createElement)("div",{className:"wordcamp-block-edit-mode-option"},Object(E.createElement)(zo,{isDefault:!0,isLarge:!0,onClick:function(){o({mode:"all"})}},zn("all",s.mode))),Object(E.createElement)("div",{className:"wordcamp-block-edit-mode-option"},Object(E.createElement)(Ro,u()({icon:n,label:Ho("Choose specific speakers or groups","wordcamporg")},this.props))))}return e}}]),t}(Wo),$o=wp.blockEditor.InspectorControls,qo=wp.components,Yo=qo.PanelBody,Xo=qo.PanelRow,Ko=qo.SelectControl,Zo=qo.ToggleControl,Jo=wp.element.Component,Qo=wp.i18n.__,ei={grid_columns:{default:2,minimum:2,maximum:4},avatar_size:{default:150,minimum:25,maximum:600}},ti={align_image:{},content:{},sort:{}},ni=function(e){function t(){return c()(this,t),m()(this,g()(t).apply(this,arguments))}return v()(t,e),d()(t,[{key:"render",value:function(){var e=this.props,t=e.attributes,n=e.setAttributes,r=e.blockData
 ,o=t.show_avatars,i=t.avatar_size,a=t.avatar_align,s=t.content,u=t.show_session,l=t.sort,c=r.schema,p=void 0===c?ei:c,d=r.options,f=void 0===d?ti:d;return Object(E.createElement)($o,null,Object(E.createElement)(L,this.props),Object(E.createElement)(Mn,{title:Qo("Avatar Settings","wordcamporg"),show:o,onChangeShow:function(e){return n({show_avatars:e})},size:i,onChangeSize:function(e){return n({avatar_size:e})},sizeSchema:p.avatar_size,sizePresets:dn,align:a,onChangeAlign:function(e){return n({avatar_align:e})},alignOptions:f.align_image}),Object(E.createElement)(Yo,{title:Qo("Content Settings","wordcamporg"),initialOpen:!1},Object(E.createElement)(Xo,null,Object(E.createElement)(Ko,{label:Qo("Biography Length","wordcamporg"),value:s,options:f.content,onChange:function(e){return n({content:e})}})),Object(E.createElement)(Xo,null,Object(E.createElement)(Zo,{label:Qo("Session Information","wordcamporg"),hel
 p:Qo("Show speaker's session name, time, and track","wordcamporg"),checked:u,onChange:function(e){return n({show_session:e})}}))),Object(E.createElement)(Yo,{title:Qo("Sorting & Filtering","wordcamporg"),initialOpen:!1},Object(E.createElement)(Xo,null,Object(E.createElement)(Ko,{label:Qo("Sort by","wordcamporg"),value:l,options:f.sort,onChange:function(e){return n({sort:e})}}))))}}]),t}(Jo),ri=wp.data.withSelect,oi=wp.element,ii=oi.Component,ai=oi.Fragment,si=window.WordCampBlocks.speakers||{},ui=function(e){function t(){return c()(this,t),m()(this,g()(t).apply(this,arguments))}return v()(t,e),d()(t,[{key:"render",value:function(){var e=this.props,t=e.attributes,n=e.setAttributes,r=t.mode,o=t.layout,i=si.options.layout,a=void 0===i?{}:i;return Object(E.createElement)(ai,null,Object(E.createElement)(Go,u()({icon:fi},this.props)),r&&Object(E.createElement)(ai,null,Object(E.createElement)(ni,this.props),O
 bject(E.createElement)(M,{layout:o,options:a,setAttributes:n})))}}]),t}(ii),li=ri(function(e){var t=e("wordcamp").getEntities,n={wcb_speaker:t("postType","wcb_speaker",{_embed:!0}),wcb_speaker_group:t("taxonomy","wcb_speaker_group"),wcb_track:t("taxonomy","wcb_track")};return{blockData:si,entities:n}})(ui),ci=wp.i18n.__,pi="wordcamp/speakers",di=ci("Speakers","wordcamporg"),fi="megaphone",mi={title:ci("Speakers","wordcamporg"),description:ci("Add a list of speakers.","wordcamporg"),icon:fi,category:"wordcamp",supports:{align:["wide","full"]},edit:li,save:function(){return null}},hi=wp.element.Component,gi=wp.i18n.__,bi=function(e){function t(e){var n;return c()(this,t),(n=m()(this,g()(t).call(this,e))).getFilteredPosts=n.getFilteredPosts.bind(ne()(ne()(n))),n}return v()(t,e),d()(t,[{key:"getFilteredPo
 sts",value:function(){var e=this.props,t=e.attributes,n=e.entities.wcb_sponsor,r=t.mode,o=t.item_ids,i=t.sort,a={};return Array.isArray(o)&&o.length>0&&(a.filter=[{fieldName:"wcb_sponsor"===r?"id":"sponsor_level",fieldValue:o}]),a.sort=i,Z(n,a)}},{key:"render",value:function(){var e=this.props.attributes,t=e.show_name,n=e.show_logo,r=e.featured_image_width,o=e.image_align,i=e.content,a=this.getFilteredPosts(),s=!Array.isArray(a),l=!s&&a.length>0;return s||!l?Object(E.createElement)(nr,{loading:s}):Object(E.createElement)(V,u()({},this.props,{className:"wordcamp-sponsors-block"}),a.map(function(e){return Object(E.createElement)("div",{key:e.slug,className:S()("wordcamp-sponsor","wordcamp-sponsor-"+e.slug)},t&&Object(E.createElement)(rr,{className:"wordcamp-sponsor-title",headingLevel:3,title:e.title.rendered.trim(),link:e.link}),n&&Object(E.crea
 teElement)(wn,{imageData:Object(w.get)(e,"_embedded.wp:featuredmedia[0]",{}),width:r,className:S()("wordcamp-sponsor-featured-image","wordcamp-sponsor-logo","align-"+o),imageLink:e.link}),"none"!==i&&Object(E.createElement)(or,{className:S()("wordcamp-sponsor-content-"+i),content:"full"===i?e.content.rendered.trim():e.excerpt.rendered.trim()}),"full"===i&&Object(E.createElement)(ir,{link:e.link,linkText:gi("Visit sponsor page","wordcamporg"),className:"wordcamp-sponsor-permalink"}))}))}}]),t}(hi),vi=wp.element.Component,Ei=wp.i18n.__,yi=function(e){function t(e){var n;return c()(this,t),(n=m()(this,g()(t).call(this,e))).buildSelectOptions=n.buildSelectOptions.bind(ne()(ne()(n))),n.getCurrentSelectValue=n.getCurrentSelectValue.bind(ne()(ne()(n))),n.isLoading=n.isLoading.bind(ne()(ne()(n))),n}return v()(t,e),d()(t,[{key:"buildSelectOptions",value:func
 tion(){var e=this.props.entities,t=e.wcb_sponsor,n=e.wcb_sponsor_level,r=[{entityType:"post",type:"wcb_sponsor",label:Ei("Sponsors","wordcamporg"),items:t},{entityType:"term",type:"wcb_sponsor_level",label:Ei("Sponsors Levels","wordcamporg"),items:n}];return Bn(r)}},{key:"getCurrentSelectValue",value:function(){var e=this.props.attributes,t=e.mode,n=e.item_ids,r=Object(w.flatMap)(this.buildSelectOptions(),function(e){return e.options}),o=[];return t&&n.length&&(o=r.filter(function(e){return t===e.type&&Object(w.includes)(n,e.value)})),o}},{key:"isLoading",value:function(){var e=this.props.entities;return!Object(w.every)(e,function(e){return Array.isArray(e)})}},{key:"render",value:function(){var e=this.props,t=e.label,n=e.icon,r=e.setAttributes;return Object(E.createElement)(Yn,{className:"wordcamp-sponsors-select",label:t,value:this.getCurr
 entSelectValue(),onChange:function(e){return r(e)},selectProps:{options:this.buildSelectOptions(),isLoading:this.isLoading(),formatOptionLabel:function(e){return Object(E.createElement)(Un,u()({icon:"wcb_sponsor_level"===e.type?n:null},e))}}})}}]),t}(vi),wi=wp.components,Oi=wi.Button,Ci=wi.Placeholder,ki=wp.element.Component,Si=wp.i18n.__,Ai=function(e){function t(){return c()(this,t),m()(this,g()(t).apply(this,arguments))}return v()(t,e),d()(t,[{key:"render",value:function(){var e,t=this.props,n=t.icon,r=t.attributes,o=t.setAttributes,i=t.blockData,a=r.mode,s=i.options;switch(a){case"all":e=Object(E.createElement)(bi,this.props);break;case"wcb_sponsor":case"wcb_sponsor_level":e=Object(E.createElement)(ee,{label:zn(a,s.mode),icon:n,content:Object(E.createElement)(bi,this.props),placeholderChildren:Object(E.createElement)(yi,this.props)});break;default:e=Object(E.createElement)(Ci,{className:S()("wordcamp-block-edit-placeholder&q
 uot;,"wordcamp-block-edit-placeholder-no-mode"),icon:n,label:Gi},Object(E.createElement)("div",{className:"wordcamp-block-edit-mode-option"},Object(E.createElement)(Oi,{isDefault:!0,isLarge:!0,onClick:function(){o({mode:"all"})}},zn("all",s.mode))),Object(E.createElement)("div",{className:"wordcamp-block-edit-mode-option"},Object(E.createElement)(yi,u()({icon:n,label:Si("Choose specific sponsors or levels","wordcamporg")},this.props))))}return e}}]),t}(ki),xi=wp.blockEditor.InspectorControls,_i=wp.components,ji=_i.PanelBody,Fi=(_i.PanelRow,_i.ToggleControl),Di=_i.SelectControl,Ni=wp.element.Component,Pi=wp.i18n.__,Li={align_image:{},content:{},sort:{}},Ti=function(e){function t(){return c()(this,t),m()(this,g()(t).apply(this,arguments))}return v()(t,e),d()(t,[{key:"render",value:function(){var e=this.props,t=e.attributes,n=e.setAttributes,r=e.blockData,o=t.show_logo,i=t.featured_image
 _width,a=t.image_align,s=t.show_name,u=t.content,l=t.sort,c=r.schema,p=r.options,d=void 0===p?Li:p;return Object(E.createElement)(xi,null,Object(E.createElement)(L,this.props),Object(E.createElement)(Mn,{title:Pi("Logo Settings","wordcamporg"),show:o,onChangeShow:function(e){return n({show_logo:e})},size:i,onChangeSize:function(e){return n({featured_image_width:e})},sizeSchema:c.featured_image_width,sizePresets:yn,align:a,onChangeAlign:function(e){return n({image_align:e})},alignOptions:d.align_image}),Object(E.createElement)(ji,{title:Pi("Content Settings","wordcamporg"),initialOpen:!0},Object(E.createElement)(Fi,{label:Pi("Name","wordcamporg"),help:Pi("Show or hide sponsor name","wordcamporg"),checked:s,onChange:function(e){return n({show_name:e})}}),Object(E.createElement)(Di,{label:Pi("Description","wordcamporg"),value:u,options:d.content,help:Pi("Length of sponsor descriptio
 n","wordcamporg"),onChange:function(e){return n({content:e})}})),Object(E.createElement)(ji,{title:Pi("Sorting","wordcamporg"),initialOpen:!1},Object(E.createElement)(Di,{label:Pi("Sort by","wordcamporg"),value:l,options:d.sort,onChange:function(e){return n({sort:e})}})))}}]),t}(Ni),Ii=wp.data.withSelect,Mi=wp.element,Vi=Mi.Component,Ri=Mi.Fragment,Bi=window.WordCampBlocks.sponsors||{},zi=function(e){function t(){return c()(this,t),m()(this,g()(t).apply(this,arguments))}return v()(t,e),d()(t,[{key:"render",value:function(){var e=this.props,t=e.attributes,n=e.setAttributes,r=t.mode,o=t.layout,i=Bi.options.layout,a=void 0===i?{}:i;return Object(E.createElement)(Ri,null,Object(E.createElement)(Ai,u()({icon:$i},this.props)),r&&Object(E.createElement)(Ri,null,Object(E.createElement)(Ti,this.props),Object(E.createElement)(M,{layout:o,options:a,setAttributes:n})))}}]),t}(Vi),Ui=Ii(function(e){var t=e("wordcamp&qu
 ot;),n=t.getEntities,r=t.getSiteSettings,o={wcb_sponsor:n("postType","wcb_sponsor",{_embed:!0}),wcb_sponsor_level:n("taxonomy","wcb_sponsor_level")};return{blockData:Bi,entities:o,siteSettings:r()}})(zi),Wi=wp.i18n.__,Hi="wordcamp/sponsors",Gi=Wi("Sponsors","wordcamporg"),$i="heart",qi={title:Wi("Sponsors","wordcamporg"),description:Wi("We wouldn't have WordCamp without their support.","wordcamporg"),icon:$i,category:"wordcamp",supports:{align:["wide","full"]},edit:Ui,save:function(){return null}},Yi=[r,o,i,a],Xi=wp.blocks.registerBlockType;Yi.forEach(function(e){var t=e.NAME,n=e.SETTINGS;Xi(t,n)})}]);
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblocksorganizersphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/organizers.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/organizers.php                          (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/organizers.php    2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,210 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Organizers;
+
+use WordCamp\Blocks;
+use function WordCamp\Blocks\Components\{ render_post_list };
+use function WordCamp\Blocks\Definitions\{ get_shared_definitions, get_shared_definition };
+
+defined( 'WPINC' ) || die();
+
+
+/**
+ * Register block types and enqueue scripts.
+ *
+ * @return void
+ */
+function init() {
+       register_block_type(
+               'wordcamp/organizers',
+               [
+                       'attributes'      => get_attributes_schema(),
+                       'render_callback' => __NAMESPACE__ . '\render',
+                       'editor_script'   => 'wordcamp-blocks',
+                       'editor_style'    => 'wordcamp-blocks',
+                       'style'           => 'wordcamp-blocks',
+               ]
+       );
+}
+add_action( 'init', __NAMESPACE__ . '\init' );
+
+/**
+ * Render the block on the front end.
+ *
+ * @param array $attributes Block attributes.
+ *
+ * @return string
+ */
+function render( $attributes ) {
+       $defaults   = wp_list_pluck( get_attributes_schema(), 'default' );
+       $attributes = wp_parse_args( $attributes, $defaults );
+
+       $organizers               = get_organizer_posts( $attributes );
+       $rendered_organizer_posts = [];
+
+       foreach ( $organizers as $organizer ) {
+               ob_start();
+               require Blocks\PLUGIN_DIR . 'views/organizer.php';
+               $rendered_organizer_posts[] = ob_get_clean();
+       }
+
+       $container_classes = [
+               'wordcamp-organizers-block',
+               sanitize_html_class( $attributes['className'] ),
+       ];
+
+       if ( ! empty( $attributes['align'] ) ) {
+               $container_classes[] = 'align' . sanitize_html_class( $attributes['align'] );
+       }
+
+       return render_post_list( $rendered_organizer_posts, $attributes['layout'], $attributes['grid_columns'], $container_classes );
+}
+
+/**
+ * Add data to be used by the JS scripts in the block editor.
+ *
+ * @param array $data
+ *
+ * @return array
+ */
+function add_script_data( array $data ) {
+       $data['organizers'] = [
+               'schema'  => get_attributes_schema(),
+               'options' => get_options(),
+       ];
+
+       return $data;
+}
+add_filter( 'wordcamp_blocks_script_data', __NAMESPACE__ . '\add_script_data' );
+
+/**
+ * Get the posts to display in the block.
+ *
+ * @param array $attributes
+ *
+ * @return array
+ */
+function get_organizer_posts( array $attributes ) {
+       if ( empty( $attributes['mode'] ) ) {
+               return [];
+       }
+
+       $post_args = [
+               'post_type'      => 'wcb_organizer',
+               'post_status'    => 'publish',
+               'posts_per_page' => -1,
+       ];
+
+       $sort = explode( '_', $attributes['sort'] );
+
+       if ( 2 === count( $sort ) ) {
+               $post_args['orderby'] = $sort[0];
+               $post_args['order']   = $sort[1];
+       }
+
+       switch ( $attributes['mode'] ) {
+               case 'wcb_organizer':
+                       $post_args['post__in'] = $attributes['item_ids'];
+                       break;
+
+               case 'wcb_organizer_team':
+                       $post_args['tax_query'] = [
+                               [
+                                       'taxonomy' => $attributes['mode'],
+                                       'field'    => 'id',
+                                       'terms'    => $attributes['item_ids'],
+                               ],
+                       ];
+                       break;
+       }
+
+       return get_posts( $post_args );
+}
+
+/**
+ * Get the schema for the block's attributes.
+ *
+ * @return array
+ */
+function get_attributes_schema() {
+       $schema = array_merge(
+               get_shared_definitions(
+                       [
+                               'content',
+                               'grid_columns',
+                               'item_ids',
+                               'layout',
+                       ],
+                       'attribute'
+               ),
+               [
+                       'align'        => get_shared_definition( 'align_block', 'attribute' ),
+                       'avatar_align' => get_shared_definition( 'align_image', 'attribute' ),
+                       'avatar_size'  => get_shared_definition( 'image_size_avatar', 'attribute' ),
+                       'className'    => get_shared_definition( 'string_empty', 'attribute' ),
+                       'mode'         => [
+                               'type'    => 'string',
+                               'enum'    => wp_list_pluck( get_options( 'mode' ), 'value' ),
+                               'default' => '',
+                       ],
+                       'show_avatars' => get_shared_definition( 'boolean_true', 'attribute' ),
+                       'sort'         => [
+                               'type'    => 'string',
+                               'enum'    => wp_list_pluck( get_options( 'sort' ), 'value' ),
+                               'default' => 'title_asc',
+                       ],
+               ]
+       );
+
+       return $schema;
+}
+
+/**
+ * Get the label/value pairs for all options or a specific type.
+ *
+ * @param string $type
+ *
+ * @return array
+ */
+function get_options( $type = '' ) {
+       $options = array_merge(
+               get_shared_definitions(
+                       [
+                               'align_block',
+                               'align_image',
+                               'content',
+                               'layout',
+                       ],
+                       'option'
+               ),
+               [
+                       'mode' => [
+                               [
+                                       'label' => '',
+                                       'value' => '',
+                               ],
+                               [
+                                       'label' => _x( 'List all organizers', 'mode option', 'wordcamporg' ),
+                                       'value' => 'all',
+                               ],
+                               [
+                                       'label' => _x( 'Choose organizers', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_organizer',
+                               ],
+                               [
+                                       'label' => _x( 'Choose teams', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_organizer_team',
+                               ],
+                       ],
+                       'sort' => array_merge(
+                               get_shared_definition( 'sort_title', 'option' ),
+                               get_shared_definition( 'sort_date', 'option' )
+                       ),
+               ]
+       );
+
+       if ( $type ) {
+               return empty( $options[ $type ] ) ? [] : $options[ $type ];
+       }
+
+       return $options;
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblockssessionsphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/sessions.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/sessions.php                            (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/sessions.php      2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,302 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Sessions;
+
+use WordCamp\Blocks;
+use function WordCamp\Blocks\Components\{ render_post_list };
+use function WordCamp\Blocks\Definitions\{ get_shared_definitions, get_shared_definition };
+
+defined( 'WPINC' ) || die();
+
+/**
+ * Register block types and enqueue scripts.
+ *
+ * @return void
+ */
+function init() {
+       register_block_type(
+               'wordcamp/sessions',
+               [
+                       'attributes'      => get_attributes_schema(),
+                       'render_callback' => __NAMESPACE__ . '\render',
+                       'editor_script'   => 'wordcamp-blocks',
+                       'editor_style'    => 'wordcamp-blocks',
+                       'style'           => 'wordcamp-blocks',
+               ]
+       );
+}
+
+add_action( 'init', __NAMESPACE__ . '\init' );
+
+/**
+ * Render the block on the front end.
+ *
+ * @param array $attributes Block attributes.
+ *
+ * @return string
+ */
+function render( $attributes ) {
+       $defaults   = wp_list_pluck( get_attributes_schema(), 'default' );
+       $attributes = wp_parse_args( $attributes, $defaults );
+       $sessions   = get_session_posts( $attributes );
+
+       $speakers = [];
+       if ( ! empty( $sessions ) && true === $attributes['show_speaker'] ) {
+               $speakers = get_session_speakers( wp_list_pluck( $sessions, 'ID' ) );
+       }
+
+       $rendered_session_posts = [];
+
+       foreach ( $sessions as $session ) {
+               ob_start();
+               require Blocks\PLUGIN_DIR . 'views/session.php';
+               $rendered_session_posts[] = ob_get_clean();
+       }
+
+       $container_classes = [
+               'wordcamp-sessions-block',
+               sanitize_html_class( $attributes['className'] ),
+       ];
+
+       if ( ! empty( $attributes['align'] ) ) {
+               $container_classes[] = 'align' . sanitize_html_class( $attributes['align'] );
+       }
+
+       return render_post_list( $rendered_session_posts, $attributes['layout'], $attributes['grid_columns'], $container_classes );
+}
+
+/**
+ * Add data to be used by the JS scripts in the block editor.
+ *
+ * @param array $data
+ *
+ * @return array
+ */
+function add_script_data( array $data ) {
+       $data['sessions'] = [
+               'schema'  => get_attributes_schema(),
+               'options' => get_options(),
+       ];
+
+       return $data;
+}
+
+add_filter( 'wordcamp_blocks_script_data', __NAMESPACE__ . '\add_script_data' );
+
+/**
+ * Get the schema for the block's attributes.
+ *
+ * @return array
+ */
+function get_attributes_schema() {
+       $schema = array_merge(
+               get_shared_definitions(
+                       [
+                               'content',
+                               'grid_columns',
+                               'item_ids',
+                               'layout',
+                       ],
+                       'attribute'
+               ),
+               [
+                       'align'                => get_shared_definition( 'align_block', 'attribute' ),
+                       'className'            => get_shared_definition( 'string_empty', 'attribute' ),
+                       'featured_image_width' => get_shared_definition( 'image_size', 'attribute' ),
+                       'image_align'          => get_shared_definition( 'align_image', 'attribute' ),
+                       'mode'                 => [
+                               'type'    => 'string',
+                               'enum'    => wp_list_pluck( get_options( 'mode' ), 'value' ),
+                               'default' => '',
+                       ],
+                       'show_category'        => get_shared_definition( 'boolean_false', 'attribute' ),
+                       'show_images'          => get_shared_definition( 'boolean_true', 'attribute' ),
+                       'show_meta'            => get_shared_definition( 'boolean_false', 'attribute' ),
+                       'show_speaker'         => get_shared_definition( 'boolean_false', 'attribute' ),
+                       'sort'                 => [
+                               'type'    => 'string',
+                               'enum'    => wp_list_pluck( get_options( 'sort' ), 'value' ),
+                               'default' => 'session_time',
+                       ],
+               ]
+       );
+
+       return $schema;
+}
+
+/**
+ * Get the label/value pairs for all options or a specific type.
+ *
+ * @param string $type
+ *
+ * @return array
+ */
+function get_options( $type = '' ) {
+       $options = array_merge(
+               get_shared_definitions(
+                       [
+                               'align_block',
+                               'align_image',
+                               'content',
+                               'layout',
+                       ],
+                       'option'
+               ),
+               [
+                       'mode' => [
+                               [
+                                       'label' => '',
+                                       'value' => '',
+                               ],
+                               [
+                                       'label' => _x( 'List all sessions', 'mode option', 'wordcamporg' ),
+                                       'value' => 'all',
+                               ],
+                               [
+                                       'label' => _x( 'Choose sessions', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_session',
+                               ],
+                               [
+                                       'label' => _x( 'Choose tracks', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_track',
+                               ],
+                               [
+                                       'label' => _x( 'Choose session categories', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_session_category',
+                               ],
+                       ],
+                       'sort' => array_merge(
+                               [
+                                       [
+                                               'label' => _x( 'Day and Time', 'sort option', 'wordcamporg' ),
+                                               'value' => 'session_time',
+                                       ],
+                               ],
+                               get_shared_definition( 'sort_title', 'option' ),
+                               get_shared_definition( 'sort_date', 'option' )
+                       ),
+               ]
+       );
+
+       if ( $type ) {
+               if ( ! empty( $options[ $type ] ) ) {
+                       return $options[ $type ];
+               } else {
+                       return [];
+               }
+       }
+
+       return $options;
+}
+
+/**
+ * Get the posts to display in the block.
+ *
+ * @param array $attributes
+ *
+ * @return array
+ */
+function get_session_posts( array $attributes ) {
+       if ( empty( $attributes['mode'] ) ) {
+               return [];
+       }
+
+       $post_args = [
+               'post_type'      => 'wcb_session',
+               'post_status'    => 'publish',
+               'posts_per_page' => -1,
+               'meta_query'     => [
+                       'relation' => 'AND',
+                       [
+                               'relation' => 'OR',
+                               [
+                                       'key'     => '_wcpt_session_type',
+                                       'value'   => 'session',
+                                       'compare' => '=',
+                               ],
+                               [
+                                       'key'     => '_wcpt_session_type',
+                                       'value'   => '',
+                                       'compare' => 'NOT EXISTS',
+                               ],
+                       ],
+               ],
+       ];
+
+       switch ( $attributes['sort'] ) {
+               case 'session_time':
+                       $post_args['meta_key'] = '_wcpt_session_time';
+                       $post_args['orderby']  = 'meta_value_num title';
+                       $post_args['order']    = 'asc';
+                       break;
+
+               case 'title_asc':
+               case 'title_desc':
+               case 'date_desc':
+               case 'date_asc':
+                       $sort = explode( '_', $attributes['sort'] );
+
+                       if ( 2 === count( $sort ) ) {
+                               $post_args['orderby'] = $sort[0];
+                               $post_args['order']   = $sort[1];
+                       }
+                       break;
+       }
+
+       switch ( $attributes['mode'] ) {
+               case 'wcb_session':
+                       $post_args['post__in'] = $attributes['item_ids'];
+                       break;
+
+               case 'wcb_track':
+               case 'wcb_session_category':
+                       $post_args['tax_query'] = [
+                               [
+                                       'taxonomy' => $attributes['mode'],
+                                       'field'    => 'id',
+                                       'terms'    => $attributes['item_ids'],
+                               ],
+                       ];
+                       break;
+       }
+
+       return get_posts( $post_args );
+}
+
+/**
+ * Get speaker posts grouped by session.
+ *
+ * @param array $session_ids
+ *
+ * @return array
+ */
+function get_session_speakers( array $session_ids ) {
+       $speakers_by_session = [];
+
+       $session_args = [
+               'post_type'      => 'wcb_session',
+               'post_status'    => 'publish',
+               'posts_per_page' => -1,
+               'post__in'       => $session_ids,
+       ];
+
+       $session_posts = get_posts( $session_args );
+
+       foreach ( $session_posts as $session ) {
+               $speaker_ids = get_post_meta( $session->ID, '_wcpt_speaker_id', false );
+
+               if ( ! empty( $speaker_ids ) ) {
+                       $speaker_args = [
+                               'post_type'      => 'wcb_speaker',
+                               'post_status'    => 'publish',
+                               'posts_per_page' => -1,
+                               'post__in'       => $speaker_ids,
+                               'orderby'        => 'post__in',
+                               'order'          => 'ASC',
+                       ];
+
+                       $speakers_by_session[ $session->ID ] = get_posts( $speaker_args );
+               }
+       }
+
+       return $speakers_by_session;
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblocksspeakersphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/speakers.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/speakers.php                            (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/speakers.php      2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,260 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Speakers;
+
+use WordCamp\Blocks;
+use function WordCamp\Blocks\Components\{ render_post_list };
+use function WordCamp\Blocks\Definitions\{ get_shared_definitions, get_shared_definition };
+
+defined( 'WPINC' ) || die();
+
+/**
+ * Register block types and enqueue scripts.
+ *
+ * @return void
+ */
+function init() {
+       register_block_type(
+               'wordcamp/speakers',
+               [
+                       'attributes'      => get_attributes_schema(),
+                       'render_callback' => __NAMESPACE__ . '\render',
+                       'editor_script'   => 'wordcamp-blocks',
+                       'editor_style'    => 'wordcamp-blocks',
+                       'style'           => 'wordcamp-blocks',
+               ]
+       );
+}
+
+add_action( 'init', __NAMESPACE__ . '\init' );
+
+/**
+ * Render the block on the front end.
+ *
+ * @param array $attributes Block attributes.
+ *
+ * @return string
+ */
+function render( $attributes ) {
+       $defaults   = wp_list_pluck( get_attributes_schema(), 'default' );
+       $attributes = wp_parse_args( $attributes, $defaults );
+       $speakers   = get_speaker_posts( $attributes );
+
+       $sessions = [];
+       if ( ! empty( $speakers ) && true === $attributes['show_session'] ) {
+               $sessions = get_speaker_sessions( wp_list_pluck( $speakers, 'ID' ) );
+       }
+
+       $rendered_speaker_posts = [];
+
+       foreach ( $speakers as $speaker ) {
+               ob_start();
+               require Blocks\PLUGIN_DIR . 'views/speaker.php';
+               $rendered_speaker_posts[] = ob_get_clean();
+       }
+
+       $container_classes = [
+               'wordcamp-speakers-block',
+               sanitize_html_class( $attributes['className'] ),
+       ];
+
+       if ( ! empty( $attributes['align'] ) ) {
+               $container_classes[] = 'align' . sanitize_html_class( $attributes['align'] );
+       }
+
+       return render_post_list( $rendered_speaker_posts, $attributes['layout'], $attributes['grid_columns'], $container_classes );
+}
+
+/**
+ * Add data to be used by the JS scripts in the block editor.
+ *
+ * @param array $data
+ *
+ * @return array
+ */
+function add_script_data( array $data ) {
+       $data['speakers'] = [
+               'schema'  => get_attributes_schema(),
+               'options' => get_options(),
+       ];
+
+       return $data;
+}
+
+add_filter( 'wordcamp_blocks_script_data', __NAMESPACE__ . '\add_script_data' );
+
+/**
+ * Get the posts to display in the block.
+ *
+ * @param array $attributes
+ *
+ * @return array
+ */
+function get_speaker_posts( array $attributes ) {
+       if ( empty( $attributes['mode'] ) ) {
+               return [];
+       }
+
+       $post_args = [
+               'post_type'      => 'wcb_speaker',
+               'post_status'    => 'publish',
+               'posts_per_page' => -1,
+       ];
+
+       $sort = explode( '_', $attributes['sort'] );
+
+       if ( 2 === count( $sort ) ) {
+               $post_args['orderby'] = $sort[0];
+               $post_args['order']   = $sort[1];
+       }
+
+       switch ( $attributes['mode'] ) {
+               case 'wcb_speaker':
+                       $post_args['post__in'] = $attributes['item_ids'];
+                       break;
+
+               case 'wcb_speaker_group':
+                       $post_args['tax_query'] = [
+                               [
+                                       'taxonomy' => $attributes['mode'],
+                                       'field'    => 'id',
+                                       'terms'    => $attributes['item_ids'],
+                               ],
+                       ];
+                       break;
+       }
+
+       return get_posts( $post_args );
+}
+
+/**
+ * Get session posts grouped by speaker.
+ *
+ * @param array $speaker_ids
+ *
+ * @return array
+ */
+function get_speaker_sessions( array $speaker_ids ) {
+       $sessions_by_speaker = [];
+
+       $session_args = [
+               'post_type'      => 'wcb_session',
+               'post_status'    => 'publish',
+               'posts_per_page' => -1,
+               'meta_key'       => '_wcpt_session_time',
+               'orderby'        => 'meta_value_num',
+       ];
+
+       $session_posts = get_posts( $session_args );
+
+       foreach ( $session_posts as $session ) {
+               $session_speaker_ids = get_post_meta( $session->ID, '_wcpt_speaker_id', false );
+
+               foreach ( $session_speaker_ids as $speaker_id ) {
+                       $speaker_id = absint( $speaker_id );
+
+                       if ( in_array( $speaker_id, $speaker_ids, true ) ) {
+                               if ( ! isset( $sessions_by_speaker[ $speaker_id ] ) ) {
+                                       $sessions_by_speaker[ $speaker_id ] = [];
+                               }
+
+                               $sessions_by_speaker[ $speaker_id ][] = $session;
+                       }
+               }
+       }
+
+       return $sessions_by_speaker;
+}
+
+/**
+ * Get the schema for the block's attributes.
+ *
+ * @return array
+ */
+function get_attributes_schema() {
+       $schema = array_merge(
+               get_shared_definitions(
+                       [
+                               'content',
+                               'grid_columns',
+                               'item_ids',
+                               'layout',
+                       ],
+                       'attribute'
+               ),
+               [
+                       'align'        => get_shared_definition( 'align_block', 'attribute' ),
+                       'avatar_align' => get_shared_definition( 'align_image', 'attribute' ),
+                       'avatar_size'  => get_shared_definition( 'image_size_avatar', 'attribute' ),
+                       'className'    => get_shared_definition( 'string_empty', 'attribute' ),
+                       'mode'         => [
+                               'type'    => 'string',
+                               'enum'    => wp_list_pluck( get_options( 'mode' ), 'value' ),
+                               'default' => '',
+                       ],
+                       'show_avatars' => get_shared_definition( 'boolean_true', 'attribute' ),
+                       'show_session' => get_shared_definition( 'boolean_false', 'attribute' ),
+                       'sort'         => [
+                               'type'    => 'string',
+                               'enum'    => wp_list_pluck( get_options( 'sort' ), 'value' ),
+                               'default' => 'title_asc',
+                       ],
+               ]
+       );
+
+       return $schema;
+}
+
+/**
+ * Get the label/value pairs for all options or a specific type.
+ *
+ * @param string $type
+ *
+ * @return array
+ */
+function get_options( $type = '' ) {
+       $options = array_merge(
+               get_shared_definitions(
+                       [
+                               'align_block',
+                               'align_image',
+                               'content',
+                               'layout',
+                       ],
+                       'option'
+               ),
+               [
+                       'mode' => [
+                               [
+                                       'label' => '',
+                                       'value' => '',
+                               ],
+                               [
+                                       'label' => _x( 'List all speakers', 'mode option', 'wordcamporg' ),
+                                       'value' => 'all',
+                               ],
+                               [
+                                       'label' => _x( 'Choose speakers', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_speaker',
+                               ],
+                               [
+                                       'label' => _x( 'Choose groups', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_speaker_group',
+                               ],
+                       ],
+                       'sort' => array_merge(
+                               get_shared_definition( 'sort_title', 'option' ),
+                               get_shared_definition( 'sort_date', 'option' )
+                       ),
+               ]
+       );
+
+       if ( $type ) {
+               if ( ! empty( $options[ $type ] ) ) {
+                       return $options[ $type ];
+               } else {
+                       return [];
+               }
+       }
+
+       return $options;
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesblockssponsorsphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/sponsors.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/sponsors.php                            (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/blocks/sponsors.php      2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,214 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Sponsors;
+
+use WordCamp\Blocks;
+use function WordCamp\Blocks\Components\{ render_post_list };
+use function WordCamp\Blocks\Definitions\{ get_shared_definitions, get_shared_definition };
+
+defined( 'WPINC' ) || die();
+
+/**
+ * Register sponsor block and enqueue scripts.
+ */
+function init() {
+       register_block_type(
+               'wordcamp/sponsors',
+               [
+                       'attributes'      => get_attributes_schema(),
+                       'render_callback' => __NAMESPACE__ . '\render',
+                       'editor_script'   => 'wordcamp-blocks',
+                       'editor_style'    => 'wordcamp-blocks',
+                       'style'           => 'wordcamp-blocks',
+               ]
+       );
+}
+
+add_action( 'init', __NAMESPACE__ . '\init' );
+
+/**
+ * Renders content of Sponsor block based on attributes.
+ *
+ * @param array $attributes
+ *
+ * @return false|string
+ */
+function render( $attributes ) {
+       $defaults   = wp_list_pluck( get_attributes_schema(), 'default' );
+       $attributes = wp_parse_args( $attributes, $defaults );
+
+       $sponsors               = get_sponsor_posts( $attributes );
+       $rendered_sponsor_posts = [];
+
+       foreach ( $sponsors as $sponsor ) {
+               ob_start();
+               require Blocks\PLUGIN_DIR . 'views/sponsor.php';
+               $rendered_sponsor_posts[] = ob_get_clean();
+       }
+
+       $container_classes = [
+               'wordcamp-sponsors-block',
+               sanitize_html_class( $attributes['className'] ),
+       ];
+
+       if ( ! empty( $attributes['align'] ) ) {
+               $container_classes[] = 'align' . sanitize_html_class( $attributes['align'] );
+       }
+
+       return render_post_list( $rendered_sponsor_posts, $attributes['layout'], $attributes['grid_columns'], $container_classes );
+}
+
+/**
+ * Add data to be used by the JS scripts in the block editor.
+ *
+ * @param array $data
+ *
+ * @return array
+ */
+function add_script_data( array $data ) {
+       $data['sponsors'] = [
+               'schema'  => get_attributes_schema(),
+               'options' => get_options(),
+       ];
+
+       return $data;
+}
+
+add_filter( 'wordcamp_blocks_script_data', __NAMESPACE__ . '\add_script_data' );
+
+/**
+ * Return sponsor posts what will rendered based on attributes.
+ *
+ * @param array $attributes
+ *
+ * @return array
+ */
+function get_sponsor_posts( $attributes ) {
+       if ( empty( $attributes['mode'] ) ) {
+               return [];
+       }
+
+       $post_args = array(
+               'post_type'      => 'wcb_sponsor',
+               'post_status'    => 'publish',
+               'posts_per_page' => - 1,
+       );
+
+       $sort = explode( '_', $attributes['sort'] );
+
+       if ( 2 === count( $sort ) ) {
+               $post_args['orderby'] = $sort[0];
+               $post_args['order']   = $sort[1];
+       }
+
+       switch ( $attributes['mode'] ) {
+               case 'wcb_sponsor':
+                       $post_args['post__in'] = $attributes['item_ids'];
+                       break;
+
+               case 'wcb_sponsor_level':
+                       $post_args['tax_query'] = [
+                               [
+                                       'taxonomy' => $attributes['mode'],
+                                       'field'    => 'id',
+                                       'terms'    => $attributes['item_ids'],
+                               ],
+                       ];
+                       break;
+       }
+
+       return get_posts( $post_args );
+}
+
+/**
+ * Get attribute schema for Sponsor block
+ *
+ * @return array
+ */
+function get_attributes_schema() {
+       $schema = array_merge(
+               get_shared_definitions(
+                       [
+                               'content',
+                               'grid_columns',
+                               'item_ids',
+                               'layout',
+                       ],
+                       'attribute'
+               ),
+               [
+                       'align'                => get_shared_definition( 'align_block', 'attribute' ),
+                       'className'            => get_shared_definition( 'string_empty', 'attribute' ),
+                       'featured_image_width' => get_shared_definition( 'image_size', 'attribute', [ 'default' => 600 ] ),
+                       'image_align'          => get_shared_definition( 'align_image', 'attribute' ),
+                       'mode'                 => [
+                               'type'    => 'string',
+                               'enum'    => wp_list_pluck( get_options( 'mode' ), 'value' ),
+                               'default' => '',
+                       ],
+                       'show_logo'            => get_shared_definition( 'boolean_true', 'attribute' ),
+                       'show_name'            => get_shared_definition( 'boolean_true', 'attribute' ),
+                       'sort'                 => [
+                               'type'    => 'string',
+                               'enum'    => wp_list_pluck( get_options( 'sort' ), 'value' ),
+                               'default' => 'title_asc',
+                       ],
+               ]
+       );
+
+       return $schema;
+}
+
+/**
+ * Get the label/value pairs for all options or a specific type.
+ *
+ * @param string $type
+ *
+ * @return array
+ */
+function get_options( $type = '' ) {
+       $options = array_merge(
+               get_shared_definitions(
+                       [
+                               'align_block',
+                               'align_image',
+                               'content',
+                               'layout',
+                       ],
+                       'option'
+               ),
+               [
+                       'mode' => [
+                               [
+                                       'label' => '',
+                                       'value' => '',
+                               ],
+                               [
+                                       'label' => _x( 'List all sponsors', 'mode option', 'wordcamporg' ),
+                                       'value' => 'all',
+                               ],
+                               [
+                                       'label' => _x( 'Choose sponsors', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_sponsor',
+                               ],
+                               [
+                                       'label' => _x( 'Choose sponsor level', 'mode option', 'wordcamporg' ),
+                                       'value' => 'wcb_sponsor_level',
+                               ],
+                       ],
+                       'sort' => array_merge(
+                               get_shared_definition( 'sort_title', 'option' ),
+                               get_shared_definition( 'sort_date', 'option' )
+                       ),
+               ]
+       );
+
+       if ( $type ) {
+               if ( ! empty( $options[ $type ] ) ) {
+                       return $options[ $type ];
+               } else {
+                       return [];
+               }
+       }
+
+       return $options;
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludescomponentsblockcontentphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/block-content.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/block-content.php                           (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/block-content.php     2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,101 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Components;
+
+use function WordCamp\Blocks\Utilities\{ render_class_string };
+
+defined( 'WPINC' ) || die();
+
+/**
+ * Render HTML for a title with specified heading level and optionally a link.
+ *
+ * @param string $title
+ * @param string $link
+ * @param int    $heading_level
+ * @param array  $classes
+ *
+ * @return false|string
+ */
+function render_item_title( $title, $link = '', $heading_level = 3, array $classes = [] ) {
+       $valid_heading_levels = [ 1, 2, 3, 4, 5, 6 ];
+
+       if ( ! in_array( $heading_level, $valid_heading_levels, true ) ) {
+               $heading_level = 3;
+       }
+
+       $tag = 'h' . $heading_level;
+
+       $classes = render_class_string( array_merge(
+               [ 'wordcamp-item-title' ],
+               $classes
+       ) );
+
+       ob_start();
+       ?>
+       <<?php echo esc_html( $tag ); ?> class="<?php echo esc_attr( $classes ); ?>">
+       <?php if ( $link ) : ?>
+               <a href="<?php echo esc_url( $link ); ?>">
+       <?php endif; ?>
+       <?php echo wp_kses_post( $title ); ?>
+       <?php if ( $link ) : ?>
+               </a>
+       <?php endif; ?>
+       </<?php echo esc_html( $tag ); ?>>
+       <?php
+
+       return ob_get_clean();
+}
+
+/**
+ * Render arbitrary HTML content within a div container.
+ *
+ * @param string $content
+ * @param array  $classes
+ *
+ * @return false|string
+ */
+function render_item_content( $content, array $classes = [] ) {
+       $classes = render_class_string( array_merge(
+               [ 'wordcamp-item-content' ],
+               $classes
+       ) );
+
+       ob_start();
+       ?>
+       <div class="<?php echo esc_attr( $classes ); ?>">
+               <?php echo wp_kses_post( wpautop( $content ) ); ?>
+       </div>
+       <?php
+
+       return ob_get_clean();
+}
+
+/**
+ * Render HTML for a permalink wrapped in its own paragraph.
+ *
+ * @param string $link
+ * @param string $label
+ * @param array  $classes
+ *
+ * @return false|string
+ */
+function render_item_permalink( $link, $label = '', array $classes = [] ) {
+       if ( ! $label ) {
+               $label = __( 'Read more', 'wordcamporg' );
+       }
+
+       $classes = render_class_string( array_merge(
+               [ 'wordcamp-item-permalink' ],
+               $classes
+       ) );
+
+       ob_start();
+       ?>
+       <p class="<?php echo esc_attr( $classes ); ?>">
+               <a href="<?php echo esc_url( $link ); ?>">
+                       <?php echo esc_html( $label ); ?>
+               </a>
+       </p>
+       <?php
+
+       return ob_get_clean();
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludescomponentsfeaturedimagephp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/featured-image.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/featured-image.php                          (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/featured-image.php    2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,69 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Components;
+
+use WP_Post;
+
+defined( 'WPINC' ) || die();
+
+/**
+ * Provides render backend for FeaturedImage component.
+ *
+ * @param WP_Post  $post        Current post object. This will be used to calculate srcset attribute.
+ * @param int      $width       Width of the image.
+ * @param array    $class_names Additional classes to add inside <img> tag.
+ * @param string   $image_link  URL link. If provided, image will be linked to this URL.
+ *
+ * @return string Output markup for featured image.
+ */
+function render_featured_image( $post, $width, $class_names = [], $image_link = '' ) {
+       $attachment_id = get_post_thumbnail_id( $post->ID );
+       $image_data    = wp_get_attachment_metadata( $attachment_id );
+
+       if ( ! isset( $image_data['width'], $image_data['height'] ) ) {
+               return '';
+       }
+
+       $aspect_ratio = $image_data['height'] / $image_data['width'];
+       $height       = round( $aspect_ratio * $width, 1 );
+       $size         = array( $width, $height );
+
+       $container_classes = array_merge(
+               [ 'wordcamp-image-container', 'wordcamp-featured-image-container' ],
+               $class_names
+       );
+       $container_classes = implode( ' ', $container_classes );
+
+       $image = render_featured_image_element( $post, $size );
+
+       ob_start();
+       ?>
+               <div class="<?php echo esc_attr( $container_classes ); ?>">
+                       <?php if ( '' !== $image_link ) { ?>
+                               <a href="<?php echo esc_html( $image_link ); ?>" class="wordcamp-image-link wordcamp-featured-image-link">
+                                       <?php echo wp_kses_post( $image ); ?>
+                               </a>
+                       <?php } else { ?>
+                               <?php echo wp_kses_post( $image ); ?>
+                       <?php } ?>
+               </div>
+       <?php
+
+       return ob_get_clean();
+}
+
+/**
+ * Helper method to render thumbnail image.
+ *
+ * @param \WP_Post     $post
+ * @param string|array $size
+ * @param string       $class_names
+ *
+ * @return string
+ */
+function render_featured_image_element( $post, $size ) {
+       $attr = [
+               'class' => 'wordcamp-featured-image',
+       ];
+
+       return get_the_post_thumbnail( $post, $size, $attr );
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludescomponentspostlistphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/post-list.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/post-list.php                               (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/components/post-list.php 2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,54 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Components;
+
+use function WordCamp\Blocks\Utilities\{ render_class_string };
+
+defined( 'WPINC' ) || die();
+
+/**
+ * Render the containing HTML structures of a post list.
+ *
+ * @param array  $rendered_items    Array of rendered post list items.
+ * @param string $layout            Whether the layout is `grid` or `list`.
+ * @param int    $columns           Number of columns if layout is `grid`. Assumed to be 1 if layout is list.
+ * @param array  $container_classes Array of classes that will be added to container.
+ *
+ * @return string Markup of output layout.
+ */
+function render_post_list( array $rendered_items, $layout = 'list', $columns = 1, array $container_classes = [] ) {
+       if ( count( $rendered_items ) < 1 ) {
+               return '';
+       }
+
+       $container_classes = array_merge(
+               [
+                       'wordcamp-block',
+                       'wordcamp-post-list',
+                       'layout-' . sanitize_html_class( $layout )
+               ],
+               $container_classes
+       );
+
+       if ( 'grid' === $layout ) {
+               if ( $columns < 2 ) {
+                       $columns = 2;
+               }
+
+               $container_classes[] = 'grid-columns-' . absint( $columns );
+       }
+
+       $container_classes = render_class_string( $container_classes );
+
+       ob_start();
+       ?>
+               <ul class="<?php echo esc_attr( $container_classes ); ?>">
+                       <?php foreach ( $rendered_items as $item ) : ?>
+                               <li class="wordcamp-post-list-item wordcamp-clearfix">
+                                       <?php echo wp_kses_post( $item ); ?>
+                               </li>
+                       <?php endforeach; ?>
+               </ul>
+       <?php
+
+       return ob_get_clean();
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesdefinitionsphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/definitions.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/definitions.php                                (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/definitions.php  2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,191 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Definitions;
+
+defined( 'WPINC' ) || die();
+
+/**
+ * Retrieve an array of definitions for use within a block.
+ *
+ * Currently there are two types of definitions: attributes, which make up a block's schema, and options, which
+ * are label/value pairs used in situations where the value of an attribute must come from an enumerated list.
+ *
+ * @param array|string $keys The keys of the definitions to retrieve. An array of strings, or 'all'.
+ * @param string       $type The type of definition to retrieve. 'attribute' or 'option'.
+ *
+ * @return array
+ */
+function get_shared_definitions( $keys, $type ) {
+       switch ( $type ) {
+               case 'attribute':
+                       $definitions = [
+                               // Generic attributes.
+                               'boolean_false'     => [
+                                       'type'    => 'bool',
+                                       'default' => false,
+                               ],
+                               'boolean_true'      => [
+                                       'type'    => 'bool',
+                                       'default' => true,
+                               ],
+                               'string_empty'      => [
+                                       'type'    => 'string',
+                                       'default' => '',
+                               ],
+                               // Specific attributes.
+                               'align_block'       => [
+                                       'type'    => 'string',
+                                       'enum'    => wp_list_pluck( get_shared_definition( 'align_block', 'option' ), 'value' ),
+                                       'default' => '',
+                               ],
+                               'align_image'       => [
+                                       'type'    => 'string',
+                                       'enum'    => wp_list_pluck( get_shared_definition( 'align_image', 'option' ), 'value' ),
+                                       'default' => 'none',
+                               ],
+                               'content'           => [
+                                       'type'    => 'string',
+                                       'enum'    => wp_list_pluck( get_shared_definition( 'content', 'option' ), 'value' ),
+                                       'default' => 'full',
+                               ],
+                               'grid_columns'      => [
+                                       'type'    => 'integer',
+                                       'minimum' => 2,
+                                       'maximum' => 4,
+                                       'default' => 2,
+                               ],
+                               'image_size'        => [
+                                       'type'    => 'integer',
+                                       'minimum' => 100,
+                                       'maximum' => 1024,
+                                       'default' => 150,
+                               ],
+                               'image_size_avatar' => [
+                                       'type'    => 'integer',
+                                       'minimum' => 25,
+                                       'maximum' => 600,
+                                       'default' => 150,
+                               ],
+                               'item_ids'          => [
+                                       'type'    => 'array',
+                                       'default' => [],
+                                       'items'   => [
+                                               'type' => 'integer',
+                                       ],
+                               ],
+                               'layout'            => [
+                                       'type'    => 'string',
+                                       'enum'    => wp_list_pluck( get_shared_definition( 'layout', 'option' ), 'value' ),
+                                       'default' => 'list',
+                               ],
+                       ];
+                       break;
+
+               case 'option':
+                       $definitions = [
+                               'align_block' => [
+                                       [
+                                               'label' => _x( 'Wide', 'alignment option', 'wordcamporg' ),
+                                               'value' => 'wide',
+                                       ],
+                                       [
+                                               'label' => _x( 'Full', 'alignment option', 'wordcamporg' ),
+                                               'value' => 'full',
+                                       ],
+                               ],
+                               'align_image' => [
+                                       [
+                                               'label' => _x( 'None', 'alignment option', 'wordcamporg' ),
+                                               'value' => 'none',
+                                       ],
+                                       [
+                                               'label' => _x( 'Left', 'alignment option', 'wordcamporg' ),
+                                               'value' => 'left',
+                                       ],
+                                       [
+                                               'label' => _x( 'Center', 'alignment option', 'wordcamporg' ),
+                                               'value' => 'center',
+                                       ],
+                                       [
+                                               'label' => _x( 'Right', 'alignment option', 'wordcamporg' ),
+                                               'value' => 'right',
+                                       ],
+                               ],
+                               'content'     => [
+                                       [
+                                               'label' => _x( 'Full', 'content option', 'wordcamporg' ),
+                                               'value' => 'full',
+                                       ],
+                                       [
+                                               'label' => _x( 'Excerpt', 'content option', 'wordcamporg' ),
+                                               'value' => 'excerpt',
+                                       ],
+                                       [
+                                               'label' => _x( 'None', 'content option', 'wordcamporg' ),
+                                               'value' => 'none',
+                                       ],
+                               ],
+                               'layout'      => [
+                                       [
+                                               'label' => _x( 'List', 'content option', 'wordcamporg' ),
+                                               'value' => 'list',
+                                       ],
+                                       [
+                                               'label' => _x( 'Grid', 'content option', 'wordcamporg' ),
+                                               'value' => 'grid',
+                                       ],
+                               ],
+                               'sort_title'  => [
+                                       [
+                                               'label' => _x( 'A â†’ Z', 'sort option', 'wordcamporg' ),
+                                               'value' => 'title_asc',
+                                       ],
+                                       [
+                                               'label' => _x( 'Z â†’ A', 'sort option', 'wordcamporg' ),
+                                               'value' => 'title_desc',
+                                       ],
+                               ],
+                               'sort_date'   => [
+                                       [
+                                               'label' => _x( 'Newest to Oldest', 'sort option', 'wordcamporg' ),
+                                               'value' => 'date_desc',
+                                       ],
+                                       [
+                                               'label' => _x( 'Oldest to Newest', 'sort option', 'wordcamporg' ),
+                                               'value' => 'date_asc',
+                                       ],
+                               ],
+                       ];
+                       break;
+
+               default:
+                       $definitions = [];
+                       break;
+       }
+
+       if ( 'all' === $keys ) {
+               return $definitions;
+       }
+
+       $keys = array_fill_keys( (array) $keys, '' );
+
+       return array_intersect_key( $definitions, $keys );
+}
+
+/**
+ * Retrieve a single definition for use within a block.
+ *
+ * @param string $key   The key of the definition to retrieve.
+ * @param string $type  The type of definition to retrieve. 'attribute' or 'option'.
+ * @param array  $props Properties to override in the shared definition.
+ *
+ * @return array
+ */
+function get_shared_definition( $key, $type, $props = [] ) {
+       $result = get_shared_definitions( $key, $type );
+
+       if ( ! empty( $result ) ) {
+               $result = wp_parse_args( $props, array_shift( $result ) );
+       }
+
+       return $result;
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesorganizersphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/organizers.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/organizers.php 2019-05-10 20:20:52 UTC (rev 8778)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/organizers.php   2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,210 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-namespace WordCamp\Blocks\Organizers;
-use WordCamp\Blocks;
-use function WordCamp\Blocks\Shared\Components\{ render_post_list };
-use function WordCamp\Blocks\Shared\Definitions\{ get_shared_definitions, get_shared_definition };
-
-defined( 'WPINC' ) || die();
-
-
-/**
- * Register block types and enqueue scripts.
- *
- * @return void
- */
-function init() {
-       register_block_type(
-               'wordcamp/organizers',
-               [
-                       'attributes'      => get_attributes_schema(),
-                       'render_callback' => __NAMESPACE__ . '\render',
-                       'editor_script'   => 'wordcamp-blocks',
-                       'editor_style'    => 'wordcamp-blocks',
-                       'style'           => 'wordcamp-blocks',
-               ]
-       );
-}
-add_action( 'init', __NAMESPACE__ . '\init' );
-
-/**
- * Render the block on the front end.
- *
- * @param array $attributes Block attributes.
- *
- * @return string
- */
-function render( $attributes ) {
-       $defaults   = wp_list_pluck( get_attributes_schema(), 'default' );
-       $attributes = wp_parse_args( $attributes, $defaults );
-
-       $organizers               = get_organizer_posts( $attributes );
-       $rendered_organizer_posts = [];
-
-       foreach ( $organizers as $organizer ) {
-               ob_start();
-               require Blocks\PLUGIN_DIR . 'view/organizer.php';
-               $rendered_organizer_posts[] = ob_get_clean();
-       }
-
-       $container_classes = [
-               'wordcamp-organizers-block',
-               sanitize_html_class( $attributes['className'] ),
-       ];
-
-       if ( ! empty( $attributes['align'] ) ) {
-               $container_classes[] = 'align' . sanitize_html_class( $attributes['align'] );
-       }
-
-       return render_post_list( $rendered_organizer_posts, $attributes['layout'], $attributes['grid_columns'], $container_classes );
-}
-
-/**
- * Add data to be used by the JS scripts in the block editor.
- *
- * @param array $data
- *
- * @return array
- */
-function add_script_data( array $data ) {
-       $data['organizers'] = [
-               'schema'  => get_attributes_schema(),
-               'options' => get_options(),
-       ];
-
-       return $data;
-}
-add_filter( 'wordcamp_blocks_script_data', __NAMESPACE__ . '\add_script_data' );
-
-/**
- * Get the posts to display in the block.
- *
- * @param array $attributes
- *
- * @return array
- */
-function get_organizer_posts( array $attributes ) {
-       if ( empty( $attributes['mode'] ) ) {
-               return [];
-       }
-
-       $post_args = [
-               'post_type'      => 'wcb_organizer',
-               'post_status'    => 'publish',
-               'posts_per_page' => -1,
-       ];
-
-       $sort = explode( '_', $attributes['sort'] );
-
-       if ( 2 === count( $sort ) ) {
-               $post_args['orderby'] = $sort[0];
-               $post_args['order']   = $sort[1];
-       }
-
-       switch ( $attributes['mode'] ) {
-               case 'wcb_organizer':
-                       $post_args['post__in'] = $attributes['item_ids'];
-                       break;
-
-               case 'wcb_organizer_team':
-                       $post_args['tax_query'] = [
-                               [
-                                       'taxonomy' => $attributes['mode'],
-                                       'field'    => 'id',
-                                       'terms'    => $attributes['item_ids'],
-                               ],
-                       ];
-                       break;
-       }
-
-       return get_posts( $post_args );
-}
-
-/**
- * Get the schema for the block's attributes.
- *
- * @return array
- */
-function get_attributes_schema() {
-       $schema = array_merge(
-               get_shared_definitions(
-                       [
-                               'content',
-                               'grid_columns',
-                               'item_ids',
-                               'layout',
-                       ],
-                       'attribute'
-               ),
-               [
-                       'align'        => get_shared_definition( 'align_block', 'attribute' ),
-                       'avatar_align' => get_shared_definition( 'align_image', 'attribute' ),
-                       'avatar_size'  => get_shared_definition( 'image_size_avatar', 'attribute' ),
-                       'className'    => get_shared_definition( 'string_empty', 'attribute' ),
-                       'mode'         => [
-                               'type'    => 'string',
-                               'enum'    => wp_list_pluck( get_options( 'mode' ), 'value' ),
-                               'default' => '',
-                       ],
-                       'show_avatars' => get_shared_definition( 'boolean_true', 'attribute' ),
-                       'sort'         => [
-                               'type'    => 'string',
-                               'enum'    => wp_list_pluck( get_options( 'sort' ), 'value' ),
-                               'default' => 'title_asc',
-                       ],
-               ]
-       );
-
-       return $schema;
-}
-
-/**
- * Get the label/value pairs for all options or a specific type.
- *
- * @param string $type
- *
- * @return array
- */
-function get_options( $type = '' ) {
-       $options = array_merge(
-               get_shared_definitions(
-                       [
-                               'align_block',
-                               'align_image',
-                               'content',
-                               'layout',
-                       ],
-                       'option'
-               ),
-               [
-                       'mode' => [
-                               [
-                                       'label' => '',
-                                       'value' => '',
-                               ],
-                               [
-                                       'label' => _x( 'List all organizers', 'mode option', 'wordcamporg' ),
-                                       'value' => 'all',
-                               ],
-                               [
-                                       'label' => _x( 'Choose organizers', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_organizer',
-                               ],
-                               [
-                                       'label' => _x( 'Choose teams', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_organizer_team',
-                               ],
-                       ],
-                       'sort' => array_merge(
-                               get_shared_definition( 'sort_title', 'option' ),
-                               get_shared_definition( 'sort_date', 'option' )
-                       ),
-               ]
-       );
-
-       if ( $type ) {
-               return empty( $options[ $type ] ) ? [] : $options[ $type ];
-       }
-
-       return $options;
-}
</del></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludessessionsphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/sessions.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/sessions.php   2019-05-10 20:20:52 UTC (rev 8778)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/sessions.php     2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,302 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-namespace WordCamp\Blocks\Sessions;
-use WordCamp\Blocks;
-use function WordCamp\Blocks\Shared\Components\{ render_post_list };
-use function WordCamp\Blocks\Shared\Definitions\{ get_shared_definitions, get_shared_definition };
-
-defined( 'WPINC' ) || die();
-
-/**
- * Register block types and enqueue scripts.
- *
- * @return void
- */
-function init() {
-       register_block_type(
-               'wordcamp/sessions',
-               [
-                       'attributes'      => get_attributes_schema(),
-                       'render_callback' => __NAMESPACE__ . '\render',
-                       'editor_script'   => 'wordcamp-blocks',
-                       'editor_style'    => 'wordcamp-blocks',
-                       'style'           => 'wordcamp-blocks',
-               ]
-       );
-}
-
-add_action( 'init', __NAMESPACE__ . '\init' );
-
-/**
- * Render the block on the front end.
- *
- * @param array $attributes Block attributes.
- *
- * @return string
- */
-function render( $attributes ) {
-       $defaults   = wp_list_pluck( get_attributes_schema(), 'default' );
-       $attributes = wp_parse_args( $attributes, $defaults );
-       $sessions   = get_session_posts( $attributes );
-
-       $speakers = [];
-       if ( ! empty( $sessions ) && true === $attributes['show_speaker'] ) {
-               $speakers = get_session_speakers( wp_list_pluck( $sessions, 'ID' ) );
-       }
-
-       $rendered_session_posts = [];
-
-       foreach ( $sessions as $session ) {
-               ob_start();
-               require Blocks\PLUGIN_DIR . 'view/session.php';
-               $rendered_session_posts[] = ob_get_clean();
-       }
-
-       $container_classes = [
-               'wordcamp-sessions-block',
-               sanitize_html_class( $attributes['className'] ),
-       ];
-
-       if ( ! empty( $attributes['align'] ) ) {
-               $container_classes[] = 'align' . sanitize_html_class( $attributes['align'] );
-       }
-
-       return render_post_list( $rendered_session_posts, $attributes['layout'], $attributes['grid_columns'], $container_classes );
-}
-
-/**
- * Add data to be used by the JS scripts in the block editor.
- *
- * @param array $data
- *
- * @return array
- */
-function add_script_data( array $data ) {
-       $data['sessions'] = [
-               'schema'  => get_attributes_schema(),
-               'options' => get_options(),
-       ];
-
-       return $data;
-}
-
-add_filter( 'wordcamp_blocks_script_data', __NAMESPACE__ . '\add_script_data' );
-
-/**
- * Get the schema for the block's attributes.
- *
- * @return array
- */
-function get_attributes_schema() {
-       $schema = array_merge(
-               get_shared_definitions(
-                       [
-                               'content',
-                               'grid_columns',
-                               'item_ids',
-                               'layout',
-                       ],
-                       'attribute'
-               ),
-               [
-                       'align'                => get_shared_definition( 'align_block', 'attribute' ),
-                       'className'            => get_shared_definition( 'string_empty', 'attribute' ),
-                       'featured_image_width' => get_shared_definition( 'image_size', 'attribute' ),
-                       'image_align'          => get_shared_definition( 'align_image', 'attribute' ),
-                       'mode'                 => [
-                               'type'    => 'string',
-                               'enum'    => wp_list_pluck( get_options( 'mode' ), 'value' ),
-                               'default' => '',
-                       ],
-                       'show_category'        => get_shared_definition( 'boolean_false', 'attribute' ),
-                       'show_images'          => get_shared_definition( 'boolean_true', 'attribute' ),
-                       'show_meta'            => get_shared_definition( 'boolean_false', 'attribute' ),
-                       'show_speaker'         => get_shared_definition( 'boolean_false', 'attribute' ),
-                       'sort'                 => [
-                               'type'    => 'string',
-                               'enum'    => wp_list_pluck( get_options( 'sort' ), 'value' ),
-                               'default' => 'session_time',
-                       ],
-               ]
-       );
-
-       return $schema;
-}
-
-/**
- * Get the label/value pairs for all options or a specific type.
- *
- * @param string $type
- *
- * @return array
- */
-function get_options( $type = '' ) {
-       $options = array_merge(
-               get_shared_definitions(
-                       [
-                               'align_block',
-                               'align_image',
-                               'content',
-                               'layout',
-                       ],
-                       'option'
-               ),
-               [
-                       'mode' => [
-                               [
-                                       'label' => '',
-                                       'value' => '',
-                               ],
-                               [
-                                       'label' => _x( 'List all sessions', 'mode option', 'wordcamporg' ),
-                                       'value' => 'all',
-                               ],
-                               [
-                                       'label' => _x( 'Choose sessions', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_session',
-                               ],
-                               [
-                                       'label' => _x( 'Choose tracks', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_track',
-                               ],
-                               [
-                                       'label' => _x( 'Choose session categories', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_session_category',
-                               ],
-                       ],
-                       'sort' => array_merge(
-                               [
-                                       [
-                                               'label' => _x( 'Day and Time', 'sort option', 'wordcamporg' ),
-                                               'value' => 'session_time',
-                                       ],
-                               ],
-                               get_shared_definition( 'sort_title', 'option' ),
-                               get_shared_definition( 'sort_date', 'option' )
-                       ),
-               ]
-       );
-
-       if ( $type ) {
-               if ( ! empty( $options[ $type ] ) ) {
-                       return $options[ $type ];
-               } else {
-                       return [];
-               }
-       }
-
-       return $options;
-}
-
-/**
- * Get the posts to display in the block.
- *
- * @param array $attributes
- *
- * @return array
- */
-function get_session_posts( array $attributes ) {
-       if ( empty( $attributes['mode'] ) ) {
-               return [];
-       }
-
-       $post_args = [
-               'post_type'      => 'wcb_session',
-               'post_status'    => 'publish',
-               'posts_per_page' => -1,
-               'meta_query'     => [
-                       'relation' => 'AND',
-                       [
-                               'relation' => 'OR',
-                               [
-                                       'key'     => '_wcpt_session_type',
-                                       'value'   => 'session',
-                                       'compare' => '=',
-                               ],
-                               [
-                                       'key'     => '_wcpt_session_type',
-                                       'value'   => '',
-                                       'compare' => 'NOT EXISTS',
-                               ],
-                       ],
-               ],
-       ];
-
-       switch ( $attributes['sort'] ) {
-               case 'session_time':
-                       $post_args['meta_key'] = '_wcpt_session_time';
-                       $post_args['orderby']  = 'meta_value_num title';
-                       $post_args['order']    = 'asc';
-                       break;
-
-               case 'title_asc':
-               case 'title_desc':
-               case 'date_desc':
-               case 'date_asc':
-                       $sort = explode( '_', $attributes['sort'] );
-
-                       if ( 2 === count( $sort ) ) {
-                               $post_args['orderby'] = $sort[0];
-                               $post_args['order']   = $sort[1];
-                       }
-                       break;
-       }
-
-       switch ( $attributes['mode'] ) {
-               case 'wcb_session':
-                       $post_args['post__in'] = $attributes['item_ids'];
-                       break;
-
-               case 'wcb_track':
-               case 'wcb_session_category':
-                       $post_args['tax_query'] = [
-                               [
-                                       'taxonomy' => $attributes['mode'],
-                                       'field'    => 'id',
-                                       'terms'    => $attributes['item_ids'],
-                               ],
-                       ];
-                       break;
-       }
-
-       return get_posts( $post_args );
-}
-
-/**
- * Get speaker posts grouped by session.
- *
- * @param array $session_ids
- *
- * @return array
- */
-function get_session_speakers( array $session_ids ) {
-       $speakers_by_session = [];
-
-       $session_args = [
-               'post_type'      => 'wcb_session',
-               'post_status'    => 'publish',
-               'posts_per_page' => -1,
-               'post__in'       => $session_ids,
-       ];
-
-       $session_posts = get_posts( $session_args );
-
-       foreach ( $session_posts as $session ) {
-               $speaker_ids = get_post_meta( $session->ID, '_wcpt_speaker_id', false );
-
-               if ( ! empty( $speaker_ids ) ) {
-                       $speaker_args = [
-                               'post_type'      => 'wcb_speaker',
-                               'post_status'    => 'publish',
-                               'posts_per_page' => -1,
-                               'post__in'       => $speaker_ids,
-                               'orderby'        => 'post__in',
-                               'order'          => 'ASC',
-                       ];
-
-                       $speakers_by_session[ $session->ID ] = get_posts( $speaker_args );
-               }
-       }
-
-       return $speakers_by_session;
-}
</del></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesspeakersphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/speakers.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/speakers.php   2019-05-10 20:20:52 UTC (rev 8778)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/speakers.php     2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,260 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-namespace WordCamp\Blocks\Speakers;
-use WordCamp\Blocks;
-use function WordCamp\Blocks\Shared\Components\{ render_post_list };
-use function WordCamp\Blocks\Shared\Definitions\{ get_shared_definitions, get_shared_definition };
-
-defined( 'WPINC' ) || die();
-
-/**
- * Register block types and enqueue scripts.
- *
- * @return void
- */
-function init() {
-       register_block_type(
-               'wordcamp/speakers',
-               [
-                       'attributes'      => get_attributes_schema(),
-                       'render_callback' => __NAMESPACE__ . '\render',
-                       'editor_script'   => 'wordcamp-blocks',
-                       'editor_style'    => 'wordcamp-blocks',
-                       'style'           => 'wordcamp-blocks',
-               ]
-       );
-}
-
-add_action( 'init', __NAMESPACE__ . '\init' );
-
-/**
- * Render the block on the front end.
- *
- * @param array $attributes Block attributes.
- *
- * @return string
- */
-function render( $attributes ) {
-       $defaults   = wp_list_pluck( get_attributes_schema(), 'default' );
-       $attributes = wp_parse_args( $attributes, $defaults );
-       $speakers   = get_speaker_posts( $attributes );
-
-       $sessions = [];
-       if ( ! empty( $speakers ) && true === $attributes['show_session'] ) {
-               $sessions = get_speaker_sessions( wp_list_pluck( $speakers, 'ID' ) );
-       }
-
-       $rendered_speaker_posts = [];
-
-       foreach ( $speakers as $speaker ) {
-               ob_start();
-               require Blocks\PLUGIN_DIR . 'view/speaker.php';
-               $rendered_speaker_posts[] = ob_get_clean();
-       }
-
-       $container_classes = [
-               'wordcamp-speakers-block',
-               sanitize_html_class( $attributes['className'] ),
-       ];
-
-       if ( ! empty( $attributes['align'] ) ) {
-               $container_classes[] = 'align' . sanitize_html_class( $attributes['align'] );
-       }
-
-       return render_post_list( $rendered_speaker_posts, $attributes['layout'], $attributes['grid_columns'], $container_classes );
-}
-
-/**
- * Add data to be used by the JS scripts in the block editor.
- *
- * @param array $data
- *
- * @return array
- */
-function add_script_data( array $data ) {
-       $data['speakers'] = [
-               'schema'  => get_attributes_schema(),
-               'options' => get_options(),
-       ];
-
-       return $data;
-}
-
-add_filter( 'wordcamp_blocks_script_data', __NAMESPACE__ . '\add_script_data' );
-
-/**
- * Get the posts to display in the block.
- *
- * @param array $attributes
- *
- * @return array
- */
-function get_speaker_posts( array $attributes ) {
-       if ( empty( $attributes['mode'] ) ) {
-               return [];
-       }
-
-       $post_args = [
-               'post_type'      => 'wcb_speaker',
-               'post_status'    => 'publish',
-               'posts_per_page' => -1,
-       ];
-
-       $sort = explode( '_', $attributes['sort'] );
-
-       if ( 2 === count( $sort ) ) {
-               $post_args['orderby'] = $sort[0];
-               $post_args['order']   = $sort[1];
-       }
-
-       switch ( $attributes['mode'] ) {
-               case 'wcb_speaker':
-                       $post_args['post__in'] = $attributes['item_ids'];
-                       break;
-
-               case 'wcb_speaker_group':
-                       $post_args['tax_query'] = [
-                               [
-                                       'taxonomy' => $attributes['mode'],
-                                       'field'    => 'id',
-                                       'terms'    => $attributes['item_ids'],
-                               ],
-                       ];
-                       break;
-       }
-
-       return get_posts( $post_args );
-}
-
-/**
- * Get session posts grouped by speaker.
- *
- * @param array $speaker_ids
- *
- * @return array
- */
-function get_speaker_sessions( array $speaker_ids ) {
-       $sessions_by_speaker = [];
-
-       $session_args = [
-               'post_type'      => 'wcb_session',
-               'post_status'    => 'publish',
-               'posts_per_page' => -1,
-               'meta_key'       => '_wcpt_session_time',
-               'orderby'        => 'meta_value_num',
-       ];
-
-       $session_posts = get_posts( $session_args );
-
-       foreach ( $session_posts as $session ) {
-               $session_speaker_ids = get_post_meta( $session->ID, '_wcpt_speaker_id', false );
-
-               foreach ( $session_speaker_ids as $speaker_id ) {
-                       $speaker_id = absint( $speaker_id );
-
-                       if ( in_array( $speaker_id, $speaker_ids, true ) ) {
-                               if ( ! isset( $sessions_by_speaker[ $speaker_id ] ) ) {
-                                       $sessions_by_speaker[ $speaker_id ] = [];
-                               }
-
-                               $sessions_by_speaker[ $speaker_id ][] = $session;
-                       }
-               }
-       }
-
-       return $sessions_by_speaker;
-}
-
-/**
- * Get the schema for the block's attributes.
- *
- * @return array
- */
-function get_attributes_schema() {
-       $schema = array_merge(
-               get_shared_definitions(
-                       [
-                               'content',
-                               'grid_columns',
-                               'item_ids',
-                               'layout',
-                       ],
-                       'attribute'
-               ),
-               [
-                       'align'        => get_shared_definition( 'align_block', 'attribute' ),
-                       'avatar_align' => get_shared_definition( 'align_image', 'attribute' ),
-                       'avatar_size'  => get_shared_definition( 'image_size_avatar', 'attribute' ),
-                       'className'    => get_shared_definition( 'string_empty', 'attribute' ),
-                       'mode'         => [
-                               'type'    => 'string',
-                               'enum'    => wp_list_pluck( get_options( 'mode' ), 'value' ),
-                               'default' => '',
-                       ],
-                       'show_avatars' => get_shared_definition( 'boolean_true', 'attribute' ),
-                       'show_session' => get_shared_definition( 'boolean_false', 'attribute' ),
-                       'sort'         => [
-                               'type'    => 'string',
-                               'enum'    => wp_list_pluck( get_options( 'sort' ), 'value' ),
-                               'default' => 'title_asc',
-                       ],
-               ]
-       );
-
-       return $schema;
-}
-
-/**
- * Get the label/value pairs for all options or a specific type.
- *
- * @param string $type
- *
- * @return array
- */
-function get_options( $type = '' ) {
-       $options = array_merge(
-               get_shared_definitions(
-                       [
-                               'align_block',
-                               'align_image',
-                               'content',
-                               'layout',
-                       ],
-                       'option'
-               ),
-               [
-                       'mode' => [
-                               [
-                                       'label' => '',
-                                       'value' => '',
-                               ],
-                               [
-                                       'label' => _x( 'List all speakers', 'mode option', 'wordcamporg' ),
-                                       'value' => 'all',
-                               ],
-                               [
-                                       'label' => _x( 'Choose speakers', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_speaker',
-                               ],
-                               [
-                                       'label' => _x( 'Choose groups', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_speaker_group',
-                               ],
-                       ],
-                       'sort' => array_merge(
-                               get_shared_definition( 'sort_title', 'option' ),
-                               get_shared_definition( 'sort_date', 'option' )
-                       ),
-               ]
-       );
-
-       if ( $type ) {
-               if ( ! empty( $options[ $type ] ) ) {
-                       return $options[ $type ];
-               } else {
-                       return [];
-               }
-       }
-
-       return $options;
-}
</del></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludessponsorsphp"></a>
<div class="delfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Deleted: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/sponsors.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/sponsors.php   2019-05-10 20:20:52 UTC (rev 8778)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/sponsors.php     2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,214 +0,0 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
-
-namespace WordCamp\Blocks\Sponsors;
-use WordCamp\Blocks;
-use function WordCamp\Blocks\Shared\Components\{ render_post_list };
-use function WordCamp\Blocks\Shared\Definitions\{ get_shared_definitions, get_shared_definition };
-
-defined( 'WPINC' ) || die();
-
-/**
- * Register sponsor block and enqueue scripts.
- */
-function init() {
-       register_block_type(
-               'wordcamp/sponsors',
-               [
-                       'attributes'      => get_attributes_schema(),
-                       'render_callback' => __NAMESPACE__ . '\render',
-                       'editor_script'   => 'wordcamp-blocks',
-                       'editor_style'    => 'wordcamp-blocks',
-                       'style'           => 'wordcamp-blocks',
-               ]
-       );
-}
-
-add_action( 'init', __NAMESPACE__ . '\init' );
-
-/**
- * Renders content of Sponsor block based on attributes.
- *
- * @param array $attributes
- *
- * @return false|string
- */
-function render( $attributes ) {
-       $defaults   = wp_list_pluck( get_attributes_schema(), 'default' );
-       $attributes = wp_parse_args( $attributes, $defaults );
-
-       $sponsors               = get_sponsor_posts( $attributes );
-       $rendered_sponsor_posts = [];
-
-       foreach ( $sponsors as $sponsor ) {
-               ob_start();
-               require Blocks\PLUGIN_DIR . 'view/sponsor.php';
-               $rendered_sponsor_posts[] = ob_get_clean();
-       }
-
-       $container_classes = [
-               'wordcamp-sponsors-block',
-               sanitize_html_class( $attributes['className'] ),
-       ];
-
-       if ( ! empty( $attributes['align'] ) ) {
-               $container_classes[] = 'align' . sanitize_html_class( $attributes['align'] );
-       }
-
-       return render_post_list( $rendered_sponsor_posts, $attributes['layout'], $attributes['grid_columns'], $container_classes );
-}
-
-/**
- * Add data to be used by the JS scripts in the block editor.
- *
- * @param array $data
- *
- * @return array
- */
-function add_script_data( array $data ) {
-       $data['sponsors'] = [
-               'schema'  => get_attributes_schema(),
-               'options' => get_options(),
-       ];
-
-       return $data;
-}
-
-add_filter( 'wordcamp_blocks_script_data', __NAMESPACE__ . '\add_script_data' );
-
-/**
- * Return sponsor posts what will rendered based on attributes.
- *
- * @param array $attributes
- *
- * @return array
- */
-function get_sponsor_posts( $attributes ) {
-       if ( empty( $attributes['mode'] ) ) {
-               return [];
-       }
-
-       $post_args = array(
-               'post_type'      => 'wcb_sponsor',
-               'post_status'    => 'publish',
-               'posts_per_page' => - 1,
-       );
-
-       $sort = explode( '_', $attributes['sort'] );
-
-       if ( 2 === count( $sort ) ) {
-               $post_args['orderby'] = $sort[0];
-               $post_args['order']   = $sort[1];
-       }
-
-       switch ( $attributes['mode'] ) {
-               case 'wcb_sponsor':
-                       $post_args['post__in'] = $attributes['item_ids'];
-                       break;
-
-               case 'wcb_sponsor_level':
-                       $post_args['tax_query'] = [
-                               [
-                                       'taxonomy' => $attributes['mode'],
-                                       'field'    => 'id',
-                                       'terms'    => $attributes['item_ids'],
-                               ],
-                       ];
-                       break;
-       }
-
-       return get_posts( $post_args );
-}
-
-/**
- * Get attribute schema for Sponsor block
- *
- * @return array
- */
-function get_attributes_schema() {
-       $schema = array_merge(
-               get_shared_definitions(
-                       [
-                               'content',
-                               'grid_columns',
-                               'item_ids',
-                               'layout',
-                       ],
-                       'attribute'
-               ),
-               [
-                       'align'                => get_shared_definition( 'align_block', 'attribute' ),
-                       'className'            => get_shared_definition( 'string_empty', 'attribute' ),
-                       'featured_image_width' => get_shared_definition( 'image_size', 'attribute', [ 'default' => 600 ] ),
-                       'image_align'          => get_shared_definition( 'align_image', 'attribute' ),
-                       'mode'                 => [
-                               'type'    => 'string',
-                               'enum'    => wp_list_pluck( get_options( 'mode' ), 'value' ),
-                               'default' => '',
-                       ],
-                       'show_logo'            => get_shared_definition( 'boolean_true', 'attribute' ),
-                       'show_name'            => get_shared_definition( 'boolean_true', 'attribute' ),
-                       'sort'                 => [
-                               'type'    => 'string',
-                               'enum'    => wp_list_pluck( get_options( 'sort' ), 'value' ),
-                               'default' => 'title_asc',
-                       ],
-               ]
-       );
-
-       return $schema;
-}
-
-/**
- * Get the label/value pairs for all options or a specific type.
- *
- * @param string $type
- *
- * @return array
- */
-function get_options( $type = '' ) {
-       $options = array_merge(
-               get_shared_definitions(
-                       [
-                               'align_block',
-                               'align_image',
-                               'content',
-                               'layout',
-                       ],
-                       'option'
-               ),
-               [
-                       'mode' => [
-                               [
-                                       'label' => '',
-                                       'value' => '',
-                               ],
-                               [
-                                       'label' => _x( 'List all sponsors', 'mode option', 'wordcamporg' ),
-                                       'value' => 'all',
-                               ],
-                               [
-                                       'label' => _x( 'Choose sponsors', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_sponsor',
-                               ],
-                               [
-                                       'label' => _x( 'Choose sponsor level', 'mode option', 'wordcamporg' ),
-                                       'value' => 'wcb_sponsor_level',
-                               ],
-                       ],
-                       'sort' => array_merge(
-                               get_shared_definition( 'sort_title', 'option' ),
-                               get_shared_definition( 'sort_date', 'option' )
-                       ),
-               ]
-       );
-
-       if ( $type ) {
-               if ( ! empty( $options[ $type ] ) ) {
-                       return $options[ $type ];
-               } else {
-                       return [];
-               }
-       }
-
-       return $options;
-}
</del></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksincludesutilitiescontentphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/utilities/content.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/utilities/content.php                          (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/includes/utilities/content.php    2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,91 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Utilities;
+
+use WP_Post;
+
+defined( 'WPINC' ) || die();
+
+/**
+ * Get the full content of a post, ignoring more and noteaser tags and pagination.
+ *
+ * This works similarly to `the_content`, including applying filters, but:
+ * - It skips all of the logic in `get_the_content` that deals with tags like <!--more--> and
+ *   <!--noteaser-->, as well as pagination and global state variables like `$page`, `$more`, and
+ *   `$multipage`.
+ * - It returns a string of content, rather than echoing it.
+ *
+ * @param int|WP_Post $post Post ID or post object.
+ *
+ * @return string The full, filtered post content.
+ */
+function get_all_the_content( $post ) {
+       $post = get_post( $post );
+
+       $content = $post->post_content;
+
+       /** This filter is documented in wp-includes/post-template.php */
+       $content = apply_filters( 'the_content', $content );
+       $content = str_replace( ']]>', ']]&gt;', $content );
+
+       return $content;
+}
+
+/**
+ * Convert an array of strings into one string that is a punctuated, human-readable list.
+ *
+ * @param array $array
+ *
+ * @return string
+ */
+function array_to_human_readable_list( array $array ) {
+       $count = count( $array );
+       $list  = '';
+
+       switch ( $count ) {
+               case 0:
+                       break;
+               case 1:
+                       $list = array_shift( $array );
+                       break;
+               case 2:
+                       $list = sprintf(
+                               /* translators: Each %s is a person's name. */
+                               _x( '%1$s and %2$s', 'list of two items', 'wordcamporg' ),
+                               array_shift( $array ),
+                               array_shift( $array )
+                       );
+                       break;
+               default:
+                       /* translators: used between list items, there is a space after the comma */
+                       $item_separator = esc_html__( ', ', 'wordcamporg' );
+
+                       $initial = array_slice( $array, 0, $count - 1 );
+                       $initial = implode( $item_separator, $initial ) . $item_separator;
+                       $last    = array_slice( $array, -1, 1 )[0];
+
+                       $list = sprintf(
+                               /* translators: 1: A list of items. 2: The last item in a list of items. */
+                               _x( '%1$s and %2$s', 'list of three or more items', 'wordcamporg' ),
+                               $initial,
+                               $last
+                       );
+                       break;
+       }
+
+       return $list;
+}
+
+/**
+ * Convert an array of class names into a space-separated string for use in an HTML attribute.
+ *
+ * @param array $classes
+ *
+ * @return string
+ */
+function render_class_string( array $classes ) {
+       $classes = array_map( 'sanitize_html_class', $classes );
+       $classes = array_filter( $classes );
+       $classes = array_unique( $classes );
+
+       return implode( ' ', $classes );
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksindexjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/index.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/index.js                          (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/index.js    2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,11 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+import * as organizers from './organizers';
+import * as sessions   from './sessions';
+import * as speakers   from './speakers';
+import * as sponsors   from './sponsors';
+
+export const BLOCKS = [
+       organizers,
+       sessions,
+       speakers,
+       sponsors,
+];
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizersblockcontentjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/block-content.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/block-content.js                               (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/block-content.js 2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,115 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
+/**
+ * WordPress dependencies
+ */
+const { Component } = wp.element;
+
+/**
+ * Internal dependencies
+ */
+import { AvatarImage }                                from '../../components/image';
+import { BlockNoContent, ItemTitle, ItemHTMLContent } from '../../components/block-content';
+import { PostList }                                   from '../../components/post-list';
+import { filterEntities }                             from '../../data';
+
+/**
+ * Component for displaying the block content.
+ */
+export class BlockContent extends Component {
+       /**
+        * Run additional operations during component initialization.
+        *
+        * @param {Object} props
+        */
+       constructor( props ) {
+               super( props );
+
+               this.getFilteredPosts = this.getFilteredPosts.bind( this );
+       }
+
+       /**
+        * Filter and sort the content that will be rendered.
+        *
+        * @returns {Array}
+        */
+       getFilteredPosts() {
+               const { attributes, entities } = this.props;
+               const { wcb_organizer: posts } = entities;
+               const { mode, item_ids, sort } = attributes;
+
+               const args = {};
+
+               if ( Array.isArray( item_ids ) && item_ids.length > 0 ) {
+                       args.filter = [
+                               {
+                                       fieldName  : mode === 'wcb_organizer' ? 'id' : 'organizer_team',
+                                       fieldValue : item_ids,
+                               },
+                       ];
+               }
+
+               args.sort = sort;
+
+               return filterEntities( posts, args );
+       }
+
+       /**
+        * Render the block content.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { attributes } = this.props;
+               const { show_avatars, avatar_size, avatar_align, content } = attributes;
+
+               const posts     = this.getFilteredPosts();
+               const isLoading = ! Array.isArray( posts );
+               const hasPosts  = ! isLoading && posts.length > 0;
+
+               if ( isLoading || ! hasPosts ) {
+                       return (
+                               <BlockNoContent loading={ isLoading } />
+                       );
+               }
+
+               return (
+                       <PostList
+                               { ...this.props }
+                               className="wordcamp-organizers-block"
+                       >
+                               { posts.map( ( post ) => /* Note that organizer posts are not 'public', so there are no permalinks. */
+                                       <div
+                                               key={ post.slug }
+                                               className={ classnames( 'wordcamp-organizer', 'wordcamp-organizer-' + post.slug.trim() ) }
+                                       >
+                                               <ItemTitle
+                                                       className="wordcamp-organizer-title"
+                                                       headingLevel={ 3 }
+                                                       title={ post.title.rendered.trim() }
+                                               />
+
+                                               { show_avatars &&
+                                                       <AvatarImage
+                                                               className={ classnames( 'align-' + avatar_align ) }
+                                                               name={ post.title.rendered.trim() || '' }
+                                                               size={ avatar_size }
+                                                               url={ post.avatar_urls[ '24' ] }
+                                                       />
+                                               }
+
+                                               { ( 'none' !== content ) &&
+                                                       <ItemHTMLContent
+                                                               className={ classnames( 'wordcamp-organizer-content-' + content ) }
+                                                               content={  'full' === content ? post.content.rendered.trim() : post.excerpt.rendered.trim() }
+                                                       />
+                                               }
+                                       </div>
+                               ) }
+                       </PostList>
+               );
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizersblockcontrolsjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/block-controls.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/block-controls.js                              (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/block-controls.js        2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,93 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
+/**
+ * WordPress dependencies
+ */
+const { Button, Placeholder } = wp.components;
+const { Component }           = wp.element;
+const { __ }                  = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { PlaceholderSpecificMode } from '../../components/block-controls';
+import { getOptionLabel }          from '../../components/item-select';
+import { BlockContent }            from './block-content';
+import { ContentSelect }           from './content-select';
+import { LABEL }                   from './index';
+
+/**
+ * Component for displaying a UI within the block.
+ */
+export class BlockControls extends Component {
+       /**
+        * Render the internal block UI.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { icon, attributes, setAttributes, blockData } = this.props;
+               const { mode } = attributes;
+               const { options } = blockData;
+
+               let output;
+
+               switch ( mode ) {
+                       case 'all' :
+                               output = (
+                                       <BlockContent { ...this.props } />
+                               );
+                               break;
+
+                       case 'wcb_organizer' :
+                       case 'wcb_organizer_team' :
+                               output = (
+                                       <PlaceholderSpecificMode
+                                               label={ getOptionLabel( mode, options.mode ) }
+                                               icon={ icon }
+                                               content={
+                                                       <BlockContent { ...this.props } />
+                                               }
+                                               placeholderChildren={
+                                                       <ContentSelect { ...this.props } />
+                                               }
+                                       />
+                               );
+                               break;
+
+                       default :
+                               output = (
+                                       <Placeholder
+                                               className={ classnames( 'wordcamp-block-edit-placeholder', 'wordcamp-block-edit-placeholder-no-mode' ) }
+                                               icon={ icon }
+                                               label={ LABEL }
+                                       >
+                                               <div className="wordcamp-block-edit-mode-option">
+                                                       <Button
+                                                               isDefault
+                                                               isLarge
+                                                               onClick={ () => {
+                                                                       setAttributes( { mode: 'all' } );
+                                                               } }
+                                                       >
+                                                               { getOptionLabel( 'all', options.mode ) }
+                                                       </Button>
+                                               </div>
+
+                                               <div className="wordcamp-block-edit-mode-option">
+                                                       <ContentSelect
+                                                               label={ __( 'Choose specific organizers or teams', 'wordcamporg' ) }
+                                                               { ...this.props }
+                                                       />
+                                               </div>
+                                       </Placeholder>
+                               );
+                               break;
+               }
+
+               return output;
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizerscontentselectjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/content-select.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/content-select.js                              (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/content-select.js        2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,124 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import { every, flatMap, includes } from 'lodash';
+
+/**
+ * WordPress dependencies
+ */
+const { Component } = wp.element;
+const { __ }        = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { buildOptions, ItemSelect, Option } from '../../components/item-select';
+
+/**
+ * Component for selecting posts/terms for populating the block content.
+ */
+export class ContentSelect extends Component {
+       /**
+        * Run additional operations during component initialization.
+        *
+        * @param {Object} props
+        */
+       constructor( props ) {
+               super( props );
+
+               this.buildSelectOptions    = this.buildSelectOptions.bind( this );
+               this.getCurrentSelectValue = this.getCurrentSelectValue.bind( this );
+               this.isLoading             = this.isLoading.bind( this );
+       }
+
+       /**
+        * Build or retrieve the options that will populate the Select dropdown.
+        *
+        * @return {Array}
+        */
+       buildSelectOptions() {
+               const { entities } = this.props;
+               const { wcb_organizer, wcb_organizer_team } = entities;
+
+               const optionGroups = [
+                       {
+                               entityType : 'post',
+                               type       : 'wcb_organizer',
+                               label      : __( 'Organizers', 'wordcamporg' ),
+                               items      : wcb_organizer,
+                       },
+                       {
+                               entityType : 'term',
+                               type       : 'wcb_organizer_team',
+                               label      : __( 'Teams', 'wordcamporg' ),
+                               items      : wcb_organizer_team,
+                       },
+               ];
+
+               return buildOptions( optionGroups );
+       }
+
+       /**
+        * Determine the currently selected options in the Select dropdown based on block attributes.
+        *
+        * @return {Array}
+        */
+       getCurrentSelectValue() {
+               const { attributes } = this.props;
+               const { mode, item_ids } = attributes;
+
+               const options = flatMap( this.buildSelectOptions(), ( group ) => {
+                       return group.options;
+               } );
+
+               let value = [];
+
+               if ( mode && item_ids.length ) {
+                       value = options.filter( ( option ) => {
+                               return mode === option.type && includes( item_ids, option.value );
+                       } );
+               }
+
+               return value;
+       }
+
+       /**
+        * Check if all of the entity groups have finished loading.
+        *
+        * @return {boolean}
+        */
+       isLoading() {
+               const { entities } = this.props;
+
+               return ! every( entities, ( value ) => {
+                       return Array.isArray( value );
+               } );
+       }
+
+       /**
+        * Render an ItemSelect component with block-specific settings.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { label, setAttributes } = this.props;
+
+               return (
+                       <ItemSelect
+                               className="wordcamp-organizers-select"
+                               label={ label }
+                               value={ this.getCurrentSelectValue() }
+                               onChange={ ( changed ) => setAttributes( changed ) }
+                               selectProps={ {
+                                       options           : this.buildSelectOptions(),
+                                       isLoading         : this.isLoading(),
+                                       formatOptionLabel : ( optionData ) => {
+                                               return (
+                                                       <Option { ...optionData } />
+                                               );
+                                       },
+                               } }
+                       />
+               );
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizerseditjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/edit.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/edit.js                                (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/edit.js  2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,68 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+const { withSelect }          = wp.data;
+const { Component, Fragment } = wp.element;
+
+/**
+ * Internal dependencies
+ */
+import { LayoutToolbar }     from '../../components/post-list';
+import { WC_BLOCKS_STORE }   from '../../data';
+import { BlockControls }     from './block-controls';
+import { InspectorControls } from './inspector-controls';
+import { ICON }              from './index';
+
+const blockData = window.WordCampBlocks.organizers || {};
+
+/**
+ * Top-level component for the editing UI for the block.
+ */
+class OrganizersEdit extends Component {
+       /**
+        * Render the block's editing UI.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { attributes, setAttributes }  = this.props;
+               const { mode, layout }               = attributes;
+               const { layout: layoutOptions = {} } = blockData.options;
+
+               return (
+                       <Fragment>
+                               <BlockControls
+                                       icon={ ICON }
+                                       { ...this.props }
+                               />
+
+                               { '' !== mode &&
+                                       <Fragment>
+                                               <InspectorControls { ...this.props } />
+                                               <LayoutToolbar
+                                                       layout={ layout }
+                                                       options={ layoutOptions }
+                                                       setAttributes={ setAttributes }
+                                               />
+                                       </Fragment>
+                               }
+                       </Fragment>
+               );
+       }
+}
+
+const organizerSelect = ( select ) => {
+       const { getEntities } = select( WC_BLOCKS_STORE );
+
+       const entities = {
+               wcb_organizer      : getEntities( 'postType', 'wcb_organizer', { _embed: true } ),
+               wcb_organizer_team : getEntities( 'taxonomy', 'wcb_organizer_team' ),
+       };
+
+       return {
+               blockData,
+               entities,
+       };
+};
+
+export const Edit = withSelect( organizerSelect )( OrganizersEdit );
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizersindexjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/index.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/index.js                               (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/index.js 2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,27 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+const { __ } = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { Edit } from './edit';
+
+export const NAME  = 'wordcamp/organizers';
+export const LABEL = __( 'Organizers', 'wordcamporg' );
+export const ICON  = 'groups';
+
+const supports = {
+       align: [ 'wide', 'full' ],
+};
+
+export const SETTINGS = {
+       title       : __( 'Organizers', 'wordcamporg' ),
+       description : __( 'Add a list of organizers.', 'wordcamporg' ),
+       icon        : ICON,
+       category    : 'wordcamp',
+       supports    : supports,
+       edit        : Edit,
+       save        : () => null,
+};
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksorganizersinspectorcontrolsjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/inspector-controls.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/inspector-controls.js                          (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/organizers/inspector-controls.js    2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,92 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+const { InspectorControls: CoreInspectorControlsContainer } = wp.blockEditor;
+const { PanelBody, PanelRow, SelectControl, ToggleControl } = wp.components;
+const { Component }                                         = wp.element;
+const { __ }                                                = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { avatarSizePresets, ImageInspectorPanel } from '../../components/image';
+import { GridInspectorPanel }                     from '../../components/post-list';
+
+const DEFAULT_SCHEMA = {
+       grid_columns: {
+               default : 2,
+               minimum : 2,
+               maximum : 4,
+       },
+
+       avatar_size: {
+               default : 150,
+               minimum : 25,
+               maximum : 600,
+       },
+};
+
+const DEFAULT_OPTIONS = {
+       align   : {},
+       content : {},
+       sort    : {},
+};
+
+/**
+ * Component for block controls that appear in the Inspector Panel.
+ */
+export class InspectorControls extends Component {
+       /**
+        * Render the controls.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { attributes, setAttributes, blockData }                   = this.props;
+               const { show_avatars, avatar_size, avatar_align, content, sort } = attributes;
+               const { schema = DEFAULT_SCHEMA, options = DEFAULT_OPTIONS }     = blockData;
+
+               return (
+                       <CoreInspectorControlsContainer>
+                               <GridInspectorPanel
+                                       { ...this.props }
+                               />
+
+                               <ImageInspectorPanel
+                                       title={ __( 'Avatar Settings', 'wordcamporg' ) }
+                                       show={ show_avatars }
+                                       onChangeShow={ ( value ) => setAttributes( { show_avatars: value } ) }
+                                       size={ avatar_size }
+                                       onChangeSize={ ( value ) => setAttributes( { avatar_size: value } ) }
+                                       sizeSchema={ schema.avatar_size }
+                                       sizePresets={ avatarSizePresets }
+                                       align={ avatar_align }
+                                       onChangeAlign={ ( value ) => setAttributes( { avatar_align: value } ) }
+                                       alignOptions={ options.align_image }
+                               />
+
+                               <PanelBody title={ __( 'Content Settings', 'wordcamporg' ) } initialOpen={ false }>
+                                       <PanelRow>
+                                               <SelectControl
+                                                       label={ __( 'Biography Length', 'wordcamporg' ) }
+                                                       value={ content }
+                                                       options={ options.content }
+                                                       onChange={ ( value ) => setAttributes( { content: value } ) }
+                                               />
+                                       </PanelRow>
+                               </PanelBody>
+
+                               <PanelBody title={ __( 'Sorting & Filtering', 'wordcamporg' ) } initialOpen={ false }>
+                                       <PanelRow>
+                                               <SelectControl
+                                                       label={ __( 'Sort by', 'wordcamporg' ) }
+                                                       value={ sort }
+                                                       options={ options.sort }
+                                                       onChange={ ( value ) => setAttributes( { sort: value } ) }
+                                               />
+                                       </PanelRow>
+                               </PanelBody>
+                       </CoreInspectorControlsContainer>
+               );
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionsblockcontentjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/block-content.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/block-content.js                         (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/block-content.js   2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,311 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import { get }    from 'lodash';
+import classnames from 'classnames';
+
+/**
+ * WordPress dependencies
+ */
+const { Component } = wp.element;
+const { __ }        = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { ItemTitle, ItemHTMLContent, ItemPermalink, BlockNoContent } from '../../components/block-content';
+import { FeaturedImage }                                             from '../../components/image';
+import { PostList }                                                  from '../../components/post-list';
+import { filterEntities }                                            from '../../data';
+import { tokenSplit, arrayTokenReplace, intersperse, listify }       from '../../i18n';
+
+/**
+ * Component for the section of each session post that displays information about the session's speakers.
+ *
+ * @param {Object} session
+ *
+ * @return {Element}
+ */
+function SessionSpeakers( { session } ) {
+       let speakerData = get( session, '_embedded.speakers', [] );
+
+       speakerData = speakerData.map( ( speaker ) => {
+               if ( speaker.hasOwnProperty( 'code' ) ) {
+                       // The wporg username given for this speaker returned an error.
+                       return null;
+               }
+
+               const { link }     = speaker;
+               let { title = {} } = speaker;
+
+               title = title.rendered.trim() || __( 'Unnamed', 'wordcamporg' );
+
+               if ( ! link ) {
+                       return title;
+               }
+
+               return (
+                       <a key={ link } href={ link }>
+                               { title }
+                       </a>
+               );
+       } );
+
+       const speakers = arrayTokenReplace(
+               /* translators: %s is a list of names. */
+               tokenSplit( __( 'Presented by %s', 'wordcamporg' ) ),
+               [ listify( speakerData ) ]
+       );
+
+       return (
+               <div className="wordcamp-item-meta wordcamp-session-speakers">
+                       { speakers }
+               </div>
+       );
+}
+
+/**
+ * Component for the section of each session post that displays metadata including date, time, and location (track).
+ *
+ * @param {Object} session
+ *
+ * @return {Element}
+ */
+function SessionMeta( { session } ) {
+       let metaContent;
+       const terms = get( session, '_embedded[\'wp:term\']', [] ).flat();
+
+       if ( session.session_track.length ) {
+               const [ firstTrack ] = terms.filter( ( term ) => {
+                       return 'wcb_track' === term.taxonomy;
+               } );
+
+               metaContent = arrayTokenReplace(
+                       /* translators: 1: A date; 2: A time; 3: A location; */
+                       tokenSplit( __( '%1$s at %2$s in %3$s', 'wordcamporg' ) ),
+                       [
+                               session.session_date_time.date,
+                               session.session_date_time.time,
+                               (
+                                       <span
+                                               key={ firstTrack.id }
+                                               className={ classnames( 'wordcamp-session-track', 'wordcamp-session-track-' + firstTrack.slug.trim() ) }
+                                       >
+                                               { firstTrack.name.trim() }
+                                       </span>
+                               ),
+                       ]
+               );
+       } else {
+               metaContent = arrayTokenReplace(
+                       /* translators: 1: A date; 2: A time; */
+                       tokenSplit( __( '%1$s at %2$s', 'wordcamporg' ) ),
+                       [
+                               session.session_date_time.date,
+                               session.session_date_time.time,
+                       ]
+               );
+       }
+
+       return (
+               <div className="wordcamp-session-time-location">
+                       { metaContent }
+               </div>
+       );
+}
+
+/**
+ * Component for the section of each session post that displays a session's assigned categories.
+ *
+ * @param {Object} session
+ *
+ * @return {Element}
+ */
+function SessionCategory( { session } ) {
+       let categoryContent;
+       const terms = get( session, '_embedded[\'wp:term\']', [] ).flat();
+
+       if ( session.session_category.length ) {
+               /* translators: used between list items, there is a space after the comma */
+               const separator = __( ', ', 'wordcamporg' );
+               const categories = terms
+                       .filter( ( term ) => {
+                               return 'wcb_session_category' === term.taxonomy;
+                       } )
+                       .map( ( term ) => {
+                               return (
+                                       <span
+                                               key={ term.slug }
+                                               className={ classnames( 'wordcamp-session-category', 'wordcamp-session-category-' + term.slug ) }
+                                       >
+                                               { term.name.trim() }
+                                       </span>
+                               );
+                       } );
+
+               categoryContent = intersperse( categories, separator );
+       }
+
+       return (
+               <div className="wordcamp-session-categories">
+                       { categoryContent }
+               </div>
+       );
+}
+
+/**
+ * Component for displaying the block content.
+ */
+export class BlockContent extends Component {
+       /**
+        * Run additional operations during component initialization.
+        *
+        * @param {Object} props
+        */
+       constructor( props ) {
+               super( props );
+
+               this.getFilteredPosts = this.getFilteredPosts.bind( this );
+       }
+
+       /**
+        * Determine if a session has related speaker data.
+        *
+        * @param {Object} session
+        *
+        * @return {boolean}
+        */
+       static hasSpeaker( session ) {
+               return get( session, '_embedded.speakers', [] ).length > 0;
+       }
+
+       /**
+        * Filter and sort the content that will be rendered.
+        *
+        * @returns {Array}
+        */
+       getFilteredPosts() {
+               const { attributes, entities } = this.props;
+               const { wcb_session: posts } = entities;
+               const { mode, item_ids, sort } = attributes;
+
+               const args = {};
+
+               if ( Array.isArray( item_ids ) && item_ids.length > 0 ) {
+                       let fieldName;
+
+                       switch ( mode ) {
+                               case 'wcb_session':
+                                       fieldName = 'id';
+                                       break;
+                               case 'wcb_track':
+                                       fieldName = 'session_track';
+                                       break;
+                               case 'wcb_session_category':
+                                       fieldName = 'session_category';
+                                       break;
+                       }
+
+                       args.filter  = [
+                               {
+                                       fieldName  : fieldName,
+                                       fieldValue : item_ids,
+                               },
+                       ];
+               }
+
+               if ( 'session_time' !== sort ) {
+                       args.sort = sort;
+               }
+
+               let filtered = filterEntities( posts, args );
+
+               if ( Array.isArray( filtered ) && 'session_time' === sort ) {
+                       filtered = filtered.sort( ( a, b ) => {
+                               return Number( a.meta._wcpt_session_time ) - Number( b.meta._wcpt_session_time );
+                       } );
+               }
+
+               return filtered;
+       }
+
+       /**
+        * Render the block content.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { attributes } = this.props;
+               const { show_speaker, show_images, image_align, featured_image_width, content, show_meta, show_category } = attributes;
+
+               const posts     = this.getFilteredPosts();
+               const isLoading = ! Array.isArray( posts );
+               const hasPosts  = ! isLoading && posts.length > 0;
+
+               if ( isLoading || ! hasPosts ) {
+                       return (
+                               <BlockNoContent loading={ isLoading } />
+                       );
+               }
+
+               return (
+                       <PostList
+                               { ...this.props }
+                               className="wordcamp-sessions-block"
+                       >
+                               { posts.map( ( post ) =>
+                                       <div
+                                               key={ post.slug }
+                                               className={ classnames( 'wordcamp-session', 'wordcamp-session-' + post.slug ) }
+                                       >
+                                               <ItemTitle
+                                                       className="wordcamp-session-title"
+                                                       headingLevel={ 3 }
+                                                       title={ post.title.rendered.trim() }
+                                                       link={ post.link }
+                                               />
+
+                                               { show_speaker && this.constructor.hasSpeaker( post ) &&
+                                                       <SessionSpeakers session={ post } />
+                                               }
+
+                                               { show_images &&
+                                                       <FeaturedImage
+                                                               imageData={ get( post, '_embedded.wp:featuredmedia[0]', {} ) }
+                                                               width={ Number( featured_image_width ) }
+                                                               className={ classnames( 'wordcamp-session-featured-image', 'align-' + image_align ) }
+                                                               imageLink={ post.link }
+                                                       />
+                                               }
+
+                                               { 'none' !== content &&
+                                                       <ItemHTMLContent
+                                                               className={ classnames( 'wordcamp-session-content-' + content ) }
+                                                               content={ 'full' === content ? post.content.rendered.trim() : post.excerpt.rendered.trim() }
+                                                       />
+                                               }
+
+                                               { ( show_meta || show_category ) &&
+                                                       <div className="wordcamp-item-meta wordcamp-session-details">
+                                                               { show_meta &&
+                                                                       <SessionMeta session={ post } />
+                                                               }
+                                                               { show_category &&
+                                                                       <SessionCategory session={ post } />
+                                                               }
+                                                       </div>
+                                               }
+
+                                               { ( 'full' === content ) &&
+                                                       <ItemPermalink
+                                                               link={ post.link }
+                                                               linkText={ __( 'Visit session page', 'wordcamporg' ) }
+                                                               className="wordcamp-session-permalink"
+                                                       />
+                                               }
+                                       </div>
+                               ) }
+                       </PostList>
+               );
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionsblockcontrolsjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/block-controls.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/block-controls.js                                (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/block-controls.js  2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,95 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
+/**
+ * WordPress dependencies
+ */
+const { Button, Placeholder } = wp.components;
+const { Component }           = wp.element;
+const { __ }                  = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { PlaceholderSpecificMode } from '../../components/block-controls';
+import { getOptionLabel }          from '../../components/item-select';
+import { BlockContent }            from './block-content';
+import { ContentSelect }           from './content-select';
+import { LABEL }                   from './index';
+
+/**
+ * Component for displaying a UI within the block.
+ */
+export class BlockControls extends Component {
+       /**
+        * Render the internal block UI.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { icon, attributes, setAttributes, blockData } = this.props;
+               const { mode } = attributes;
+               const { options } = blockData;
+
+               let output;
+
+               switch ( mode ) {
+                       case 'all' :
+                               output = (
+                                       <BlockContent { ...this.props } />
+                               );
+                               break;
+
+                       case 'wcb_session' :
+                       case 'wcb_track' :
+                       case 'wcb_session_category' :
+                               output = (
+                                       <PlaceholderSpecificMode
+                                               label={ getOptionLabel( mode, options.mode ) }
+                                               icon={ icon }
+                                               content={
+                                                       <BlockContent { ...this.props } />
+                                               }
+                                               placeholderChildren={
+                                                       <ContentSelect { ...this.props } />
+                                               }
+                                       />
+                               );
+                               break;
+
+                       default :
+                               output = (
+                                       <Placeholder
+                                               className={ classnames( 'wordcamp-block-edit-placeholder', 'wordcamp-block-edit-placeholder-no-mode' ) }
+                                               icon={ icon }
+                                               label={ LABEL }
+                                       >
+                                               <div className="wordcamp-block-edit-mode-option">
+                                                       <Button
+                                                               isDefault
+                                                               isLarge
+                                                               onClick={ () => {
+                                                                       setAttributes( { mode: 'all' } );
+                                                               } }
+                                                       >
+                                                               { getOptionLabel( 'all', options.mode ) }
+                                                       </Button>
+                                               </div>
+
+                                               <div className="wordcamp-block-edit-mode-option">
+                                                       <ContentSelect
+                                                               icon={ icon }
+                                                               label={ __( 'Choose specific sessions, tracks, or categories', 'wordcamporg' ) }
+                                                               { ...this.props }
+                                                       />
+                                               </div>
+                                       </Placeholder>
+                               );
+                               break;
+               }
+
+               return output;
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionscontentselectjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/content-select.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/content-select.js                                (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/content-select.js  2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,133 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import { every, flatMap, includes } from 'lodash';
+
+/**
+ * WordPress dependencies
+ */
+const { Component } = wp.element;
+const { __ }        = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { buildOptions, ItemSelect, Option } from '../../components/item-select';
+
+/**
+ * Component for selecting posts/terms for populating the block content.
+ */
+export class ContentSelect extends Component {
+       /**
+        * Run additional operations during component initialization.
+        *
+        * @param {Object} props
+        */
+       constructor( props ) {
+               super( props );
+
+               this.buildSelectOptions    = this.buildSelectOptions.bind( this );
+               this.getCurrentSelectValue = this.getCurrentSelectValue.bind( this );
+               this.isLoading             = this.isLoading.bind( this );
+       }
+
+       /**
+        * Build or retrieve the options that will populate the Select dropdown.
+        *
+        * @return {Array}
+        */
+       buildSelectOptions() {
+               const { entities } = this.props;
+               const { wcb_session, wcb_track, wcb_session_category } = entities;
+
+               const optionGroups = [
+                       {
+                               entityType : 'post',
+                               type       : 'wcb_session',
+                               label      : __( 'Sessions', 'wordcamporg' ),
+                               items      : wcb_session,
+                       },
+                       {
+                               entityType : 'term',
+                               type       : 'wcb_track',
+                               label      : __( 'Tracks', 'wordcamporg' ),
+                               items      : wcb_track,
+                       },
+                       {
+                               entityType : 'term',
+                               type       : 'wcb_session_category',
+                               label      : __( 'Session Categories', 'wordcamporg' ),
+                               items      : wcb_session_category,
+                       },
+               ];
+
+               return buildOptions( optionGroups );
+       }
+
+       /**
+        * Determine the currently selected options in the Select dropdown based on block attributes.
+        *
+        * @return {Array}
+        */
+       getCurrentSelectValue() {
+               const { attributes } = this.props;
+               const { mode, item_ids } = attributes;
+
+               const options = flatMap( this.buildSelectOptions(), ( group ) => {
+                       return group.options;
+               } );
+
+               let value = [];
+
+               if ( mode && item_ids.length ) {
+                       value = options.filter( ( option ) => {
+                               return mode === option.type && includes( item_ids, option.value );
+                       } );
+               }
+
+               return value;
+       }
+
+       /**
+        * Check if all of the entity groups have finished loading.
+        *
+        * @return {boolean}
+        */
+       isLoading() {
+               const { entities } = this.props;
+
+               return ! every( entities, ( value ) => {
+                       return Array.isArray( value );
+               } );
+       }
+
+       /**
+        * Render an ItemSelect component with block-specific settings.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { icon, label, setAttributes } = this.props;
+
+               return (
+                       <ItemSelect
+                               className="wordcamp-sessions-select"
+                               label={ label }
+                               value={ this.getCurrentSelectValue() }
+                               onChange={ ( changed ) => setAttributes( changed ) }
+                               selectProps={ {
+                                       options           : this.buildSelectOptions(),
+                                       isLoading         : this.isLoading(),
+                                       formatOptionLabel : ( optionData ) => {
+                                               return (
+                                                       <Option
+                                                               icon={ includes( [ 'wcb_track', 'wcb_session_category' ], optionData.type ) ? icon : null }
+                                                               { ...optionData }
+                                                       />
+                                               );
+                                       },
+                               } }
+                       />
+               );
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionseditjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/edit.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/edit.js                          (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/edit.js    2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,74 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+const { withSelect }          = wp.data;
+const { Component, Fragment } = wp.element;
+
+/**
+ * Internal dependencies
+ */
+import { LayoutToolbar }     from '../../components/post-list';
+import { WC_BLOCKS_STORE }   from '../../data';
+import { BlockControls }     from './block-controls';
+import { InspectorControls } from './inspector-controls';
+import { ICON }              from './index';
+
+const blockData = window.WordCampBlocks.sessions || {};
+
+/**
+ * Top-level component for the editing UI for the block.
+ */
+class SessionsEdit extends Component {
+       /**
+        * Render the block's editing UI.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { attributes, setAttributes }  = this.props;
+               const { mode, layout }               = attributes;
+               const { layout: layoutOptions = {} } = blockData.options;
+
+               return (
+                       <Fragment>
+                               <BlockControls
+                                       icon={ ICON }
+                                       { ...this.props }
+                               />
+                               { mode &&
+                                       <Fragment>
+                                               <InspectorControls { ...this.props } />
+                                               <LayoutToolbar
+                                                       layout={ layout }
+                                                       options={ layoutOptions }
+                                                       setAttributes={ setAttributes }
+                                               />
+                                       </Fragment>
+                               }
+                       </Fragment>
+               );
+       }
+}
+
+const sessionsSelect = ( select ) => {
+       const { getEntities } = select( WC_BLOCKS_STORE );
+
+       const sessionArgs = {
+               _embed        : true,
+               wc_meta_key   : '_wcpt_session_type',
+               wc_meta_value : 'session', // Regular sessions only, no breaks/lunch/etc sessions.
+       };
+
+       const entities = {
+               wcb_session          : getEntities( 'postType', 'wcb_session', sessionArgs ),
+               wcb_track            : getEntities( 'taxonomy', 'wcb_track' ),
+               wcb_session_category : getEntities( 'taxonomy', 'wcb_session_category' ),
+       };
+
+       return {
+               blockData,
+               entities,
+       };
+};
+
+export const Edit = withSelect( sessionsSelect )( SessionsEdit );
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionsindexjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/index.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/index.js                         (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/index.js   2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,27 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+const { __ } = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { Edit } from './edit';
+
+export const NAME  = 'wordcamp/sessions';
+export const LABEL = __( 'Sessions', 'wordcamporg' );
+export const ICON  = 'list-view';
+
+const supports = {
+       align: [ 'wide', 'full' ],
+};
+
+export const SETTINGS = {
+       title       : __( 'Sessions', 'wordcamporg' ),
+       description : __( 'Add a list of sessions.', 'wordcamporg' ),
+       icon        : ICON,
+       category    : 'wordcamp',
+       supports    : supports,
+       edit        : Edit,
+       save        : () => null,
+};
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssessionsinspectorcontrolsjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/inspector-controls.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/inspector-controls.js                            (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sessions/inspector-controls.js      2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,96 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+const { InspectorControls: CoreInspectorControlsContainer } = wp.blockEditor;
+const { PanelBody, PanelRow, SelectControl, ToggleControl } = wp.components;
+const { Component }                                         = wp.element;
+const { __ }                                                = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { featuredImageSizePresets, ImageInspectorPanel } from '../../components/image';
+import { GridInspectorPanel }                            from '../../components/post-list';
+
+/**
+ * Component for block controls that appear in the Inspector Panel.
+ */
+export class InspectorControls extends Component {
+       /**
+        * Render the controls.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { attributes, setAttributes, blockData } = this.props;
+               const { show_images, featured_image_width, image_align, show_speaker, content, show_meta, show_category, sort } = attributes;
+               const { schema, options } = blockData;
+
+               return (
+                       <CoreInspectorControlsContainer>
+                               <GridInspectorPanel
+                                       { ...this.props }
+                               />
+
+                               <ImageInspectorPanel
+                                       title={ __( 'Featured Image Settings', 'wordcamporg' ) }
+                                       show={ show_images }
+                                       onChangeShow={ ( value ) => setAttributes( { show_images: value } ) }
+                                       size={ featured_image_width }
+                                       onChangeSize={ ( value ) => setAttributes( { featured_image_width: value } ) }
+                                       sizeSchema={ schema.featured_image_width }
+                                       sizePresets={ featuredImageSizePresets }
+                                       align={ image_align }
+                                       onChangeAlign={ ( value ) => setAttributes( { image_align: value } ) }
+                                       alignOptions={ options.align_image }
+                               />
+
+                               <PanelBody title={ __( 'Content Settings', 'wordcamporg' ) } initialOpen={ true }>
+                                       <PanelRow>
+                                               <SelectControl
+                                                       label={ __( 'Description', 'wordcamporg' ) }
+                                                       value={ content || 'full'  }
+                                                       options={ options.content }
+                                                       onChange={ ( value ) => setAttributes( { content: value } ) }
+                                               />
+                                       </PanelRow>
+                                       <PanelRow>
+                                               <ToggleControl
+                                                       label={ __( 'Details', 'wordcamporg' ) }
+                                                       help={ __( 'Show date, time, and track.', 'wordcamporg' ) }
+                                                       checked={ show_meta === undefined ? false : show_meta }
+                                                       onChange={ ( value ) => setAttributes( { show_meta: value } ) }
+                                               />
+                                       </PanelRow>
+                                       <PanelRow>
+                                               <ToggleControl
+                                                       label={ __( 'Categories', 'wordcamporg' ) }
+                                                       help={ __( 'Show session categories.', 'wordcamporg' ) }
+                                                       checked={ show_category === undefined ? false : show_category }
+                                                       onChange={ ( value ) => setAttributes( { show_category: value } ) }
+                                               />
+                                       </PanelRow>
+                                       <PanelRow>
+                                               <ToggleControl
+                                                       label={ __( 'Speakers', 'wordcamporg' ) }
+                                                       help={ __( 'Show session speakers.', 'wordcamporg' ) }
+                                                       checked={ show_speaker  === undefined ? false : show_speaker }
+                                                       onChange={ ( value ) => setAttributes( { show_speaker: value } ) }
+                                               />
+                                       </PanelRow>
+                               </PanelBody>
+
+                               <PanelBody title={ __( 'Sorting', 'wordcamporg' ) }>
+                                       <PanelRow>
+                                               <SelectControl
+                                                       label={ __( 'Sort by', 'wordcamporg' ) }
+                                                       value={ sort }
+                                                       options={ options.sort || 'session_time' }
+                                                       onChange={ ( value ) => setAttributes( { sort: value } ) }
+                                               />
+                                       </PanelRow>
+                               </PanelBody>
+                       </CoreInspectorControlsContainer>
+               );
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakersblockcontentjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/block-content.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/block-content.js                         (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/block-content.js   2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,214 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import { get }    from 'lodash';
+import classnames from 'classnames';
+
+/**
+ * WordPress dependencies
+ */
+const { Disabled }            = wp.components;
+const { Component, Fragment } = wp.element;
+const { __, _n }              = wp.i18n;
+const { escapeAttribute }     = wp.escapeHtml;
+
+/**
+ * Internal dependencies
+ */
+import { ItemTitle, ItemHTMLContent, ItemPermalink, BlockNoContent } from '../../components/block-content';
+import { AvatarImage }                                               from '../../components/image';
+import { PostList }                                                  from '../../components/post-list';
+import { filterEntities }                                            from '../../data';
+import { tokenSplit, arrayTokenReplace }                             from '../../i18n';
+
+import './block-content.scss';
+
+/**
+ * Component for the section of each speaker post that displays information about relevant sessions.
+ *
+ * @param {Object} props {
+ *     @type {Object} speaker
+ *     @type {Array}  tracks
+ * }
+ *
+ * @return {Element}
+ */
+function SpeakerSessions( { speaker, tracks } ) {
+       const sessions = get( speaker, '_embedded.sessions', [] );
+
+       let output = ( <Fragment>{ null }</Fragment> );
+
+       if ( sessions.length ) {
+               output = (
+                       <div className={ classnames( 'wordcamp-item-meta', 'wordcamp-speaker-sessions' ) }>
+                               <h4 className="wordcamp-speaker-sessions-heading">
+                                       { _n( 'Session', 'Sessions', sessions.length, 'wordcamporg' ) }
+                               </h4>
+
+                               <ul className="wordcamp-speaker-sessions-list">
+                                       { sessions.map( ( session ) =>
+                                               <li
+                                                       key={ escapeAttribute( session.slug ) }
+                                                       className="wordcamp-speaker-sessions-list-item"
+                                               >
+                                                       <Disabled>
+                                                               <a
+                                                                       className="wordcamp-speaker-session-link"
+                                                                       href={ session.link }
+                                                               >
+                                                                       { session.title.rendered.trim() || __( '(Untitled)', 'wordcamporg' ) }
+                                                               </a>
+                                                               <span className="wordcamp-speaker-session-info">
+                                                                       { session.session_track.length && Array.isArray( tracks ) &&
+                                                                               arrayTokenReplace(
+                                                                                       /* translators: 1: A date; 2: A time; 3: A location; */
+                                                                                       tokenSplit( __( '%1$s at %2$s in %3$s', 'wordcamporg' ) ),
+                                                                                       [
+                                                                                               session.session_date_time.date,
+                                                                                               session.session_date_time.time,
+                                                                                               get( tracks.find( ( value ) => {
+                                                                                                       const [ firstTrackId ] = session.session_track;
+                                                                                                       return parseInt( value.id ) === firstTrackId;
+                                                                                               } ), 'name' ),
+                                                                                       ]
+                                                                               )
+                                                                       }
+                                                                       { ( ! session.session_track.length || ! Array.isArray( tracks ) ) &&
+                                                                               arrayTokenReplace(
+                                                                                       /* translators: 1: A date; 2: A time; */
+                                                                                       tokenSplit( __( '%1$s at %2$s', 'wordcamporg' ), ),
+                                                                                       [
+                                                                                               session.session_date_time.date,
+                                                                                               session.session_date_time.time,
+                                                                                       ]
+                                                                               )
+                                                                       }
+                                                               </span>
+                                                       </Disabled>
+                                               </li>
+                                       ) }
+                               </ul>
+                       </div>
+               );
+       }
+
+       return output;
+}
+
+/**
+ * Component for displaying the block content.
+ */
+export class BlockContent extends Component {
+       /**
+        * Run additional operations during component initialization.
+        *
+        * @param {Object} props
+        */
+       constructor( props ) {
+               super( props );
+
+               this.getFilteredPosts = this.getFilteredPosts.bind( this );
+       }
+
+       /**
+        * Filter and sort the content that will be rendered.
+        *
+        * @returns {Array}
+        */
+       getFilteredPosts() {
+               const { attributes, entities } = this.props;
+               const { wcb_speaker: posts } = entities;
+               const { mode, item_ids, sort } = attributes;
+
+               const args = {};
+
+               if ( Array.isArray( item_ids ) && item_ids.length > 0 ) {
+                       args.filter  = [
+                               {
+                                       fieldName  : mode === 'wcb_speaker' ? 'id' : 'speaker_group',
+                                       fieldValue : item_ids,
+                               },
+                       ];
+               }
+
+               args.sort = sort;
+
+               return filterEntities( posts, args );
+       }
+
+       /**
+        * Render the block content.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { attributes, entities } = this.props;
+               const { wcb_track: tracks } = entities;
+               const { show_avatars, avatar_size, avatar_align, content, show_session } = attributes;
+
+               const posts     = this.getFilteredPosts();
+               const isLoading = ! Array.isArray( posts );
+               const hasPosts  = ! isLoading && posts.length > 0;
+
+               if ( isLoading || ! hasPosts ) {
+                       return (
+                               <BlockNoContent loading={ isLoading } />
+                       );
+               }
+
+               return (
+                       <PostList
+                               { ...this.props }
+                               className="wordcamp-speakers-block"
+                       >
+                               { posts.map( ( post ) =>
+                                       <div
+                                               key={ post.slug }
+                                               className={ classnames(
+                                                       'wordcamp-speaker',
+                                                       'wordcamp-speaker-' + post.slug,
+                                               ) }
+                                       >
+                                               <ItemTitle
+                                                       className="wordcamp-speaker-title"
+                                                       headingLevel={ 3 }
+                                                       title={ post.title.rendered.trim() }
+                                                       link={ post.link }
+                                               />
+
+                                               { show_avatars &&
+                                                       <AvatarImage
+                                                               className={ classnames( 'align-' + avatar_align ) }
+                                                               name={ post.title.rendered.trim() || '' }
+                                                               size={ avatar_size }
+                                                               url={ post.avatar_urls[ '24' ] }
+                                                               imageLink={ post.link }
+                                                       />
+                                               }
+
+                                               { ( 'none' !== content ) &&
+                                                       <ItemHTMLContent
+                                                               className={ classnames( 'wordcamp-speaker-content-' + content ) }
+                                                               content={ 'full' === content ? post.content.rendered.trim() : post.excerpt.rendered.trim() }
+                                                       />
+                                               }
+
+                                               { true === show_session &&
+                                                       <SpeakerSessions
+                                                               speaker={ post }
+                                                               tracks={ tracks }
+                                                       />
+                                               }
+
+                                               { ( 'full' === content ) &&
+                                                       <ItemPermalink
+                                                               link={ post.link }
+                                                               linkText={ __( 'Visit speaker page', 'wordcamporg' ) }
+                                                       />
+                                               }
+                                       </div>
+                               ) }
+                       </PostList>
+               );
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakersblockcontentscss"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/block-content.scss</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/block-content.scss                               (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/block-content.scss 2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,18 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.wordcamp-speaker-sessions-list {
+       // The double-ampersand will output the same class name twice in a row,
+       // which defeats an overzealous ul rule in Core's editor-blocks.css.
+       // https://css-tricks.com/the-sass-ampersand/#article-header-id-11
+       &#{&} {
+               list-style: none;
+               margin: 0;
+       }
+}
+
+.wordcamp-speaker-session-link,
+.wordcamp-speaker-session-info {
+       display: block;
+}
+
+.wordcamp-speaker-session-info {
+       font-style: italic;
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakersblockcontrolsjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/block-controls.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/block-controls.js                                (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/block-controls.js  2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,94 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
+/**
+ * WordPress dependencies
+ */
+const { Button, Placeholder } = wp.components;
+const { Component }           = wp.element;
+const { __ }                  = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { PlaceholderSpecificMode } from '../../components/block-controls';
+import { getOptionLabel }          from '../../components/item-select';
+import { BlockContent }            from './block-content';
+import { ContentSelect }           from './content-select';
+import { LABEL }                   from './index';
+
+/**
+ * Component for displaying a UI within the block.
+ */
+export class BlockControls extends Component {
+       /**
+        * Render the internal block UI.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { icon, attributes, setAttributes, blockData } = this.props;
+               const { mode } = attributes;
+               const { options } = blockData;
+
+               let output;
+
+               switch ( mode ) {
+                       case 'all' :
+                               output = (
+                                       <BlockContent { ...this.props } />
+                               );
+                               break;
+
+                       case 'wcb_speaker' :
+                       case 'wcb_speaker_group' :
+                               output = (
+                                       <PlaceholderSpecificMode
+                                               label={ getOptionLabel( mode, options.mode ) }
+                                               icon={ icon }
+                                               content={
+                                                       <BlockContent { ...this.props } />
+                                               }
+                                               placeholderChildren={
+                                                       <ContentSelect { ...this.props } />
+                                               }
+                                       />
+                               );
+                               break;
+
+                       default :
+                               output = (
+                                       <Placeholder
+                                               className={ classnames( 'wordcamp-block-edit-placeholder', 'wordcamp-block-edit-placeholder-no-mode' ) }
+                                               icon={ icon }
+                                               label={ LABEL }
+                                       >
+                                               <div className="wordcamp-block-edit-mode-option">
+                                                       <Button
+                                                               isDefault
+                                                               isLarge
+                                                               onClick={ () => {
+                                                                       setAttributes( { mode: 'all' } );
+                                                               } }
+                                                       >
+                                                               { getOptionLabel( 'all', options.mode ) }
+                                                       </Button>
+                                               </div>
+
+                                               <div className="wordcamp-block-edit-mode-option">
+                                                       <ContentSelect
+                                                               icon={ icon }
+                                                               label={ __( 'Choose specific speakers or groups', 'wordcamporg' ) }
+                                                               { ...this.props }
+                                                       />
+                                               </div>
+                                       </Placeholder>
+                               );
+                               break;
+               }
+
+               return output;
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakerscontentselectjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/content-select.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/content-select.js                                (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/content-select.js  2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,127 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import { every, flatMap, includes } from 'lodash';
+
+/**
+ * WordPress dependencies
+ */
+const { Component } = wp.element;
+const { __ }        = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { buildOptions, ItemSelect, Option } from '../../components/item-select';
+
+/**
+ * Component for selecting posts/terms for populating the block content.
+ */
+export class ContentSelect extends Component {
+       /**
+        * Run additional operations during component initialization.
+        *
+        * @param {Object} props
+        */
+       constructor( props ) {
+               super( props );
+
+               this.buildSelectOptions    = this.buildSelectOptions.bind( this );
+               this.getCurrentSelectValue = this.getCurrentSelectValue.bind( this );
+               this.isLoading             = this.isLoading.bind( this );
+       }
+
+       /**
+        * Build or retrieve the options that will populate the Select dropdown.
+        *
+        * @return {Array}
+        */
+       buildSelectOptions() {
+               const { entities } = this.props;
+               const { wcb_speaker, wcb_speaker_group } = entities;
+
+               const optionGroups = [
+                       {
+                               entityType : 'post',
+                               type       : 'wcb_speaker',
+                               label      : __( 'Speakers', 'wordcamporg' ),
+                               items      : wcb_speaker,
+                       },
+                       {
+                               entityType : 'term',
+                               type       : 'wcb_speaker_group',
+                               label      : __( 'Groups', 'wordcamporg' ),
+                               items      : wcb_speaker_group,
+                       },
+               ];
+
+               return buildOptions( optionGroups );
+       }
+
+       /**
+        * Determine the currently selected options in the Select dropdown based on block attributes.
+        *
+        * @return {Array}
+        */
+       getCurrentSelectValue() {
+               const { attributes } = this.props;
+               const { mode, item_ids } = attributes;
+
+               const options = flatMap( this.buildSelectOptions(), ( group ) => {
+                       return group.options;
+               } );
+
+               let value = [];
+
+               if ( mode && item_ids.length ) {
+                       value = options.filter( ( option ) => {
+                               return mode === option.type && includes( item_ids, option.value );
+                       } );
+               }
+
+               return value;
+       }
+
+       /**
+        * Check if all of the entity groups have finished loading.
+        *
+        * @return {boolean}
+        */
+       isLoading() {
+               const { entities } = this.props;
+
+               return ! every( entities, ( value ) => {
+                       return Array.isArray( value );
+               } );
+       }
+
+       /**
+        * Render an ItemSelect component with block-specific settings.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { label, icon, setAttributes } = this.props;
+
+               return (
+                       <ItemSelect
+                               className="wordcamp-speakers-select"
+                               label={ label }
+                               value={ this.getCurrentSelectValue() }
+                               onChange={ ( changed ) => setAttributes( changed ) }
+                               selectProps={ {
+                                       options           : this.buildSelectOptions(),
+                                       isLoading         : this.isLoading(),
+                                       formatOptionLabel : ( optionData ) => {
+                                               return (
+                                                       <Option
+                                                               icon={ 'wcb_speaker_group' === optionData.type ? icon : null }
+                                                               { ...optionData }
+                                                       />
+                                               );
+                                       },
+                               } }
+                       />
+               );
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakerseditjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/edit.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/edit.js                          (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/edit.js    2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,68 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+const { withSelect }          = wp.data;
+const { Component, Fragment } = wp.element;
+
+/**
+ * Internal dependencies
+ */
+import { LayoutToolbar }     from '../../components/post-list';
+import { WC_BLOCKS_STORE }   from '../../data';
+import { BlockControls }     from './block-controls';
+import { InspectorControls } from './inspector-controls';
+import { ICON }              from './index';
+
+const blockData = window.WordCampBlocks.speakers || {};
+
+/**
+ * Top-level component for the editing UI for the block.
+ */
+class SpeakersEdit extends Component {
+       /**
+        * Render the block's editing UI.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { attributes, setAttributes }  = this.props;
+               const { mode, layout }               = attributes;
+               const { layout: layoutOptions = {} } = blockData.options;
+
+               return (
+                       <Fragment>
+                               <BlockControls
+                                       icon={ ICON }
+                                       { ...this.props }
+                               />
+                               { mode &&
+                                       <Fragment>
+                                               <InspectorControls { ...this.props } />
+                                               <LayoutToolbar
+                                                       layout={ layout }
+                                                       options={ layoutOptions }
+                                                       setAttributes={ setAttributes }
+                                               />
+                                       </Fragment>
+                               }
+                       </Fragment>
+               );
+       }
+}
+
+const speakersSelect = ( select ) => {
+       const { getEntities } = select( WC_BLOCKS_STORE );
+
+       const entities = {
+               wcb_speaker       : getEntities( 'postType', 'wcb_speaker', { _embed: true } ),
+               wcb_speaker_group : getEntities( 'taxonomy', 'wcb_speaker_group' ),
+               wcb_track         : getEntities( 'taxonomy', 'wcb_track' ),
+       };
+
+       return {
+               blockData,
+               entities,
+       };
+};
+
+export const Edit = withSelect( speakersSelect )( SpeakersEdit );
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakersindexjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/index.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/index.js                         (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/index.js   2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,27 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+const { __ } = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { Edit } from './edit.js';
+
+export const NAME  = 'wordcamp/speakers';
+export const LABEL = __( 'Speakers', 'wordcamporg' );
+export const ICON  = 'megaphone';
+
+const supports = {
+       align: [ 'wide', 'full' ],
+};
+
+export const SETTINGS = {
+       title       : __( 'Speakers', 'wordcamporg' ),
+       description : __( 'Add a list of speakers.', 'wordcamporg' ),
+       icon        : ICON,
+       category    : 'wordcamp',
+       supports    : supports,
+       edit        : Edit,
+       save        : () => null,
+};
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksspeakersinspectorcontrolsjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/inspector-controls.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/inspector-controls.js                            (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/speakers/inspector-controls.js      2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,99 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+const { InspectorControls: CoreInspectorControlsContainer } = wp.blockEditor;
+const { PanelBody, PanelRow, SelectControl, ToggleControl } = wp.components;
+const { Component }                                         = wp.element;
+const { __ }                                                = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { avatarSizePresets, ImageInspectorPanel } from '../../components/image';
+import { GridInspectorPanel }                     from '../../components/post-list';
+
+const DEFAULT_SCHEMA = {
+       grid_columns: {
+               default : 2,
+               minimum : 2,
+               maximum : 4,
+       },
+       avatar_size: {
+               default : 150,
+               minimum : 25,
+               maximum : 600,
+       },
+};
+
+const DEFAULT_OPTIONS = {
+       align_image : {},
+       content     : {},
+       sort        : {},
+};
+
+/**
+ * Component for block controls that appear in the Inspector Panel.
+ */
+export class InspectorControls extends Component {
+       /**
+        * Render the controls.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { attributes, setAttributes, blockData } = this.props;
+               const { show_avatars, avatar_size, avatar_align, content, show_session, sort } = attributes;
+               const { schema = DEFAULT_SCHEMA, options = DEFAULT_OPTIONS } = blockData;
+
+               return (
+                       <CoreInspectorControlsContainer>
+                               <GridInspectorPanel
+                                       { ...this.props }
+                               />
+
+                               <ImageInspectorPanel
+                                       title={ __( 'Avatar Settings', 'wordcamporg' ) }
+                                       show={ show_avatars }
+                                       onChangeShow={ ( value ) => setAttributes( { show_avatars: value } ) }
+                                       size={ avatar_size }
+                                       onChangeSize={ ( value ) => setAttributes( { avatar_size: value } ) }
+                                       sizeSchema={ schema.avatar_size }
+                                       sizePresets={ avatarSizePresets }
+                                       align={ avatar_align }
+                                       onChangeAlign={ ( value ) => setAttributes( { avatar_align: value } ) }
+                                       alignOptions={ options.align_image }
+                               />
+
+                               <PanelBody title={ __( 'Content Settings', 'wordcamporg' ) } initialOpen={ false }>
+                                       <PanelRow>
+                                               <SelectControl
+                                                       label={ __( 'Biography Length', 'wordcamporg' ) }
+                                                       value={ content }
+                                                       options={ options.content }
+                                                       onChange={ ( value ) => setAttributes( { content: value } ) }
+                                               />
+                                       </PanelRow>
+                                       <PanelRow>
+                                               <ToggleControl
+                                                       label={ __( 'Session Information', 'wordcamporg' ) }
+                                                       help={ __( "Show speaker's session name, time, and track", 'wordcamporg' ) }
+                                                       checked={ show_session }
+                                                       onChange={ ( value ) => setAttributes( { show_session: value } ) }
+                                               />
+                                       </PanelRow>
+                               </PanelBody>
+
+                               <PanelBody title={ __( 'Sorting & Filtering', 'wordcamporg' ) } initialOpen={ false }>
+                                       <PanelRow>
+                                               <SelectControl
+                                                       label={ __( 'Sort by', 'wordcamporg' ) }
+                                                       value={ sort }
+                                                       options={ options.sort }
+                                                       onChange={ ( value ) => setAttributes( { sort: value } ) }
+                                               />
+                                       </PanelRow>
+                               </PanelBody>
+                       </CoreInspectorControlsContainer>
+               );
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorsblockcontentjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/block-content.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/block-content.js                         (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/block-content.js   2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,128 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import { get }    from 'lodash';
+import classnames from 'classnames';
+
+/**
+ * WordPress dependencies
+ */
+const { Component } = wp.element;
+const { __ }        = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { ItemTitle, ItemHTMLContent, ItemPermalink, BlockNoContent } from '../../components/block-content';
+import { FeaturedImage }                                             from '../../components/image';
+import { PostList }                                                  from '../../components/post-list';
+import { filterEntities }                                            from '../../data';
+
+/**
+ * Component for displaying the block content.
+ */
+export class BlockContent extends Component {
+       /**
+        * Run additional operations during component initialization.
+        *
+        * @param {Object} props
+        */
+       constructor( props ) {
+               super( props );
+
+               this.getFilteredPosts = this.getFilteredPosts.bind( this );
+       }
+
+       /**
+        * Filter and sort the content that will be rendered.
+        *
+        * @returns {Array}
+        */
+       getFilteredPosts() {
+               const { attributes, entities } = this.props;
+               const { wcb_sponsor: posts } = entities;
+               const { mode, item_ids, sort } = attributes;
+
+               const args = {};
+
+               if ( Array.isArray( item_ids ) && item_ids.length > 0 ) {
+                       args.filter  = [
+                               {
+                                       fieldName  : mode === 'wcb_sponsor' ? 'id' : 'sponsor_level',
+                                       fieldValue : item_ids,
+                               },
+                       ];
+               }
+
+               args.sort = sort;
+
+               return filterEntities( posts, args );
+       }
+
+       /**
+        * Render the block content.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { attributes } = this.props;
+               const { show_name, show_logo, featured_image_width, image_align, content } = attributes;
+
+               const posts     = this.getFilteredPosts();
+               const isLoading = ! Array.isArray( posts );
+               const hasPosts  = ! isLoading && posts.length > 0;
+
+               if ( isLoading || ! hasPosts ) {
+                       return (
+                               <BlockNoContent loading={ isLoading } />
+                       );
+               }
+
+               return (
+                       <PostList
+                               { ...this.props }
+                               className="wordcamp-sponsors-block"
+                       >
+                               { posts.map( ( post ) =>
+                                       <div
+                                               key={ post.slug }
+                                               className={ classnames( 'wordcamp-sponsor', 'wordcamp-sponsor-' + post.slug ) }
+                                       >
+                                               { show_name &&
+                                                       <ItemTitle
+                                                               className="wordcamp-sponsor-title"
+                                                               headingLevel={ 3 }
+                                                               title={ post.title.rendered.trim() }
+                                                               link={ post.link }
+                                                       />
+                                               }
+
+                                               { show_logo &&
+                                                       <FeaturedImage
+                                                               imageData={ get( post, '_embedded.wp:featuredmedia[0]', {} ) }
+                                                               width={ featured_image_width }
+                                                               className={ classnames( 'wordcamp-sponsor-featured-image', 'wordcamp-sponsor-logo', 'align-' + image_align ) }
+                                                               imageLink={ post.link }
+                                                       />
+                                               }
+
+                                               { ( 'none' !== content ) &&
+                                                       <ItemHTMLContent
+                                                               className={ classnames( 'wordcamp-sponsor-content-' + content ) }
+                                                               content={ 'full' === content ? post.content.rendered.trim() : post.excerpt.rendered.trim() }
+                                                       />
+                                               }
+
+                                               { ( 'full' === content ) &&
+                                                       <ItemPermalink
+                                                               link={ post.link }
+                                                               linkText={ __( 'Visit sponsor page', 'wordcamporg' ) }
+                                                               className="wordcamp-sponsor-permalink"
+                                                       />
+                                               }
+                                       </div>
+                               ) }
+                       </PostList>
+               );
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorsblockcontrolsjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/block-controls.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/block-controls.js                                (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/block-controls.js  2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,94 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
+/**
+ * WordPress dependencies
+ */
+const { Button, Placeholder } = wp.components;
+const { Component }           = wp.element;
+const { __ }                  = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { PlaceholderSpecificMode } from '../../components/block-controls';
+import { getOptionLabel }          from '../../components/item-select';
+import { BlockContent }            from './block-content';
+import { ContentSelect }           from './content-select';
+import { LABEL }                   from './index';
+
+/**
+ * Component for displaying a UI within the block.
+ */
+export class BlockControls extends Component {
+       /**
+        * Render the internal block UI.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { icon, attributes, setAttributes, blockData } = this.props;
+               const { mode } = attributes;
+               const { options } = blockData;
+
+               let output;
+
+               switch ( mode ) {
+                       case 'all' :
+                               output = (
+                                       <BlockContent { ...this.props } />
+                               );
+                               break;
+
+                       case 'wcb_sponsor' :
+                       case 'wcb_sponsor_level' :
+                               output = (
+                                       <PlaceholderSpecificMode
+                                               label={ getOptionLabel( mode, options.mode ) }
+                                               icon={ icon }
+                                               content={
+                                                       <BlockContent { ...this.props } />
+                                               }
+                                               placeholderChildren={
+                                                       <ContentSelect { ...this.props } />
+                                               }
+                                       />
+                               );
+                               break;
+
+                       default :
+                               output = (
+                                       <Placeholder
+                                               className={ classnames( 'wordcamp-block-edit-placeholder', 'wordcamp-block-edit-placeholder-no-mode' ) }
+                                               icon={ icon }
+                                               label={ LABEL }
+                                       >
+                                               <div className="wordcamp-block-edit-mode-option">
+                                                       <Button
+                                                               isDefault
+                                                               isLarge
+                                                               onClick={ () => {
+                                                                       setAttributes( { mode: 'all' } );
+                                                               } }
+                                                       >
+                                                               { getOptionLabel( 'all', options.mode ) }
+                                                       </Button>
+                                               </div>
+
+                                               <div className="wordcamp-block-edit-mode-option">
+                                                       <ContentSelect
+                                                               icon={ icon }
+                                                               label={ __( 'Choose specific sponsors or levels', 'wordcamporg' ) }
+                                                               { ...this.props }
+                                                       />
+                                               </div>
+                                       </Placeholder>
+                               );
+                               break;
+               }
+
+               return output;
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorscontentselectjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/content-select.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/content-select.js                                (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/content-select.js  2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,127 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import { every, flatMap, includes } from 'lodash';
+
+/**
+ * WordPress dependencies
+ */
+const { Component } = wp.element;
+const { __ }        = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { buildOptions, ItemSelect, Option } from '../../components/item-select';
+
+/**
+ * Component for selecting posts/terms for populating the block content.
+ */
+export class ContentSelect extends Component {
+       /**
+        * Run additional operations during component initialization.
+        *
+        * @param {Object} props
+        */
+       constructor( props ) {
+               super( props );
+
+               this.buildSelectOptions    = this.buildSelectOptions.bind( this );
+               this.getCurrentSelectValue = this.getCurrentSelectValue.bind( this );
+               this.isLoading             = this.isLoading.bind( this );
+       }
+
+       /**
+        * Build or retrieve the options that will populate the Select dropdown.
+        *
+        * @return {Array}
+        */
+       buildSelectOptions() {
+               const { entities } = this.props;
+               const { wcb_sponsor, wcb_sponsor_level } = entities;
+
+               const optionGroups = [
+                       {
+                               entityType : 'post',
+                               type       : 'wcb_sponsor',
+                               label      : __( 'Sponsors', 'wordcamporg' ),
+                               items      : wcb_sponsor,
+                       },
+                       {
+                               entityType : 'term',
+                               type       : 'wcb_sponsor_level',
+                               label      : __( 'Sponsors Levels', 'wordcamporg' ),
+                               items      : wcb_sponsor_level,
+                       },
+               ];
+
+               return buildOptions( optionGroups );
+       }
+
+       /**
+        * Determine the currently selected options in the Select dropdown based on block attributes.
+        *
+        * @return {Array}
+        */
+       getCurrentSelectValue() {
+               const { attributes } = this.props;
+               const { mode, item_ids } = attributes;
+
+               const options = flatMap( this.buildSelectOptions(), ( group ) => {
+                       return group.options;
+               } );
+
+               let value = [];
+
+               if ( mode && item_ids.length ) {
+                       value = options.filter( ( option ) => {
+                               return mode === option.type && includes( item_ids, option.value );
+                       } );
+               }
+
+               return value;
+       }
+
+       /**
+        * Check if all of the entity groups have finished loading.
+        *
+        * @return {boolean}
+        */
+       isLoading() {
+               const { entities } = this.props;
+
+               return ! every( entities, ( value ) => {
+                       return Array.isArray( value );
+               } );
+       }
+
+       /**
+        * Render an ItemSelect component with block-specific settings.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { label, icon, setAttributes } = this.props;
+
+               return (
+                       <ItemSelect
+                               className="wordcamp-sponsors-select"
+                               label={ label }
+                               value={ this.getCurrentSelectValue() }
+                               onChange={ ( changed ) => setAttributes( changed ) }
+                               selectProps={ {
+                                       options           : this.buildSelectOptions(),
+                                       isLoading         : this.isLoading(),
+                                       formatOptionLabel : ( optionData ) => {
+                                               return (
+                                                       <Option
+                                                               icon={ 'wcb_sponsor_level' === optionData.type ? icon : null }
+                                                               { ...optionData }
+                                                       />
+                                               );
+                                       },
+                               } }
+                       />
+               );
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorseditjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/edit.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/edit.js                          (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/edit.js    2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,68 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+const { withSelect }          = wp.data;
+const { Component, Fragment } = wp.element;
+
+/**
+ * Internal dependencies
+ */
+import { LayoutToolbar }     from '../../components/post-list';
+import { WC_BLOCKS_STORE }   from '../../data';
+import { BlockControls }     from './block-controls';
+import { InspectorControls } from './inspector-controls';
+import { ICON }              from './index';
+
+const blockData = window.WordCampBlocks.sponsors || {};
+
+/**
+ * Top-level component for the editing UI for the block.
+ */
+class SponsorsEdit extends Component {
+       /**
+        * Render the block's editing UI.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { attributes, setAttributes }  = this.props;
+               const { mode, layout }               = attributes;
+               const { layout: layoutOptions = {} } = blockData.options;
+
+               return (
+                       <Fragment>
+                               <BlockControls
+                                       icon={ ICON }
+                                       { ...this.props }
+                               />
+                               { mode &&
+                                       <Fragment>
+                                               <InspectorControls { ...this.props } />
+                                               <LayoutToolbar
+                                                       layout={ layout }
+                                                       options={ layoutOptions }
+                                                       setAttributes={ setAttributes }
+                                               />
+                                       </Fragment>
+                               }
+                       </Fragment>
+               );
+       }
+}
+
+const sponsorSelect = ( select ) => {
+       const { getEntities, getSiteSettings } = select( WC_BLOCKS_STORE );
+
+       const entities = {
+               wcb_sponsor       : getEntities( 'postType', 'wcb_sponsor', { _embed: true } ),
+               wcb_sponsor_level : getEntities( 'taxonomy', 'wcb_sponsor_level' ),
+       };
+
+       return {
+               blockData    : blockData,
+               entities     : entities,
+               siteSettings : getSiteSettings(),
+       };
+};
+
+export const Edit = withSelect( sponsorSelect )( SponsorsEdit );
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorsindexjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/index.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/index.js                         (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/index.js   2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,27 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+const { __ } = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { Edit } from './edit.js';
+
+export const NAME  = 'wordcamp/sponsors';
+export const LABEL = __( 'Sponsors', 'wordcamporg' );
+export const ICON  = 'heart';
+
+const supports = {
+       align: [ 'wide', 'full' ],
+};
+
+export const SETTINGS = {
+       title       : __( 'Sponsors', 'wordcamporg' ),
+       description : __( "We wouldn't have WordCamp without their support.", 'wordcamporg' ),
+       icon        : ICON,
+       category    : 'wordcamp',
+       supports    : supports,
+       edit        : Edit,
+       save        : () => null,
+};
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblockssponsorsinspectorcontrolsjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/inspector-controls.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/inspector-controls.js                            (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks/sponsors/inspector-controls.js      2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,87 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies.
+ */
+const { InspectorControls: CoreInspectorControlsContainer } = wp.blockEditor;
+const { PanelBody, PanelRow, ToggleControl, SelectControl } = wp.components;
+const { Component }                                         = wp.element;
+const { __ }                                                = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { featuredImageSizePresets, ImageInspectorPanel } from '../../components/image';
+import { GridInspectorPanel }                            from '../../components/post-list';
+
+const DEFAULT_OPTIONS = {
+       align_image : {},
+       content     : {},
+       sort        : {},
+};
+
+/**
+ * Component for block controls that appear in the Inspector Panel.
+ */
+export class InspectorControls extends Component {
+       /**
+        * Render the controls.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { attributes, setAttributes, blockData } = this.props;
+               const { show_logo, featured_image_width, image_align, show_name, content, sort } = attributes;
+               const { schema, options = DEFAULT_OPTIONS } = blockData;
+
+               return (
+                       <CoreInspectorControlsContainer>
+                               <GridInspectorPanel
+                                       { ...this.props }
+                               />
+
+                               <ImageInspectorPanel
+                                       title={ __( 'Logo Settings', 'wordcamporg' ) }
+                                       show={ show_logo }
+                                       onChangeShow={ ( value ) => setAttributes( { show_logo: value } ) }
+                                       size={ featured_image_width }
+                                       onChangeSize={ ( value ) => setAttributes( { featured_image_width: value } ) }
+                                       sizeSchema={ schema.featured_image_width }
+                                       sizePresets={ featuredImageSizePresets }
+                                       align={ image_align }
+                                       onChangeAlign={ ( value ) => setAttributes( { image_align: value } ) }
+                                       alignOptions={ options.align_image }
+                               />
+
+                               <PanelBody
+                                       title={ __( 'Content Settings', 'wordcamporg' ) }
+                                       initialOpen={ true }
+                               >
+                                       <ToggleControl
+                                               label={ __( 'Name', 'wordcamporg' ) }
+                                               help={ __( 'Show or hide sponsor name', 'wordcamporg' ) }
+                                               checked={ show_name }
+                                               onChange={ ( value ) => setAttributes( { show_name: value } ) }
+                                       />
+                                       <SelectControl
+                                               label={ __( 'Description', 'wordcamporg' ) }
+                                               value={ content }
+                                               options={ options.content }
+                                               help={ __( 'Length of sponsor description', 'wordcamporg' ) }
+                                               onChange={ ( value ) => setAttributes( { content: value } ) }
+                                       />
+                               </PanelBody>
+
+                               <PanelBody
+                                       title={ __( 'Sorting', 'wordcamporg' ) }
+                                       initialOpen={ false }
+                               >
+                                       <SelectControl
+                                               label={ __( 'Sort by', 'wordcamporg' ) }
+                                               value={ sort }
+                                               options={ options.sort }
+                                               onChange={ ( value ) => setAttributes( { sort: value } ) }
+                                       />
+                               </PanelBody>
+                       </CoreInspectorControlsContainer>
+               );
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourceblocksjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks.js                                (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/blocks.js  2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,13 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+const { registerBlockType } = wp.blocks;
+
+/**
+ * Internal dependencies
+ */
+import { BLOCKS } from './blocks/'; // Trailing slash required to differentiate the folder from the file.
+
+BLOCKS.forEach( ( { NAME, SETTINGS } ) => {
+       registerBlockType( NAME, SETTINGS );
+} );
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsblockcontentindexjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-content/index.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-content/index.js                                (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-content/index.js  2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,144 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
+/**
+ * WordPress dependencies
+ */
+const { Disabled, Spinner } = wp.components;
+const { Fragment, RawHTML } = wp.element;
+const { __ }                = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import './style.scss';
+
+/**
+ * Component for indicating why there is no content.
+ *
+ * @param {Object} props {
+ *     @type {boolean} loading
+ * }
+ *
+ * @return {Element}
+ */
+export function BlockNoContent( { loading } ) {
+       return (
+               <div className="wordcamp-block-content-none">
+                       { loading ?
+                               <Spinner /> :
+                               __( 'No content found.', 'wordcamporg' )
+                       }
+               </div>
+       );
+}
+
+/**
+ * Component for an entity title, optionally linked.
+ *
+ * @param {Object} props {
+ *     @type {number} headingLevel
+ *     @type {string} className
+ *     @type {string} title
+ *     @type {string} link
+ * }
+ *
+ * @return {Element}
+ */
+export function ItemTitle( { headingLevel, className, title, link } ) {
+       const validLevels = [ 1, 2, 3, 4, 5, 6 ];
+       let Tag = 'h3';
+
+       if ( validLevels.includes( headingLevel ) ) {
+               Tag = 'h' + headingLevel;
+       }
+
+       const classes = [
+               'wordcamp-item-title',
+               className,
+       ];
+
+       const content = title || __( '(Untitled)', 'wordcamporg' );
+
+       return (
+               <Tag className={ classnames( classes ) }>
+                       { link &&
+                               <Disabled>
+                                       <a href={ link }>
+                                               { content }
+                                       </a>
+                               </Disabled>
+                       }
+
+                       { ! link &&
+                               <Fragment>
+                                       { content }
+                               </Fragment>
+                       }
+               </Tag>
+       );
+}
+
+/**
+ * Component for an entity's content, with an optional permalink appended.
+ *
+ * DO NOT use this to output untrusted content. Note that this takes a blob of arbitrary HTML as input,
+ * and uses RawHTML (which uses dangerouslySetHTML) to render it in the node tree.
+ *
+ * @param {Object} props {
+ *     @type {string} className
+ *     @type {string} content
+ *     @type {string} link
+ *     @type {string} linkText
+ * }
+ *
+ * @return {Element}
+ */
+export function ItemHTMLContent( { className, content, link, linkText } ) {
+       const classes = [
+               'wordcamp-item-content',
+               className,
+       ];
+
+       return (
+               <div className={ classnames( classes ) }>
+                       <Disabled>
+                               <RawHTML children={ content } />
+                               { link &&
+                                       <ItemPermalink
+                                               link={ link }
+                                               linkText={ linkText }
+                                       />
+                               }
+                       </Disabled>
+               </div>
+       );
+}
+
+/**
+ * Component for an entity's permalink.
+ *
+ * @param {Object} props {
+ *     @type {string} className
+ *     @type {string} link
+ *     @type {string} linkText
+ * }
+ *
+ * @return {Element}
+ */
+export function ItemPermalink( { className, link, linkText } ) {
+       const classes = [
+               'wordcamp-item-permalink',
+               className,
+       ];
+
+       return (
+               <p className={ classnames( classes ) }>
+                       <a href={ link }>
+                               { linkText || __( 'Read more', 'wordcamporg' ) }
+                       </a>
+               </p>
+       );
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsblockcontentstylescss"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-content/style.scss</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-content/style.scss                              (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-content/style.scss        2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,12 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.wordcamp-block-content-none {
+       margin: 1em 0;
+       text-align: center;
+
+       .components-spinner {
+               float: none;
+       }
+}
+
+.wordcamp-item-meta {
+       margin: 0 0 1.5em;
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsblockcontrolsindexjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-controls/index.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-controls/index.js                               (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-controls/index.js 2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,49 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
+/**
+ * WordPress dependencies
+ */
+const { Placeholder } = wp.components;
+const { Fragment }    = wp.element;
+
+/**
+ * Internal dependencies
+ */
+import './style.scss';
+
+/**
+ * Component for block controls when the block has a specific mode selected.
+ *
+ * @param {Object} props {
+ *     @type {string} className
+ *     @type {string} label
+ *     @type {string} icon
+ *     @type {string} content
+ *     @type {Array}  placeholderChildren
+ * }
+ *
+ * @return {Element}
+ */
+export function PlaceholderSpecificMode( { className, label, icon, content, placeholderChildren } ) {
+       const classes = [
+               'wordcamp-block-edit-placeholder',
+               'wordcamp-block-edit-placeholder-specific-mode',
+               className,
+       ];
+
+       return (
+               <Fragment>
+                       { content }
+                       <Placeholder
+                               className={ classnames( classes ) }
+                               label={ label }
+                               icon={ icon }
+                       >
+                               { placeholderChildren }
+                       </Placeholder>
+               </Fragment>
+       );
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsblockcontrolsstylescss"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-controls/style.scss</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-controls/style.scss                             (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/block-controls/style.scss       2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,4 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.wordcamp-block-edit-mode-option {
+       flex-basis: 100%;
+       padding: 0.5em;
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsimageavatarjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/avatar.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/avatar.js                               (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/avatar.js 2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,98 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
+/**
+ * WordPress dependencies
+ */
+const { Disabled }            = wp.components;
+const { __, _x, sprintf }     = wp.i18n;
+const { addQueryArgs, isURL } = wp.url;
+
+// Avatar-specific presets for the ImageSizeControl component.
+export const avatarSizePresets = [
+       {
+               name      : __( 'Small', 'wordcamporg' ),
+               shortName : _x( 'S', 'size small', 'wordcamporg' ),
+               size      : 90,
+               slug      : 'small',
+       },
+       {
+               name      : __( 'Regular', 'wordcamporg' ),
+               shortName : _x( 'M', 'size medium', 'wordcamporg' ),
+               size      : 150,
+               slug      : 'regular',
+       },
+       {
+               name      : __( 'Large', 'wordcamporg' ),
+               shortName : _x( 'L', 'size large', 'wordcamporg' ),
+               size      : 300,
+               slug      : 'large',
+       },
+       {
+               name      : __( 'Larger', 'wordcamporg' ),
+               shortName : _x( 'XL', 'size extra large', 'wordcamporg' ),
+               size      : 500,
+               slug      : 'larger',
+       },
+];
+
+/**
+ * Component for an avatar image, optionally including a link.
+ *
+ * This tries to mirror the markup output by WP's get_avatar function, with the addition
+ * of an optional wrapping link and a container div.
+ *
+ * @param {Object} props {
+ *     @type {string} className
+ *     @type {string} name
+ *     @type {number} size
+ *     @type {string} url
+ *     @type {string} imageLink
+ * }
+ *
+ * @return {Element}
+ */
+export function AvatarImage( {
+       className,
+       name,
+       size,
+       url,
+       imageLink,
+} ) {
+       const getSizedURL = ( avatar_url, avatar_size ) => {
+               // 's' is the name of the parameter used by Gravatar.
+               // eslint-disable-next-line id-length
+               return addQueryArgs( avatar_url, { s: avatar_size } );
+       };
+
+       let image = (
+               <img
+                       className={ classnames( 'avatar', 'avatar-' + size, 'photo' ) }
+                       src={ getSizedURL( url, size ) }
+                       srcSet={ getSizedURL( url, size * 2 ) + ' 2x' }
+                       alt={ name ? sprintf( __( 'Avatar of %s', 'wordcamporg' ), name ) : '' }
+                       width={ size }
+                       height={ size }
+               />
+       );
+
+       if ( isURL( imageLink ) ) {
+               image = (
+                       <Disabled>
+                               <a href={ imageLink } className={ classnames( 'wordcamp-image-link', 'wordcamp-avatar-link' ) }>
+                                       { image }
+                               </a>
+                       </Disabled>
+               );
+       }
+
+       image = (
+               <div className={ classnames( 'wordcamp-image-container', 'wordcamp-avatar-container', className ) }>
+                       { image }
+               </div>
+       );
+
+       return image;
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsimagefeaturedimagejs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/featured-image.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/featured-image.js                               (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/featured-image.js 2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,162 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+import { sortBy } from 'lodash';
+
+/**
+ * WordPress dependencies.
+ */
+const { Disabled }  = wp.components;
+const { Component } = wp.element;
+const { __, _x }    = wp.i18n;
+const { isURL }     = wp.url;
+
+/**
+ * Internal dependencies
+ */
+import './featured-image.scss';
+
+// Featured Image-specific presets for the ImageSizeControl component.
+export const featuredImageSizePresets = [
+       {
+               name      : __( 'Small', 'wordcamporg' ),
+               shortName : _x( 'S', 'size small', 'wordcamporg' ),
+               size      : 150,
+               slug      : 'small',
+       },
+       {
+               name      : __( 'Regular', 'wordcamporg' ),
+               shortName : _x( 'M', 'size medium', 'wordcamporg' ),
+               size      : 300,
+               slug      : 'regular',
+       },
+       {
+               name      : __( 'Large', 'wordcamporg' ),
+               shortName : _x( 'L', 'size large', 'wordcamporg' ),
+               size      : 600,
+               slug      : 'large',
+       },
+       {
+               name      : __( 'Larger', 'wordcamporg' ),
+               shortName : _x( 'XL', 'size extra large', 'wordcamporg' ),
+               size      : 1024,
+               slug      : 'larger',
+       },
+];
+
+/**
+ * Displays a featured image, can be linked with block control for size.
+ *
+ * Unlike the PHP function that outputs a featured image, this doesn't bother with a `srcset` attribute, because
+ * it's assumed that this is being used in the block editor interface, and it just uses the largest image size
+ * available.
+ */
+export class FeaturedImage extends Component {
+       /**
+        * @param {Object} props
+        * @param {Array}  props.imageData Meta data about the featured image, including available sizes and the image's
+        *                                 alt text. This is the `_embedded.wp:featuredMedia[0]` object in a REST response.
+        * @param {number} props.width     Width in pixels for the image.
+        * @param {string} props.className Additional class names for the image element
+        * @param {string} props.imageLink URL for wrapping the image in an anchor tag
+        */
+       constructor( props ) {
+               super( props );
+
+               const { imageData } = props;
+               const { media_details = {}, alt_text = '' } = imageData;
+               const image = this.constructor.getWidestImage( media_details );
+
+               this.state = {
+                       image : image,
+                       alt   : alt_text,
+               };
+       }
+
+       /**
+        * Get the details of the widest image size available.
+        *
+        * @param {Object} media_details
+        *
+        * @return {Object}
+        */
+       static getWidestImage( media_details ) {
+               let image = {};
+               const { sizes = {} } = media_details;
+
+               if ( sizes.hasOwnProperty( 'full' ) && sizes.full.hasOwnProperty( 'source_url' ) ) {
+                       image = sizes.full;
+               } else if ( Object.getOwnPropertyDescriptors( sizes ).length > 0 ) {
+                       const sortedSizes = sortBy( sizes, 'width' );
+                       image = sortedSizes.pop();
+               }
+
+               return image;
+       }
+
+       /**
+        * Calculate a height based on the aspect ratio and a given width.
+        *
+        * @param {number} newWidth
+        * @param {Object} image
+        *
+        * @return {number|null}
+        */
+       static getNewHeight( newWidth, image ) {
+               let newHeight = null;
+               const { width, height } = image;
+
+               if ( width && height ) {
+                       const aspectRatio = Number( height ) / Number( width );
+                       newHeight = Number.parseFloat( aspectRatio * newWidth ).toFixed( 1 );
+               }
+
+               return newHeight;
+       }
+
+       /**
+        * Renders FeaturedImage component.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { width, className, imageLink } = this.props;
+               const { image, alt } = this.state;
+               const { source_url: src = '' } = image;
+
+               if ( ! src ) {
+                       return '';
+               }
+
+               const height = this.constructor.getNewHeight( width, image );
+
+               let output = (
+                       <img
+                               className={ classnames( 'wordcamp-featured-image', 'wp-post-image' ) }
+                               src={ src }
+                               alt={ alt }
+                               width={ width }
+                               height={ height }
+                       />
+               );
+
+               if ( isURL( imageLink ) ) {
+                       output = (
+                               <Disabled>
+                                       <a href={ imageLink } className={ classnames( 'wordcamp-image-link', 'wordcamp-featured-image-link' ) }>
+                                               { output }
+                                       </a>
+                               </Disabled>
+                       );
+               }
+
+               output = (
+                       <div className={ classnames( 'wordcamp-image-container', 'wordcamp-featured-image-container', className ) }>
+                               { output }
+                       </div>
+               );
+
+               return output;
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsimagefeaturedimagescss"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/featured-image.scss</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/featured-image.scss                             (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/featured-image.scss       2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,5 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+img.wordcamp-featured-image {
+       max-width: 100%;
+       max-height: 100%;
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsimageindexjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/index.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/index.js                                (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/index.js  2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,11 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Internal dependencies
+ */
+import './style.scss';
+
+/**
+ * Additional component exports
+ */
+export * from './avatar';
+export * from './featured-image';
+export * from './inspector-controls';
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsimageinspectorcontrolsjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/inspector-controls.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/inspector-controls.js                           (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/inspector-controls.js     2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,261 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import classnames   from 'classnames';
+import { debounce } from 'lodash';
+
+/**
+ * WordPress dependencies
+ */
+const { BaseControl, Button, ButtonGroup, PanelBody, PanelRow, RangeControl, ToggleControl, Toolbar } = wp.components;
+const { Component, Fragment }                                                                         = wp.element;
+const { __ }                                                                                          = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import './inspector-controls.scss';
+
+/**
+ * Component for a UI control for image size.
+ *
+ * This control assumes the image only has one adjustable size dimension. For avatars, this is because the images are
+ * always square. For featured images, this is because the width is adjustable, while the height is automatically
+ * calculated to maintain the correct aspect ratio.
+ *
+ * @param {Object} props {
+ *     @type {string}   className
+ *     @type {string}   label
+ *     @type {string}   help
+ *     @type {number}   value
+ *     @type {Array}    sizePresets
+ *     @type {Function} onChange
+ *     @type {number}   initialPosition
+ *     @type {Object}   rangeProps
+ * }
+ */
+export class ImageSizeControl extends Component {
+       /**
+        * Run additional operations during component initialization.
+        *
+        * @param {Object} props
+        */
+       constructor( props ) {
+               super( props );
+
+               this.state = {
+                       value    : props.value,
+                       onChange : debounce( props.onChange, 10 ), // Higher values lead to a noticeable degradation in visual feedback.
+               };
+
+               this.onChange = this.onChange.bind( this );
+       }
+
+       /**
+        * Wrapper for debouncing the onChange callback set in props.
+        *
+        * @param {number} value
+        */
+       onChange( value ) {
+               this.setState( { value } );
+               this.state.onChange( value );
+       }
+
+       /**
+        * Render the size control.
+        *
+        * @return {Element}
+        */
+       render() {
+               const {
+                       className,
+                       label,
+                       help,
+                       sizePresets = [],
+                       initialPosition,
+                       rangeProps,
+               } = this.props;
+               const { value } = this.state;
+
+               return (
+                       <BaseControl
+                               className={ classnames( 'wordcamp-image-size', className ) }
+                               label={ label }
+                               help={ help }
+                       >
+                               <div className="wordcamp-image-size-preset-buttons">
+                                       { sizePresets.length > 0 &&
+                                               <ButtonGroup aria-label={ label }>
+                                                       { sizePresets.map( ( preset ) => {
+                                                               const { name, shortName, size, slug } = preset;
+                                                               const isCurrent = value === size;
+
+                                                               return (
+                                                                       <Button
+                                                                               key={ slug }
+                                                                               isLarge
+                                                                               isPrimary={ isCurrent }
+                                                                               aria-label={ name }
+                                                                               aria-pressed={ isCurrent }
+                                                                               onClick={ () => this.onChange( Number( size ) ) }
+                                                                       >
+                                                                               { shortName || name }
+                                                                       </Button>
+                                                               );
+                                                       })}
+                                               </ButtonGroup>
+                                       }
+
+                                       <Button
+                                               className="wordcamp-image-size-button-reset"
+                                               isLarge
+                                               isDefault
+                                               onClick={ () => this.onChange( Number( initialPosition ) ) }
+                                       >
+                                               { __( 'Reset', 'wordcamporg' ) }
+                                       </Button>
+                               </div>
+
+                               <RangeControl
+                                       className="wordcamp-image-size-range"
+                                       value={ value }
+                                       initialPosition={ initialPosition }
+                                       onChange={ this.onChange }
+                                       beforeIcon="format-image"
+                                       afterIcon="format-image"
+                                       aria-label={ label }
+                                       { ...rangeProps }
+                               />
+                       </BaseControl>
+               );
+       }
+}
+
+/**
+ * Component for a UI control for image alignment.
+ *
+ * @param {Object} props {
+ *     @type {string}   className
+ *     @type {string}   label
+ *     @type {string}   help
+ *     @type {string}   value
+ *     @type {Function} onChange
+ *     @type {Array}    alignOptions
+ * }
+ *
+ * @return {Element}
+ */
+export function ImageAlignmentControl( {
+    className,
+    label,
+    help,
+    value,
+    onChange,
+    alignOptions,
+} ) {
+       return (
+               <BaseControl
+                       className={ classnames( 'wordcamp-image-alignment', className ) }
+                       label={ label }
+                       help={ help }
+               >
+                       <Toolbar
+                               controls={ alignOptions.map( ( alignment ) => {
+                                       const isActive = value === alignment.value;
+                                       const iconSlug = `align-${ alignment.value }`;
+
+                                       return {
+                                               title    : alignment.label,
+                                               icon     : iconSlug,
+                                               isActive : isActive,
+                                               onClick  : () => {
+                                                       onChange( alignment.value );
+                                               },
+                                       };
+                               } ) }
+                       />
+               </BaseControl>
+       );
+}
+
+/**
+ * Component to add an Inspector panel with image-related controls.
+ *
+ * @param {Object} props {
+ *     @type {string}   title
+ *     @type {boolean}  initialOpen
+ *     @type {string}   className
+ *     @type {boolean}  show
+ *     @type {Function} onChangeShow
+ *     @type {number}   size
+ *     @type {Function} onChangeSize
+ *     @type {Object}   sizeSchema
+ *     @type {Array}    sizePresets
+ *     @type {string}   align
+ *     @type {Function} onChangeAlign
+ *     @type {Array}    alignOptions
+ * }
+ */
+export class ImageInspectorPanel extends Component {
+       /**
+        * Render the control.
+        *
+        * @return {Element}
+        */
+       render() {
+               const {
+                       title = __( 'Image Settings', 'wordcamporg' ),
+                       initialOpen = true,
+                       className,
+                       show,
+                       onChangeShow,
+                       size,
+                       onChangeSize,
+                       sizeSchema,
+                       sizePresets = [],
+                       align,
+                       onChangeAlign,
+                       alignOptions = [],
+               } = this.props;
+
+               return (
+                       <PanelBody
+                               title={ title }
+                               initialOpen={ initialOpen }
+                               className={ classnames( 'wordcamp-image-inspector-panel', className ) }
+                       >
+                               <ToggleControl
+                                       label={ __( 'Show images', 'wordcamporg' ) }
+                                       checked={ show }
+                                       onChange={ onChangeShow }
+                               />
+                               { show &&
+                                       <Fragment>
+                                               <ImageSizeControl
+                                                       label={ __( 'Size', 'wordcamporg' ) }
+                                                       value={ Number( size ) }
+                                                       initialPosition={ Number( sizeSchema.default ) }
+                                                       sizePresets={ sizePresets }
+                                                       onChange={ onChangeSize }
+                                                       rangeProps={ {
+                                                               min : Number( sizeSchema.minimum ),
+                                                               max : Number( sizeSchema.maximum ),
+                                                       } }
+                                               />
+                                               { /* The PanelRow wrapper prevents the toolbar from expanding to full width. */ }
+                                               <PanelRow>
+                                                       <ImageAlignmentControl
+                                                               label={ __( 'Alignment', 'wordcamporg' ) }
+                                                               value={ align }
+                                                               onChange={ onChangeAlign }
+                                                               alignOptions={ alignOptions }
+                                                       />
+                                               </PanelRow>
+                                       </Fragment>
+                               }
+                       </PanelBody>
+               );
+       }
+}
+
+
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsimageinspectorcontrolsscss"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/inspector-controls.scss</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/inspector-controls.scss                         (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/inspector-controls.scss   2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,11 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+.wordcamp-image-size-preset-buttons {
+       display: flex;
+       justify-content: space-between;
+}
+
+.wordcamp-image-size-range {
+       .edit-post-settings-sidebar__panel-block .components-panel__body & {
+               margin-top: 1em;
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsimagestylescss"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/style.scss</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/style.scss                              (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/image/style.scss        2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,17 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.wordcamp-image-container {
+       &.align-left {
+               float: left;
+               margin-right: 1em;
+       }
+
+       &.align-center {
+               margin-left: auto;
+               margin-right: auto;
+               text-align: center;
+       }
+
+       &.align-right {
+               float: right;
+               margin-left: 1em;
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsitemselectindexjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/item-select/index.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/item-select/index.js                          (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/item-select/index.js    2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,155 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+import Select     from 'react-select';
+
+/**
+ * WordPress dependencies
+ */
+const { BaseControl, Button } = wp.components;
+const { Component }           = wp.element;
+const { __ }                  = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import './style.scss';
+
+/**
+ * Component for selecting one or more related entities to be used as content in a block.
+ */
+export class ItemSelect extends Component {
+       /**
+        * Run additional operations during component initialization.
+        *
+        * @param {Object} props
+        */
+       constructor( props ) {
+               super( props );
+
+               this.state = {
+                       selectedOptions: null,
+               };
+
+               this.getNewAttributes = this.getNewAttributes.bind( this );
+       }
+
+       /**
+        * Determine if an option should be selectable based on what else is already selected.
+        *
+        * @param {Object} option
+        * @param {Array}  selected
+        *
+        * @return {boolean}
+        */
+       static isOptionDisabled( option, selected ) {
+               let chosen;
+
+               if ( Array.isArray( selected ) && selected.length ) {
+                       chosen = selected[ 0 ].type;
+               }
+
+               return chosen && chosen !== option.type;
+       }
+
+       /**
+        * Render the label of an option group.
+        *
+        * @param {Object} groupData
+        *
+        * @returns {Element}
+        */
+       static formatGroupLabel( groupData ) {
+               return (
+                       <span className="wordcamp-item-select-option-group-label">
+                               { groupData.label }
+                       </span>
+               );
+       }
+
+       /**
+        * Convert a selection of options into values for a block's attributes.
+        *
+        * @return {Object}
+        */
+       getNewAttributes() {
+               const { selectedOptions } = this.state;
+               let attributes = {};
+
+               if ( null === selectedOptions ) {
+                       return attributes;
+               }
+
+               const newValue = selectedOptions.map( ( option ) => option.value ) || [];
+
+               if ( newValue.length ) {
+                       const chosen = selectedOptions[ 0 ].type;
+
+                       attributes = {
+                               mode     : chosen,
+                               item_ids : newValue,
+                       };
+               } else {
+                       attributes = {
+                               mode     : '',
+                               item_ids : [],
+                       };
+               }
+
+               return attributes;
+       }
+
+       /**
+        * Render the select dropdown and related UI.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { instanceId, className, label, help, submitLabel, onChange, selectProps } = this.props;
+               const value = this.state.selectedOptions || this.props.value;
+               const id = `wordcamp-item-select-control-${ instanceId }`;
+
+               const mergedSelectProps = {
+                       isMulti          : true,
+                       isOptionDisabled : this.constructor.isOptionDisabled,
+                       formatGroupLabel : this.constructor.formatGroupLabel,
+                       ...selectProps,
+               };
+
+               return (
+                       <BaseControl
+                               id={ id }
+                               className={ classnames( 'wordcamp-item-select', className ) }
+                               label={ label }
+                               help={ help }
+                       >
+                               <div className="wordcamp-item-select-inner">
+                                       <Select
+                                               id={ id }
+                                               className="wordcamp-item-select-select"
+                                               value={ value }
+                                               aria-label={ label }
+                                               onChange={ ( selectedOptions ) => {
+                                                       this.setState( { selectedOptions } );
+                                               } }
+                                               { ...mergedSelectProps }
+                                       />
+                                       <Button
+                                               className="wordcamp-item-select-button"
+                                               isLarge
+                                               isDefault
+                                               onClick={ () => onChange( this.getNewAttributes() ) }
+                                       >
+                                               { submitLabel || __( 'Select', 'wordcamporg' ) }
+                                       </Button>
+                               </div>
+                       </BaseControl>
+               );
+       }
+}
+
+/**
+ * Additional component exports
+ */
+export * from './option';
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsitemselectoptionjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/item-select/option.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/item-select/option.js                         (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/item-select/option.js   2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,176 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import { get }        from 'lodash';
+import createSelector from 'rememo';
+
+/**
+ * WordPress dependencies
+ */
+const { Dashicon } = wp.components;
+const { __ }       = wp.i18n;
+
+/**
+ * Internal dependencies
+ */
+import { filterEntities } from '../../data';
+import { AvatarImage }    from '../image';
+
+const buildOptionGroup = ( entityType, type, label, items ) => {
+       items = items.map( ( item ) => {
+               let parsedItem;
+
+               switch ( entityType ) {
+                       case 'post':
+                               parsedItem = {
+                                       label : item.title.rendered.trim() || __( '(Untitled)', 'wordcamporg' ),
+                                       value : item.id,
+                                       type  : type,
+                               };
+
+                               parsedItem.avatar = get( item, 'avatar_urls[\'24\']', '' );
+                               parsedItem.image  = get( item, '_embedded[\'wp:featuredmedia\'].media_details.sizes.thumbnail.source_url', '' );
+                               break;
+
+                       case 'term':
+                               parsedItem = {
+                                       label : item.name || __( '(Untitled)', 'wordcamporg' ),
+                                       value : item.id,
+                                       type  : type,
+                                       count : item.count,
+                               };
+                               break;
+               }
+
+               return parsedItem;
+       } );
+
+       return {
+               label   : label,
+               options : items,
+       };
+};
+
+/**
+ * A memoized function that parses structured data into a format used as an option set by ItemSelect.
+ *
+ * @return {Array}
+ */
+export const buildOptions = createSelector(
+       ( groups ) => {
+               const options = [];
+
+               groups.forEach( ( group ) => {
+                       const { entityType, type, label, items } = group;
+                       let orderby;
+
+                       switch ( entityType ) {
+                               case 'post':
+                                       orderby = 'title.rendered';
+                                       break;
+                               case 'term':
+                                       orderby = 'name';
+                                       break;
+                       }
+
+                       if ( Array.isArray( items ) && items.length ) {
+                               const sortedItems = filterEntities( items, { sort: orderby + '_asc' } );
+
+                               options.push( buildOptionGroup( entityType, type, label, sortedItems ) );
+                       }
+               } );
+
+               return options;
+       },
+       ( groups ) => {
+               const references = [];
+
+               groups.forEach( ( group ) => {
+                       const { items } = group;
+
+                       references.push( items );
+               } );
+
+               return references;
+       }
+);
+
+/**
+ * Find the label for an option with a specific value.
+ *
+ * @param {string} value
+ * @param {Array}  options
+ *
+ * @return {string}
+ */
+export function getOptionLabel( value, options ) {
+       let label = '';
+
+       const selectedOption = options.find( ( option ) => {
+               return value === option.value;
+       } );
+
+       if ( selectedOption.hasOwnProperty( 'label' ) ) {
+               label = selectedOption.label;
+       }
+
+       return label;
+}
+
+/**
+ * Component for a single option in an ItemSelect dropdown.
+ *
+ * Not all of the props need or should have a value. An option representing a speaker will have
+ * an avatar prop, but not an icon or a count (of terms).
+ *
+ * @param {Object} props {
+ *     @type {string} avatar
+ *     @type {string} icon
+ *     @type {string} label
+ *     @type {number} count
+ * }
+ *
+ * @return {Element}
+ */
+export function Option( { avatar, icon, label, count } ) {
+       let image;
+
+       if ( avatar ) {
+               image = (
+                       <AvatarImage
+                               className="wordcamp-item-select-option-avatar"
+                               name={ label }
+                               size={ 24 }
+                               url={ avatar }
+                       />
+               );
+       } else if ( icon ) {
+               image = (
+                       <div className="wordcamp-item-select-option-icon-container">
+                               <Dashicon
+                                       className="wordcamp-item-select-option-icon"
+                                       icon={ icon }
+                                       size={ 16 }
+                               />
+                       </div>
+               );
+       }
+
+       const content = (
+               <span className="wordcamp-item-select-option-label">
+                       { label }
+                       { 'undefined' !== typeof count &&
+                               <span className="wordcamp-item-select-option-label-count">
+                                       { count }
+                               </span>
+                       }
+               </span>
+       );
+
+       return (
+               <div className="wordcamp-item-select-option">
+                       { image }
+                       { content }
+               </div>
+       );
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentsitemselectstylescss"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/item-select/style.scss</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/item-select/style.scss                                (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/item-select/style.scss  2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,66 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.wordcamp-block-edit-placeholder .components-placeholder__fieldset {
+       /*
+        * By default the fieldset has a `z-index` of `1`, and `.editor-block-list__insertion-point` has a value of
+        * `6`, so the `Add Block` button will stack on top of things like an expanded `ItemSelect` list. This
+        * corrects that.
+        */
+       z-index: 7;
+}
+
+.wordcamp-item-select-inner {
+       display: flex;
+       align-items: center;
+       justify-content: space-between;
+       text-align: left;
+}
+
+.wordcamp-item-select-select {
+       flex-grow: 2;
+       margin-right: 1em;
+
+       .rtl &  {
+               margin-left: 1em;
+               margin-right: 0;
+       }
+
+       input[type="text"]:focus {
+               box-shadow: none;
+       }
+}
+
+.wordcamp-item-select-option {
+       display: flex;
+       align-items: center;
+}
+
+.wordcamp-item-select-option-avatar,
+.wordcamp-item-select-option-icon-container {
+       display: inline-flex;
+       align-items: center;
+       justify-content: center;
+       flex: 0 0 24px;
+       height: 24px;
+       background-color: #f3f3f4;
+}
+
+.wordcamp-item-select-option-label {
+       margin: 0 0.5em;
+       white-space: normal;
+}
+
+.wordcamp-item-select-option-label-count {
+       font-size: 0.6em;
+       display: inline-block;
+       border-radius: 50%;
+       background-color: #f3f3f4;
+       width: 2.2em;
+       height: 2.2em;
+       margin: 0 0.5em;
+       text-align: center;
+       line-height: 2.2em;
+       vertical-align: text-top;
+}
+
+.wordcamp-item-select {
+       width: 100%;
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentspostlistindexjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/index.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/index.js                            (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/index.js      2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,65 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
+/**
+ * WordPress dependencies
+ */
+const { Component } = wp.element;
+
+/**
+ * Internal dependencies
+ */
+import './style.scss';
+
+/**
+ * Implements post list markup for WordCamp blocks, with options for list and grid layout.
+ *
+ * Should be used with rest of the components in this folder. Uses attributes `layout` and `columns`.
+ */
+export class PostList extends Component {
+       /**
+        * Render the content.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { attributes, className, children = [] } = this.props;
+               const { align, grid_columns, layout } = attributes;
+
+               const containerClasses = [
+                       'wordcamp-block',
+                       'wordcamp-post-list',
+                       'layout-' + layout,
+                       className,
+               ];
+
+               if ( 'grid' === layout ) {
+                       containerClasses.push( 'grid-columns-' + Number( grid_columns ) );
+               }
+
+               if ( align ) {
+                       containerClasses.push( 'align' + align );
+               }
+
+               return (
+                       <ul className={ classnames( containerClasses ) }>
+                               { ( children ).map( ( childComponent ) =>
+                                       <li
+                                               key={ childComponent.key }
+                                               className={ classnames( 'wordcamp-post-list-item', 'wordcamp-clearfix' ) }
+                                       >
+                                               { childComponent }
+                                       </li>
+                               ) }
+                       </ul>
+               );
+       }
+}
+
+/**
+ * Additional component exports
+ */
+export * from './inspector-controls';
+export * from './toolbar';
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentspostlistinspectorcontrolsjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/inspector-controls.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/inspector-controls.js                               (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/inspector-controls.js 2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,74 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies.
+ */
+const { PanelBody, PanelRow, RangeControl } = wp.components;
+const { Component, Fragment }               = wp.element;
+const { __ }                                = wp.i18n;
+
+/**
+ * Component for a range control that adjusts the number of columns in a post list grid.
+ *
+ * For use within a block, consider GridInspectorPanel instead unless you want to include this control
+ * in a panel with other unrelated controls.
+ *
+ * @param {Object} props {
+ *     @type {number}   grid_columns
+ *     @type {Object}   schema
+ *     @type {Function} setAttributes
+ * }
+ *
+ * @return {Element}
+ */
+export function GridColumnsControl( {
+       grid_columns,
+       schema,
+       setAttributes,
+} ) {
+       const { default: defaultValue = 2, maximum = 4, minimum = 4 } = schema;
+
+       return (
+               <RangeControl
+                       label={ __( 'Grid Columns', 'wordcamporg' ) }
+                       value={ Number( grid_columns ) }
+                       min={ minimum }
+                       max={ maximum }
+                       initialPosition={ defaultValue }
+                       onChange={ ( value ) => setAttributes( { grid_columns: value } ) }
+               />
+       );
+}
+
+/**
+ * Component to add an Inspector panel
+ *
+ * Should be used with rest of the components in this folder. Will use and set attributes `layout` and `grid_columns`.
+ */
+export class GridInspectorPanel extends Component {
+       /**
+        * Render the control.
+        *
+        * @return {Element}
+        */
+       render() {
+               const { attributes, setAttributes, blockData } = this.props;
+               const { layout, grid_columns } = attributes;
+               const { schema } = blockData;
+
+               return (
+                       <Fragment>
+                               { 'grid' === layout &&
+                                       <PanelBody
+                                               title={ __( 'Grid Layout', 'wordcamporg' ) }
+                                               initialOpen={ true }
+                                       >
+                                               <GridColumnsControl
+                                                       grid_columns={ grid_columns }
+                                                       schema={ schema.grid_columns || {} }
+                                                       setAttributes={ setAttributes }
+                                               />
+                                       </PanelBody>
+                               }
+                       </Fragment>
+               );
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentspostliststylescss"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/style.scss</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/style.scss                          (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/style.scss    2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,57 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.wordcamp-clearfix::after {
+       content: "";
+       display: table;
+       clear: both;
+}
+
+.wordcamp-post-list {
+       // The double-ampersand will output the same class name twice in a row,
+       // which defeats an overzealous ul rule in Core's editor-blocks.css.
+       // https://css-tricks.com/the-sass-ampersand/#article-header-id-11
+       &#{&} {
+               list-style: none;
+       }
+
+       .wordcamp-post-list-item {
+               margin: 0 0 1em 0;
+
+               .layout-list & {
+                       margin-bottom: 1em;
+
+                       &:last-child {
+                               margin-bottom: 0;
+                       }
+               }
+       }
+
+       @media ( min-width: 400px ) {
+               &.layout-grid {
+                       display: grid;
+                       grid-template-columns: repeat( 2, 1fr );
+                       grid-column-gap: 1em;
+                       grid-row-gap: 1em;
+
+                       /* Ensure columns maintain equal widths. */
+                       /* https://stackoverflow.com/a/43312314 */
+                       min-height: 0;
+                       min-width: 0;
+
+                       & .wordcamp-post-list-item {
+                               overflow: hidden;
+                               min-width: 0;
+                       }
+               }
+       }
+
+       @media ( min-width: 600px ) {
+               &.layout-grid.grid-columns-3 {
+                       grid-template-columns: repeat( 3, 1fr );
+               }
+       }
+
+       @media ( min-width: 800px ) {
+               &.layout-grid.grid-columns-4 {
+                       grid-template-columns: repeat( 4, 1fr );
+               }
+       }
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcecomponentspostlisttoolbarjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/toolbar.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/toolbar.js                          (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/components/post-list/toolbar.js    2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,42 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+const { Toolbar }       = wp.components;
+const { BlockControls } = wp.editor;
+
+/**
+ * Component for a toolbar UI to the top of a post list block to change the layout.
+ *
+ * @param {Object} props {
+ *     @type {string}   layout
+ *     @type {Array}    options
+ *     @type {Function} setAttributes
+ * }
+ *
+ * @return {Element}
+ */
+export function LayoutToolbar( {
+       layout,
+       options,
+       setAttributes,
+} ) {
+       const controls = options.map( ( option ) => {
+               const icon     = `${ option.value }-view`;
+               const isActive = layout === option.value;
+
+               return {
+                       icon     : icon,
+                       title    : option.label,
+                       isActive : isActive,
+                       onClick  : () => {
+                               setAttributes( { layout: option.value } );
+                       },
+               };
+       } );
+
+       return (
+               <BlockControls>
+                       <Toolbar controls={ controls } />
+               </BlockControls>
+       );
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcedataindexjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/data/index.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/data/index.js                            (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/data/index.js      2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,190 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * External dependencies
+ */
+import { intersection, orderBy, split } from 'lodash';
+
+/**
+ * WordPress dependencies
+ */
+const apiFetch                            = wp.apiFetch;
+const { registerStore, select, dispatch } = wp.data;
+
+/**
+ * Define store name.
+ */
+export const WC_BLOCKS_STORE = 'wordcamp';
+
+const DEFAULT_STATE = {};
+
+/**
+ * Filter or sort an array of entities retrieved from the store.
+ *
+ * Note: Don't use the output for this in a prop because it could cause performance issues
+ * since the reference of the returned object will always be different.
+ * See https://reactjs.org/docs/optimizing-performance.html#avoid-reconciliation
+ *
+ * TODO: Can this be memoized?
+ *
+ * @param {Array}  entities List of entities to filter or sort.
+ * @param {Object} args     Arguments for the filter. {
+ *     @type {Array}  filter Array of objects, each of which as a fieldName and fieldValue property.
+ *     @type {string} sort   One string with two values, separated by `_`. The first value is the field to sort by.
+ *                           The second value is the direction of the sort, either `asc` or `desc`.
+ * }
+ *
+ * @return {Array} The filtered entities.
+ */
+export const filterEntities = ( entities, args ) => {
+       const { isArray } = Array;
+
+       if ( ! isArray( entities ) ) {
+               return entities;
+       }
+
+       let result = [ ...entities ];
+
+       if ( args.hasOwnProperty( 'filter' ) && isArray( args.filter ) ) {
+               args.filter.forEach( ( filterParams ) => {
+                       let { fieldName, fieldValue } = filterParams;
+
+                       if ( ! isArray( fieldValue ) ) {
+                               fieldValue = [ fieldValue ];
+                       }
+
+                       result = result.filter( ( entity ) => {
+                               if ( ! entity.hasOwnProperty( fieldName ) ) {
+                                       return false;
+                               }
+
+                               const compareValue = isArray( entity[ fieldName ] ) ? entity[ fieldName ] : [ entity[ fieldName ] ];
+
+                               return intersection( fieldValue, compareValue ).length > 0;
+                       } );
+               } );
+       }
+
+       if ( args.hasOwnProperty( 'sort' ) ) {
+               let [ orderby, order ] = split( args.sort, '_', 2 );
+
+               // TODO: Figure out a way to move this out of data store.
+               if ( 'title' === orderby && result.length && result[ 0 ].title.hasOwnProperty( 'rendered' ) ) {
+                       orderby = 'title.rendered';
+               }
+
+               result = orderBy( result, [ orderby ], [ order ] );
+       }
+
+       return result;
+};
+
+/**
+ * Defines actions provided by this store.
+ */
+const actions = {
+       /**
+        * Queues api fetch for settings.
+        *
+        * @return {{type: string}}
+        */
+       fetchSiteSettings() {
+               return {
+                       type: 'FETCH_SETTINGS',
+               };
+       },
+
+       /**
+        * Set the site settings object in this store.
+        *
+        * @param { Object } settings
+
+        * @return { Object }
+        */
+       setSiteSettings( settings ) {
+               return {
+                       type     : 'SET_SETTINGS',
+                       settings : settings,
+               };
+       },
+};
+
+/**
+ * Defines selectors provided by this store.
+ *
+ * @type {{getPosts(*, *)}}
+ */
+const selectors = {
+       /**
+        * Get query results from the Core data store.
+        *
+        * Returns data from current state. Caches [state, entityType] for
+        * quick resolution.
+        *
+        * @param {Object} state      Current store state
+        * @param {string} entityType Type of the entity to fetch
+        * @param {string} entityName Type of the entity to fetch
+        * @param {Object} queryArgs  Optional. Additional arguments for the fetch query.
+        *
+        * @return {Array} The results of the query.
+        */
+       getEntities( state, entityType, entityName, queryArgs = {} ) {
+               const defaultArgs = {
+                       per_page: -1, // The data store has middleware that converts this to paginated requests of 100 items each.
+               };
+
+               const mergedArgs = { ...defaultArgs, ...queryArgs };
+
+               return select( 'core' ).getEntityRecords( entityType, entityName, mergedArgs );
+       },
+
+       /**
+        * Get a site's settings via the REST API.
+        *
+        * @param {Object} state
+        *
+        * @return {Object.settings|null}
+        */
+       getSiteSettings( state ) {
+               if ( ! state.hasOwnProperty( 'siteSettings' ) ) {
+                       dispatch( WC_BLOCKS_STORE ).fetchSiteSettings();
+
+                       return null;
+               }
+
+               return state.siteSettings;
+       },
+};
+
+/**
+ * Decide how to change the store's state based on the given action.
+ *
+ * @param {Object} state
+ * @param {Object} action
+ *
+ * @return {{state}}
+ */
+const reducer = ( state = DEFAULT_STATE, action ) => {
+       switch ( action.type ) {
+               case 'FETCH_SETTINGS':
+                       if ( state.loadingSettings ) {
+                               break;
+                       }
+
+                       apiFetch( { path: '/wp/v2/settings' } ).then(
+                               ( fetchedSettings ) => {
+                                       dispatch( WC_BLOCKS_STORE ).setSiteSettings( fetchedSettings );
+                               }
+                       );
+
+                       state.loadingSettings = true;
+                       break;
+
+               case 'SET_SETTINGS':
+                       state.siteSettings = action.settings;
+                       state.loadingSettings = false;
+                       break;
+       }
+
+       return state;
+};
+
+registerStore( WC_BLOCKS_STORE, { selectors, actions, reducer } );
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockssourcei18nindexjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/i18n/index.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/i18n/index.js                            (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/source/i18n/index.js      2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,167 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * WordPress dependencies
+ */
+const { __ } = wp.i18n;
+
+/**
+ * Split a string into an array with sprintf-style tokens as the delimiter.
+ *
+ * Including the entire match as a capture group causes the tokens to be included in the array
+ * as separate items instead of being removed.
+ *
+ * This allows translated strings, which may contain tokens in different positions than they have
+ * in English, to be manipulated, modified, and included as an array of child elements in a
+ * React template.
+ *
+ * See also arrayTokenReplace
+ *
+ * Example:
+ *
+ *   tokenSplit( 'I accuse %1$s in the %2$s with the %3$s!' )
+ *
+ *   becomes
+ *
+ *   [ 'I accuse ', '%1$s', ' in the ', '%2$s', ' with the ', '%3$s', '!' ]
+ *
+ * @param {string} string
+ *
+ * @return {Array} The split string.
+ */
+export function tokenSplit( string ) {
+       const regex = /(%[1-9]?\$?s)/;
+
+       return string.split( regex );
+}
+
+/**
+ * Replace array items that are sprintf-style tokens with argument values.
+ *
+ * This allows tokens to be replaced with complex objects such as React elements, instead of just strings.
+ * This way, for example, a translation can include both plain strings and HTML and be inserted as an array
+ * of child elements into a React template without having to use RawHTML.
+ *
+ * See also tokenSplit
+ *
+ * Example:
+ *
+ *   arrayTokenReplace(
+ *       [ 'I accuse ', '%1$s', ' in the ', '%2$s', ' with the ', '%3$s', '!' ],
+ *       [ 'Professor Plum', 'Conservatory', 'Wrench' ]
+ *   )
+ *
+ *   becomes
+ *
+ *   [ 'I accuse ', 'Professor Plum', ' in the ', 'Conservatory', ' with the ', 'Wrench', '!' ]
+ *
+ * @param {Array} source
+ * @param {Array} args
+ *
+ * @return {Array} Array with token items replaced.
+ */
+export function arrayTokenReplace( source, args ) {
+       let specificArgIndex,
+               nextArgIndex = 0;
+
+       return source.flatMap( ( value ) => {
+               const regex = /^%([1-9])?\$?s$/;
+               const match = value.match( regex );
+
+               if ( Array.isArray( match ) ) {
+                       if ( match.length > 1 && 'undefined' !== typeof match[ 1 ] ) {
+                               specificArgIndex = Number( match[ 1 ] ) - 1;
+
+                               if ( 'undefined' !== typeof args[ specificArgIndex ] ) {
+                                       value = args[ specificArgIndex ];
+                               }
+                       } else {
+                               value = args[ nextArgIndex ];
+
+                               nextArgIndex++;
+                       }
+               }
+
+               return value;
+       } );
+}
+
+/**
+ * Insert a separator item in between each item in an array.
+ *
+ * See https://stackoverflow.com/a/23619085/402766
+ *
+ * @param {Array} array
+ * @param {string} separator
+ *
+ * @return {Array} Array with separator items.
+ */
+export function intersperse( array, separator ) {
+       if ( ! array.length ) {
+               return [];
+       }
+
+       return array
+               .slice( 1 )
+               .reduce(
+                       ( accumulator, curValue, curIndex ) => {
+                               const sep = ( typeof separator === 'function' ) ? sep( curIndex ) : separator;
+
+                               return accumulator.concat( [ sep, curValue ] );
+                       },
+                       [ array[ 0 ] ]
+               );
+}
+
+/**
+ * Add proper list grammar to an array of strings.
+ *
+ * Insert punctuation and conjunctions in between array items so that when it is joined into
+ * a single string, it is a human-readable list.
+ *
+ * Example:
+ *
+ *   listify( [ '<em>apples</em>', '<strong>oranges</strong>', '<del>bananas</del>' ] )
+ *
+ *   becomes
+ *
+ *   [ '<em>apples</em>', ', ', '<strong>oranges</strong>', ', ', ' and ', '<del>bananas</del>' ]
+ *
+ *   so that when the array is joined, it becomes
+ *
+ *   '<em>apples</em>, <strong>oranges</strong>, and <del>bananas</del>'
+ *
+ * @param {Array} array
+ *
+ * @return {Array} Array with separator items.
+ */
+export function listify( array ) {
+       let list = [];
+
+       /* translators: used between list items, there is a space after the comma */
+       const separator = __( ', ', 'wordcamporg' );
+       /* translators: preceding the last item in a list, there are spaces on both sides */
+       const conjunction = __( ' and ', 'wordcamporg' );
+
+       if ( ! Array.isArray( array ) ) {
+               return list;
+       }
+
+       const count = array.length;
+
+       switch ( count ) {
+               case 0:
+                       break;
+               case 1:
+                       list = array;
+                       break;
+               case 2:
+                       list = intersperse( array, conjunction );
+                       break;
+               default:
+                       const [ last, ...initial ] = [ ...array ].reverse();
+
+                       list = intersperse( initial, separator ).concat( [ separator, conjunction, last ] );
+                       break;
+       }
+
+       return list;
+}
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewsorganizerphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/organizer.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/organizer.php                             (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/organizer.php       2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,53 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Organizers;
+
+use WP_Post;
+use function WordCamp\Blocks\Components\{ render_item_title, render_item_content };
+use function WordCamp\Blocks\Utilities\{ get_all_the_content };
+
+defined( 'WPINC' ) || die();
+
+/** @var array   $attributes */
+/** @var WP_Post $organizer */
+
+// Note that organizer posts are not 'public', so there are no permalinks.
+
+setup_postdata( $organizer ); // This is necessary for generating an excerpt from content if the excerpt field is empty.
+?>
+
+<div class="wordcamp-organizer wordcamp-organizer-<?php echo esc_attr( $organizer->post_name ); ?>">
+       <?php echo wp_kses_post(
+               render_item_title(
+                       get_the_title( $organizer ),
+                       '',
+                       3,
+                       [ 'wordcamp-organizer-title' ]
+               )
+       ); ?>
+
+       <?php if ( true === $attributes['show_avatars'] ) : ?>
+               <div class="wordcamp-image-container wordcamp-avatar-container align-<?php echo esc_attr( $attributes['avatar_align'] ); ?>">
+                       <?php echo get_avatar(
+                               $organizer->_wcpt_user_id,
+                               $attributes['avatar_size'],
+                               '',
+                               sprintf( __( 'Avatar of %s', 'wordcamporg'), get_the_title( $organizer ) ),
+                               [ 'force_display' => true ]
+                       ); ?>
+               </div>
+       <?php endif; ?>
+
+       <?php if ( 'none' !== $attributes['content'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_item_content(
+                               'excerpt' === $attributes['content']
+                                       ? apply_filters( 'the_excerpt', get_the_excerpt( $organizer ) )
+                                       : get_all_the_content( $organizer ),
+                               [ 'wordcamp-organizer-content-' . $attributes['content'] ]
+                       )
+               ); ?>
+       <?php endif; ?>
+</div>
+
+<?php
+wp_reset_postdata();
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewssessionphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/session.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/session.php                               (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/session.php 2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,138 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Sessions;
+
+use WP_Post;
+use function WordCamp\Blocks\Components\{ render_featured_image, render_item_title, render_item_content, render_item_permalink };
+use function WordCamp\Blocks\Utilities\{ get_all_the_content, array_to_human_readable_list };
+
+defined( 'WPINC' ) || die();
+
+/** @var array   $attributes */
+/** @var array   $speakers */
+/** @var WP_Post $session */
+
+setup_postdata( $session );
+?>
+
+<div class="wordcamp-session wordcamp-session-<?php echo sanitize_html_class( $session->post_name ); ?>">
+       <?php echo wp_kses_post(
+               render_item_title(
+                       get_the_title( $session ),
+                       get_permalink( $session ),
+                       3,
+                       [ 'wordcamp-session-title' ]
+               )
+       ); ?>
+
+       <?php if ( true === $attributes['show_speaker'] && ! empty( $speakers[ $session->ID ] ) ) :
+               $speaker_linked_names = array_map(
+                       function( $speaker ) {
+                               return sprintf(
+                                       '<a href="%s">%s</a>',
+                                       get_permalink( $speaker ),
+                                       get_the_title( $speaker )
+                               );
+                       },
+                       $speakers[ $session->ID ]
+               );
+               ?>
+
+               <div class="wordcamp-item-meta wordcamp-session-speakers">
+                       <?php
+                       printf(
+                               /* translators: %s is a list of names. */
+                               wp_kses_post( __( 'Presented by %s', 'wordcamporg' ) ),
+                               wp_kses_post( array_to_human_readable_list( $speaker_linked_names ) )
+                       );
+                       ?>
+               </div>
+       <?php endif; ?>
+
+       <?php if ( true === $attributes['show_images'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_featured_image(
+                               $session,
+                               $attributes['featured_image_width'],
+                               [ 'wordcamp-session-featured-image', 'align-' . esc_attr( $attributes['image_align'] ) ],
+                               get_permalink( $session )
+                       )
+               ); ?>
+       <?php endif; ?>
+
+       <?php if ( 'none' !== $attributes['content'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_item_content(
+                               'excerpt' === $attributes['content']
+                                       ? apply_filters( 'the_excerpt', get_the_excerpt( $session ) )
+                                       : get_all_the_content( $session ),
+                               [ 'wordcamp-session-content-' . $attributes['content'] ]
+                       )
+               ); ?>
+       <?php endif; ?>
+
+       <?php if ( $attributes['show_meta'] || $attributes['show_category'] ) : ?>
+               <div class="wordcamp-item-meta wordcamp-session-details">
+                       <?php if ( $attributes['show_meta'] ) : ?>
+                               <?php $tracks = get_the_terms( $session, 'wcb_track' ); ?>
+
+                               <div class="wordcamp-session-time-location">
+                                       <?php if ( ! is_wp_error( $tracks ) && ! empty( $tracks ) ) :
+                                               printf(
+                                                       /* translators: 1: A date; 2: A time; 3: A location; */
+                                                       esc_html__( '%1$s at %2$s in %3$s', 'wordcamporg' ),
+                                                       esc_html( date_i18n( get_option( 'date_format' ), $session->_wcpt_session_time ) ),
+                                                       esc_html( date_i18n( get_option( 'time_format' ), $session->_wcpt_session_time ) ),
+                                                       sprintf(
+                                                               '<span class="wordcamp-session-track wordcamp-session-track-%s">%s</span>',
+                                                               esc_attr( $tracks[0]->slug ),
+                                                               esc_html( $tracks[0]->name )
+                                                       )
+                                               );
+
+                                       else :
+                                               printf(
+                                                       /* translators: 1: A date; 2: A time; */
+                                                       esc_html__( '%1$s at %2$s', 'wordcamporg' ),
+                                                       esc_html( date_i18n( get_option( 'date_format' ), $session->_wcpt_session_time ) ),
+                                                       esc_html( date_i18n( get_option( 'time_format' ), $session->_wcpt_session_time ) )
+                                               );
+                                       endif; ?>
+                               </div>
+                       <?php endif; ?>
+
+                       <?php if ( $attributes['show_category'] && has_term( null, 'wcb_session_category', $session ) ) :
+                               $categories = array_map(
+                                       function( $category ) {
+                                               return sprintf(
+                                                       '<span class="wordcamp-session-category wordcamp-session-category-%s">%s</span>',
+                                                       esc_attr( $category->slug ),
+                                                       esc_html( $category->name )
+                                               );
+                                       },
+                                       get_the_terms( $session, 'wcb_session_category' )
+                               );
+                               ?>
+
+                               <div class="wordcamp-session-categories">
+                                       <?php
+                                       /* translators: used between list items, there is a space after the comma */
+                                       echo wp_kses_post( implode( __( ', ', 'wordcamporg' ), $categories ) );
+                                       ?>
+                               </div>
+                       <?php endif; ?>
+               </div>
+       <?php endif; ?>
+
+       <?php if ( 'full' === $attributes['content'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_item_permalink(
+                               get_permalink( $session ),
+                               __( 'Visit session page', 'wordcamporg' ),
+                               [ 'wordcamp-session-permalink' ]
+                       )
+               ); ?>
+       <?php endif; ?>
+</div>
+
+<?php
+wp_reset_postdata();
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewsspeakerphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/speaker.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/speaker.php                               (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/speaker.php 2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,107 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Speakers;
+
+use WP_Post;
+use function WordCamp\Blocks\Components\{ render_item_title, render_item_content, render_item_permalink };
+use function WordCamp\Blocks\Utilities\{ get_all_the_content };
+
+defined( 'WPINC' ) || die();
+
+/** @var array   $attributes */
+/** @var array   $sessions */
+/** @var WP_Post $speaker */
+
+setup_postdata( $speaker ); // This is necessary for generating an excerpt from content if the excerpt field is empty.
+?>
+
+<div class="wordcamp-speaker wordcamp-speaker-<?php echo esc_attr( $speaker->post_name ); ?>">
+       <?php echo wp_kses_post(
+               render_item_title(
+                       get_the_title( $speaker ),
+                       get_permalink( $speaker ),
+                       3,
+                       [ 'wordcamp-speaker-title' ]
+               )
+       ); ?>
+
+       <?php if ( true === $attributes['show_avatars'] ) : ?>
+               <div class="wordcamp-image-container wordcamp-avatar-container align-<?php echo esc_attr( $attributes['avatar_align'] ); ?>">
+                       <a href="<?php echo esc_url( get_permalink( $speaker ) ); ?>" class="wordcamp-image-link wordcamp-avatar-link">
+                               <?php echo get_avatar(
+                                       $speaker->_wcb_speaker_email,
+                                       $attributes['avatar_size'],
+                                       '',
+                                       sprintf( __( 'Avatar of %s', 'wordcamporg'), get_the_title( $speaker ) ),
+                                       [ 'force_display' => true ]
+                               ); ?>
+                       </a>
+               </div>
+       <?php endif; ?>
+
+       <?php if ( 'none' !== $attributes['content'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_item_content(
+                               'excerpt' === $attributes['content']
+                                       ? apply_filters( 'the_excerpt', get_the_excerpt( $speaker ) )
+                                       : get_all_the_content( $speaker ),
+                               [ 'wordcamp-speaker-content-' . $attributes['content'] ]
+                       )
+               ); ?>
+       <?php endif; ?>
+
+       <?php if ( true === $attributes['show_session'] && ! empty( $sessions[ $speaker->ID ] ) ) : ?>
+               <div class="wordcamp-item-meta wordcamp-speaker-sessions">
+                       <h4 class="wordcamp-speaker-sessions-heading">
+                               <?php echo esc_html( _n( 'Session', 'Sessions', count( $sessions[ $speaker->ID ] ), 'wordcamporg' ) ); ?>
+                       </h4>
+
+                       <ul class="wordcamp-speaker-sessions-list">
+                               <?php foreach ( $sessions[ $speaker->ID ] as $session ) : ?>
+                                       <?php $tracks = get_the_terms( $session, 'wcb_track' ); ?>
+                                       <li class="wordcamp-speaker-sessions-list-item">
+                                               <a class="wordcamp-speaker-session-link" href="<?php echo esc_url( get_permalink( $session ) ); ?>">
+                                                       <?php echo wp_kses_post( get_the_title( $session ) ); ?>
+                                               </a>
+
+                                               <span class="wordcamp-speaker-session-info">
+                                                       <?php if ( ! is_wp_error( $tracks ) && ! empty( $tracks ) ) : ?>
+                                                               <?php
+                                                                       printf(
+                                                                               /* translators: 1: A date; 2: A time; 3: A location; */
+                                                                               esc_html__( '%1$s at %2$s in %3$s', 'wordcamporg' ),
+                                                                               esc_html( date_i18n( get_option( 'date_format' ), $session->_wcpt_session_time ) ),
+                                                                               esc_html( date_i18n( get_option( 'time_format' ), $session->_wcpt_session_time ) ),
+                                                                               esc_html( $tracks[0]->name )
+                                                                       );
+                                                               ?>
+
+                                                       <?php else : ?>
+                                                               <?php
+                                                                       printf(
+                                                                               /* translators: 1: A date; 2: A time; */
+                                                                               esc_html__( '%1$s at %2$s', 'wordcamporg' ),
+                                                                               esc_html( date_i18n( get_option( 'date_format' ), $session->_wcpt_session_time ) ),
+                                                                               esc_html( date_i18n( get_option( 'time_format' ), $session->_wcpt_session_time ) )
+                                                                       );
+                                                               ?>
+                                                       <?php endif; ?>
+                                               </span>
+                                       </li>
+                               <?php endforeach; ?>
+                       </ul>
+               </div>
+       <?php endif; ?>
+
+       <?php if ( 'full' === $attributes['content'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_item_permalink(
+                               get_permalink( $speaker ),
+                               __( 'Visit speaker page', 'wordcamporg' ),
+                               [ 'wordcamp-speaker-permalink' ]
+                       )
+               ); ?>
+       <?php endif; ?>
+</div>
+
+<?php
+wp_reset_postdata();
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblocksviewssponsorphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/sponsor.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/sponsor.php                               (rev 0)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/views/sponsor.php 2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,62 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+namespace WordCamp\Blocks\Sponsors;
+
+use WP_Post;
+use function WordCamp\Blocks\Components\{ render_featured_image, render_item_title, render_item_content, render_item_permalink };
+use function WordCamp\Blocks\Utilities\{ get_all_the_content };
+
+defined( 'WPINC' ) || die();
+
+/** @var array   $attributes */
+/** @var WP_Post $sponsor */
+
+setup_postdata( $sponsor ); // This is necessary for generating an excerpt from content if the excerpt field is empty.
+?>
+
+<div class="wordcamp-sponsor wordcamp-sponsor-<?php echo esc_attr( $sponsor->post_name ); ?>">
+       <?php if ( true === $attributes['show_name'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_item_title(
+                               get_the_title( $sponsor ),
+                               get_permalink( $sponsor ),
+                               3,
+                               [ 'wordcamp-sponsor-title' ]
+                       )
+               ); ?>
+       <?php endif; ?>
+
+       <?php if ( true === $attributes['show_logo'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_featured_image(
+                               $sponsor,
+                               $attributes['featured_image_width'],
+                               [ 'wordcamp-sponsor-featured-image', 'wordcamp-sponsor-logo', 'align-' . esc_attr( $attributes['image_align'] ) ],
+                               get_permalink( $sponsor )
+                       )
+               ); ?>
+       <?php endif; ?>
+
+       <?php if ( 'none' !== $attributes['content'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_item_content(
+                               'excerpt' === $attributes['content']
+                                       ? apply_filters( 'the_excerpt', get_the_excerpt( $sponsor ) )
+                                       : get_all_the_content( $sponsor ),
+                               [ 'wordcamp-sponsor-content-' . $attributes['content'] ]
+                       )
+               ); ?>
+       <?php endif; ?>
+
+       <?php if ( 'full' === $attributes['content'] ) : ?>
+               <?php echo wp_kses_post(
+                       render_item_permalink(
+                               get_permalink( $sponsor ),
+                               __( 'Visit sponsor page', 'wordcamporg' ),
+                               [ 'wordcamp-sponsor-permalink' ]
+                       )
+               ); ?>
+       <?php endif; ?>
+</div>
+
+<?php
+wp_reset_postdata();
</ins></span></pre></div>
<a id="sitestrunkwordcamporgpublic_htmlwpcontentmupluginsblockswebpackconfigjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/webpack.config.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/webpack.config.js       2019-05-10 20:20:52 UTC (rev 8778)
+++ sites/trunk/wordcamp.org/public_html/wp-content/mu-plugins/blocks/webpack.config.js 2019-05-10 22:24:19 UTC (rev 8779)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -23,12 +23,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">        devtool: SOURCE_MAPS ? 'cheap-module-eval-source-map' : 'none',
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        entry: {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                blocks: path.resolve( __dirname, 'assets/src/blocks.js' ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         blocks: path.resolve( __dirname, 'source/blocks.js' ),
</ins><span class="cx" style="display: block; padding: 0 10px">         },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        output: {
</span><span class="cx" style="display: block; padding: 0 10px">                filename : '[name].min.js',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                path     : path.resolve( __dirname, 'assets' ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         path     : path.resolve( __dirname, 'build' ),
</ins><span class="cx" style="display: block; padding: 0 10px">         },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        module: {
</span></span></pre>
</div>
</div>

</body>
</html>