code:
import { toFixed } from 'common/math';
import { useBackend, useLocalState } from '../backend';
import { Button, Flex, LabeledControls, NoticeBox, RoundGauge, Section, Stack } from '../components';
import { Window } from '../layouts';

const TAB2NAME = [
  {
    title: 'Debugging',
    blurb: 'Where useless shit goes to die',
    gauge: 5,
    component: () => DebuggingTab,
  },
  {
    title: 'Helpful',
    blurb: 'Where fuckwits put logging',
    gauge: 25,
    component: () => HelpfulTab,
  },
  {
    title: 'Fun',
    blurb: 'How I ran an """event"""',
    gauge: 75,
    component: () => FunTab,
  },
  {
    title: 'Only Fun For You',
    blurb: 'How I spent my last day adminning',
    gauge: 95,
    component: () => FunForYouTab,
  },
];

const lineHeightNormal = 2.79;
const buttonWidthNormal = 12.9;
const lineHeightDebug = 6.09;

const DebuggingTab = (props, context) => {
  const { act } = useBackend(context);
  return (
    <Stack fill vertical>
      <Stack.Item>
        <Button
          color="average"
          lineHeight={lineHeightDebug}
          icon="question"
          fluid
          content="Change all maintenance doors to engie/brig access only"
          onClick={() => act("maint_access_engiebrig")} />
      </Stack.Item>
      <Stack.Item>
        <Button
          color="average"
          lineHeight={lineHeightDebug}
          icon="question"
          fluid
          content="Change all maintenance doors to brig access only"
          onClick={() => act("maint_access_brig")} />
      </Stack.Item>
      <Stack.Item>
        <Button
          color="average"
          lineHeight={lineHeightDebug}
          icon="question"
          fluid
          content="Remove cap on security officers"
          onClick={() => act("infinite_sec")} />
      </Stack.Item>
    </Stack>
  );
};

const HelpfulTab = (props, context) => {
  const { act } = useBackend(context);
  return (
    <Stack fill vertical>
      <Stack.Item>
        <Stack fill>
          <Stack.Item>
            <NoticeBox
              mb={-0.5}
              width={buttonWidthNormal}
              height={lineHeightNormal}>
              Your admin button here, coder!
            </NoticeBox>
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="plus"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Cure all diseases"
              onClick={() => act("clear_virus")} />
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="biohazard"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Trigger Outbreak"
              onClick={() => act("virus")} />
          </Stack.Item>
        </Stack>
      </Stack.Item>
      <Stack.Item>
        <Stack fill>
          <Stack.Item>
            <NoticeBox
              mb={-0.5}
              width={buttonWidthNormal}
              height={lineHeightNormal}>
              Your admin button here, coder!
            </NoticeBox>
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="grin-beam-sweat"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Break all lights"
              onClick={() => act("blackout")} />
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="magic"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Fix all lights"
              onClick={() => act("whiteout")} />
          </Stack.Item>
        </Stack>
      </Stack.Item>
      <Stack.Item>
        <Stack fill>
          <Stack.Item>
            <Button
              icon="bomb"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="List Bombers"
              onClick={() => act("list_bombers")} />
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="signal"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="List Signalers"
              onClick={() => act("list_signalers")} />
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="robot"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="List laws"
              onClick={() => act("list_lawchanges")} />
          </Stack.Item>
        </Stack>
      </Stack.Item>
      <Stack.Item>
        <Stack fill>
          <Stack.Item>
            <Button
              icon="address-book"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Show Manifest"
              onClick={() => act("manifest")} />
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="dna"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Show DNA"
              onClick={() => act("dna")} />
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="fingerprint"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Show Fingerprints"
              onClick={() => act("fingerprints")} />
          </Stack.Item>
        </Stack>
      </Stack.Item>
      <Stack.Item>
        <Stack fill>
          <Stack.Item>
            <Button
              icon="flag"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Toggle CTF"
              onClick={() => act("ctfbutton")} />
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="sync-alt"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Reset Thunderdome"
              onClick={() => act("tdomereset")} />
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="moon"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Set Nightshift"
              onClick={() => act("night_shift_set")} />
          </Stack.Item>
        </Stack>
      </Stack.Item>
      <Stack.Item>
        <Stack fill>
          <Stack.Item>
            <Button
              icon="pencil-alt"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Rename Station"
              onClick={() => act("set_name")} />
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="eraser"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Default Station Name"
              onClick={() => act("reset_name")} />
          </Stack.Item>
          <Stack.Item>
            <NoticeBox
              mb={-0.5}
              width={buttonWidthNormal}
              height={lineHeightNormal}>
              Your admin button here, coder!
            </NoticeBox>
          </Stack.Item>
        </Stack>
      </Stack.Item>
    </Stack>
  );
};

const FunTab = (props, context) => {
  const { act } = useBackend(context);
  return (
    <Stack fill vertical>
      <Stack.Item>
        <Stack fill>
          <Stack.Item>
            <Button
              icon="robot"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Make N.E.R.D."
              onClick={() => act("makeNerd")} />
          </Stack.Item>
          <Stack.Item>
            <NoticeBox
              mb={-0.5}
              width={buttonWidthNormal}
              height={lineHeightNormal}>
              Your admin button here, coder!
            </NoticeBox>
          </Stack.Item>
          <Stack.Item>
            <NoticeBox
              mb={0.0}
              width={buttonWidthNormal}
              height={lineHeightNormal}>
              Your admin button here, coder!
            </NoticeBox>
          </Stack.Item>
        </Stack>
      </Stack.Item>
      <Stack.Item>
        <Stack fill>
          <Stack.Item>
            <Button
              icon="bolt"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="All areas powered"
              onClick={() => act("power")} />
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="moon"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="All areas unpowered"
              onClick={() => act("unpower")} />
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="plug"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="recharge SMESs"
              onClick={() => act("quickpower")} />
          </Stack.Item>
        </Stack>
      </Stack.Item>
      <Stack.Item>
        <Stack fill>
          <Stack.Item>
            <Button
              icon="user-ninja"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Anonymous Names"
              onClick={() => act("anon_name")} />
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="users"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Triple AI mode"
              onClick={() => act("tripleAI")} />
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="bullhorn"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="THERE CAN ONLY BE-"
              onClick={() => act("onlyone")} />
          </Stack.Item>
        </Stack>
      </Stack.Item>
      <Stack.Item>
        <Stack fill>
          <Stack.Item>
            <Button
              icon="grin-beam-sweat"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Summon Guns"
              onClick={() => act("guns")} />
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="magic"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Summon Magic"
              onClick={() => act("magic")} />
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="meteor"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Summon Events"
              onClick={() => act("events")} />
          </Stack.Item>
        </Stack>
      </Stack.Item>
      <Stack.Item>
        <Stack fill>
          <Stack.Item>
            <Button
              icon="hammer"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Egalitarian Station"
              onClick={() => act("eagles")} />
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="dollar-sign"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Ancap Station"
              onClick={() => act("ancap")} />
          </Stack.Item>
          <Stack.Item>
            <NoticeBox
              mb={-0.5}
              width={buttonWidthNormal}
              height={lineHeightNormal}>
              Your admin button here, coder!
            </NoticeBox>
          </Stack.Item>
        </Stack>
      </Stack.Item>
      <Stack.Item>
        <Stack fill>
          <Stack.Item>
            <Button
              icon="bullseye"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Custom Portal Storm"
              onClick={() => act("customportal")} />
          </Stack.Item>
          <Stack.Item>
            <Button
              icon="bomb"
              lineHeight={lineHeightNormal}
              width={buttonWidthNormal}
              content="Change Bomb Cap"
              onClick={() => act("changebombcap")} />
          </Stack.Item>
          <Stack.Item>
            <NoticeBox
              mb={-0.5}
              width={buttonWidthNormal}
              height={lineHeightNormal}>
              Your admin button here, coder!
            </NoticeBox>
          </Stack.Item>
        </Stack>
      </Stack.Item>
    </Stack>
  );
};

