() => {
      // TODO(jeremy): figure out why this times out under ASan
      ifit(!process.env.IS_ASAN)('adds --enable-sandbox to all renderer processes', done => {
        const appPath = path.join(fixturesPath, 'api', 'mixed-sandbox-app');
        appProcess = cp.spawn(process.execPath, [appPath, '--enable-sandbox']);

        server.once('error', error => { done(error); });

        server.on('connection', client => {
          client.once('data', data => {
            const argv = JSON.parse(data.toString());
            expect(argv.sandbox).to.include('--enable-sandbox');
            expect(argv.sandbox).to.not.include('--no-sandbox');

            expect(argv.noSandbox).to.include('--enable-sandbox');
            expect(argv.noSandbox).to.not.include('--no-sandbox');

            expect(argv.noSandboxDevtools).to.equal(true);
            expect(argv.sandboxDevtools).to.equal(true);

            done();
          });
        });
      });
    }


done => {
        const appPath = path.join(fixturesPath, 'api', 'mixed-sandbox-app');
        appProcess = cp.spawn(process.execPath, [appPath, '--enable-sandbox']);

        server.once('error', error => { done(error); });

        server.on('connection', client => {
          client.once('data', data => {
            const argv = JSON.parse(data.toString());
            expect(argv.sandbox).to.include('--enable-sandbox');
            expect(argv.sandbox).to.not.include('--no-sandbox');

            expect(argv.noSandbox).to.include('--enable-sandbox');
            expect(argv.noSandbox).to.not.include('--no-sandbox');

            expect(argv.noSandboxDevtools).to.equal(true);
            expect(argv.sandboxDevtools).to.equal(true);

            done();
          });
        });
      }


client => {
          client.once('data', data => {
            const argv = JSON.parse(data.toString());
            expect(argv.sandbox).to.include('--enable-sandbox');
            expect(argv.sandbox).to.not.include('--no-sandbox');

            expect(argv.noSandbox).to.include('--enable-sandbox');
            expect(argv.noSandbox).to.not.include('--no-sandbox');

            expect(argv.noSandboxDevtools).to.equal(true);
            expect(argv.sandboxDevtools).to.equal(true);

            done();
          });
        }


data => {
            const argv = JSON.parse(data.toString());
            expect(argv.sandbox).to.include('--enable-sandbox');
            expect(argv.sandbox).to.not.include('--no-sandbox');

            expect(argv.noSandbox).to.include('--enable-sandbox');
            expect(argv.noSandbox).to.not.include('--no-sandbox');

            expect(argv.noSandboxDevtools).to.equal(true);
            expect(argv.sandboxDevtools).to.equal(true);

            done();
          }


() => {
    it('throws when called after app is ready', () => {
      expect(() => {
        app.disableDomainBlockingFor3DAPIs();
      }).to.throw(/before app is ready/);
    });
  }


() => {
      expect(() => {
        app.disableDomainBlockingFor3DAPIs();
      }).to.throw(/before app is ready/);
    }


() => {
        app.disableDomainBlockingFor3DAPIs();
      }


() => {
    after(async () => {
      await app.dock.show();
    });

    describe('dock.setMenu', () => {
      it('can be retrieved via dock.getMenu', () => {
        expect(app.dock.getMenu()).to.equal(null);
        const menu = new Menu();
        app.dock.setMenu(menu);
        expect(app.dock.getMenu()).to.equal(menu);
      });

      it('keeps references to the menu', () => {
        app.dock.setMenu(new Menu());
        const v8Util = process._linkedBinding('electron_common_v8_util');
        v8Util.requestGarbageCollectionForTesting();
      });
    });

    describe('dock.setIcon', () => {
      it('throws a descriptive error for a bad icon path', () => {
        const badPath = path.resolve('I', 'Do', 'Not', 'Exist');
        expect(() => {
          app.dock.setIcon(badPath);
        }).to.throw(/Failed to load image from path (.+)/);
      });
    });

    describe('dock.bounce', () => {
      it('should return -1 for unknown bounce type', () => {
        expect(app.dock.bounce('bad type' as any)).to.equal(-1);
      });

      it('should return a positive number for informational type', () => {
        const appHasFocus = !!BrowserWindow.getFocusedWindow();
        if (!appHasFocus) {
          expect(app.dock.bounce('informational')).to.be.at.least(0);
        }
      });

      it('should return a positive number for critical type', () => {
        const appHasFocus = !!BrowserWindow.getFocusedWindow();
        if (!appHasFocus) {
          expect(app.dock.bounce('critical')).to.be.at.least(0);
        }
      });
    });

    describe('dock.cancelBounce', () => {
      it('should not throw', () => {
        app.dock.cancelBounce(app.dock.bounce('critical'));
      });
    });

    describe('dock.setBadge', () => {
      after(() => {
        app.dock.setBadge('');
      });

      it('should not throw', () => {
        app.dock.setBadge('1');
      });

      it('should be retrievable via getBadge', () => {
        app.dock.setBadge('test');
        expect(app.dock.getBadge()).to.equal('test');
      });
    });

    describe('dock.hide', () => {
      it('should not throw', () => {
        app.dock.hide();
        expect(app.dock.isVisible()).to.equal(false);
      });
    });

    // Note that dock.show tests should run after dock.hide tests, to work
    // around a bug of macOS.
    // See https://github.com/electron/electron/pull/25269 for more.
    describe('dock.show', () => {
      it('should not throw', () => {
        return app.dock.show().then(() => {
          expect(app.dock.isVisible()).to.equal(true);
        });
      });

      it('returns a Promise', () => {
        expect(app.dock.show()).to.be.a('promise');
      });

      it('eventually fulfills', async () => {
        await expect(app.dock.show()).to.eventually.be.fulfilled.equal(undefined);
      });
    });
  }


async () => {
      await app.dock.show();
    }


() => {
      it('can be retrieved via dock.getMenu', () => {
        expect(app.dock.getMenu()).to.equal(null);
        const menu = new Menu();
        app.dock.setMenu(menu);
        expect(app.dock.getMenu()).to.equal(menu);
      });

      it('keeps references to the menu', () => {
        app.dock.setMenu(new Menu());
        const v8Util = process._linkedBinding('electron_common_v8_util');
        v8Util.requestGarbageCollectionForTesting();
      });
    }


() => {
        expect(app.dock.getMenu()).to.equal(null);
        const menu = new Menu();
        app.dock.setMenu(menu);
        expect(app.dock.getMenu()).to.equal(menu);
      }


() => {
        app.dock.setMenu(new Menu());
        const v8Util = process._linkedBinding('electron_common_v8_util');
        v8Util.requestGarbageCollectionForTesting();
      }


() => {
      it('throws a descriptive error for a bad icon path', () => {
        const badPath = path.resolve('I', 'Do', 'Not', 'Exist');
        expect(() => {
          app.dock.setIcon(badPath);
        }).to.throw(/Failed to load image from path (.+)/);
      });
    }


() => {
        const badPath = path.resolve('I', 'Do', 'Not', 'Exist');
        expect(() => {
          app.dock.setIcon(badPath);
        }).to.throw(/Failed to load image from path (.+)/);
      }


() => {
          app.dock.setIcon(badPath);
        }


() => {
      it('should return -1 for unknown bounce type', () => {
        expect(app.dock.bounce('bad type' as any)).to.equal(-1);
      });

      it('should return a positive number for informational type', () => {
        const appHasFocus = !!BrowserWindow.getFocusedWindow();
        if (!appHasFocus) {
          expect(app.dock.bounce('informational')).to.be.at.least(0);
        }
      });

      it('should return a positive number for critical type', () => {
        const appHasFocus = !!BrowserWindow.getFocusedWindow();
        if (!appHasFocus) {
          expect(app.dock.bounce('critical')).to.be.at.least(0);
        }
      });
    }


() => {
        expect(app.dock.bounce('bad type' as any)).to.equal(-1);
      }


() => {
        const appHasFocus = !!BrowserWindow.getFocusedWindow();
        if (!appHasFocus) {
          expect(app.dock.bounce('informational')).to.be.at.least(0);
        }
      }


() => {
        const appHasFocus = !!BrowserWindow.getFocusedWindow();
        if (!appHasFocus) {
          expect(app.dock.bounce('critical')).to.be.at.least(0);
        }
      }


() => {
      it('should not throw', () => {
        app.dock.cancelBounce(app.dock.bounce('critical'));
      });
    }


() => {
        app.dock.cancelBounce(app.dock.bounce('critical'));
      }


() => {
      after(() => {
        app.dock.setBadge('');
      });

      it('should not throw', () => {
        app.dock.setBadge('1');
      });

      it('should be retrievable via getBadge', () => {
        app.dock.setBadge('test');
        expect(app.dock.getBadge()).to.equal('test');
      });
    }


() => {
        app.dock.setBadge('');
      }


() => {
        app.dock.setBadge('1');
      }


() => {
        app.dock.setBadge('test');
        expect(app.dock.getBadge()).to.equal('test');
      }


() => {
      it('should not throw', () => {
        app.dock.hide();
        expect(app.dock.isVisible()).to.equal(false);
      });
    }


() => {
        app.dock.hide();
        expect(app.dock.isVisible()).to.equal(false);
      }


() => {
      it('should not throw', () => {
        return app.dock.show().then(() => {
          expect(app.dock.isVisible()).to.equal(true);
        });
      });

      it('returns a Promise', () => {
        expect(app.dock.show()).to.be.a('promise');
      });

      it('eventually fulfills', async () => {
        await expect(app.dock.show()).to.eventually.be.fulfilled.equal(undefined);
      });
    }


() => {
        return app.dock.show().then(() => {
          expect(app.dock.isVisible()).to.equal(true);
        });
      }


() => {
          expect(app.dock.isVisible()).to.equal(true);
        }


() => {
        expect(app.dock.show()).to.be.a('promise');
      }


async () => {
        await expect(app.dock.show()).to.eventually.be.fulfilled.equal(undefined);
      }


() => {
    it('returns a Promise', () => {
      expect(app.whenReady()).to.be.a('promise');
    });

    it('becomes fulfilled if the app is already ready', async () => {
      expect(app.isReady()).to.equal(true);
      await expect(app.whenReady()).to.be.eventually.fulfilled.equal(undefined);
    });
  }


() => {
      expect(app.whenReady()).to.be.a('promise');
    }


async () => {
      expect(app.isReady()).to.equal(true);
      await expect(app.whenReady()).to.be.eventually.fulfilled.equal(undefined);
    }


() => {
    it('has the applicationMenu property', () => {
      expect(app).to.have.property('applicationMenu');
    });
  }


() => {
      expect(app).to.have.property('applicationMenu');
    }


() => {
    it('returns true when present', () => {
      app.commandLine.appendSwitch('foobar1');
      expect(app.commandLine.hasSwitch('foobar1')).to.equal(true);
    });

    it('returns false when not present', () => {
      expect(app.commandLine.hasSwitch('foobar2')).to.equal(false);
    });
  }