const FunForYouTab = (props, context) => {
  const { act } = useBackend(context);
  return (
    <Stack fill vertical>
      <Stack.Item>
        <Stack>
          <Stack.Item>
            <NoticeBox danger mb={0} width={19.6}>
              <Button
                color="red"
                icon="user-secret"
                fluid
                content="Everyone is the traitor"
                onClick={() => act("traitor_all")} />
            </NoticeBox>
          </Stack.Item>
          <Stack.Item>
            <NoticeBox danger width={19.6} mb={0}>
              <Button
                color="red"
                icon="brain"
                fluid
                content="Everyone gets brain damage"
                onClick={() => act("massbraindamage")} />
            </NoticeBox>
          </Stack.Item>
        </Stack>
      </Stack.Item>
      <Stack.Item>
        <NoticeBox danger mb={0}>
          <Button
            color="red"
            icon="hand-lizard"
            fluid
            content="Change everyone's species"
            onClick={() => act("allspecies")} />
        </NoticeBox>
      </Stack.Item>
      <Stack.Item>
        <NoticeBox danger mb={0}>
          <Button
            color="black"
            icon="paw"
            fluid
            content="Turn all humans into monkeys (DANGEROUS: worst species)"
            onClick={() => act("monkey")} />
        </NoticeBox>
      </Stack.Item>
      <Stack.Item>
        <NoticeBox danger mb={0}>
          <Button
            color="black"
            icon="fire"
            fluid
            content="The floor is lava! (DANGEROUS: extremely lame)"
            onClick={() => act("floorlava")} />
        </NoticeBox>
      </Stack.Item>
      <Stack.Item>
        <NoticeBox danger mb={0}>
          <Button
            color="black"
            icon="fire"
            fluid
            content="Chinese Cartoons! (DANGEROUS: no going back, also fuck you)"
            onClick={() => act("anime")} />
        </NoticeBox>
      </Stack.Item>
      <Stack.Item>
        <Stack fill>
          <Stack.Item>
            <NoticeBox danger width={19.6} mb={0}>
              <Button
                color="red"
                icon="cat"
                fluid
                content="Mass Purrbation"
                onClick={() => act("masspurrbation")} />
            </NoticeBox>
          </Stack.Item>
          <Stack.Item>
            <NoticeBox info width={19.6} mb={0}>
              <Button
                color="blue"
                icon="user"
                fluid
                content="Cure Purrbation"
                onClick={() => act("massremovepurrbation")} />
            </NoticeBox>
          </Stack.Item>
        </Stack>
      </Stack.Item>
      <Stack.Item>
        <Stack>
          <Stack.Item grow>
            <NoticeBox danger width={19.6} mb={0}>
              <Button
                color="red"
                icon="flushed"
                fluid
                content="Fully Immerse Everyone"
                onClick={() => act("massimmerse")} />
            </NoticeBox>
          </Stack.Item>
          <Stack.Item grow>
            <NoticeBox info width={19.6} mb={0}>
              <Button
                color="blue"
                icon="sync-alt"
                fluid
                content="Shatter the Immersion"
                onClick={() => act("unmassimmerse")} />
            </NoticeBox>
          </Stack.Item>
        </Stack>
      </Stack.Item>
    </Stack>
  );
};

export const Secrets = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    is_debugger,
    is_funmin,
  } = data;
  const [
    tabIndex,
    setTabIndex,
  ] = useLocalState(context, 'tab-index', 2);
  const TabComponent = TAB2NAME[tabIndex-1].component();
  return (
    <Window
      title="Secrets Panel"
      width={500}
      height={488}
      theme="admin">
      <Window.Content>
        <Flex direction="column" height="100%">
          <Flex.Item mb={1}>
            <Section
              title="Secrets"
              buttons={(
                <>
                  <Button
                    color="blue"
                    icon="address-card"
                    content="Admin Log"
                    onClick={() => act("admin_log")} />
                  <Button
                    color="blue"
                    icon="eye"
                    content="Show Admins"
                    onClick={() => act("show_admins")} />
                </>
              )}>
              <Flex
                mx={-0.5}
                align="stretch"
                justify="center">
                <Flex.Item bold>
                  <NoticeBox color="black">
                    "The first rule of adminbuse is:
                    you don't talk about the adminbuse."
                  </NoticeBox>
                </Flex.Item>
              </Flex>
              <Flex
                textAlign="center"
                mx={-0.5}
                align="stretch"
                justify="center">
                <Flex.Item ml={-10} mr={1}>
                  <Button
                    selected={tabIndex === 2}
                    icon="check-circle"
                    content="Helpful"
                    onClick={() => setTabIndex(2)} />
                </Flex.Item>
                <Flex.Item ml={1}>
                  <Button
                    disabled={is_funmin === 0}
                    selected={tabIndex === 3}
                    icon="smile"
                    content="Fun"
                    onClick={() => setTabIndex(3)} />
                </Flex.Item>
              </Flex>
              <Flex
                mx={-0.5}
                align="stretch"
                justify="center">
                <Flex.Item mt={1}>
                  <Button
                    disabled={is_debugger === 0}
                    selected={tabIndex === 1}
                    icon="glasses"
                    content="Debugging"
                    onClick={() => setTabIndex(1)} />
                </Flex.Item>
                <Flex.Item>
                  <LabeledControls>
                    <LabeledControls.Item
                      minWidth="66px"
                      label="Chances of admin complaint">
                      <RoundGauge
                        size={2}
                        value={TAB2NAME[tabIndex-1].gauge}
                        minValue={0}
                        maxValue={100}
                        alertAfter={100 * 0.70}
                        ranges={{
                          "good": [-2, 100 * 0.25],
                          "average": [100 * 0.25, 100 * 0.75],
                          "bad": [100 * 0.75, 100],
                        }}
                        format={value => toFixed(value) + '%'} />
                    </LabeledControls.Item>
                  </LabeledControls>
                </Flex.Item>
                <Flex.Item mt={1}>
                  <Button
                    disabled={is_funmin === 0}
                    selected={tabIndex === 4}
                    icon="smile-wink"
                    content="Only Fun For You"
                    onClick={() => setTabIndex(4)} />
                </Flex.Item>
              </Flex>
            </Section>
          </Flex.Item>
          <Flex.Item grow={1}>
            <Section
              fill={false}
              title={TAB2NAME[tabIndex-1].title
                + " Or: " + TAB2NAME[tabIndex-1].blurb}>
              <TabComponent />
            </Section>
          </Flex.Item>
        </Flex>
      </Window.Content>
    </Window>
  );
};


code:
import { sortBy } from 'common/collections';
import { flow } from 'common/fp';
import { toTitleCase } from 'common/string';
import { useBackend } from '../backend';
import { Button, Section, Table } from '../components';
import { Window } from '../layouts';

/**
 * This method takes a seed string and splits the values
 * into an object
 */
const splitSeedString = text => {
  const re = /([^;=]+)=([^;]+)/g;
  const ret = {};
  let m;
  do {
    m = re.exec(text);
    if (m) {
      ret[m[1]] = m[2] + '';
    }
  } while (m);
  return ret;
};

/**
 * This method splits up the string "name" we get for the seeds
 * and creates an object from it include the value that is the
 * ammount
 *
 * @returns {any[]}
 */
const createSeeds = seedStrings => {
  const objs = Object.keys(seedStrings).map(key => {
    const obj = splitSeedString(key);
    obj.amount = seedStrings[key];
    obj.key = key;
    obj.name = toTitleCase(obj.name.replace('pack of ', ''));
    return obj;
  });
  return flow([
    sortBy(item => item.name),
  ])(objs);
};

export const SeedExtractor = (props, context) => {
  const { act, data } = useBackend(context);
  const seeds = createSeeds(data.seeds);
  return (
    <Window
      width={1000}
      height={400}>
      <Window.Content scrollable>

Name

Lifespan

Endurance

Maturation

Production

Yield

Potency

Instability

Stock

            {seeds.map(item => (

{item.name}

{item.lifespan}

{item.endurance}

{item.maturation}

{item.production}

{item.yield}

{item.potency}

{item.instability}

                  <Button
                    content="Vend"
                    onClick={() => act('select', {
                      item: item.key,
                    })} />
                  ({item.amount} left)

            ))}

      </Window.Content>
    </Window>
  );
};

repo_name: AnalWerewolf/sundown

license: mit


code:
import { filter, map, sortBy, uniq } from 'common/collections';
import { flow } from 'common/fp';
import { createSearch } from 'common/string';
import { useBackend, useLocalState } from '../backend';
import { Box, Button, Icon, Input, Section, Stack, Tabs } from '../components';
import { Window } from '../layouts';

// here's an important mental define:
// custom outfits give a ref keyword instead of path
const getOutfitKey = outfit => outfit.path || outfit.ref;

const useOutfitTabs = (context, categories) => {
  return useLocalState(context, 'selected-tab', categories[0]);
};

export const SelectEquipment = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    name,
    icon64,
    current_outfit,
    favorites,
  } = data;

  const isFavorited = entry => favorites?.includes(entry.path);

  const outfits = map(entry => ({
    ...entry,
    favorite: isFavorited(entry),
  }))([
    ...data.outfits,
    ...data.custom_outfits,
  ]);

  // even if no custom outfits were sent, we still want to make sure there's
  // at least a 'Custom' tab so the button to create a new one pops up
  const categories = uniq([
    ...outfits.map(entry => entry.category),
    'Custom',
  ]);
  const [tab] = useOutfitTabs(context, categories);

  const [searchText, setSearchText] = useLocalState(
    context, 'searchText', '');
  const searchFilter = createSearch(searchText, entry => (
    entry.name + entry.path
  ));

  const visibleOutfits = flow([
    filter(entry => entry.category === tab),
    filter(searchFilter),
    sortBy(
      entry => !entry.favorite,
      entry => !entry.priority,
      entry => entry.name
    ),
  ])(outfits);

  const getOutfitEntry = current_outfit => outfits.find(outfit => (
    getOutfitKey(outfit) === current_outfit
  ));

  const currentOutfitEntry = getOutfitEntry(current_outfit);

  return (
    <Window
      width={650}
      height={415}
      theme="admin">
      <Window.Content>
        <Stack fill>
          <Stack.Item>
            <Stack fill vertical>
              <Stack.Item>
                <Input
                  fluid
                  autoFocus
                  placeholder="Search"
                  value={searchText}
                  onInput={(e, value) => setSearchText(value)} />
              </Stack.Item>
              <Stack.Item>
                <DisplayTabs categories={categories} />
              </Stack.Item>
              <Stack.Item mt={0} grow={1} basis={0}>
                <OutfitDisplay
                  entries={visibleOutfits}
                  currentTab={tab} />
              </Stack.Item>
            </Stack>
          </Stack.Item>
          <Stack.Item grow={1} basis={0}>
            <Stack fill vertical>
              <Stack.Item>
                <Section>
                  <CurrentlySelectedDisplay entry={currentOutfitEntry} />
                </Section>
              </Stack.Item>
              <Stack.Item grow={1}>
                <Section
                  fill
                  title={name}
                  textAlign="center">
                  <Box
                    as="img"
                    m={0}
                    src={`data:image/jpeg;base64,${icon64}`}
                    height="100%"
                    style={{
                      '-ms-interpolation-mode': 'nearest-neighbor',
                    }} />
                </Section>
              </Stack.Item>
            </Stack>
          </Stack.Item>
        </Stack>
      </Window.Content>
    </Window>
  );
};

const DisplayTabs = (props, context) => {
  const { categories } = props;
  const [tab, setTab] = useOutfitTabs(context, categories);
  return (
    <Tabs textAlign="center">
      {categories.map(category => (
        <Tabs.Tab
          key={category}
          selected={tab === category}
          onClick={() => setTab(category)}>
          {category}
        </Tabs.Tab>
      ))}
    </Tabs>
  );
};

const OutfitDisplay = (props, context) => {
  const { act, data } = useBackend(context);
  const { current_outfit } = data;
  const { entries, currentTab } = props;
  return (
    <Section fill scrollable>
      {entries.map(entry => (
        <Button
          key={getOutfitKey(entry)}
          fluid
          ellipsis
          icon={entry.favorite && 'star'}
          iconColor="gold"
          content={entry.name}
          title={entry.path || entry.name}
          selected={getOutfitKey(entry) === current_outfit}
          onClick={() => act('preview', {
            path: getOutfitKey(entry),
          })}
          onDblClick={() => act('applyoutfit', {
            path: getOutfitKey(entry),
          })} />
      ))}
      {currentTab === "Custom" && (
        <Button
          color="transparent"
          icon="plus"
          fluid
          onClick={() => act('customoutfit')}>
          Create a custom outfit...
        </Button>
      )}
    </Section>
  );
};

const CurrentlySelectedDisplay = (props, context) => {
  const { act, data } = useBackend(context);
  const { current_outfit } = data;
  const { entry } = props;
  return (
    <Stack align="center">
      {entry?.path && (
        <Stack.Item>
          <Icon
            size={1.6}
            name={entry.favorite ? 'star' : 'star-o'}
            color="gold"
            style={{ cursor: 'pointer' }}
            onClick={() => act('togglefavorite', {
              path: entry.path,
            })} />
        </Stack.Item>
      )}
      <Stack.Item grow={1} basis={0}>
        <Box color="label">
          Currently selected:
        </Box>
        <Box
          title={entry?.path}
          style={{
            'overflow': 'hidden',
            'white-space': 'nowrap',
            'text-overflow': 'ellipsis',
          }}>
          {entry?.name}
        </Box>
      </Stack.Item>
      <Stack.Item>
        <Button
          mr={0.8}
          lineHeight={2}
          color="green"
          onClick={() => act('applyoutfit', {
            path: current_outfit,
          })}>
          Confirm
        </Button>
      </Stack.Item>
    </Stack>
  );
};


code:
import { useBackend } from "../backend";
import { Button, NumberInput, Section, Stack, Input, LabeledList } from '../components';
import { Window } from "../layouts";

export const SentienceFunBalloon = (props, context) => {
  const { act, data } = useBackend(context);
  const { group_name, range } = data;
  return (
    <Window
      title={"Sentience Fun Balloon"}
      width={400}
      height={175}
    >
      <Window.Content>
        <Stack vertical>

            <LabeledList>
              <LabeledList.Item label="Group name">
                <Input
                  fluid
                  value={group_name}
                  onChange={(e, value) => act("group_name", {
                    updated_name: value,
                  })} />
              </LabeledList.Item>
              <LabeledList.Item label="Effect range">
                <NumberInput
                  width="84px"
                  value={range}
                  minValue={1}
                  maxValue={100}
                  stepPixelSize={15}
                  onDrag={(e, value) => act('effect_range', {
                    updated_range: value,
                  })} />
              </LabeledList.Item>
            </LabeledList>

            <Button.Confirm
              fluid
              icon="magic"
              color="good"
              textAlign="center"
              content="Pop Balloon"
              onClick={() => act("pop")} />

        </Stack>
      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from '../backend';
import { Box, Button, Dropdown, Flex, Icon, LabeledList, Modal, Section } from '../components';
import { Window } from '../layouts';

export const ShuttleConsole = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    type = "shuttle",
    blind_drop,
  } = props;
  const {
    authorization_required,
  } = data;
  return (
    <Window
      width={350}
      height={230}>
      {!!authorization_required && (
        <Modal
          ml={1}
          mt={1}
          width={26}
          height={12}
          fontSize="28px"
          fontFamily="monospace"
          textAlign="center">
          <Flex>
            <Flex.Item mt={2}>
              <Icon
                name="minus-circle" />
            </Flex.Item>
            <Flex.Item
              mt={2}
              ml={2}
              color="bad">
              {type === "shuttle" ? 'SHUTTLE LOCKED' : "BASE LOCKED"}
            </Flex.Item>
          </Flex>
          <Box
            fontSize="18px"
            mt={4}>
            <Button
              lineHeight="40px"
              icon="arrow-circle-right"
              content="Request Authorization"
              color="bad"
              onClick={() => act('request')} />
          </Box>
        </Modal>
      )}
      <Window.Content>
        <ShuttleConsoleContent
          type={type}
          blind_drop={blind_drop} />
      </Window.Content>
    </Window>
  );
};

const getLocationNameById = (locations, id) => {
  return locations?.find(location => location.id === id)?.name;
};

const getLocationIdByName = (locations, name) => {
  return locations?.find(location => location.name === name)?.id;
};

const STATUS_COLOR_KEYS = {
  "In Transit": "good",
  "Idle": "average",
  "Igniting": "average",
  "Recharging": "average",
  "Missing": "bad",
  "Unauthorized Access": "bad",
  "Locked": "bad",
};

export const ShuttleConsoleContent = (props, context) => {
  const { act, data } = useBackend(context);
  const { type, blind_drop } = props;
  const {
    status,
    locked,
    authorization_required,
    destination,
    docked_location,
    timer_str,
    locations = [],
  } = data;
  return (
    <Section>
      <Box
        bold
        fontSize="26px"
        textAlign="center"
        fontFamily="monospace">
        {timer_str || "00:00"}
      </Box>
      <Box
        textAlign="center"
        fontSize="14px"
        mb={1}>
        <Box
          inline
          bold>
          STATUS:
        </Box>
        <Box
          inline
          color={STATUS_COLOR_KEYS[status] || "bad"}
          ml={1}>
          {status || "Not Available"}
        </Box>
      </Box>
      <Section
        title={type === "shuttle" ? "Shuttle Controls" : "Base Launch Controls"}
        level={2}>
        <LabeledList>
          <LabeledList.Item label="Location">
            {docked_location || "Not Available"}
          </LabeledList.Item>
          <LabeledList.Item
            label="Destination"
            buttons={(
              type !== "shuttle" && locations.length===0 && !!blind_drop && (
                <Button
                  color="bad"
                  icon="exclamation-triangle"
                  disabled={authorization_required || !blind_drop}
                  content={"Blind Drop"}
                  onClick={() => act('random')} />
              ))} >
            {locations.length===0 && (
              <Box
                mb={1.7}
                color="bad">
                Not Available
              </Box>
            ) || locations.length===1 &&(
              <Box
                mb={1.7}
                color="average">
                {getLocationNameById(locations, destination)}
              </Box>
            ) || (
              <Dropdown
                mb={1.7}
                over
                width="240px"
                options={locations.map(location => location.name)}
                disabled={locked || authorization_required}
                selected={getLocationNameById(locations, destination) || "Select a Destination"}
                onSelected={value => act('set_destination', {
                  destination: getLocationIdByName(locations, value),
                })} />)}
          </LabeledList.Item>
        </LabeledList>
        <Button
          fluid
          content="Depart"
          disabled={!getLocationNameById(locations, destination)
            || locked || authorization_required}
          icon="arrow-up"
          textAlign="center"
          onClick={() => act('move', {
            shuttle_id: destination,
          })} />
      </Section>
    </Section>
  );
};