() => {
      app.commandLine.appendSwitch('foobar1');
      expect(app.commandLine.hasSwitch('foobar1')).to.equal(true);
    }


() => {
      expect(app.commandLine.hasSwitch('foobar2')).to.equal(false);
    }


() => {
    it('returns true when present', async () => {
      const { hasSwitch } = await runTestApp('command-line', '--foobar');
      expect(hasSwitch).to.equal(true);
    });

    it('returns false when not present', async () => {
      const { hasSwitch } = await runTestApp('command-line');
      expect(hasSwitch).to.equal(false);
    });
  }


async () => {
      const { hasSwitch } = await runTestApp('command-line', '--foobar');
      expect(hasSwitch).to.equal(true);
    }


async () => {
      const { hasSwitch } = await runTestApp('command-line');
      expect(hasSwitch).to.equal(false);
    }


() => {
    it('returns the value when present', () => {
      app.commandLine.appendSwitch('foobar', 'æøåü');
      expect(app.commandLine.getSwitchValue('foobar')).to.equal('æøåü');
    });

    it('returns an empty string when present without value', () => {
      app.commandLine.appendSwitch('foobar1');
      expect(app.commandLine.getSwitchValue('foobar1')).to.equal('');
    });

    it('returns an empty string when not present', () => {
      expect(app.commandLine.getSwitchValue('foobar2')).to.equal('');
    });
  }


() => {
      app.commandLine.appendSwitch('foobar', 'æøåü');
      expect(app.commandLine.getSwitchValue('foobar')).to.equal('æøåü');
    }


() => {
      app.commandLine.appendSwitch('foobar1');
      expect(app.commandLine.getSwitchValue('foobar1')).to.equal('');
    }


() => {
      expect(app.commandLine.getSwitchValue('foobar2')).to.equal('');
    }


() => {
    it('returns the value when present', async () => {
      const { getSwitchValue } = await runTestApp('command-line', '--foobar=test');
      expect(getSwitchValue).to.equal('test');
    });

    it('returns an empty string when present without value', async () => {
      const { getSwitchValue } = await runTestApp('command-line', '--foobar');
      expect(getSwitchValue).to.equal('');
    });

    it('returns an empty string when not present', async () => {
      const { getSwitchValue } = await runTestApp('command-line');
      expect(getSwitchValue).to.equal('');
    });
  }


async () => {
      const { getSwitchValue } = await runTestApp('command-line', '--foobar=test');
      expect(getSwitchValue).to.equal('test');
    }


async () => {
      const { getSwitchValue } = await runTestApp('command-line', '--foobar');
      expect(getSwitchValue).to.equal('');
    }


async () => {
      const { getSwitchValue } = await runTestApp('command-line');
      expect(getSwitchValue).to.equal('');
    }


() => {
    it('changes Secure Keyboard Entry is enabled', () => {
      app.setSecureKeyboardEntryEnabled(true);
      expect(app.isSecureKeyboardEntryEnabled()).to.equal(true);
      app.setSecureKeyboardEntryEnabled(false);
      expect(app.isSecureKeyboardEntryEnabled()).to.equal(false);
    });
  }


() => {
      app.setSecureKeyboardEntryEnabled(true);
      expect(app.isSecureKeyboardEntryEnabled()).to.equal(true);
      app.setSecureKeyboardEntryEnabled(false);
      expect(app.isSecureKeyboardEntryEnabled()).to.equal(false);
    }


() => {
  describe('application menu', () => {
    it('creates the default menu if the app does not set it', async () => {
      const result = await runTestApp('default-menu');
      expect(result).to.equal(false);
    });

    it('does not create the default menu if the app sets a custom menu', async () => {
      const result = await runTestApp('default-menu', '--custom-menu');
      expect(result).to.equal(true);
    });

    it('does not create the default menu if the app sets a null menu', async () => {
      const result = await runTestApp('default-menu', '--null-menu');
      expect(result).to.equal(true);
    });
  });

  describe('window-all-closed', () => {
    it('quits when the app does not handle the event', async () => {
      const result = await runTestApp('window-all-closed');
      expect(result).to.equal(false);
    });

    it('does not quit when the app handles the event', async () => {
      const result = await runTestApp('window-all-closed', '--handle-event');
      expect(result).to.equal(true);
    });
  });

  describe('user agent fallback', () => {
    let initialValue: string;

    before(() => {
      initialValue = app.userAgentFallback!;
    });

    it('should have a reasonable default', () => {
      expect(initialValue).to.include(`Electron/${process.versions.electron}`);
      expect(initialValue).to.include(`Chrome/${process.versions.chrome}`);
    });

    it('should be overridable', () => {
      app.userAgentFallback = 'test-agent/123';
      expect(app.userAgentFallback).to.equal('test-agent/123');
    });

    it('should be restorable', () => {
      app.userAgentFallback = 'test-agent/123';
      app.userAgentFallback = '';
      expect(app.userAgentFallback).to.equal(initialValue);
    });
  });

  describe('app.allowRendererProcessReuse', () => {
    it('should default to true', () => {
      expect(app.allowRendererProcessReuse).to.equal(true);
    });

    it('should cause renderer processes to get new PIDs when false', async () => {
      const output = await runTestApp('site-instance-overrides', 'false');
      expect(output[0]).to.be.a('number').that.is.greaterThan(0);
      expect(output[1]).to.be.a('number').that.is.greaterThan(0);
      expect(output[0]).to.not.equal(output[1]);
    });

    it('should cause renderer processes to keep the same PID when true', async () => {
      const output = await runTestApp('site-instance-overrides', 'true');
      expect(output[0]).to.be.a('number').that.is.greaterThan(0);
      expect(output[1]).to.be.a('number').that.is.greaterThan(0);
      expect(output[0]).to.equal(output[1]);
    });
  });

  describe('login event', () => {
    afterEach(closeAllWindows);
    let server: http.Server;
    let serverUrl: string;

    before((done) => {
      server = http.createServer((request, response) => {
        if (request.headers.authorization) {
          return response.end('ok');
        }
        response
          .writeHead(401, { 'WWW-Authenticate': 'Basic realm="Foo"' })
          .end();
      }).listen(0, '127.0.0.1', () => {
        serverUrl = 'http://127.0.0.1:' + (server.address() as net.AddressInfo).port;
        done();
      });
    });

    it('should emit a login event on app when a WebContents hits a 401', async () => {
      const w = new BrowserWindow({ show: false });
      w.loadURL(serverUrl);
      const [, webContents] = await emittedOnce(app, 'login');
      expect(webContents).to.equal(w.webContents);
    });
  });
}


() => {
    it('creates the default menu if the app does not set it', async () => {
      const result = await runTestApp('default-menu');
      expect(result).to.equal(false);
    });

    it('does not create the default menu if the app sets a custom menu', async () => {
      const result = await runTestApp('default-menu', '--custom-menu');
      expect(result).to.equal(true);
    });

    it('does not create the default menu if the app sets a null menu', async () => {
      const result = await runTestApp('default-menu', '--null-menu');
      expect(result).to.equal(true);
    });
  }


async () => {
      const result = await runTestApp('default-menu');
      expect(result).to.equal(false);
    }


async () => {
      const result = await runTestApp('default-menu', '--custom-menu');
      expect(result).to.equal(true);
    }


async () => {
      const result = await runTestApp('default-menu', '--null-menu');
      expect(result).to.equal(true);
    }


() => {
    it('quits when the app does not handle the event', async () => {
      const result = await runTestApp('window-all-closed');
      expect(result).to.equal(false);
    });

    it('does not quit when the app handles the event', async () => {
      const result = await runTestApp('window-all-closed', '--handle-event');
      expect(result).to.equal(true);
    });
  }


async () => {
      const result = await runTestApp('window-all-closed');
      expect(result).to.equal(false);
    }


async () => {
      const result = await runTestApp('window-all-closed', '--handle-event');
      expect(result).to.equal(true);
    }


() => {
    let initialValue: string;

    before(() => {
      initialValue = app.userAgentFallback!;
    });

    it('should have a reasonable default', () => {
      expect(initialValue).to.include(`Electron/${process.versions.electron}`);
      expect(initialValue).to.include(`Chrome/${process.versions.chrome}`);
    });

    it('should be overridable', () => {
      app.userAgentFallback = 'test-agent/123';
      expect(app.userAgentFallback).to.equal('test-agent/123');
    });

    it('should be restorable', () => {
      app.userAgentFallback = 'test-agent/123';
      app.userAgentFallback = '';
      expect(app.userAgentFallback).to.equal(initialValue);
    });
  }


() => {
      initialValue = app.userAgentFallback!;
    }


() => {
      expect(initialValue).to.include(`Electron/${process.versions.electron}`);
      expect(initialValue).to.include(`Chrome/${process.versions.chrome}`);
    }


() => {
      app.userAgentFallback = 'test-agent/123';
      expect(app.userAgentFallback).to.equal('test-agent/123');
    }


() => {
      app.userAgentFallback = 'test-agent/123';
      app.userAgentFallback = '';
      expect(app.userAgentFallback).to.equal(initialValue);
    }


() => {
    it('should default to true', () => {
      expect(app.allowRendererProcessReuse).to.equal(true);
    });

    it('should cause renderer processes to get new PIDs when false', async () => {
      const output = await runTestApp('site-instance-overrides', 'false');
      expect(output[0]).to.be.a('number').that.is.greaterThan(0);
      expect(output[1]).to.be.a('number').that.is.greaterThan(0);
      expect(output[0]).to.not.equal(output[1]);
    });

    it('should cause renderer processes to keep the same PID when true', async () => {
      const output = await runTestApp('site-instance-overrides', 'true');
      expect(output[0]).to.be.a('number').that.is.greaterThan(0);
      expect(output[1]).to.be.a('number').that.is.greaterThan(0);
      expect(output[0]).to.equal(output[1]);
    });
  }


() => {
      expect(app.allowRendererProcessReuse).to.equal(true);
    }


async () => {
      const output = await runTestApp('site-instance-overrides', 'false');
      expect(output[0]).to.be.a('number').that.is.greaterThan(0);
      expect(output[1]).to.be.a('number').that.is.greaterThan(0);
      expect(output[0]).to.not.equal(output[1]);
    }


async () => {
      const output = await runTestApp('site-instance-overrides', 'true');
      expect(output[0]).to.be.a('number').that.is.greaterThan(0);
      expect(output[1]).to.be.a('number').that.is.greaterThan(0);
      expect(output[0]).to.equal(output[1]);
    }


() => {
    afterEach(closeAllWindows);
    let server: http.Server;
    let serverUrl: string;

    before((done) => {
      server = http.createServer((request, response) => {
        if (request.headers.authorization) {
          return response.end('ok');
        }
        response
          .writeHead(401, { 'WWW-Authenticate': 'Basic realm="Foo"' })
          .end();
      }).listen(0, '127.0.0.1', () => {
        serverUrl = 'http://127.0.0.1:' + (server.address() as net.AddressInfo).port;
        done();
      });
    });

    it('should emit a login event on app when a WebContents hits a 401', async () => {
      const w = new BrowserWindow({ show: false });
      w.loadURL(serverUrl);
      const [, webContents] = await emittedOnce(app, 'login');
      expect(webContents).to.equal(w.webContents);
    });
  }


(done) => {
      server = http.createServer((request, response) => {
        if (request.headers.authorization) {
          return response.end('ok');
        }
        response
          .writeHead(401, { 'WWW-Authenticate': 'Basic realm="Foo"' })
          .end();
      }).listen(0, '127.0.0.1', () => {
        serverUrl = 'http://127.0.0.1:' + (server.address() as net.AddressInfo).port;
        done();
      });
    }


(request, response) => {
        if (request.headers.authorization) {
          return response.end('ok');
        }
        response
          .writeHead(401, { 'WWW-Authenticate': 'Basic realm="Foo"' })
          .end();
      }


() => {
        serverUrl = 'http://127.0.0.1:' + (server.address() as net.AddressInfo).port;
        done();
      }


async () => {
      const w = new BrowserWindow({ show: false });
      w.loadURL(serverUrl);
      const [, webContents] = await emittedOnce(app, 'login');
      expect(webContents).to.equal(w.webContents);
    }


(data) => { output += data; }


(props) => {
  const { hidden, handleChange, handleBlur, values } = props;

  const handleLabel = (label: LabelDefinition) => {
    handleChange(createFakeEvent("labels", [...values.labels, label]) as any);
    handleBlur(createFakeEvent("labels") as any);
  };

  const removeLabel = (idx: number) => {
    const labels = values.labels.filter((label, i) => i !== idx);
    handleChange(createFakeEvent("labels", labels) as any);
  };

  return (
    <React.Fragment>
      <EuiFlexGroup
        style={hidden ? HIDDEN_STYLE : {}}
        gutterSize="s"
        responsive={false}
      >
        <EuiFlexItem>
          <BooleanLabelForm labels={values.labels} handleLabel={handleLabel} />
        </EuiFlexItem>

        <EuiFlexItem>
          <NumericalLabelForm
            labels={values.labels}
            handleLabel={handleLabel}
          />
        </EuiFlexItem>
      </EuiFlexGroup>

      <EuiListGroup style={hidden ? HIDDEN_STYLE : {}}>
        <EuiSpacer size="m" />
        {values.labels.map((label, i) => {
          const color = label.variant === "numerical" ? "secondary" : "primary";
          const append = `(${label.minimum}, ${label.maximum}, ${label.interval})`;
          const badgeContent = `${label.variant} ${
            label.variant === "numerical" ? append : ""
          }`;

          return (
            <EuiListGroupItem
              key={label.name}
              icon={<EuiAvatar size="s" type="space" name={label.name} />}
              label={
                <span>
                  {label.name + " "}
                  <EuiBadge color={color}>{badgeContent}</EuiBadge>
                </span>
              }
              extraAction={{
                iconType: "trash",
                alwaysShow: true,
                "aria-label": "Delete label",
                onClick: () => removeLabel(i),
              }}


(label: LabelDefinition) => {
    handleChange(createFakeEvent("labels", [...values.labels, label]) as any);
    handleBlur(createFakeEvent("labels") as any);
  }


(idx: number) => {
    const labels = values.labels.filter((label, i) => i !== idx);
    handleChange(createFakeEvent("labels", labels) as any);
  }


(label, i) => i !== idx


(label, i) => {
          const color = label.variant === "numerical" ? "secondary" : "primary";
          const append = `(${label.minimum}, ${label.maximum}, ${label.interval})`;
          const badgeContent = `${label.variant} ${
            label.variant === "numerical" ? append : ""
          }`;

          return (
            <EuiListGroupItem
              key={label.name}
              icon={<EuiAvatar size="s" type="space" name={label.name} />}


() => removeLabel(i)


interface IProps {
  hidden: boolean;
  handleChange: (event: React.SyntheticEvent) => void;
  handleBlur: (event: React.SyntheticEvent) => void;
  values: FormValues;
}


export declare function getEmitFlags(node: ts.Node): ts.EmitFlags | undefined;


props => {
  const internal = /^\/(?!\/)/.test(props.to);

  if (internal) {
    return <GatsbyLink to={props.to}>{props.children}</GatsbyLink>;
  }

  return {props.children};
}


interface LinkProps {
  to: string;
}


export function getJsonObj(
    obj: EnableExternalPluggableDatabaseOperationsInsightsDetails
  ): object {
    const jsonObj = { ...obj, ...{} };

    return jsonObj;
  }


export function getDeserializedJsonObj(
    obj: EnableExternalPluggableDatabaseOperationsInsightsDetails
  ): object {
    const jsonObj = { ...obj, ...{} };

    return jsonObj;
  }


/**
 * Details to enable Operations Insights on the external pluggable database
 */
export interface EnableExternalPluggableDatabaseOperationsInsightsDetails {
  /**
   * The [OCID](https://docs.cloud.oracle.com/Content/General/Concepts/identifiers.htm) of the
   * {@link #createExternalDatabaseConnectorDetails(CreateExternalDatabaseConnectorDetailsRequest) createExternalDatabaseConnectorDetails}.
   *
   */
  "externalDatabaseConnectorId": string;
}


props => {
  const action = getActionById(
    getConnectorActions(getConnectionConnector(props.connection)),
    props.actionId
  );
  return (
    <WithActionDescriptor
      connectionId={props.connection.id!}
      actionId={action.id!}
      configuredProperties={props.initialValue || {}}
    >
      {({ data, hasData, error, errorMessage })


export interface IOnUpdatedIntegrationProps {
  /**
   * the action object that has been configured.
   */
  action: Action;
  /**
   * true if the configuration is not complete because there are other steps,
   * false otherwise.
   * If true the form should be re-rendered with an incremented
   * [configurationPage]{@link IWithConfigurationFormProps#configurationPage}.
   */
  moreConfigurationSteps: boolean;
  /**
   * the configured values.
   */
  values: { [key: string]: string } | null;
}


export interface IWithConfigurationFormProps {
  /**
   * the connection object that contains the action with the provided
   * [actionId]{@link IWithConfigurationFormProps#actionId}. Used to retrieve
   * the form definition.
   */
  connection: IConnectionOverview;
  /**
   * the ID of the action that needs to be configured.
   */
  actionId: string;

  oldAction?: Action;
  /**
   * for actions whose configuration must be performed in multiple steps,
   * indicates the current step.
   */
  configurationPage: number;
  /**
   * the values to assign to the form once rendered. These can come either from
   * an existing integration or from the [onUpdatedIntegration]{@link IWithConfigurationFormProps#onUpdatedIntegration}
   * callback.
   */
  initialValue?: { [key: string]: string };

  chooseActionHref: H.LocationDescriptor;

  /**
   * the callback that is fired after the form submit with valid values.
   *
   * @see [action]{@link IOnUpdatedIntegrationProps#action}
   * @see [moreConfigurationSteps]{@link IOnUpdatedIntegrationProps#moreConfigurationSteps}
   * @see [values]{@link IOnUpdatedIntegrationProps#values}
   */
  onUpdatedIntegration(props: IOnUpdatedIntegrationProps): Promise<void>;
}


export function Delay(time?: number): ClassDecorator {
  return target => {
    Reflect.defineMetadata(NAMESPACE.DELAY, time || -1, target);
  }
}


export function Description(str: string): ClassDecorator {
  return target => {
    Reflect.defineMetadata(NAMESPACE.DESCRIPTION, str, target);
  }
}


export function Group(group: string): ClassDecorator {
  return target => {
    Reflect.defineMetadata(NAMESPACE.GROUP, group, target);
  }
}


export function Interface(name: string): ClassDecorator {
  return target => {
    Reflect.defineMetadata(NAMESPACE.INTERFACE, name, target);
  }
}


export function Method(target: Object, property: string | symbol, descriptor: TypedPropertyDescriptor<(...args: any[]) => any>) {
  Reflect.defineMetadata(NAMESPACE.METHOD, true, descriptor.value);
}


export function Retries(count?: number): ClassDecorator {
  return target => {
    Reflect.defineMetadata(NAMESPACE.RETRIES, count || 2, target);
  }
}


export function Timeout(time?: number): ClassDecorator {
  return target => {
    Reflect.defineMetadata(NAMESPACE.TIMEOUT, time || 3000, target);
  }
}


export function Version(version?: string): ClassDecorator {
  return target => {
    Reflect.defineMetadata(NAMESPACE.VERSION, version || '0.0.0', target);
  }
}


export function setParameterMetaData<T = any>(callback: (ctx: Context) => T): ParameterDecorator {
  return (target, property, index) => {
    const clazz = target.constructor.prototype[property];
    const meta = ParameterMetadata.bind(clazz);
    meta.set(index, callback);
  }
}


export function setFunctionalParameterMetaData<T = any>(callback: (ctx: Context, ...args: any[]) => T) {
  return (...args: any[]): ParameterDecorator => {
    return (target, property, index) => {
      const clazz = target.constructor.prototype[property];
      const meta = ParameterMetadata.bind(clazz);
      meta.set(index, (ctx) => callback(ctx, ...args));
    }
  }
}


export function Middleware<T extends Context = Context>(...args: ComposeMiddleware<T>[]): MethodDecorator {
  return (target, property, descriptor) => {
    const clazz = descriptor.value;
    if (!Reflect.hasMetadata(NAMESPACE.MIDDLEWARE, clazz)) Reflect.defineMetadata(NAMESPACE.MIDDLEWARE, new MiddlewareMetadata<T>(), clazz);
    const metadata = Reflect.getMetadata(NAMESPACE.MIDDLEWARE, clazz) as MiddlewareMetadata<T>;
    metadata.use(...args);
  }
}


target => {
    Reflect.defineMetadata(NAMESPACE.DELAY, time || -1, target);
  }


target => {
    Reflect.defineMetadata(NAMESPACE.DESCRIPTION, str, target);
  }


target => {
    Reflect.defineMetadata(NAMESPACE.GROUP, group, target);
  }


target => {
    Reflect.defineMetadata(NAMESPACE.INTERFACE, name, target);
  }


target => {
    Reflect.defineMetadata(NAMESPACE.RETRIES, count || 2, target);
  }


target => {
    Reflect.defineMetadata(NAMESPACE.TIMEOUT, time || 3000, target);
  }


target => {
    Reflect.defineMetadata(NAMESPACE.VERSION, version || '0.0.0', target);
  }


(target, property, descriptor) => {
      Reflect.defineMetadata(NAMESPACE.SWAGGER_REQUEST_SCHEMA, schemas, descriptor.value);
    }


(target, property, descriptor) => {
      Reflect.defineMetadata(NAMESPACE.SWAGGER_RESPONSE_SCHEMA, schema, descriptor.value);
    }


(target, property, descriptor) => {
      Reflect.defineMetadata(NAMESPACE.SWAGGER_SUMMARY, str, descriptor.value);
    }


(fn, index) => {
      if (typeof fn === 'function') return Promise.resolve(fn(ctx));
      return Promise.resolve(ctx.req.parameters[index]);
    }


ctx => ctx.req.requestId


ctx => ctx.req.dubboVersion


ctx => ctx.req.interfaceName


ctx => ctx.req.method


ctx => ctx.req.interfaceVersion


ctx => ctx.req.attachments


(ctx, key: keyof ContextRequestType['attachments']) => ctx.req.attachments[key]


ctx => ctx.req.parameters


(ctx, index: number) => ctx.req.parameters[index]


(target, property, index) => {
    const clazz = target.constructor.prototype[property];
    const meta = ParameterMetadata.bind(clazz);
    meta.set(index, callback);
  }


(...args: any[]): ParameterDecorator => {
    return (target, property, index) => {
      const clazz = target.constructor.prototype[property];
      const meta = ParameterMetadata.bind(clazz);
      meta.set(index, (ctx) => callback(ctx, ...args));
    }
  }


(target, property, index) => {
      const clazz = target.constructor.prototype[property];
      const meta = ParameterMetadata.bind(clazz);
      meta.set(index, (ctx) => callback(ctx, ...args));
    }


(ctx) => callback(ctx, ...args)


(target, property, descriptor) => {
    const clazz = descriptor.value;
    if (!Reflect.hasMetadata(NAMESPACE.MIDDLEWARE, clazz)) Reflect.defineMetadata(NAMESPACE.MIDDLEWARE, new MiddlewareMetadata<T>(), clazz);
    const metadata = Reflect.getMetadata(NAMESPACE.MIDDLEWARE, clazz) as MiddlewareMetadata<T>;
    metadata.use(...args);
  }


export class ParameterMetadata {
  private readonly parameters: ((ctx: Context) => any)[] = [];
  set(index: number, callback: (ctx: Context) => any) {
    this.parameters[index] = callback;
    return this;
  }
  exec(ctx: Context) {
    return Promise.all(this.parameters.map((fn, index) => {
      if (typeof fn === 'function') return Promise.resolve(fn(ctx));
      return Promise.resolve(ctx.req.parameters[index]);
    }));
  }

  static bind(target: Object) {
    let meta: ParameterMetadata;
    if (!Reflect.hasMetadata(NAMESPACE.REQ, target)) {
      meta = new ParameterMetadata();
      Reflect.defineMetadata(NAMESPACE.REQ, meta, target);
    } else {
      meta = Reflect.getMetadata(NAMESPACE.REQ, target) as ParameterMetadata;
    }
    return meta;
  }
}


export class MiddlewareMetadata<T extends Context = Context>{
  private readonly stacks: ComposeMiddleware<T>[] = [];
  use(...args: ComposeMiddleware<T>[]) {
    this.stacks.unshift(...args);
    return this;
  }
  exec(ctx: T, fn?: ComposeMiddleware<T>) {
    const stacks = this.stacks.slice(0);
    fn && stacks.push(fn);
    return Compose<T>(stacks)(ctx);
  }
}


export enum NAMESPACE {
  DELAY = 'rpc.delay',
  DESCRIPTION = 'rpc.description',
  GROUP = 'rpc.group',
  INTERFACE = 'rpc.interface',
  METHOD = 'rpc.method',
  RETRIES = 'rpc.retries',
  TIMEOUT = 'rpc.timeout',
  VERSION = 'rpc.version',
  REQ = 'rpc.req',
  MIDDLEWARE = 'rpc.middleware',
  SWAGGER_REQUEST_SCHEMA = 'rpc.method.swagger.schema.request',
  SWAGGER_RESPONSE_SCHEMA = 'rpc.method.swagger.schema.response',
  SWAGGER_SUMMARY = 'rpc.method.swagger.summary',
}


type ContextRequestType = ProviderContext['req'];


type AttachmentItemType = ContextRequestType['attachments'][keyof ContextRequestType['attachments']];


Request(...schemas: ProviderServiceChunkMethodParametersSchema[]): MethodDecorator {
    return (target, property, descriptor) => {
      Reflect.defineMetadata(NAMESPACE.SWAGGER_REQUEST_SCHEMA, schemas, descriptor.value);
    }
  }


Response(schema: any): MethodDecorator {
    return (target, property, descriptor) => {
      Reflect.defineMetadata(NAMESPACE.SWAGGER_RESPONSE_SCHEMA, schema, descriptor.value);
    }
  }


Summary(str: string): MethodDecorator {
    return (target, property, descriptor) => {
      Reflect.defineMetadata(NAMESPACE.SWAGGER_SUMMARY, str, descriptor.value);
    }
  }


set(index: number, callback: (ctx: Context) => any) {
    this.parameters[index] = callback;
    return this;
  }


exec(ctx: Context) {
    return Promise.all(this.parameters.map((fn, index) => {
      if (typeof fn === 'function') return Promise.resolve(fn(ctx));
      return Promise.resolve(ctx.req.parameters[index]);
    }));
  }


static bind(target: Object) {
    let meta: ParameterMetadata;
    if (!Reflect.hasMetadata(NAMESPACE.REQ, target)) {
      meta = new ParameterMetadata();
      Reflect.defineMetadata(NAMESPACE.REQ, meta, target);
    } else {
      meta = Reflect.getMetadata(NAMESPACE.REQ, target) as ParameterMetadata;
    }
    return meta;
  }


use(...args: ComposeMiddleware<T>[]) {
    this.stacks.unshift(...args);
    return this;
  }


exec(ctx: T, fn?: ComposeMiddleware<T>) {
    const stacks = this.stacks.slice(0);
    fn && stacks.push(fn);
    return Compose<T>(stacks)(ctx);
  }


() => ProductEntity


product => product.categories


/**
 * The app's main category entity class
 *
 * Class that represents the entity that deals with rating
 */
@Entity('category')
export class CategoryEntity extends BaseEntity implements ToDto<CategoryDto> {
  //#region Columns

  @ApiProperty()
  @Column({
    type: 'varchar',
    length: 30,
    nullable: false
  })
  public name: string

  //#region

  @ApiPropertyOptional({ type: () => ProductEntity, isArray: true })
  @JoinTable()
  @ManyToMany(
    () => ProductEntity,
    product => product.categories
  )
  public products?: ProductEntity[]

  //#endregion

  //#endregion

  public constructor(partialEntity: Partial<CategoryEntity>) {
    super()
    Object.assign(this, partialEntity)
  }

  /**
   * Method that converts the entity to your dto
   *
   * @returns the dto data
   */
  public toDto(): CategoryDto {
    return new CategoryDto(this)
  }
}


/**
   * Method that converts the entity to your dto
   *
   * @returns the dto data
   */
public toDto(): CategoryDto {
    return new CategoryDto(this)
  }


@Pipe({
  name : 'safeStyle',
})

export class SafeStylePipe implements PipeTransform {
  constructor(private sanitizer: DomSanitizer) {

  }

  public transform(style: string): SafeStyle {
    return this.sanitizer.bypassSecurityTrustStyle(style)
  }
}


public transform(style: string): SafeStyle {
    return this.sanitizer.bypassSecurityTrustStyle(style)
  }


function increment() {
      store.state.counter++
    }


() => store.state.counter * 2


setup() {
    const store = useStore()

    const doubleCount = computed(() => store.state.counter * 2)
    function increment() {
      store.state.counter++
    }

    return {
      doubleCount,
      increment,
      state: store.state,
    }
  }


export default function Reply({ reply, onReplyUpdate }: IReplyProps) {
  const { t } = useGiscusTranslation();
  const formatDate = useDateFormatter();
  const formatDateDistance = useRelativeTimeFormatter();

  const updateReactions = useCallback(
    (content: Reaction, promise: Promise<unknown>) =>
      onReplyUpdate(updateCommentReaction(reply, content), promise),
    [reply, onReplyUpdate],
  );

  const [renderedReply, setRenderedComment] = useState(undefined);
  useEffect(() => {
    setRenderedComment(processCommentBody(renderMarkdown(reply.body)));
  }, [reply.body]);

  const hidden = reply.deletedAt || reply.isMinimized;

  return (

      <div className={`flex py-2 pl-4 ${hidden ? 'items-center' : ''}`}>

            <img
              className="rounded-full"
              src={reply.author.avatarUrl}
              width="30"
              height="30"
              alt={`@${reply.author.login}`}


(content: Reaction, promise: Promise<unknown>) =>
      onReplyUpdate(updateCommentReaction(reply, content), promise)


() => {
    setRenderedComment(processCommentBody(renderMarkdown(reply.body)));
  }


interface IReplyProps {
  reply: IReply;
  onReplyUpdate: (newReply: IReply, promise: Promise<unknown>) => void;
}


formatDate(reply


formatDateDistance(reply


t(reply


t('lastEditedAt', { date: reply


t('edited')


hidden ? (
              <em className="color-text-secondary">
                {reply.deletedAt ? t('thisCommentWasDeleted') : t('thisCommentWasHidden')}
              </em>
            ) : null


()=> {
    console.log(`Koa server is listening on port ${port}`)
}


(typeName: string) => {
    let pluralizedTypeName;
    if (typeName.length === 1) {
        pluralizedTypeName = `${typeName}s`;
    } else {
        pluralizedTypeName = pluralize(typeName);
    }
    return pluralizedTypeName;
}


(alias) => alias


(option) => option


export default class HelpInteraction extends Interaction {
  constructor(bot: Bot) {
    super(bot, {
      name: "help",
      description: "Return more information about a command",
      options: [
        {
          name: "command",
          type: "STRING",
          description: "The command you're looking for",
          required: true,
        },
      ],
    });
  }

  async execute(interaction: CommandInteraction, args: (string | number | boolean | undefined)[]) {
    const arg = `${args[0]}`;
    const command = this.bot.utils.resolveCommand(arg);
    const lang = await this.bot.utils.getGuildLang(interaction.guild?.id);

    if (!command) {
      return interaction.reply(lang.HELP.CMD_NOT_FOUND);
    } else {
      const aliases = command.options.aliases
        ? command.options.aliases.map((alias) => alias)
        : lang.GLOBAL.NONE;
      const options = command.options.options
        ? command.options.options.map((option) => option)
        : lang.GLOBAL.NONE;
      const cooldown = command.options.cooldown ? `${command.options.cooldown}s` : "3s";
      const guild = await this.bot.utils.getGuildById(interaction.guild?.id);
      const prefix = guild?.prefix;
      const memberPerms = getMemberPermissions(command, lang);
      const botPerms = getBotPermissions(command, lang);

      const embed = this.bot.utils
        .baseEmbed({
          author: interaction.user,
        })
        .addField(lang.HELP.ALIASES, aliases, true)
        .addField(lang.HELP.COOLDOWN, `${cooldown}`, true)
        .addField(
          lang.HELP.USAGE,
          command.options.usage
            ? `${prefix}${command.name} ${command.options.usage}`
            : lang.GLOBAL.NOT_SPECIFIED,
          true,
        )
        .addField(lang.UTIL.CATEGORY, command.options.category, true)
        .addField(
          lang.UTIL.DESCRIPTION,
          command.options.description ? command.options.description : lang.GLOBAL.NOT_SPECIFIED,
          true,
        )
        .addField(lang.HELP.OPTIONS, options, true)
        .addField(lang.HELP.BOT_PERMS, botPerms, true)
        .addField(lang.HELP.MEMBER_PERMS, memberPerms, true);

      interaction.reply(embed);
    }
  }
}


async execute(interaction: CommandInteraction, args: (string | number | boolean | undefined)[]) {
    const arg = `${args[0]}`;
    const command = this.bot.utils.resolveCommand(arg);
    const lang = await this.bot.utils.getGuildLang(interaction.guild?.id);

    if (!command) {
      return interaction.reply(lang.HELP.CMD_NOT_FOUND);
    } else {
      const aliases = command.options.aliases
        ? command.options.aliases.map((alias) => alias)
        : lang.GLOBAL.NONE;
      const options = command.options.options
        ? command.options.options.map((option) => option)
        : lang.GLOBAL.NONE;
      const cooldown = command.options.cooldown ? `${command.options.cooldown}s` : "3s";
      const guild = await this.bot.utils.getGuildById(interaction.guild?.id);
      const prefix = guild?.prefix;
      const memberPerms = getMemberPermissions(command, lang);
      const botPerms = getBotPermissions(command, lang);

      const embed = this.bot.utils
        .baseEmbed({
          author: interaction.user,
        })
        .addField(lang.HELP.ALIASES, aliases, true)
        .addField(lang.HELP.COOLDOWN, `${cooldown}`, true)
        .addField(
          lang.HELP.USAGE,
          command.options.usage
            ? `${prefix}${command.name} ${command.options.usage}`
            : lang.GLOBAL.NOT_SPECIFIED,
          true,
        )
        .addField(lang.UTIL.CATEGORY, command.options.category, true)
        .addField(
          lang.UTIL.DESCRIPTION,
          command.options.description ? command.options.description : lang.GLOBAL.NOT_SPECIFIED,
          true,
        )
        .addField(lang.HELP.OPTIONS, options, true)
        .addField(lang.HELP.BOT_PERMS, botPerms, true)
        .addField(lang.HELP.MEMBER_PERMS, memberPerms, true);

      interaction.reply(embed);
    }
  }


() => {
  const { queryByText, queryByTestId } = render(<Contact />)
  expect(queryByTestId("contact-form")).toBeTruthy()
  expect(queryByTestId("email")).toBeTruthy()
  expect(queryByTestId("name")).toBeTruthy()
  expect(queryByTestId("message")).toBeTruthy()
  expect(queryByTestId("submit-button")).toBeTruthy()
  expect(queryByText("Contact")).toBeTruthy()
}


() => this.dispatchAdd()


/**
 * This web component has the HTML name `track-data`. It is meant for binaural beats. It displays a track's frequencies
 * and effects, with a button meant to save the track. If the track has effects to display, add the effects HTML between
 * this element's HTML tags. Call [[setTrack]] before the element is connected to the DOM.
 *
 * Example:
 * ```
 * <track-data id="track"><ul><li>Focusing</li></ul></track-data>
 * <script>document.querySelector('#track').setTrack({frequency: 8});</script>
 * ```
 */
export class TrackDataElement extends HTMLElement {
    private track!: PureTrack | IsochronicTrack | SolfeggioTrack;
    private readonly effects = document.createElement('titled-item') as TitledItemElement;
    private readonly layout: VerticalLayoutElement = document.createElement('vaadin-vertical-layout');

    constructor() {
        super();
        this.attachShadow({mode: 'open'});
        this.effects.title = 'Effects';
    }

    /** @returns A `vaadin-vertical-layout` block containing `child` */
    private static getDiv(child: HTMLElement): HTMLDivElement {
        const div = document.createElement('div');
        div.className = 'block';
        div.append(child);
        return div;
    }

    /** Calling this more than once will throw an `Error` */
    setTrack(track: PureTrack | IsochronicTrack | SolfeggioTrack): void {
        if (this.track) throw new Error('Track already set');
        this.track = track;
    }

    connectedCallback() {
        if (!this.isConnected) return;
        this.effects.append(...this.childNodes);
        this.layout.append(TrackDataElement.getDiv(this.getFrequency()));
        if (this.effects) this.layout.append(TrackDataElement.getDiv(this.effects));
        this.layout.append(TrackDataElement.getDiv(this.getButton()));
        this.shadowRoot!.append(this.layout);
    }

    disconnectedCallback() {
        for (const child of this.shadowRoot!.childNodes) child.remove();
    }

    /**
     * Dispatches the `add` `Event`
     *
     * Fired when the button is clicked
     * @event
     */
    private dispatchAdd(): void {
        this.dispatchEvent(new Event('add'));
    }

    private getButton(): ButtonElement {
        const button = document.createElement('vaadin-button');
        button.innerHTML = '<iron-icon icon="vaadin:plus" slot="prefix"></iron-icon> Add to category';
        button.addEventListener('click', () => this.dispatchAdd());
        return button;
    }

    private getFrequency(): HTMLHeadingElement {
        let text = '';
        if ('solfeggioFrequency' in this.track) {
            text = `${this.track.binauralBeatFrequency} Hz (${this.track.solfeggioFrequency} Hz Solfeggio)`;
        } else {
            text = `${this.track.frequency} Hz`;
        }
        const h2 = document.createElement('h2');
        h2.textContent = `Frequency: ${text}`;
        return h2;
    }
}


export interface SingleFrequencyTrack {
    /** Frequency in Hz */
    frequency: number;
}


export interface PureTrack extends SingleFrequencyTrack {
}


export interface IsochronicTrack extends SingleFrequencyTrack {
}


export interface SolfeggioTrack {
    /** Frequency in Hz */
    binauralBeatFrequency: number;
    /** Frequency in Hz */
    solfeggioFrequency: number;
}


/** @returns A `vaadin-vertical-layout` block containing `child` */
private static getDiv(child: HTMLElement): HTMLDivElement {
        const div = document.createElement('div');
        div.className = 'block';
        div.append(child);
        return div;
    }


/** Calling this more than once will throw an `Error` */
setTrack(track: PureTrack | IsochronicTrack | SolfeggioTrack): void {
        if (this.track) throw new Error('Track already set');
        this.track = track;
    }


connectedCallback() {
        if (!this.isConnected) return;
        this.effects.append(...this.childNodes);
        this.layout.append(TrackDataElement.getDiv(this.getFrequency()));
        if (this.effects) this.layout.append(TrackDataElement.getDiv(this.effects));
        this.layout.append(TrackDataElement.getDiv(this.getButton()));
        this.shadowRoot!.append(this.layout);
    }


disconnectedCallback() {
        for (const child of this.shadowRoot!.childNodes) child.remove();
    }


/**
     * Dispatches the `add` `Event`
     *
     * Fired when the button is clicked
     * @event
     */
private dispatchAdd(): void {
        this.dispatchEvent(new Event('add'));
    }


private getButton(): ButtonElement {
        const button = document.createElement('vaadin-button');
        button.innerHTML = '<iron-icon icon="vaadin:plus" slot="prefix"></iron-icon> Add to category';
        button.addEventListener('click', () => this.dispatchAdd());
        return button;
    }


private getFrequency(): HTMLHeadingElement {
        let text = '';
        if ('solfeggioFrequency' in this.track) {
            text = `${this.track.binauralBeatFrequency} Hz (${this.track.solfeggioFrequency} Hz Solfeggio)`;
        } else {
            text = `${this.track.frequency} Hz`;
        }
        const h2 = document.createElement('h2');
        h2.textContent = `Frequency: ${text}`;
        return h2;
    }


// todo this is only for web now
export function getScreenSize (): ISize {
    return {
        width: window.innerWidth,
        height: window.innerHeight
    };
}


export function getCanvas (canvas?: HTMLCanvasElement): HTMLCanvasElement {
    if (canvas) return canvas;

    canvas = document.createElement('canvas');
    document.body.appendChild(canvas);

    return canvas;
}


/**
 * Specifies information about the proximity placement group.
 */
export function getProximityPlacementGroup(args: GetProximityPlacementGroupArgs, opts?: pulumi.InvokeOptions): Promise<GetProximityPlacementGroupResult> {
    if (!opts) {
        opts = {}
    }

    if (!opts.version) {
        opts.version = utilities.getVersion();
    }
    return pulumi.runtime.invoke("azure-native:compute/v20181001:getProximityPlacementGroup", {
        "proximityPlacementGroupName": args.proximityPlacementGroupName,
        "resourceGroupName": args.resourceGroupName,
    }, opts);
}


export interface GetProximityPlacementGroupArgs {
    /**
     * The name of the proximity placement group.
     */
    proximityPlacementGroupName: string;
    /**
     * The name of the resource group.
     */
    resourceGroupName: string;
}


/**
 * Specifies information about the proximity placement group.
 */
export interface GetProximityPlacementGroupResult {
    /**
     * A list of references to all availability sets in the proximity placement group.
     */
    readonly availabilitySets: outputs.compute.v20181001.SubResourceResponse[];
    /**
     * Resource Id
     */
    readonly id: string;
    /**
     * Resource location
     */
    readonly location: string;
    /**
     * Resource name
     */
    readonly name: string;
    /**
     * Specifies the type of the proximity placement group.

 Possible values are:

 **Standard** : Co-locate resources within an Azure region or Availability Zone.

 **Ultra** : For future use.
     */
    readonly proximityPlacementGroupType?: string;
    /**
     * Resource tags
     */
    readonly tags?: {[key: string]: string};
    /**
     * Resource type
     */
    readonly type: string;
    /**
     * A list of references to all virtual machine scale sets in the proximity placement group.
     */
    readonly virtualMachineScaleSets: outputs.compute.v20181001.SubResourceResponse[];
    /**
     * A list of references to all virtual machines in the proximity placement group.
     */
    readonly virtualMachines: outputs.compute.v20181001.SubResourceResponse[];
}


// ====================================================
// GraphQL query operation: PipelineOverviewQuery
// ====================================================
export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_inputs_definition {
  __typename: "InputDefinition";
  name: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_inputs_dependsOn_definition_type {
  __typename: "RegularDagsterType" | "ListDagsterType" | "NullableDagsterType";
  displayName: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_inputs_dependsOn_definition {
  __typename: "OutputDefinition";
  name: string;
  type: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_inputs_dependsOn_definition_type;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_inputs_dependsOn_solid {
  __typename: "Solid";
  name: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_inputs_dependsOn {
  __typename: "Output";
  definition: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_inputs_dependsOn_definition;
  solid: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_inputs_dependsOn_solid;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_inputs {
  __typename: "Input";
  definition: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_inputs_definition;
  dependsOn: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_inputs_dependsOn[];
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_outputs_definition {
  __typename: "OutputDefinition";
  name: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_outputs_dependedBy_solid {
  __typename: "Solid";
  name: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_outputs_dependedBy_definition_type {
  __typename: "RegularDagsterType" | "ListDagsterType" | "NullableDagsterType";
  displayName: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_outputs_dependedBy_definition {
  __typename: "InputDefinition";
  name: string;
  type: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_outputs_dependedBy_definition_type;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_outputs_dependedBy {
  __typename: "Input";
  solid: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_outputs_dependedBy_solid;
  definition: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_outputs_dependedBy_definition;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_outputs {
  __typename: "Output";
  definition: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_outputs_definition;
  dependedBy: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_outputs_dependedBy[];
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_SolidDefinition_metadata {
  __typename: "MetadataItemDefinition";
  key: string;
  value: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_SolidDefinition_inputDefinitions_type {
  __typename: "RegularDagsterType" | "ListDagsterType" | "NullableDagsterType";
  displayName: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_SolidDefinition_inputDefinitions {
  __typename: "InputDefinition";
  name: string;
  type: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_SolidDefinition_inputDefinitions_type;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_SolidDefinition_outputDefinitions_type {
  __typename: "RegularDagsterType" | "ListDagsterType" | "NullableDagsterType";
  displayName: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_SolidDefinition_outputDefinitions {
  __typename: "OutputDefinition";
  name: string;
  type: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_SolidDefinition_outputDefinitions_type;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_SolidDefinition_configField_configType {
  __typename: "RegularConfigType" | "ArrayConfigType" | "ScalarUnionConfigType" | "NullableConfigType" | "EnumConfigType" | "CompositeConfigType";
  key: string;
  description: string | null;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_SolidDefinition_configField {
  __typename: "ConfigTypeField";
  configType: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_SolidDefinition_configField_configType;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_SolidDefinition {
  __typename: "SolidDefinition";
  name: string;
  metadata: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_SolidDefinition_metadata[];
  inputDefinitions: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_SolidDefinition_inputDefinitions[];
  outputDefinitions: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_SolidDefinition_outputDefinitions[];
  configField: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_SolidDefinition_configField | null;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_metadata {
  __typename: "MetadataItemDefinition";
  key: string;
  value: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_inputDefinitions_type {
  __typename: "RegularDagsterType" | "ListDagsterType" | "NullableDagsterType";
  displayName: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_inputDefinitions {
  __typename: "InputDefinition";
  name: string;
  type: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_inputDefinitions_type;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_outputDefinitions_type {
  __typename: "RegularDagsterType" | "ListDagsterType" | "NullableDagsterType";
  displayName: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_outputDefinitions {
  __typename: "OutputDefinition";
  name: string;
  type: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_outputDefinitions_type;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_inputMappings_definition {
  __typename: "InputDefinition";
  name: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_inputMappings_mappedInput_definition {
  __typename: "InputDefinition";
  name: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_inputMappings_mappedInput_solid {
  __typename: "Solid";
  name: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_inputMappings_mappedInput {
  __typename: "Input";
  definition: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_inputMappings_mappedInput_definition;
  solid: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_inputMappings_mappedInput_solid;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_inputMappings {
  __typename: "InputMapping";
  definition: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_inputMappings_definition;
  mappedInput: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_inputMappings_mappedInput;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_outputMappings_definition {
  __typename: "OutputDefinition";
  name: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_outputMappings_mappedOutput_definition {
  __typename: "OutputDefinition";
  name: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_outputMappings_mappedOutput_solid {
  __typename: "Solid";
  name: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_outputMappings_mappedOutput {
  __typename: "Output";
  definition: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_outputMappings_mappedOutput_definition;
  solid: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_outputMappings_mappedOutput_solid;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_outputMappings {
  __typename: "OutputMapping";
  definition: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_outputMappings_definition;
  mappedOutput: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_outputMappings_mappedOutput;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition {
  __typename: "CompositeSolidDefinition";
  name: string;
  metadata: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_metadata[];
  inputDefinitions: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_inputDefinitions[];
  outputDefinitions: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_outputDefinitions[];
  inputMappings: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_inputMappings[];
  outputMappings: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition_outputMappings[];
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid {
  __typename: "Solid";
  name: string;
  inputs: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_inputs[];
  outputs: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_outputs[];
  definition: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles {
  __typename: "SolidHandle";
  solid: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_runs_tags {
  __typename: "PipelineTag";
  key: string;
  value: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_runs_stats_PipelineRunStatsSnapshot {
  __typename: "PipelineRunStatsSnapshot";
  startTime: number | null;
  endTime: number | null;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_runs_stats_PythonError_cause {
  __typename: "PythonError";
  message: string;
  stack: string[];
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_runs_stats_PythonError {
  __typename: "PythonError";
  message: string;
  stack: string[];
  cause: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_runs_stats_PythonError_cause | null;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_runs_assets_key {
  __typename: "AssetKey";
  path: string[];
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_runs_assets {
  __typename: "Asset";
  key: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_runs_assets_key;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_runs {
  __typename: "PipelineRun";
  runId: string;
  rootRunId: string | null;
  pipelineName: string;
  solidSelection: string[] | null;
  pipelineSnapshotId: string | null;
  mode: string;
  canTerminate: boolean;
  tags: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_runs_tags[];
  status: PipelineRunStatus;
  stats: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_runs_stats;
  assets: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_runs_assets[];
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_schedules_scheduleState_lastRuns_stats_PythonError {
  __typename: "PythonError";
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_schedules_scheduleState_lastRuns_stats_PipelineRunStatsSnapshot {
  __typename: "PipelineRunStatsSnapshot";
  endTime: number | null;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_schedules_scheduleState_lastRuns {
  __typename: "PipelineRun";
  stats: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_schedules_scheduleState_lastRuns_stats;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_schedules_scheduleState_runs {
  __typename: "PipelineRun";
  runId: string;
  pipelineName: string;
  status: PipelineRunStatus;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_schedules_scheduleState {
  __typename: "ScheduleState";
  runsCount: number;
  lastRuns: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_schedules_scheduleState_lastRuns[];
  runs: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_schedules_scheduleState_runs[];
  status: ScheduleStatus;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_schedules {
  __typename: "ScheduleDefinition";
  name: string;
  scheduleState: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_schedules_scheduleState | null;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot {
  __typename: "PipelineSnapshot";
  name: string;
  description: string | null;
  solidHandles: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles[];
  runs: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_runs[];
  schedules: PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_schedules[];
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineNotFoundError {
  __typename: "PipelineNotFoundError";
  message: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshotNotFoundError {
  __typename: "PipelineSnapshotNotFoundError";
  message: string;
}


export interface PipelineOverviewQuery_pipelineSnapshotOrError_PythonError {
  __typename: "PythonError";
  message: string;
}


export interface PipelineOverviewQuery {
  pipelineSnapshotOrError: PipelineOverviewQuery_pipelineSnapshotOrError;
}


export interface PipelineOverviewQueryVariables {
  pipelineSelector: PipelineSelector;
  limit: number;
}


export type PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition = PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_SolidDefinition | PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_solidHandles_solid_definition_CompositeSolidDefinition;


export type PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_runs_stats = PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_runs_stats_PipelineRunStatsSnapshot | PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_runs_stats_PythonError;


export type PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_schedules_scheduleState_lastRuns_stats = PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_schedules_scheduleState_lastRuns_stats_PythonError | PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot_schedules_scheduleState_lastRuns_stats_PipelineRunStatsSnapshot;


export type PipelineOverviewQuery_pipelineSnapshotOrError = PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshot | PipelineOverviewQuery_pipelineSnapshotOrError_PipelineNotFoundError | PipelineOverviewQuery_pipelineSnapshotOrError_PipelineSnapshotNotFoundError | PipelineOverviewQuery_pipelineSnapshotOrError_PythonError;


(text: React.ReactNode) => <MenuOutlined />,


(text: React.ReactNode) => <a href


(text: any, record: { scene: React.ReactNode }) => (
      <Space size="middle">
        <a href


(props) => {
  const colors = ['blue', 'green'];
  return (
    <React.Fragment>
      <Row gutter={[16, 24]}>
        <Col span={24}>
          <Button
            type="primary"
            icon={<PlusOutlined />}


(props: any) => {
  const { className, label, disabled, handleClick } = props
  const { handleAnimation } = useContext(LayoutContext)
  const customHandleClick = async (e: any) => {
    const { success } = await handleClick(e)
    if (success && handleAnimation) handleAnimation(e)
  }
  return (
    <button
      disabled={disabled}
      className={className}
      onClick={customHandleClick}
    >
      {label}
    </button>


async (e: any) => {
    const { success } = await handleClick(e)
    if (success && handleAnimation) handleAnimation(e)
  }


({
  product,
  clientId,
  endpoint,
  countryCode,
  lang = 'en-US',
  marketId,
  buildLanguages,
  cms,
  countries,
}) => {
  const router = useRouter()
  const token = useGetToken({
    clientId,
    endpoint,
    scope: marketId,
    countryCode: router.query?.countryCode as string,
  })
  const imgUrl = parseImg(_.first(product?.images)?.url as string, cms)
  const firstVariantCode = _.first(product?.variants)?.code
  const variantOptions = product?.variants?.map((variant) => {
    return {
      label: variant.size.name,
      code: variant.code,
      lineItem: {
        name: product.name,
        imageUrl: _.first(variant.images)?.url,
      },
    }
  })
  const handleBackTo = (e: any) => {
    e.preventDefault()
    router.back()
  }
  const languageCode = parseLanguageCode(lang, 'toLowerCase', true)
  return !product ? null : (
    <CommerceLayer accessToken={token} endpoint={endpoint}>
      <OrderStorage persistKey={`order-${countryCode}`}>
        <OrderContainer attributes={{ language_code: languageCode }}>
          <Layout
            cms={cms}
            title={product.name}
            lang={lang}
            buildLanguages={buildLanguages}
            countries={countries}
          >
            <ItemContainer>

                    {locale[lang].backToAllProducts}

                      BRAND

                      {product.name}

{product.description}

                          <VariantsContainer>
                            <VariantSelector
                              placeholder={locale[lang].selectSize as string}
                              options={_.sortBy(variantOptions, 'label')}
                              className="rounded border appearance-none border-gray-400 py-2 focus:outline-none focus:border-blue-500 text-base pl-3 pr-10"
                            />
                          </VariantsContainer>

                            <svg
                              fill="none"
                              stroke="currentColor"
                              strokeLinecap="round"
                              strokeLinejoin="round"
                              strokeWidth="2"
                              className="w-4 h-4"
                              viewBox="0 0 24 24"
                            >
                              <path d="M6 9l6 6 6-6"></path>
                            </svg>

                        <PricesContainer>
                          <Price
                            skuCode={firstVariantCode}
                            className="text-green-600 mr-1"
                            compareClassName="text-gray-500 line-through text-lg"
                          />
                        </PricesContainer>

                      <AddToCartButton
                        label={locale[lang].addToCart as string}
                        className="inline-flex items-center px-4 py-2 border border-gray-300 shadow-sm text-sm md:text-base font-medium rounded-md text-white bg-gray-900 hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed"
                      >
                        {AddToCartCustom}
                      </AddToCartButton>

            </ItemContainer>
          </Layout>
        </OrderContainer>
      </OrderStorage>
    </CommerceLayer>


(variant) => {
    return {
      label: variant.size.name,
      code: variant.code,
      lineItem: {
        name: product.name,
        imageUrl: _.first(variant.images)?.url,
      },
    }
  }


(e: any) => {
    e.preventDefault()
    router.back()
  }


async () => {
  return {
    paths: [],
    fallback: true,
  }
}


async ({ params }: any) => {
  const lang = params?.lang as string
  const cms = process.env.BUILD_CMS
  const countryCode =
    params?.countryCode || process.env.BUILD_COUNTRY?.toLowerCase()
  const slug = params?.product
  const countries = _.has(cmsFunctions, `${cms}AllCountries`)
    ? await cmsFunctions[`${cms}AllCountries`](lang)
    : {}
  const buildLanguages = _.compact(
    process.env.BUILD_LANGUAGES?.split(',').map((l) => {
      const country = countries.find(
        (country: Country) => country.code === parseLanguageCode(l)
      )
      return !_.isEmpty(country) ? country : null
    })
  )
  const country = countries.find(
    (country: Country) => country.code.toLowerCase() === countryCode
  )
  const product = _.has(cmsFunctions, `${cms}GetProduct`)
    ? await cmsFunctions[`${cms}GetProduct`](slug, lang)
    : {}
  return {
    props: {
      product,
      clientId: process.env.CL_CLIENT_ID,
      endpoint: process.env.CL_ENDPOINT,
      lang,
      countryCode,
      marketId: `market:${country?.marketId}`,
      buildLanguages,
      cms: process.env.BUILD_CMS,
      countries,
    },
    revalidate: 60,
  }
}


(l) => {
      const country = countries.find(
        (country: Country) => country.code === parseLanguageCode(l)
      )
      return !_.isEmpty(country) ? country : null
    }


(country: Country) => country.code === parseLanguageCode(l)


(country: Country) => country.code.toLowerCase() === countryCode


type Props = {
  product: Product
  clientId: string
  endpoint: string
  countryCode: string
  lang: string
  marketId: string
  buildLanguages?: Country[]
  cms: string
  countries: Country[]
}


function createEaseOutCubic(from: number, to: number): IAnimation {
  const delta = to - from;
  return function (completion: number): number {
    return from + delta * easeOutCubic(completion);
  };
}


function createComposed(a: IAnimation, b: IAnimation, cut: number): IAnimation {
  return function (completion: number): number {
    if (completion < cut) {
      return a(completion / cut);
    }
    return b((completion - cut) / (1 - cut));
  };
}


function easeInCubic(t: number) {
  return Math.pow(t, 3);
}


function easeOutCubic(t: number) {
  return 1 - easeInCubic(1 - t);
}


() => {
      if (!this._smoothScrolling) {
        return;
      }
      this._smoothScrolling.animationFrameDisposable = null;
      this._performSmoothScrolling();
    }


export class ScrollState implements IScrollDimensions, IScrollPosition {
  _scrollStateBrand: void;

  public readonly rawScrollLeft: number;

  public readonly rawScrollTop: number;

  public readonly width: number;

  public readonly scrollWidth: number;

  public readonly scrollLeft: number;

  public readonly height: number;

  public readonly scrollHeight: number;

  public readonly scrollTop: number;

  constructor(
    width: number,
    scrollWidth: number,
    scrollLeft: number,
    height: number,
    scrollHeight: number,
    scrollTop: number,
  ) {
    width |= 0;
    scrollWidth |= 0;
    scrollLeft |= 0;
    height |= 0;
    scrollHeight |= 0;
    scrollTop |= 0;

    this.rawScrollLeft = scrollLeft; // before validation
    this.rawScrollTop = scrollTop; // before validation

    if (width < 0) {
      width = 0;
    }
    if (scrollLeft + width > scrollWidth) {
      scrollLeft = scrollWidth - width;
    }
    if (scrollLeft < 0) {
      scrollLeft = 0;
    }

    if (height < 0) {
      height = 0;
    }
    if (scrollTop + height > scrollHeight) {
      scrollTop = scrollHeight - height;
    }
    if (scrollTop < 0) {
      scrollTop = 0;
    }

    this.width = width;
    this.scrollWidth = scrollWidth;
    this.scrollLeft = scrollLeft;
    this.height = height;
    this.scrollHeight = scrollHeight;
    this.scrollTop = scrollTop;
  }

  public equals(other: ScrollState): boolean {
    return (
      this.rawScrollLeft === other.rawScrollLeft &&
      this.rawScrollTop === other.rawScrollTop &&
      this.width === other.width &&
      this.scrollWidth === other.scrollWidth &&
      this.scrollLeft === other.scrollLeft &&
      this.height === other.height &&
      this.scrollHeight === other.scrollHeight &&
      this.scrollTop === other.scrollTop
    );
  }

  public withScrollDimensions(
    update: INewScrollDimensions,
    useRawScrollPositions: boolean,
  ): ScrollState {
    return new ScrollState(
      typeof update.width !== 'undefined' ? update.width : this.width,
      typeof update.scrollWidth !== 'undefined' ? update.scrollWidth : this.scrollWidth,
      useRawScrollPositions ? this.rawScrollLeft : this.scrollLeft,
      typeof update.height !== 'undefined' ? update.height : this.height,
      typeof update.scrollHeight !== 'undefined' ? update.scrollHeight : this.scrollHeight,
      useRawScrollPositions ? this.rawScrollTop : this.scrollTop,
    );
  }

  public withScrollPosition(update: INewScrollPosition): ScrollState {
    return new ScrollState(
      this.width,
      this.scrollWidth,
      typeof update.scrollLeft !== 'undefined' ? update.scrollLeft : this.rawScrollLeft,
      this.height,
      this.scrollHeight,
      typeof update.scrollTop !== 'undefined' ? update.scrollTop : this.rawScrollTop,
    );
  }

  public createScrollEvent(previous: ScrollState): ScrollEvent {
    const widthChanged = this.width !== previous.width;
    const scrollWidthChanged = this.scrollWidth !== previous.scrollWidth;
    const scrollLeftChanged = this.scrollLeft !== previous.scrollLeft;

    const heightChanged = this.height !== previous.height;
    const scrollHeightChanged = this.scrollHeight !== previous.scrollHeight;
    const scrollTopChanged = this.scrollTop !== previous.scrollTop;

    return {
      oldWidth: previous.width,
      oldScrollWidth: previous.scrollWidth,
      oldScrollLeft: previous.scrollLeft,

      width: this.width,
      scrollWidth: this.scrollWidth,
      scrollLeft: this.scrollLeft,

      oldHeight: previous.height,
      oldScrollHeight: previous.scrollHeight,
      oldScrollTop: previous.scrollTop,

      height: this.height,
      scrollHeight: this.scrollHeight,
      scrollTop: this.scrollTop,

      widthChanged,
      scrollWidthChanged,
      scrollLeftChanged,

      heightChanged,
      scrollHeightChanged,
      scrollTopChanged,
    };
  }
}


export class Scrollable extends Disposable {
  _scrollableBrand: void;

  private _smoothScrollDuration: number;

  private readonly _scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable;

  private _state: ScrollState;

  private _smoothScrolling: SmoothScrollingOperation | null;

  private _onScroll = this._register(new Emitter<ScrollEvent>());

  public readonly onScroll: Event<ScrollEvent> = this._onScroll.event;

  constructor(
    smoothScrollDuration: number,
    scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable,
  ) {
    super();

    this._smoothScrollDuration = smoothScrollDuration;
    this._scheduleAtNextAnimationFrame = scheduleAtNextAnimationFrame;
    this._state = new ScrollState(0, 0, 0, 0, 0, 0);
    this._smoothScrolling = null;
  }

  public dispose(): void {
    if (this._smoothScrolling) {
      this._smoothScrolling.dispose();
      this._smoothScrolling = null;
    }
    super.dispose();
  }

  public setSmoothScrollDuration(smoothScrollDuration: number): void {
    this._smoothScrollDuration = smoothScrollDuration;
  }

  public validateScrollPosition(scrollPosition: INewScrollPosition): IScrollPosition {
    return this._state.withScrollPosition(scrollPosition);
  }

  public getScrollDimensions(): IScrollDimensions {
    return this._state;
  }

  public setScrollDimensions(
    dimensions: INewScrollDimensions,
    useRawScrollPositions: boolean,
  ): void {
    const newState = this._state.withScrollDimensions(dimensions, useRawScrollPositions);
    this._setState(newState);

    // Validate outstanding animated scroll position target
    if (this._smoothScrolling) {
      this._smoothScrolling.acceptScrollDimensions(this._state);
    }
  }

  /**
   * Returns the final scroll position that the instance will have once the smooth scroll animation concludes.
   * If no scroll animation is occurring, it will return the current scroll position instead.
   */
  public getFutureScrollPosition(): IScrollPosition {
    if (this._smoothScrolling) {
      return this._smoothScrolling.to;
    }
    return this._state;
  }

  /**
   * Returns the current scroll position.
   * Note: This result might be an intermediate scroll position, as there might be an ongoing smooth scroll animation.
   */
  public getCurrentScrollPosition(): IScrollPosition {
    return this._state;
  }

  public setScrollPositionNow(update: INewScrollPosition): void {
    // no smooth scrolling requested
    const newState = this._state.withScrollPosition(update);

    // Terminate any outstanding smooth scrolling
    if (this._smoothScrolling) {
      this._smoothScrolling.dispose();
      this._smoothScrolling = null;
    }

    this._setState(newState);
  }

  public setScrollPositionSmooth(update: INewScrollPosition): void {
    if (this._smoothScrollDuration === 0) {
      // Smooth scrolling not supported.
      return this.setScrollPositionNow(update);
    }

    if (this._smoothScrolling) {
      // Combine our pending scrollLeft/scrollTop with incoming scrollLeft/scrollTop
      update = {
        scrollLeft:
          typeof update.scrollLeft === 'undefined'
            ? this._smoothScrolling.to.scrollLeft
            : update.scrollLeft,
        scrollTop:
          typeof update.scrollTop === 'undefined'
            ? this._smoothScrolling.to.scrollTop
            : update.scrollTop,
      };

      // Validate `update`
      const validTarget = this._state.withScrollPosition(update);

      if (
        this._smoothScrolling.to.scrollLeft === validTarget.scrollLeft &&
        this._smoothScrolling.to.scrollTop === validTarget.scrollTop
      ) {
        // No need to interrupt or extend the current animation since we're going to the same place
        return;
      }

      const newSmoothScrolling = this._smoothScrolling.combine(
        this._state,
        validTarget,
        this._smoothScrollDuration,
      );
      this._smoothScrolling.dispose();
      this._smoothScrolling = newSmoothScrolling;
    } else {
      // Validate `update`
      const validTarget = this._state.withScrollPosition(update);

      this._smoothScrolling = SmoothScrollingOperation.start(
        this._state,
        validTarget,
        this._smoothScrollDuration,
      );
    }

    // Begin smooth scrolling animation
    this._smoothScrolling.animationFrameDisposable = this._scheduleAtNextAnimationFrame(() => {
      if (!this._smoothScrolling) {
        return;
      }
      this._smoothScrolling.animationFrameDisposable = null;
      this._performSmoothScrolling();
    });
  }

  private _performSmoothScrolling(): void {
    if (!this._smoothScrolling) {
      return;
    }
    const update = this._smoothScrolling.tick();
    const newState = this._state.withScrollPosition(update);

    this._setState(newState);

    if (!this._smoothScrolling) {
      // Looks like someone canceled the smooth scrolling
      // from the scroll event handler
      return;
    }

    if (update.isDone) {
      this._smoothScrolling.dispose();
      this._smoothScrolling = null;
      return;
    }

    // Continue smooth scrolling animation
    this._smoothScrolling.animationFrameDisposable = this._scheduleAtNextAnimationFrame(() => {
      if (!this._smoothScrolling) {
        return;
      }
      this._smoothScrolling.animationFrameDisposable = null;
      this._performSmoothScrolling();
    });
  }

  private _setState(newState: ScrollState): void {
    const oldState = this._state;
    if (oldState.equals(newState)) {
      // no change
      return;
    }
    this._state = newState;
    this._onScroll.fire(this._state.createScrollEvent(oldState));
  }
}


export class SmoothScrollingUpdate {
  public readonly scrollLeft: number;

  public readonly scrollTop: number;

  public readonly isDone: boolean;

  constructor(scrollLeft: number, scrollTop: number, isDone: boolean) {
    this.scrollLeft = scrollLeft;
    this.scrollTop = scrollTop;
    this.isDone = isDone;
  }
}


export class SmoothScrollingOperation {
  public readonly from: ISmoothScrollPosition;

  public to: ISmoothScrollPosition;

  public readonly duration: number;

  private readonly _startTime: number;

  public animationFrameDisposable: IDisposable | null;

  private scrollLeft!: IAnimation;

  private scrollTop!: IAnimation;

  protected constructor(
    from: ISmoothScrollPosition,
    to: ISmoothScrollPosition,
    startTime: number,
    duration: number,
  ) {
    this.from = from;
    this.to = to;
    this.duration = duration;
    this._startTime = startTime;

    this.animationFrameDisposable = null;

    this._initAnimations();
  }

  private _initAnimations(): void {
    this.scrollLeft = this._initAnimation(this.from.scrollLeft, this.to.scrollLeft, this.to.width);
    this.scrollTop = this._initAnimation(this.from.scrollTop, this.to.scrollTop, this.to.height);
  }

  private _initAnimation(from: number, to: number, viewportSize: number): IAnimation {
    const delta = Math.abs(from - to);
    if (delta > 2.5 * viewportSize) {
      let stop1: number;
      let stop2: number;
      if (from < to) {
        // scroll to 75% of the viewportSize
        stop1 = from + 0.75 * viewportSize;
        stop2 = to - 0.75 * viewportSize;
      } else {
        stop1 = from - 0.75 * viewportSize;
        stop2 = to + 0.75 * viewportSize;
      }
      return createComposed(createEaseOutCubic(from, stop1), createEaseOutCubic(stop2, to), 0.33);
    }
    return createEaseOutCubic(from, to);
  }

  public dispose(): void {
    if (this.animationFrameDisposable !== null) {
      this.animationFrameDisposable.dispose();
      this.animationFrameDisposable = null;
    }
  }

  public acceptScrollDimensions(state: ScrollState): void {
    this.to = state.withScrollPosition(this.to);
    this._initAnimations();
  }

  public tick(): SmoothScrollingUpdate {
    return this._tick(Date.now());
  }

  protected _tick(now: number): SmoothScrollingUpdate {
    const completion = (now - this._startTime) / this.duration;

    if (completion < 1) {
      const newScrollLeft = this.scrollLeft(completion);
      const newScrollTop = this.scrollTop(completion);
      return new SmoothScrollingUpdate(newScrollLeft, newScrollTop, false);
    }

    return new SmoothScrollingUpdate(this.to.scrollLeft, this.to.scrollTop, true);
  }

  public combine(
    from: ISmoothScrollPosition,
    to: ISmoothScrollPosition,
    duration: number,
  ): SmoothScrollingOperation {
    return SmoothScrollingOperation.start(from, to, duration);
  }

  public static start(
    from: ISmoothScrollPosition,
    to: ISmoothScrollPosition,
    duration: number,
  ): SmoothScrollingOperation {
    // +10 / -10 : pretend the animation already started for a quicker response to a scroll request
    duration += 10;
    const startTime = Date.now() - 10;

    return new SmoothScrollingOperation(from, to, startTime, duration);
  }
}


export interface ScrollEvent {
  oldWidth: number;
  oldScrollWidth: number;
  oldScrollLeft: number;

  width: number;
  scrollWidth: number;
  scrollLeft: number;

  oldHeight: number;
  oldScrollHeight: number;
  oldScrollTop: number;

  height: number;
  scrollHeight: number;
  scrollTop: number;

  widthChanged: boolean;
  scrollWidthChanged: boolean;
  scrollLeftChanged: boolean;

  heightChanged: boolean;
  scrollHeightChanged: boolean;
  scrollTopChanged: boolean;
}


export interface IScrollDimensions {
  readonly width: number;
  readonly scrollWidth: number;
  readonly height: number;
  readonly scrollHeight: number;
}


export interface INewScrollDimensions {
  width?: number;
  scrollWidth?: number;
  height?: number;
  scrollHeight?: number;
}


export interface IScrollPosition {
  readonly scrollLeft: number;
  readonly scrollTop: number;
}


export interface ISmoothScrollPosition {
  readonly scrollLeft: number;
  readonly scrollTop: number;

  readonly width: number;
  readonly height: number;
}


export interface INewScrollPosition {
  scrollLeft?: number;
  scrollTop?: number;
}


export interface IAnimation {
  (completion: number): number;
}


export const enum ScrollbarVisibility {
  Auto = 1,
  Hidden = 2,
  Visible = 3,
}


public equals(other: ScrollState): boolean {
    return (
      this.rawScrollLeft === other.rawScrollLeft &&
      this.rawScrollTop === other.rawScrollTop &&
      this.width === other.width &&
      this.scrollWidth === other.scrollWidth &&
      this.scrollLeft === other.scrollLeft &&
      this.height === other.height &&
      this.scrollHeight === other.scrollHeight &&
      this.scrollTop === other.scrollTop
    );
  }


public withScrollDimensions(
    update: INewScrollDimensions,
    useRawScrollPositions: boolean,
  ): ScrollState {
    return new ScrollState(
      typeof update.width !== 'undefined' ? update.width : this.width,
      typeof update.scrollWidth !== 'undefined' ? update.scrollWidth : this.scrollWidth,
      useRawScrollPositions ? this.rawScrollLeft : this.scrollLeft,
      typeof update.height !== 'undefined' ? update.height : this.height,
      typeof update.scrollHeight !== 'undefined' ? update.scrollHeight : this.scrollHeight,
      useRawScrollPositions ? this.rawScrollTop : this.scrollTop,
    );
  }


public withScrollPosition(update: INewScrollPosition): ScrollState {
    return new ScrollState(
      this.width,
      this.scrollWidth,
      typeof update.scrollLeft !== 'undefined' ? update.scrollLeft : this.rawScrollLeft,
      this.height,
      this.scrollHeight,
      typeof update.scrollTop !== 'undefined' ? update.scrollTop : this.rawScrollTop,
    );
  }


public createScrollEvent(previous: ScrollState): ScrollEvent {
    const widthChanged = this.width !== previous.width;
    const scrollWidthChanged = this.scrollWidth !== previous.scrollWidth;
    const scrollLeftChanged = this.scrollLeft !== previous.scrollLeft;

    const heightChanged = this.height !== previous.height;
    const scrollHeightChanged = this.scrollHeight !== previous.scrollHeight;
    const scrollTopChanged = this.scrollTop !== previous.scrollTop;

    return {
      oldWidth: previous.width,
      oldScrollWidth: previous.scrollWidth,
      oldScrollLeft: previous.scrollLeft,

      width: this.width,
      scrollWidth: this.scrollWidth,
      scrollLeft: this.scrollLeft,

      oldHeight: previous.height,
      oldScrollHeight: previous.scrollHeight,
      oldScrollTop: previous.scrollTop,

      height: this.height,
      scrollHeight: this.scrollHeight,
      scrollTop: this.scrollTop,

      widthChanged,
      scrollWidthChanged,
      scrollLeftChanged,

      heightChanged,
      scrollHeightChanged,
      scrollTopChanged,
    };
  }


public dispose(): void {
    if (this._smoothScrolling) {
      this._smoothScrolling.dispose();
      this._smoothScrolling = null;
    }
    super.dispose();
  }


public setSmoothScrollDuration(smoothScrollDuration: number): void {
    this._smoothScrollDuration = smoothScrollDuration;
  }


public validateScrollPosition(scrollPosition: INewScrollPosition): IScrollPosition {
    return this._state.withScrollPosition(scrollPosition);
  }


public getScrollDimensions(): IScrollDimensions {
    return this._state;
  }


public setScrollDimensions(
    dimensions: INewScrollDimensions,
    useRawScrollPositions: boolean,
  ): void {
    const newState = this._state.withScrollDimensions(dimensions, useRawScrollPositions);
    this._setState(newState);

    // Validate outstanding animated scroll position target
    if (this._smoothScrolling) {
      this._smoothScrolling.acceptScrollDimensions(this._state);
    }
  }


/**
   * Returns the final scroll position that the instance will have once the smooth scroll animation concludes.
   * If no scroll animation is occurring, it will return the current scroll position instead.
   */
public getFutureScrollPosition(): IScrollPosition {
    if (this._smoothScrolling) {
      return this._smoothScrolling.to;
    }
    return this._state;
  }


/**
   * Returns the current scroll position.
   * Note: This result might be an intermediate scroll position, as there might be an ongoing smooth scroll animation.
   */
public getCurrentScrollPosition(): IScrollPosition {
    return this._state;
  }


public setScrollPositionNow(update: INewScrollPosition): void {
    // no smooth scrolling requested
    const newState = this._state.withScrollPosition(update);

    // Terminate any outstanding smooth scrolling
    if (this._smoothScrolling) {
      this._smoothScrolling.dispose();
      this._smoothScrolling = null;
    }

    this._setState(newState);
  }