code:
import { map } from 'common/collections';
import { useBackend, useLocalState } from '../backend';
import { Button, Flex, LabeledList, Section, Table, Tabs } from '../components';
import { Window } from '../layouts';

export const ShuttleManipulator = (props, context) => {
  const [tab, setTab] = useLocalState(context, 'tab', 1);
  return (
    <Window
      title="Shuttle Manipulator"
      width={800}
      height={600}
      theme="admin">
      <Window.Content scrollable>
        <Tabs>
          <Tabs.Tab
            selected={tab === 1}
            onClick={() => setTab(1)}>
            Status
          </Tabs.Tab>
          <Tabs.Tab
            selected={tab === 2}
            onClick={() => setTab(2)}>
            Templates
          </Tabs.Tab>
          <Tabs.Tab
            selected={tab === 3}
            onClick={() => setTab(3)}>
            Modification
          </Tabs.Tab>
        </Tabs>
        {tab === 1 && (
          <ShuttleManipulatorStatus />
        )}
        {tab === 2 && (
          <ShuttleManipulatorTemplates />
        )}
        {tab === 3 && (
          <ShuttleManipulatorModification />
        )}
      </Window.Content>
    </Window>
  );
};

export const ShuttleManipulatorStatus = (props, context) => {
  const { act, data } = useBackend(context);
  const shuttles = data.shuttles || [];
  return (

        {shuttles.map(shuttle => (

              <Button
                content="JMP"
                key={shuttle.id}
                onClick={() => act('jump_to', {
                  type: 'mobile',
                  id: shuttle.id,
                })} />

              <Button
                content="Fly"
                key={shuttle.id}
                disabled={!shuttle.can_fly}
                onClick={() => act('fly', {
                  id: shuttle.id,
                })} />

              {shuttle.name}

              {shuttle.id}

              {shuttle.status}

              {shuttle.mode}
              {!!shuttle.timer && (
                <>
                  ({shuttle.timeleft})
                  <Button
                    content="Fast Travel"
                    key={shuttle.id}
                    disabled={!shuttle.can_fast_travel}
                    onClick={() => act('fast_travel', {
                      id: shuttle.id,
                    })} />
                </>
              )}

        ))}

  );
};

export const ShuttleManipulatorTemplates = (props, context) => {
  const { act, data } = useBackend(context);
  const templateObject = data.templates || {};
  const selected = data.selected || {};
  const [
    selectedTemplateId,
    setSelectedTemplateId,
  ] = useLocalState(context, 'templateId', Object.keys(templateObject)[0]);
  const actualTemplates = templateObject[selectedTemplateId]?.templates || [];
  return (

      <Flex>
        <Flex.Item>
          <Tabs vertical>
            {map((template, templateId) => (
              <Tabs.Tab
                key={templateId}
                selected={selectedTemplateId === templateId}
                onClick={() => setSelectedTemplateId(templateId)}>
                {template.port_id}
              </Tabs.Tab>
            ))(templateObject)}
          </Tabs>
        </Flex.Item>
        <Flex.Item grow={1} basis={0}>
          {actualTemplates.map(actualTemplate => {
            const isSelected = (
              actualTemplate.shuttle_id === selected.shuttle_id
            );
            // Whoever made the structure being sent is an asshole
            return (
              <Section
                title={actualTemplate.name}
                level={2}
                key={actualTemplate.shuttle_id}
                buttons={(
                  <Button
                    content={isSelected ? 'Selected' : 'Select'}
                    selected={isSelected}
                    onClick={() => act('select_template', {
                      shuttle_id: actualTemplate.shuttle_id,
                    })} />
                )}>
                {(!!actualTemplate.description
                  || !!actualTemplate.admin_notes
                ) && (
                  <LabeledList>
                    {!!actualTemplate.description && (
                      <LabeledList.Item label="Description">
                        {actualTemplate.description}
                      </LabeledList.Item>
                    )}
                    {!!actualTemplate.admin_notes && (
                      <LabeledList.Item label="Admin Notes">
                        {actualTemplate.admin_notes}
                      </LabeledList.Item>
                    )}
                  </LabeledList>
                )}

            );
          })}
        </Flex.Item>
      </Flex>

  );
};

export const ShuttleManipulatorModification = (props, context) => {
  const { act, data } = useBackend(context);
  const selected = data.selected || {};
  const existingShuttle = data.existing_shuttle || {};
  return (

      {selected ? (
        <>

            {(!!selected.description || !!selected.admin_notes) && (
              <LabeledList>
                {!!selected.description && (
                  <LabeledList.Item label="Description">
                    {selected.description}
                  </LabeledList.Item>
                )}
                {!!selected.admin_notes && (
                  <LabeledList.Item label="Admin Notes">
                    {selected.admin_notes}
                  </LabeledList.Item>
                )}
              </LabeledList>
            )}

          {existingShuttle ? (

              <LabeledList>
                <LabeledList.Item
                  label="Status"
                  buttons={(
                    <Button
                      content="Jump To"
                      onClick={() => act('jump_to', {
                        type: 'mobile',
                        id: existingShuttle.id,
                      })} />
                  )}>
                  {existingShuttle.status}
                  {!!existingShuttle.timer && (
                    <>
                      ({existingShuttle.timeleft})
                    </>
                  )}
                </LabeledList.Item>
              </LabeledList>

          ) : (

          )}

            <Button
              content="Load"
              color="good"
              onClick={() => act('load', {
                shuttle_id: selected.shuttle_id,
              })} />
            <Button
              content="Preview"
              onClick={() => act('preview', {
                shuttle_id: selected.shuttle_id,
              })} />
            <Button
              content="Replace"
              color="bad"
              onClick={() => act('replace', {
                shuttle_id: selected.shuttle_id,
              })} />

        </>
      ) : 'No shuttle selected'}

  );
};


code:
import { toFixed } from 'common/math';
import { useBackend } from '../backend';
import { Button, Grid, NumberInput, Section } from '../components';
import { Window } from '../layouts';

export const Signaler = (props, context) => {
  const { act, data } = useBackend(context);
  return (
    <Window
      width={280}
      height={132}>
      <Window.Content>
        <SignalerContent />
      </Window.Content>
    </Window>
  );
};

export const SignalerContent = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    code,
    frequency,
    minFrequency,
    maxFrequency,
  } = data;
  const color = 'rgba(13, 13, 213, 0.7)';
  const backColor = 'rgba(0, 0, 69, 0.5)';
  return (
    <Section>
      <Grid>
        <Grid.Column size={1.4} color="label">
          Frequency:
        </Grid.Column>
        <Grid.Column>
          <NumberInput
            animate
            unit="kHz"
            step={0.2}
            stepPixelSize={6}
            minValue={minFrequency / 10}
            maxValue={maxFrequency / 10}
            value={frequency / 10}
            format={value => toFixed(value, 1)}
            width="80px"
            onDrag={(e, value) => act('freq', {
              freq: value,
            })} />
        </Grid.Column>
        <Grid.Column>
          <Button
            ml={1.3}
            icon="sync"
            content="Reset"
            onClick={() => act('reset', {
              reset: "freq",
            })} />
        </Grid.Column>
      </Grid>
      <Grid mt={0.6}>
        <Grid.Column size={1.4} color="label">
          Code:
        </Grid.Column>
        <Grid.Column>
          <NumberInput
            animate
            step={1}
            stepPixelSize={6}
            minValue={1}
            maxValue={100}
            value={code}
            width="80px"
            onDrag={(e, value) => act('code', {
              code: value,
            })} />
        </Grid.Column>
        <Grid.Column>
          <Button
            ml={1.3}
            icon="sync"
            content="Reset"
            onClick={() => act('reset', {
              reset: "code",
            })} />
        </Grid.Column>
      </Grid>
      <Grid mt={0.8}>
        <Grid.Column>
          <Button
            mb={-0.1}
            fluid
            icon="arrow-up"
            content="Send Signal"
            textAlign="center"
            onClick={() => act('signal')} />
        </Grid.Column>
      </Grid>
    </Section>
  );
};


code:
import { useBackend } from '../backend';
import { Box, Button, LabeledList, ProgressBar, Section } from '../components';
import { Window } from '../layouts';

const skillgreen = {
  color: 'lightgreen',
  fontWeight: 'bold',
};

const skillyellow = {
  color: '#FFDB58',
  fontWeight: 'bold',
};

export const SkillPanel = (props, context) => {
  const { act, data } = useBackend(context);
  const skills = data.skills || [];
  return (
    <Window
      title="Manage Skills"
      width={600}
      height={500}>
      <Window.Content scrollable>

          <LabeledList>
            {skills.map(skill => (
              <LabeledList.Item
                key={skill.name}
                label={skill.name}>

                  {skill.desc}

                <Level
                  skill_lvl_num={skill.lvlnum}
                  skill_lvl={skill.lvl} />

                Total Experience: [{skill.exp} XP]

                XP To Next Level:
                {skill.exp_req !== 0 ? (

                    [{skill.exp_prog} / {skill.exp_req}]

                ) : (

                    [MAXXED]

                )}

                Overall Skill Progress: [{skill.exp} / {skill.max_exp}]
                <ProgressBar
                  value={skill.exp_percent}
                  color="good" />

                <Button
                  content="Adjust Exp"
                  onClick={() => act('adj_exp', {
                    skill: skill.path,
                  })} />
                <Button
                  content="Set Exp"
                  onClick={() => act('set_exp', {
                    skill: skill.path,
                  })} />
                <Button
                  content="Set Level"
                  onClick={() => act('set_lvl', {
                    skill: skill.path,
                  })} />

              </LabeledList.Item>
            ))}
          </LabeledList>

      </Window.Content>
    </Window>
  );
};

const Level = props => {
  const {
    skill_lvl_num,
    skill_lvl,
  } = props;
  return (
    <Box inline>
      Level: [
      <Box
        inline
        bold
        textColor={`hsl(${skill_lvl_num * 50}, 50%, 50%)`}>
        {skill_lvl}
      </Box>
      ]
    </Box>
  );
};


code:
import { toFixed } from 'common/math';
import { useBackend } from '../backend';
import { Box, Button, Flex, Icon, LabeledList, NoticeBox, Section, Stack, Table } from '../components';
import { Window } from '../layouts';

export const InsertedSkillchip = (props, context) => {
  const { act, data } = useBackend(context);

  const {
    skillchip_ready,
    slot_use,
    slots_used,
    slots_max,
    implantable_reason,
    implantable,
    complexity,
    skill_name,
    skill_desc,
    skill_icon,
    working,
  } = data;

  if (!skillchip_ready) {
    return (
      (!working && (
        <NoticeBox
          info>
          Please insert a skillchip.
        </NoticeBox>
      ))
    );
  }

  return (
    <Section
      title="Inserted Skillchip"
      buttons={
        <>
          <Button
            icon="syringe"
            disabled={!implantable || !!working}
            color={implantable ? "good" : "default"}
            onClick={() => act("implant")}
            content="Implant"
            tooltip={implantable_reason} />
          <Button
            icon="eject"
            disabled={!!working}
            onClick={() => act("eject")}
            content="Eject" />
        </>
      }>
      <Stack fill align="center">
        <Stack.Item>
          <Icon m={1} size={3} name={skill_icon} />
        </Stack.Item>
        <Stack.Item grow basis={0}>
          <LabeledList>
            <LabeledList.Item
              label="Skillchip">
              <Box
                bold>{skill_name}
              </Box>
            </LabeledList.Item>
            <LabeledList.Item
              label="Description">
              <Box
                italic>
                {skill_desc}
              </Box>
            </LabeledList.Item>
            <LabeledList.Item
              label="Complexity">
              <Icon
                name="brain"
                width="15px"
                textAlign="center"
              /> {complexity}
            </LabeledList.Item>
            <LabeledList.Item
              label="Slot Size">
              <Box
                color={(slots_used + slot_use > slots_max) && "red"}>
                <Icon
                  name="save"
                  width="15px"
                  textAlign="center"
                /> {slot_use}
              </Box>
            </LabeledList.Item>
            {!!implantable_reason && (
              <LabeledList.Item
                label="Error"
                color={implantable ? "good" : "bad"}>
                {implantable_reason}
              </LabeledList.Item>
            )}
          </LabeledList>
        </Stack.Item>
      </Stack>
    </Section>
  );
};

export const ImplantedSkillchips = (props, context) => {
  const { act, data } = useBackend(context);

  const {
    slots_used,
    slots_max,
    complexity_used,
    complexity_max,
    working,
  } = data;

  const current = data.current || [];

  return (
    <Section
      title="Implanted Skillchips">
      {!current.length && "No skillchips detected."}
      {!!current.length && (
        <Table>
          <Table.Row
            header>
            <Table.Cell>
              Chip
            </Table.Cell>
            <Table.Cell
              textAlign="center">
              <Button
                color="transparent"
                icon="brain"
                tooltip="Complexity"
                tooltipPosition="top"
                content={complexity_used + "/" + complexity_max} />
            </Table.Cell>
            <Table.Cell
              textAlign="center">
              <Button
                color="transparent"
                icon="save"
                tooltip="Slot Size"
                tooltipPosition="top"
                content={slots_used + "/" + slots_max} />
            </Table.Cell>
            <Table.Cell
              textAlign="center">
              <Button
                color="transparent"
                icon="check"
                tooltip="Is Active"
                tooltipPosition="top" />
            </Table.Cell>
            <Table.Cell
              textAlign="center">
              <Button
                color="transparent"
                icon="hourglass-half"
                tooltip="Cooldown"
                tooltipPosition="top" />
            </Table.Cell>
            <Table.Cell
              textAlign="center">
              <Button
                color="transparent"
                icon="tasks"
                tooltip="Actions"
                tooltipPosition="top" />
            </Table.Cell>
          </Table.Row>
          {current.map(skill => (
            <Table.Row
              key={skill.ref}>
              <Table.Cell>
                <Icon
                  textAlign="center"
                  width="18px"
                  mr={1}
                  name={skill.icon} />
                {skill.name}
              </Table.Cell>
              <Table.Cell
                bold
                color={(!!skill.active && "good"
                ) || (
                  (skill.complexity + complexity_used > complexity_max) && "bad"
                ) || (
                  "grey"
                )}
                textAlign="center">
                {skill.complexity}
              </Table.Cell>
              <Table.Cell
                bold
                color="good"
                textAlign="center">
                {skill.slot_use}
              </Table.Cell>
              <Table.Cell
                textAlign="center">
                <Icon
                  name={skill.active ? "check" : "times"}
                  color={skill.active ? "good" : "bad"} />
              </Table.Cell>
              <Table.Cell
                textAlign="center">
                {(skill.cooldown > 0) && (
                  Math.ceil(skill.cooldown / 10) + "s"
                ) || ("0s")}
              </Table.Cell>
              <Table.Cell
                textAlign="center">
                <Button
                  onClick={() => act("remove", { "ref": skill.ref })}
                  icon={skill.removable ? "eject" : "trash"}
                  color={skill.removable ? "good" : "bad"}
                  tooltip={skill.removable ? "Extract" : "Destroy"}
                  tooltipPosition="left"
                  disabled={skill.cooldown || working} />
                <Button
                  onClick={() => act("toggle_activate", { "ref": skill.ref })}
                  icon={skill.active ? "check-square-o" : "square-o"}
                  color={skill.active ? "good" : "default"}
                  tooltip={(!!skill.active_error
                    && !skill.active
                    && skill.active_error) || (
                    skill.active && "Deactivate") || (
                    "Activate"
                  )}
                  tooltipPosition="left"
                  disabled={
                    skill.cooldown
                    || working
                    || (!skill.active
                      && (skill.complexity + complexity_used > complexity_max))
                  } />
              </Table.Cell>
            </Table.Row>))}
        </Table>
      )}
    </Section>
  );
};

export const TimeFormat = (props, context) => {
  const { value } = props;

  const seconds = toFixed(Math.floor((value/10) % 60)).padStart(2, "0");
  const minutes = toFixed(Math.floor((value/(10*60)) % 60)).padStart(2, "0");
  const hours = toFixed(Math.floor((value/(10*60*60)) % 24)).padStart(2, "0");
  const formattedValue = `${hours}:${minutes}:${seconds}`;
  return formattedValue;
};

export const SkillStation = (props, context) => {
  const { data } = useBackend(context);
  const {
    working,
    timeleft,
    error,
  } = data;
  return (
    <Window
      title="Skillsoft Station"
      width={500}
      height={500}>
      <Window.Content>
        {!!error && (
          <NoticeBox>
            {error}
          </NoticeBox>
        )}
        {!!working && (
          <NoticeBox
            danger>
            <Flex
              direction="column">
              <Flex.Item
                mb={0.5}>
                Operation in progress. Please do not leave the chamber.
              </Flex.Item>
              <Flex.Item>
                Time Left: <TimeFormat value={timeleft} />
              </Flex.Item>
            </Flex>
          </NoticeBox>
        )}
        <InsertedSkillchip />
        <ImplantedSkillchips />
      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from '../backend';
import { Box, Button, LabeledList, ProgressBar, Section } from '../components';
import { Window } from '../layouts';

const damageTypes = [
  {
    label: 'Brute',
    type: 'bruteLoss',
  },
  {
    label: 'Burn',
    type: 'fireLoss',
  },
  {
    label: 'Toxin',
    type: 'toxLoss',
  },
  {
    label: 'Oxygen',
    type: 'oxyLoss',
  },
];

export const Sleeper = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    open,
    occupant = {},
    occupied,
  } = data;
  const preSortChems = data.chems || [];
  const chems = preSortChems.sort((a, b) => {
    const descA = a.name.toLowerCase();
    const descB = b.name.toLowerCase();
    if (descA < descB) {
      return -1;
    }
    if (descA > descB) {
      return 1;
    }
    return 0;
  });
  return (
    <Window
      width={310}
      height={465}>
      <Window.Content>
        <Section
          title={occupant.name ? occupant.name : 'No Occupant'}
          minHeight="210px"
          buttons={!!occupant.stat && (
            <Box
              inline
              bold
              color={occupant.statstate}>
              {occupant.stat}
            </Box>
          )}>
          {!!occupied && (
            <>
              <ProgressBar
                value={occupant.health}
                minValue={occupant.minHealth}
                maxValue={occupant.maxHealth}
                ranges={{
                  good: [50, Infinity],
                  average: [0, 50],
                  bad: [-Infinity, 0],
                }} />
              <Box mt={1} />
              <LabeledList>
                {damageTypes.map(type => (
                  <LabeledList.Item
                    key={type.type}
                    label={type.label}>
                    <ProgressBar
                      value={occupant[type.type]}
                      minValue={0}
                      maxValue={occupant.maxHealth}
                      color="bad" />
                  </LabeledList.Item>
                ))}
                <LabeledList.Item
                  label="Cells"
                  color={occupant.cloneLoss ? 'bad' : 'good'}>
                  {occupant.cloneLoss ? 'Damaged' : 'Healthy'}
                </LabeledList.Item>
                <LabeledList.Item
                  label="Brain"
                  color={occupant.brainLoss ? 'bad' : 'good'}>
                  {occupant.brainLoss ? 'Abnormal' : 'Healthy'}
                </LabeledList.Item>
              </LabeledList>
            </>
          )}
        </Section>
        <Section
          title="Medicines"
          minHeight="205px"
          buttons={(
            <Button
              icon={open ? 'door-open' : 'door-closed'}
              content={open ? 'Open' : 'Closed'}
              onClick={() => act('door')} />
          )}>
          {chems.map(chem => (
            <Button
              key={chem.name}
              icon="flask"
              content={chem.name}
              disabled={!occupied || !chem.allowed}
              width="140px"
              onClick={() => act('inject', {
                chem: chem.id,
              })} />
          ))}
        </Section>
      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from '../backend';
import { Section, LabeledList, Button, Box } from '../components';
import { Window } from '../layouts';

const statusMap = {
  Dead: "bad",
  Unconscious: "average",
  Conscious: "good",
};

const occupiedMap = {
  owner: "You Are Here",
  stranger: "Occupied",
  available: "Swap",
};

export const BodyEntry = (props, context) => {
  const { body, swapFunc } = props;
  return (
    <Section
      title={(
        <Box inline color={body.htmlcolor}>
          {body.name}
        </Box>
      )}
      level={2}
      buttons={(
        <Button
          content={occupiedMap[body.occupied]}
          selected={body.occupied === 'owner'}
          color={(body.occupied === 'stranger') && 'bad'}
          onClick={() => swapFunc()}
        />
      )}>
      <LabeledList>
        <LabeledList.Item
          label="Status"
          bold
          color={statusMap[body.status]}>
          {body.status}
        </LabeledList.Item>
        <LabeledList.Item label="Jelly">
          {body.exoticblood}
        </LabeledList.Item>
        <LabeledList.Item label="Location">
          {body.area}
        </LabeledList.Item>
      </LabeledList>
    </Section>
  );
};

export const SlimeBodySwapper = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    bodies = [],
  } = data;
  return (
    <Window
      width={400}
      height={400}>
      <Window.Content scrollable>
        <Section>
          {bodies.map(body => (
            <BodyEntry
              key={body.name}
              body={body}
              swapFunc={() => act('swap', { ref: body.ref })} />
          ))}
        </Section>
      </Window.Content>
    </Window>
  );
};


code:
import { map } from 'common/collections';
import { useBackend } from '../backend';
import { Button, NoticeBox, Section, Table } from '../components';
import { Window } from '../layouts';

export const SmartVend = (props, context) => {
  const { act, data } = useBackend(context);
  return (
    <Window
      width={440}
      height={550}>
      <Window.Content scrollable>
        <Section
          title="Storage"
          buttons={!!data.isdryer && (
            <Button
              icon={data.drying ? 'stop' : 'tint'}
              onClick={() => act('Dry')}>
              {data.drying ? 'Stop drying' : 'Dry'}
            </Button>
          )}>
          {data.contents.length === 0 && (
            <NoticeBox>
              Unfortunately, this {data.name} is empty.
            </NoticeBox>
          ) || (
            <Table>
              <Table.Row header>
                <Table.Cell>
                  Item
                </Table.Cell>
                <Table.Cell collapsing />
                <Table.Cell collapsing textAlign="center">
                  {data.verb ? data.verb : 'Dispense'}
                </Table.Cell>
              </Table.Row>
              {map((value, key) => (
                <Table.Row key={key}>
                  <Table.Cell>
                    {value.name}
                  </Table.Cell>
                  <Table.Cell collapsing textAlign="right">
                    {value.amount}
                  </Table.Cell>
                  <Table.Cell collapsing>
                    <Button
                      content="One"
                      disabled={value.amount < 1}
                      onClick={() => act('Release', {
                        name: value.name,
                        amount: 1,
                      })} />
                    <Button
                      content="Many"
                      disabled={value.amount <= 1}
                      onClick={() => act('Release', {
                        name: value.name,
                      })} />
                  </Table.Cell>
                </Table.Row>
              ))(data.contents)}
            </Table>
          )}
        </Section>
      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from '../backend';
import { Box, Button, Flex, LabeledList, ProgressBar, Section, Slider } from '../components';
import { formatPower } from '../format';
import { Window } from '../layouts';

// Common power multiplier
const POWER_MUL = 1e3;

export const Smes = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    capacityPercent,
    capacity,
    charge,
    inputAttempt,
    inputting,
    inputLevel,
    inputLevelMax,
    inputAvailable,
    outputAttempt,
    outputting,
    outputLevel,
    outputLevelMax,
    outputUsed,
  } = data;
  const inputState = (
    capacityPercent >= 100 && 'good'
    || inputting && 'average'
    || 'bad'
  );
  const outputState = (
    outputting && 'good'
    || charge > 0 && 'average'
    || 'bad'
  );
  return (
    <Window
      width={340}
      height={350}>
      <Window.Content>

          <ProgressBar
            value={capacityPercent * 0.01}
            ranges={{
              good: [0.5, Infinity],
              average: [0.15, 0.5],
              bad: [-Infinity, 0.15],
            }} />

          <LabeledList>
            <LabeledList.Item
              label="Charge Mode"
              buttons={
                <Button
                  icon={inputAttempt ? 'sync-alt' : 'times'}
                  selected={inputAttempt}
                  onClick={() => act('tryinput')}>
                  {inputAttempt ? 'Auto' : 'Off'}
                </Button>
              }>
              <Box color={inputState}>
                {capacityPercent >= 100 && 'Fully Charged'
                  || inputting && 'Charging'
                  || 'Not Charging'}
              </Box>
            </LabeledList.Item>
            <LabeledList.Item label="Target Input">
              <Flex inline width="100%">
                <Flex.Item>
                  <Button
                    icon="fast-backward"
                    disabled={inputLevel === 0}
                    onClick={() => act('input', {
                      target: 'min',
                    })} />
                  <Button
                    icon="backward"
                    disabled={inputLevel === 0}
                    onClick={() => act('input', {
                      adjust: -10000,
                    })} />
                </Flex.Item>
                <Flex.Item grow={1} mx={1}>
                  <Slider
                    value={inputLevel / POWER_MUL}
                    fillValue={inputAvailable / POWER_MUL}
                    minValue={0}
                    maxValue={inputLevelMax / POWER_MUL}
                    step={5}
                    stepPixelSize={4}
                    format={value => formatPower(value * POWER_MUL, 1)}
                    onDrag={(e, value) => act('input', {
                      target: value * POWER_MUL,
                    })} />
                </Flex.Item>
                <Flex.Item>
                  <Button
                    icon="forward"
                    disabled={inputLevel === inputLevelMax}
                    onClick={() => act('input', {
                      adjust: 10000,
                    })} />
                  <Button
                    icon="fast-forward"
                    disabled={inputLevel === inputLevelMax}
                    onClick={() => act('input', {
                      target: 'max',
                    })} />
                </Flex.Item>
              </Flex>
            </LabeledList.Item>
            <LabeledList.Item label="Available">
              {formatPower(inputAvailable)}
            </LabeledList.Item>
          </LabeledList>

          <LabeledList>
            <LabeledList.Item
              label="Output Mode"
              buttons={
                <Button
                  icon={outputAttempt ? 'power-off' : 'times'}
                  selected={outputAttempt}
                  onClick={() => act('tryoutput')}>
                  {outputAttempt ? 'On' : 'Off'}
                </Button>
              }>
              <Box color={outputState}>
                {outputting
                  ? 'Sending'
                  : charge > 0
                    ? 'Not Sending'
                    : 'No Charge'}
              </Box>
            </LabeledList.Item>
            <LabeledList.Item label="Target Output">
              <Flex inline width="100%">
                <Flex.Item>
                  <Button
                    icon="fast-backward"
                    disabled={outputLevel === 0}
                    onClick={() => act('output', {
                      target: 'min',
                    })} />
                  <Button
                    icon="backward"
                    disabled={outputLevel === 0}
                    onClick={() => act('output', {
                      adjust: -10000,
                    })} />
                </Flex.Item>
                <Flex.Item grow={1} mx={1}>
                  <Slider
                    value={outputLevel / POWER_MUL}
                    minValue={0}
                    maxValue={outputLevelMax / POWER_MUL}
                    step={5}
                    stepPixelSize={4}
                    format={value => formatPower(value * POWER_MUL, 1)}
                    onDrag={(e, value) => act('output', {
                      target: value * POWER_MUL,
                    })} />
                </Flex.Item>
                <Flex.Item>
                  <Button
                    icon="forward"
                    disabled={outputLevel === outputLevelMax}
                    onClick={() => act('output', {
                      adjust: 10000,
                    })} />
                  <Button
                    icon="fast-forward"
                    disabled={outputLevel === outputLevelMax}
                    onClick={() => act('output', {
                      target: 'max',
                    })} />
                </Flex.Item>
              </Flex>
            </LabeledList.Item>
            <LabeledList.Item label="Outputting">
              {formatPower(outputUsed)}
            </LabeledList.Item>
          </LabeledList>

      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from '../backend';
import { AnimatedNumber, Box, Button, LabeledList, ProgressBar, Section } from '../components';
import { Window } from '../layouts';

export const SmokeMachine = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    TankContents,
    isTankLoaded,
    TankCurrentVolume,
    TankMaxVolume,
    active,
    setting,
    screen,
    maxSetting = [],
  } = data;
  return (
    <Window
      width={350}
      height={350}>
      <Window.Content>
        <Section title="Dispersal Tank"
          buttons={(
            <Button
              icon={active ? 'power-off' : 'times'}
              selected={active}
              content={active ? 'On' : 'Off'}
              onClick={() => act('power')} />
          )}>
          <ProgressBar
            value={TankCurrentVolume / TankMaxVolume}
            ranges={{
              bad: [-Infinity, 0.3],
            }}>
            <AnimatedNumber initial={0} value={TankCurrentVolume || 0} />
            {' / ' + TankMaxVolume}
          </ProgressBar>
          <Box mt={1}>
            <LabeledList>
              <LabeledList.Item label="Range">
                {[1, 2, 3, 4, 5].map(amount => (
                  <Button
                    key={amount}
                    selected={setting === amount}
                    icon="plus"
                    content={amount * 3}
                    disabled={maxSetting < amount}
                    onClick={() => act('setting', { amount })} />
                ))}
              </LabeledList.Item>
            </LabeledList>
          </Box>

        <Section title="Contents"
          buttons={(
            <Button
              icon="trash"
              content="Purge"
              onClick={() => act('purge')} />
          )}>
          {TankContents.map(chemical => (
            <Box
              key={chemical.name}
              color="label">
              <AnimatedNumber
                initial={0}
                value={chemical.volume} />
              {' '}
              units of {chemical.name}
            </Box>
          ))}

      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from '../backend';
import { Box, Button, Grid, LabeledList, NumberInput, ProgressBar, Section } from '../components';
import { Window } from '../layouts';

export const SolarControl = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    generated,
    generated_ratio,
    azimuth_current,
    azimuth_rate,
    max_rotation_rate,
    tracking_state,
    connected_panels,
    connected_tracker,
  } = data;
  return (
    <Window
      width={380}
      height={230}>
      <Window.Content>
        <Section
          title="Status"
          buttons={(
            <Button
              icon="sync"
              content="Scan for new hardware"
              onClick={() => act('refresh')} />
          )}>
          <Grid>
            <Grid.Column>
              <LabeledList>
                <LabeledList.Item
                  label="Solar tracker"
                  color={connected_tracker ? 'good' : 'bad'}>
                  {connected_tracker ? 'OK' : 'N/A'}
                </LabeledList.Item>
                <LabeledList.Item
                  label="Solar panels"
                  color={connected_panels > 0 ? 'good' : 'bad'}>
                  {connected_panels}
                </LabeledList.Item>
              </LabeledList>
            </Grid.Column>
            <Grid.Column size={1.5}>
              <LabeledList>
                <LabeledList.Item label="Power output">
                  <ProgressBar
                    ranges={{
                      good: [0.66, Infinity],
                      average: [0.33, 0.66],
                      bad: [-Infinity, 0.33],
                    }}
                    minValue={0}
                    maxValue={1}
                    value={generated_ratio}>
                    {generated + ' W'}
                  </ProgressBar>
                </LabeledList.Item>
              </LabeledList>
            </Grid.Column>
          </Grid>
        </Section>
        <Section title="Controls">
          <LabeledList>
            <LabeledList.Item label="Tracking">
              <Button
                icon="times"
                content="Off"
                selected={tracking_state === 0}
                onClick={() => act('tracking', { mode: 0 })} />
              <Button
                icon="clock-o"
                content="Timed"
                selected={tracking_state === 1}
                onClick={() => act('tracking', { mode: 1 })} />
              <Button
                icon="sync"
                content="Auto"
                selected={tracking_state === 2}
                disabled={!connected_tracker}
                onClick={() => act('tracking', { mode: 2 })} />
            </LabeledList.Item>
            <LabeledList.Item label="Azimuth">
              {(tracking_state === 0 || tracking_state === 1) && (
                <NumberInput
                  width="52px"
                  unit="°"
                  step={1}
                  stepPixelSize={2}
                  minValue={-360}
                  maxValue={+720}
                  value={azimuth_current}
                  onDrag={(e, value) => act('azimuth', { value })} />
              )}
              {tracking_state === 1 && (
                <NumberInput
                  width="80px"
                  unit="°/m"
                  step={0.01}
                  stepPixelSize={1}
                  minValue={-max_rotation_rate-0.01}
                  maxValue={max_rotation_rate+0.01}
                  value={azimuth_rate}
                  format={rate => {
                    const sign = Math.sign(rate) > 0 ? '+' : '-';
                    return sign + Math.abs(rate);
                  }}
                  onDrag={(e, value) => act('azimuth_rate', { value })} />
              )}
              {tracking_state === 2 && (
                <Box inline color="label" mt="3px">
                  {azimuth_current + ' °'} (auto)
                </Box>
              )}
            </LabeledList.Item>
          </LabeledList>
        </Section>
      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from '../backend';
import { Box, Button, LabeledList, NumberInput, ProgressBar, Section } from '../components';
import { Window } from '../layouts';

export const SpaceHeater = (props, context) => {
  const { act, data } = useBackend(context);
  return (
    <Window
      width={400}
      height={305}>
      <Window.Content>
        <Section
          title="Power"
          buttons={(
            <>
              {!!data.chemHacked && (
                <Button
                  icon="eject"
                  content="Eject beaker"
                  disabled={!data.beaker}
                  onClick={() => act('ejectBeaker')} />
              )}
              <Button
                icon="eject"
                content="Eject Cell"
                disabled={!data.hasPowercell || !data.open}
                onClick={() => act('eject')} />
              <Button
                icon={data.on ? 'power-off' : 'times'}
                content={data.on ? 'On' : 'Off'}
                selected={data.on}
                disabled={!data.hasPowercell}
                onClick={() => act('power')} />
            </>
          )}>
          <LabeledList>
            <LabeledList.Item
              label="Cell"
              color={!data.hasPowercell && 'bad'}>
              {data.hasPowercell && (
                <ProgressBar
                  value={data.powerLevel / 100}
                  ranges={{
                    good: [0.6, Infinity],
                    average: [0.3, 0.6],
                    bad: [-Infinity, 0.3],
                  }}>
                  {data.powerLevel + '%'}
                </ProgressBar>
              ) || 'None'}
            </LabeledList.Item>
          </LabeledList>
        </Section>
        <Section title="Thermostat">
          <LabeledList>
            <LabeledList.Item label="Current Temperature">
              <Box
                fontSize="18px"
                color={Math.abs(data.targetTemp - data.currentTemp) > 50
                  ? 'bad'
                  : Math.abs(data.targetTemp - data.currentTemp) > 20
                    ? 'average'
                    : 'good'}>
                {data.currentTemp}°C
              </Box>
            </LabeledList.Item>
            <LabeledList.Item label="Target Temperature">
              {data.open && (
                <NumberInput
                  animated
                  value={parseFloat(data.targetTemp)}
                  width="65px"
                  unit="°C"
                  minValue={data.minTemp}
                  maxValue={data.maxTemp}
                  onChange={(e, value) => act('target', {
                    target: value,
                  })} />
              ) || (
                data.targetTemp + '°C'
              )}
            </LabeledList.Item>
            <LabeledList.Item label="Mode">
              {!data.open && 'Auto' || (
                <>
                  <Button
                    icon="thermometer-half"
                    content="Auto"
                    selected={data.mode === 'auto'}
                    onClick={() => act('mode', {
                      mode: "auto",
                    })} />
                  <Button
                    icon="fire-alt"
                    content="Heat"
                    selected={data.mode === 'heat'}
                    onClick={() => act('mode', {
                      mode: "heat",
                    })} />
                  <Button
                    icon="fan"
                    content="Cool"
                    selected={data.mode === 'cool'}
                    onClick={() => act('mode', {
                      mode: 'cool',
                    })} />
                </>
              )}
            </LabeledList.Item>
            <LabeledList.Divider />
          </LabeledList>
        </Section>
      </Window.Content>
    </Window>
  );
};


code:
import { BooleanLike } from 'common/react';
import { multiline } from 'common/string';
import { useBackend, useLocalState } from '../backend';
import { BlockQuote, Button, Dropdown, Section, Stack } from '../components';
import { Window } from '../layouts';

// defined this so the code is more readable
const STAKES_HOLY_MATCH = 1;

const weaponlist = [
  "Fist Fight",
  "Ceremonial Weapons",
  "Melee Only",
  "Any Weapons",
];

const stakelist = [
  "No Stakes",
  "Holy Match",
  "Money Match",
  "Your Soul",
];

const weaponblurb = [
  "You will fight with your fists only. Any weapons will be considered a violation.",
  "You can only fight with ceremonial weapons. You will be at a severe disadvantage without one!",
  "You can fight with weapons, or fists if you have none. Ranged weapons are a violation.",
  "You can fight with any and all weapons as you please. Try not to kill them, okay?",
];

const stakesblurb = [
  "No stakes, just for fun. Who doesn't love some recreational sparring?",
  "A match for the chaplain's deity. The Chaplain suffers large consequences for failure, but advances their sect by winning.",
  "A match with money on the line. Whomever wins takes all the money of whomever loses.",
  "A lethal match with the loser's soul becoming under ownership of the winner.",
];

type Info = {
  set_weapon: number;
  set_area: string;
  set_stakes: number;
  left_sign: string;
  right_sign: string;
  in_area: BooleanLike;
  no_chaplains: BooleanLike;
  possible_areas: Array<string>;
};

export const SparringContract = (props, context) => {
  const { data, act } = useBackend<Info>(context);
  const {
    set_weapon,
    set_area,
    set_stakes,
    possible_areas,
    left_sign,
    right_sign,
    in_area,
    no_chaplains,
  } = data;
  const [weapon, setWeapon] = useLocalState(context, "weapon", set_weapon);
  const [area, setArea] = useLocalState(context, "area", set_area);
  const [stakes, setStakes] = useLocalState(context, "stakes", set_stakes);
  return (
    <Window
      width={420}
      height={380}>
      <Window.Content>

          <Stack vertical fill>
            <Stack.Item>
              <Stack vertical>
                <Stack.Item>
                  <Stack fill>
                    <Stack.Item grow fontSize="16px">
                      Weapons:
                    </Stack.Item>
                    <Stack.Item>
                      <Button
                        tooltip={multiline`
                        The Chaplain's Deity wishes for honorable fighting.
                        As such, it uses contracts. Signing your name will
                        set the terms for the battle. Then, the person you
                        intend to spar with must sign the other side. If terms
                        are changed on an already signed contract, the
                        signatures will erase and the new terms must be
                        re-agreed upon.
                        `}
                        icon="info">
                        Contract?
                      </Button>
                    </Stack.Item>
                  </Stack>
                </Stack.Item>
                <Stack.Item>
                  <Dropdown
                    width="100%"
                    selected={weaponlist[weapon-1]}
                    options={weaponlist}
                    onSelected={value =>
                      setWeapon(weaponlist.findIndex(title => (
                        title === value
                      ))+1)} />
                </Stack.Item>
                <Stack.Item>

                    {weaponblurb[weapon-1]}

                </Stack.Item>
              </Stack>
            </Stack.Item>
            <Stack.Item>
              <Stack vertical>
                <Stack.Item fontSize="16px">
                  Arena:
                </Stack.Item>
                <Stack.Item>
                  <Dropdown
                    width="100%"
                    selected={area}
                    options={possible_areas}
                    onSelected={value => setArea(value)} />
                </Stack.Item>
                <Stack.Item>

                    This fight will take place in the {area}.
                    Leaving the arena mid-fight is a violation.

                </Stack.Item>
              </Stack>
            </Stack.Item>
            <Stack.Item>
              <Stack vertical>
                <Stack.Item fontSize="16px">
                  Stakes:
                </Stack.Item>
                <Stack.Item>
                  <Dropdown
                    width="100%"
                    selected={stakelist[stakes-1]}
                    options={stakelist}
                    onSelected={value =>
                      setStakes(stakelist.findIndex(title => (
                        title === value
                      ))+1)} />
                </Stack.Item>
                <Stack.Item>

                    {stakesblurb[stakes-1]}

                </Stack.Item>
              </Stack>
            </Stack.Item>
            <Stack.Item grow>
              <Stack grow textAlign="center">
                <Stack.Item
                  fontSize={left_sign !== "none" && "14px"}
                  grow>
                  {left_sign === 'none' && (
                    <Button
                      icon="pen"
                      onClick={() => act('sign', {
                        "weapon": weapon,
                        "area": area,
                        "stakes": stakes,
                        "sign_position": "left",
                      })}>
                      Sign Here
                    </Button>
                  ) || (
                    left_sign
                  )}
                </Stack.Item>
                <Stack.Item fontSize="16px">
                  VS
                </Stack.Item>
                <Stack.Item
                  fontSize={right_sign !== "none" && "14px"}
                  grow>
                  {right_sign === "none" && (
                    <Button
                      icon="pen"
                      onClick={() => act('sign', {
                        "weapon": weapon,
                        "area": area,
                        "stakes": stakes,
                      })}>
                      Sign Here
                    </Button>
                  ) || (
                    right_sign
                  )}
                </Stack.Item>
              </Stack>
            </Stack.Item>
            <Stack.Item mb={-0.5}>
              <Stack fill>
                <Stack.Item grow>
                  <Button
                    disabled={
                      !in_area
                      || (no_chaplains && set_stakes === STAKES_HOLY_MATCH)
                    }
                    icon="fist-raised"
                    onClick={() => act('fight')} >
                    FIGHT!
                  </Button>
                  <Button
                    tooltip={multiline`
                      If you've already signed but you want to renegotiate
                      the terms, you can clear out the signatures with
                      this button.
                    `}
                    icon="door-open"
                    onClick={() => act('clear')} >
                    Clear
                  </Button>
                </Stack.Item>
                <Stack.Item>
                  <Button
                    tooltip={in_area
                      && "Both participants are present in the "+ area + "."
                      || "Both participants need to be in the arena!"}
                    color={in_area && "green" || "red"}
                    icon="ring" >
                    Arena
                  </Button>
                  <Button
                    tooltip={(left_sign !== "none" && right_sign !== "none")
                      && "Both signatures present, terms agreed upon."
                      || "You need signatures from both fighters on the terms!"}
                    color={(left_sign !== "none" && right_sign !== "none")
                      && "green"
                      || "red"}
                    icon="file-signature" >
                    Signatures
                  </Button>
                  <Button
                    tooltip={!no_chaplains
                      && "At least one chaplain is present. Holy matches allowed."
                      || "No chaplain present for this fight. No Holy Matches!"}
                    color={!no_chaplains && "green" || "yellow"}
                    icon="cross" >
                    Chaplain
                  </Button>
                </Stack.Item>
              </Stack>
            </Stack.Item>
          </Stack>

      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from '../backend';
import { Box, Button, Section } from '../components';
import { Window } from '../layouts';

export const SpawnersMenu = (props, context) => {
  const { act, data } = useBackend(context);
  const spawners = data.spawners || [];
  return (
    <Window
      title="Spawners Menu"
      width={700}
      height={600}>
      <Window.Content scrollable>
        <Section>
          {spawners.map(spawner => (
            <Section
              key={spawner.name}
              title={spawner.name + ' (' + spawner.amount_left + ' left)'}
              level={2}
              buttons={(
                <>
                  <Button
                    content="Jump"
                    onClick={() => act('jump', {
                      name: spawner.name,
                    })} />
                  <Button
                    content="Spawn"
                    onClick={() => act('spawn', {
                      name: spawner.name,
                    })} />
                </>
              )}>
              <Box
                bold
                mb={1}
                fontSize="20px">
                {spawner.short_desc}
              </Box>
              <Box>
                {spawner.flavor_text}
              </Box>
              {!!spawner.important_info && (
                <Box
                  mt={1}
                  bold
                  color="bad"
                  fontSize="26px">
                  {spawner.important_info}
                </Box>
              )}
            </Section>
          ))}
        </Section>
      </Window.Content>
    </Window>
  );
};