const normalizeLine = line => {
  if (line.startsWith('Error: ')) {
    return line.slice('Error: '.length);
  }
  if (line.startsWith('VError: ')) {
    return line.slice('VError: '.length);
  }
  return line;
};
const getCombinedMessage = (error, message) => {
  const stringifiedError = normalizeLine(`${error}`);
  if (message) {
    return `${message}: ${stringifiedError}`;
  }
  return stringifiedError;
};
const NewLine$2 = '\n';
const getNewLineIndex$1 = (string, startIndex = undefined) => {
  return string.indexOf(NewLine$2, startIndex);
};
const mergeStacks = (parent, child) => {
  if (!child) {
    return parent;
  }
  const parentNewLineIndex = getNewLineIndex$1(parent);
  const childNewLineIndex = getNewLineIndex$1(child);
  if (childNewLineIndex === -1) {
    return parent;
  }
  const parentFirstLine = parent.slice(0, parentNewLineIndex);
  const childRest = child.slice(childNewLineIndex);
  const childFirstLine = normalizeLine(child.slice(0, childNewLineIndex));
  if (parentFirstLine.includes(childFirstLine)) {
    return parentFirstLine + childRest;
  }
  return child;
};
class VError extends Error {
  constructor(error, message) {
    const combinedMessage = getCombinedMessage(error, message);
    super(combinedMessage);
    this.name = 'VError';
    if (error instanceof Error) {
      this.stack = mergeStacks(this.stack, error.stack);
    }
    if (error.codeFrame) {
      // @ts-ignore
      this.codeFrame = error.codeFrame;
    }
    if (error.code) {
      // @ts-ignore
      this.code = error.code;
    }
  }
}

const isMessagePort = value => {
  return value && value instanceof MessagePort;
};
const isMessagePortMain = value => {
  return value && value.constructor && value.constructor.name === 'MessagePortMain';
};
const isOffscreenCanvas = value => {
  return typeof OffscreenCanvas !== 'undefined' && value instanceof OffscreenCanvas;
};
const isInstanceOf = (value, constructorName) => {
  return value?.constructor?.name === constructorName;
};
const isSocket = value => {
  return isInstanceOf(value, 'Socket');
};
const transferrables = [isMessagePort, isMessagePortMain, isOffscreenCanvas, isSocket];
const isTransferrable = value => {
  for (const fn of transferrables) {
    if (fn(value)) {
      return true;
    }
  }
  return false;
};
const walkValue = (value, transferrables, isTransferrable) => {
  if (!value) {
    return;
  }
  if (isTransferrable(value)) {
    transferrables.push(value);
    return;
  }
  if (Array.isArray(value)) {
    for (const item of value) {
      walkValue(item, transferrables, isTransferrable);
    }
    return;
  }
  if (typeof value === 'object') {
    for (const property of Object.values(value)) {
      walkValue(property, transferrables, isTransferrable);
    }
    return;
  }
};
const getTransferrables = value => {
  const transferrables = [];
  walkValue(value, transferrables, isTransferrable);
  return transferrables;
};
const attachEvents = that => {
  const handleMessage = (...args) => {
    const data = that.getData(...args);
    that.dispatchEvent(new MessageEvent('message', {
      data
    }));
  };
  that.onMessage(handleMessage);
  const handleClose = event => {
    that.dispatchEvent(new Event('close'));
  };
  that.onClose(handleClose);
};
class Ipc extends EventTarget {
  constructor(rawIpc) {
    super();
    this._rawIpc = rawIpc;
    attachEvents(this);
  }
}
const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE';
const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON';
const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND';
const NewLine$1 = '\n';
const joinLines$1 = lines => {
  return lines.join(NewLine$1);
};
const RE_AT = /^\s+at/;
const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/;
const isNormalStackLine = line => {
  return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line);
};
const getDetails = lines => {
  const index = lines.findIndex(isNormalStackLine);
  if (index === -1) {
    return {
      actualMessage: joinLines$1(lines),
      rest: []
    };
  }
  let lastIndex = index - 1;
  while (++lastIndex < lines.length) {
    if (!isNormalStackLine(lines[lastIndex])) {
      break;
    }
  }
  return {
    actualMessage: lines[index - 1],
    rest: lines.slice(index, lastIndex)
  };
};
const splitLines$1 = lines => {
  return lines.split(NewLine$1);
};
const RE_MESSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/;
const RE_MESSAGE_CODE_BLOCK_END = /^\s* at/;
const isMessageCodeBlockStartIndex = line => {
  return RE_MESSAGE_CODE_BLOCK_START.test(line);
};
const isMessageCodeBlockEndIndex = line => {
  return RE_MESSAGE_CODE_BLOCK_END.test(line);
};
const getMessageCodeBlock = stderr => {
  const lines = splitLines$1(stderr);
  const startIndex = lines.findIndex(isMessageCodeBlockStartIndex);
  const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex);
  const relevantLines = lines.slice(startIndex, endIndex);
  const relevantMessage = relevantLines.join(' ').slice('Error: '.length);
  return relevantMessage;
};
const isModuleNotFoundMessage = line => {
  return line.includes('[ERR_MODULE_NOT_FOUND]');
};
const getModuleNotFoundError = stderr => {
  const lines = splitLines$1(stderr);
  const messageIndex = lines.findIndex(isModuleNotFoundMessage);
  const message = lines[messageIndex];
  return {
    code: ERR_MODULE_NOT_FOUND,
    message
  };
};
const isModuleNotFoundError = stderr => {
  if (!stderr) {
    return false;
  }
  return stderr.includes('ERR_MODULE_NOT_FOUND');
};
const isModulesSyntaxError = stderr => {
  if (!stderr) {
    return false;
  }
  return stderr.includes('SyntaxError: Cannot use import statement outside a module');
};
const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/;
const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/;
const isUnhelpfulNativeModuleError = stderr => {
  return RE_NATIVE_MODULE_ERROR.test(stderr) && RE_NATIVE_MODULE_ERROR_2.test(stderr);
};
const getNativeModuleErrorMessage = stderr => {
  const message = getMessageCodeBlock(stderr);
  return {
    code: E_INCOMPATIBLE_NATIVE_MODULE,
    message: `Incompatible native node module: ${message}`
  };
};
const getModuleSyntaxError = () => {
  return {
    code: E_MODULES_NOT_SUPPORTED_IN_ELECTRON,
    message: `ES Modules are not supported in electron`
  };
};
const getHelpfulChildProcessError = (stdout, stderr) => {
  if (isUnhelpfulNativeModuleError(stderr)) {
    return getNativeModuleErrorMessage(stderr);
  }
  if (isModulesSyntaxError(stderr)) {
    return getModuleSyntaxError();
  }
  if (isModuleNotFoundError(stderr)) {
    return getModuleNotFoundError(stderr);
  }
  const lines = splitLines$1(stderr);
  const {
    actualMessage,
    rest
  } = getDetails(lines);
  return {
    code: '',
    message: actualMessage,
    stack: rest
  };
};
class IpcError extends VError {
  // @ts-ignore
  constructor(betterMessage, stdout = '', stderr = '') {
    if (stdout || stderr) {
      // @ts-ignore
      const {
        code,
        message,
        stack
      } = getHelpfulChildProcessError(stdout, stderr);
      const cause = new Error(message);
      // @ts-ignore
      cause.code = code;
      cause.stack = stack;
      super(cause, betterMessage);
    } else {
      super(betterMessage);
    }
    // @ts-ignore
    this.name = 'IpcError';
    // @ts-ignore
    this.stdout = stdout;
    // @ts-ignore
    this.stderr = stderr;
  }
}
const readyMessage = 'ready';
const getData$2 = event => {
  return event.data;
};
const listen$7 = () => {
  // @ts-ignore
  if (typeof WorkerGlobalScope === 'undefined') {
    throw new TypeError('module is not in web worker scope');
  }
  return globalThis;
};
const signal$8 = global => {
  global.postMessage(readyMessage);
};
class IpcChildWithModuleWorker extends Ipc {
  getData(event) {
    return getData$2(event);
  }
  send(message) {
    // @ts-ignore
    this._rawIpc.postMessage(message);
  }
  sendAndTransfer(message) {
    const transfer = getTransferrables(message);
    // @ts-ignore
    this._rawIpc.postMessage(message, transfer);
  }
  dispose() {
    // ignore
  }
  onClose(callback) {
    // ignore
  }
  onMessage(callback) {
    this._rawIpc.addEventListener('message', callback);
  }
}
const wrap$f = global => {
  return new IpcChildWithModuleWorker(global);
};
const waitForFirstMessage = async port => {
  const {
    promise,
    resolve
  } = Promise.withResolvers();
  port.addEventListener('message', resolve, {
    once: true
  });
  const event = await promise;
  // @ts-ignore
  return event.data;
};
const listen$6 = async () => {
  const parentIpcRaw = listen$7();
  signal$8(parentIpcRaw);
  const parentIpc = wrap$f(parentIpcRaw);
  const firstMessage = await waitForFirstMessage(parentIpc);
  if (firstMessage.method !== 'initialize') {
    throw new IpcError('unexpected first message');
  }
  const type = firstMessage.params[0];
  if (type === 'message-port') {
    parentIpc.send({
      id: firstMessage.id,
      jsonrpc: '2.0',
      result: null
    });
    parentIpc.dispose();
    const port = firstMessage.params[1];
    return port;
  }
  return globalThis;
};
class IpcChildWithModuleWorkerAndMessagePort extends Ipc {
  getData(event) {
    return getData$2(event);
  }
  send(message) {
    this._rawIpc.postMessage(message);
  }
  sendAndTransfer(message) {
    const transfer = getTransferrables(message);
    this._rawIpc.postMessage(message, transfer);
  }
  dispose() {
    if (this._rawIpc.close) {
      this._rawIpc.close();
    }
  }
  onClose(callback) {
    // ignore
  }
  onMessage(callback) {
    this._rawIpc.addEventListener('message', callback);
    this._rawIpc.start();
  }
}
const wrap$e = port => {
  return new IpcChildWithModuleWorkerAndMessagePort(port);
};
const IpcChildWithModuleWorkerAndMessagePort$1 = {
  __proto__: null,
  listen: listen$6,
  wrap: wrap$e
};

const Two$1 = '2.0';
const callbacks = Object.create(null);
const get$2 = id => {
  return callbacks[id];
};
const remove$1 = id => {
  delete callbacks[id];
};
class JsonRpcError extends Error {
  constructor(message) {
    super(message);
    this.name = 'JsonRpcError';
  }
}
const NewLine = '\n';
const DomException = 'DOMException';
const ReferenceError$1 = 'ReferenceError';
const SyntaxError$1 = 'SyntaxError';
const TypeError$1 = 'TypeError';
const getErrorConstructor = (message, type) => {
  if (type) {
    switch (type) {
      case DomException:
        return DOMException;
      case TypeError$1:
        return TypeError;
      case SyntaxError$1:
        return SyntaxError;
      case ReferenceError$1:
        return ReferenceError;
      default:
        return Error;
    }
  }
  if (message.startsWith('TypeError: ')) {
    return TypeError;
  }
  if (message.startsWith('SyntaxError: ')) {
    return SyntaxError;
  }
  if (message.startsWith('ReferenceError: ')) {
    return ReferenceError;
  }
  return Error;
};
const constructError = (message, type, name) => {
  const ErrorConstructor = getErrorConstructor(message, type);
  if (ErrorConstructor === DOMException && name) {
    return new ErrorConstructor(message, name);
  }
  if (ErrorConstructor === Error) {
    const error = new Error(message);
    if (name && name !== 'VError') {
      error.name = name;
    }
    return error;
  }
  return new ErrorConstructor(message);
};
const joinLines = lines => {
  return lines.join(NewLine);
};
const splitLines = lines => {
  return lines.split(NewLine);
};
const getCurrentStack = () => {
  const stackLinesToSkip = 3;
  const currentStack = joinLines(splitLines(new Error().stack || '').slice(stackLinesToSkip));
  return currentStack;
};
const getNewLineIndex = (string, startIndex = undefined) => {
  return string.indexOf(NewLine, startIndex);
};
const getParentStack = error => {
  let parentStack = error.stack || error.data || error.message || '';
  if (parentStack.startsWith('    at')) {
    parentStack = error.message + NewLine + parentStack;
  }
  return parentStack;
};
const MethodNotFound = -32601;
const Custom = -32001;
const restoreJsonRpcError = error => {
  const currentStack = getCurrentStack();
  if (error && error instanceof Error) {
    if (typeof error.stack === 'string') {
      error.stack = error.stack + NewLine + currentStack;
    }
    return error;
  }
  if (error && error.code && error.code === MethodNotFound) {
    const restoredError = new JsonRpcError(error.message);
    const parentStack = getParentStack(error);
    restoredError.stack = parentStack + NewLine + currentStack;
    return restoredError;
  }
  if (error && error.message) {
    const restoredError = constructError(error.message, error.type, error.name);
    if (error.data) {
      if (error.data.stack && error.data.type && error.message) {
        restoredError.stack = error.data.type + ': ' + error.message + NewLine + error.data.stack + NewLine + currentStack;
      } else if (error.data.stack) {
        restoredError.stack = error.data.stack;
      }
      if (error.data.codeFrame) {
        // @ts-ignore
        restoredError.codeFrame = error.data.codeFrame;
      }
      if (error.data.code) {
        // @ts-ignore
        restoredError.code = error.data.code;
      }
      if (error.data.type) {
        // @ts-ignore
        restoredError.name = error.data.type;
      }
    } else {
      if (error.stack) {
        const lowerStack = restoredError.stack || '';
        // @ts-ignore
        const indexNewLine = getNewLineIndex(lowerStack);
        const parentStack = getParentStack(error);
        // @ts-ignore
        restoredError.stack = parentStack + lowerStack.slice(indexNewLine);
      }
      if (error.codeFrame) {
        // @ts-ignore
        restoredError.codeFrame = error.codeFrame;
      }
    }
    return restoredError;
  }
  if (typeof error === 'string') {
    return new Error(`JsonRpc Error: ${error}`);
  }
  return new Error(`JsonRpc Error: ${error}`);
};
const unwrapJsonRpcResult = responseMessage => {
  if ('error' in responseMessage) {
    const restoredError = restoreJsonRpcError(responseMessage.error);
    throw restoredError;
  }
  if ('result' in responseMessage) {
    return responseMessage.result;
  }
  throw new JsonRpcError('unexpected response message');
};
const warn = (...args) => {
  console.warn(...args);
};
const resolve = (id, response) => {
  const fn = get$2(id);
  if (!fn) {
    console.log(response);
    warn(`callback ${id} may already be disposed`);
    return;
  }
  fn(response);
  remove$1(id);
};
const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND';
const getErrorType = prettyError => {
  if (prettyError && prettyError.type) {
    return prettyError.type;
  }
  if (prettyError && prettyError.constructor && prettyError.constructor.name) {
    return prettyError.constructor.name;
  }
  return undefined;
};
const isAlreadyStack = line => {
  return line.trim().startsWith('at ');
};
const getStack = prettyError => {
  const stackString = prettyError.stack || '';
  const newLineIndex = stackString.indexOf('\n');
  if (newLineIndex !== -1 && !isAlreadyStack(stackString.slice(0, newLineIndex))) {
    return stackString.slice(newLineIndex + 1);
  }
  return stackString;
};
const getErrorProperty = (error, prettyError) => {
  if (error && error.code === E_COMMAND_NOT_FOUND) {
    return {
      code: MethodNotFound,
      message: error.message,
      data: error.stack
    };
  }
  return {
    code: Custom,
    message: prettyError.message,
    data: {
      stack: getStack(prettyError),
      codeFrame: prettyError.codeFrame,
      type: getErrorType(prettyError),
      code: prettyError.code,
      name: prettyError.name
    }
  };
};
const create$1$2 = (id, error) => {
  return {
    jsonrpc: Two$1,
    id,
    error
  };
};
const getErrorResponse = (id, error, preparePrettyError, logError) => {
  const prettyError = preparePrettyError(error);
  logError(error, prettyError);
  const errorProperty = getErrorProperty(error, prettyError);
  return create$1$2(id, errorProperty);
};
const create$3 = (message, result) => {
  return {
    jsonrpc: Two$1,
    id: message.id,
    result: result ?? null
  };
};
const getSuccessResponse = (message, result) => {
  const resultProperty = result ?? null;
  return create$3(message, resultProperty);
};
const getErrorResponseSimple = (id, error) => {
  return {
    jsonrpc: Two$1,
    id,
    error: {
      code: Custom,
      // @ts-ignore
      message: error.message,
      data: error
    }
  };
};
const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
  try {
    const result = requiresSocket(message.method) ? await execute(message.method, ipc, ...message.params) : await execute(message.method, ...message.params);
    return getSuccessResponse(message, result);
  } catch (error) {
    if (ipc.canUseSimpleErrorResponse) {
      return getErrorResponseSimple(message.id, error);
    }
    return getErrorResponse(message.id, error, preparePrettyError, logError);
  }
};
const defaultPreparePrettyError = error => {
  return error;
};
const defaultLogError = () => {
  // ignore
};
const defaultRequiresSocket = () => {
  return false;
};
const defaultResolve = resolve;

// TODO maybe remove this in v6 or v7, only accept options object to simplify the code
const normalizeParams = args => {
  if (args.length === 1) {
    const options = args[0];
    return {
      ipc: options.ipc,
      message: options.message,
      execute: options.execute,
      resolve: options.resolve || defaultResolve,
      preparePrettyError: options.preparePrettyError || defaultPreparePrettyError,
      logError: options.logError || defaultLogError,
      requiresSocket: options.requiresSocket || defaultRequiresSocket
    };
  }
  return {
    ipc: args[0],
    message: args[1],
    execute: args[2],
    resolve: args[3],
    preparePrettyError: args[4],
    logError: args[5],
    requiresSocket: args[6]
  };
};
const handleJsonRpcMessage = async (...args) => {
  const options = normalizeParams(args);
  const {
    message,
    ipc,
    execute,
    resolve,
    preparePrettyError,
    logError,
    requiresSocket
  } = options;
  if ('id' in message) {
    if ('method' in message) {
      const response = await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
      try {
        ipc.send(response);
      } catch (error) {
        const errorResponse = getErrorResponse(message.id, error, preparePrettyError, logError);
        ipc.send(errorResponse);
      }
      return;
    }
    resolve(message.id, message);
    return;
  }
  if ('method' in message) {
    await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
    return;
  }
  throw new JsonRpcError('unexpected message');
};

class CommandNotFoundError extends Error {
  constructor(command) {
    super(`Command not found ${command}`);
    this.name = 'CommandNotFoundError';
  }
}
const commands = Object.create(null);
const register = commandMap => {
  Object.assign(commands, commandMap);
};
const getCommand = key => {
  return commands[key];
};
const execute = (command, ...args) => {
  const fn = getCommand(command);
  if (!fn) {
    throw new CommandNotFoundError(command);
  }
  return fn(...args);
};

const Two = '2.0';
const create$s = (method, params) => {
  return {
    jsonrpc: Two,
    method,
    params
  };
};
const create$r = (id, method, params) => {
  const message = {
    id,
    jsonrpc: Two,
    method,
    params
  };
  return message;
};
let id = 0;
const create$q = () => {
  return ++id;
};

/* eslint-disable n/no-unsupported-features/es-syntax */

const registerPromise = map => {
  const id = create$q();
  const {
    promise,
    resolve
  } = Promise.withResolvers();
  map[id] = resolve;
  return {
    id,
    promise
  };
};

// @ts-ignore
const invokeHelper = async (callbacks, ipc, method, params, useSendAndTransfer) => {
  const {
    id,
    promise
  } = registerPromise(callbacks);
  const message = create$r(id, method, params);
  if (useSendAndTransfer && ipc.sendAndTransfer) {
    ipc.sendAndTransfer(message);
  } else {
    ipc.send(message);
  }
  const responseMessage = await promise;
  return unwrapJsonRpcResult(responseMessage);
};
const createRpc = ipc => {
  const callbacks = Object.create(null);
  ipc._resolve = (id, response) => {
    const fn = callbacks[id];
    if (!fn) {
      console.warn(`callback ${id} may already be disposed`);
      return;
    }
    fn(response);
    delete callbacks[id];
  };
  const rpc = {
    async dispose() {
      await ipc?.dispose();
    },
    invoke(method, ...params) {
      return invokeHelper(callbacks, ipc, method, params, false);
    },
    invokeAndTransfer(method, ...params) {
      return invokeHelper(callbacks, ipc, method, params, true);
    },
    // @ts-ignore
    ipc,
    /**
     * @deprecated
     */
    send(method, ...params) {
      const message = create$s(method, params);
      ipc.send(message);
    }
  };
  return rpc;
};
const requiresSocket = () => {
  return false;
};
const preparePrettyError = error => {
  return error;
};
const logError = () => {
  // handled by renderer worker
};
const handleMessage = event => {
  const actualRequiresSocket = event?.target?.requiresSocket || requiresSocket;
  const actualExecute = event?.target?.execute || execute;
  return handleJsonRpcMessage(event.target, event.data, actualExecute, event.target._resolve, preparePrettyError, logError, actualRequiresSocket);
};
const handleIpc = ipc => {
  if ('addEventListener' in ipc) {
    ipc.addEventListener('message', handleMessage);
  } else if ('on' in ipc) {
    // deprecated
    ipc.on('message', handleMessage);
  }
};
const listen$1 = async (module, options) => {
  const rawIpc = await module.listen(options);
  if (module.signal) {
    module.signal(rawIpc);
  }
  const ipc = module.wrap(rawIpc);
  return ipc;
};
const create$1$1 = async ({
  commandMap
}) => {
  // TODO create a commandMap per rpc instance
  register(commandMap);
  const ipc = await listen$1(IpcChildWithModuleWorkerAndMessagePort$1);
  handleIpc(ipc);
  const rpc = createRpc(ipc);
  return rpc;
};
const WebWorkerRpcClient = {
  __proto__: null,
  create: create$1$1
};
const createMockRpc = ({
  commandMap
}) => {
  const invocations = [];
  const invoke = (method, ...params) => {
    invocations.push([method, ...params]);
    const command = commandMap[method];
    if (!command) {
      throw new Error(`command ${method} not found`);
    }
    return command(...params);
  };
  const mockRpc = {
    invocations,
    invoke,
    invokeAndTransfer: invoke
  };
  return mockRpc;
};

const CheckBox = 'checkbox';
const Group = 'group';
const None = 'none';

const Button = 1;
const Div = 4;
const Text = 12;
const TextArea = 62;

const ClientX = 'event.clientX';
const ClientY = 'event.clientY';
const TargetName = 'event.target.name';
const TargetValue = 'event.target.value';

const Tab = 2;
const Enter = 3;
const KeyF = 34;
const F4 = 60;

const User$1 = 1;
const Script$1 = 2;

const CtrlCmd = 1 << 11 >>> 0;
const Shift = 1 << 10 >>> 0;
const Alt = 1 << 9 >>> 0;

const EditorWorker = 99;

const FocusSelector = 'Viewlet.focusSelector';
const SetCss = 'Viewlet.setCss';
const SetFocusContext = 'Viewlet.setFocusContext';
const SetValueByName = 'Viewlet.setValueByName';

const FocusFindWidget$1 = 16;
const FocusFindWidgetCloseButton$1 = 48;
const FocusFindWidgetNextMatchButton = 49;
const FocusFindWidgetPreviousMatchButton = 50;
const FocusFindWidgetReplace$1 = 43;
const FocusFindWidgetReplaceAllButton$1 = 47;
const FocusFindWidgetReplaceButton = 46;
const FocusIgnoreFiles = 1012;
const FocusSearchExcludeInput = 1008;
const FocusSearchIncludeInput = 1007;
const FocusSearchInput = 21;
const FocusSearchMatchCase = 32;
const FocusSearchOpenEditors = 1011;
const FocusSearchPreserveCase = 36;
const FocusSearchRegex = 33;
const FocusSearchReplaceAll = 35;
const FocusSearchReplaceInput = 31;
const FocusSearchWholeWord = 34;
const FocusToggleDetails = 1010;
const FocusToggleReplace = 1020;

const rpcs = Object.create(null);
const set$2 = (id, rpc) => {
  rpcs[id] = rpc;
};
const get$1 = id => {
  return rpcs[id];
};
const remove = id => {
  delete rpcs[id];
};

/* eslint-disable  @typescript-eslint/explicit-function-return-type */
const create$2 = rpcId => {
  return {
    async dispose() {
      const rpc = get$1(rpcId);
      await rpc.dispose();
    },
    // @ts-ignore
    invoke(method, ...params) {
      const rpc = get$1(rpcId);
      // @ts-ignore
      return rpc.invoke(method, ...params);
    },
    // @ts-ignore
    invokeAndTransfer(method, ...params) {
      const rpc = get$1(rpcId);
      // @ts-ignore
      return rpc.invokeAndTransfer(method, ...params);
    },
    registerMockRpc(commandMap) {
      const mockRpc = createMockRpc({
        commandMap
      });
      set$2(rpcId, mockRpc);
      // @ts-ignore
      mockRpc[Symbol.dispose] = () => {
        remove(rpcId);
      };
      // @ts-ignore
      return mockRpc;
    },
    set(rpc) {
      set$2(rpcId, rpc);
    }
  };
};

const {
  invoke,
  set: set$1
} = create$2(EditorWorker);
const getLines$1 = async editorUid => {
  const lines = await invoke('Editor.getLines2', editorUid);
  return lines;
};
const getSelections$1 = async editorUid => {
  const selections = await invoke('Editor.getSelections2', editorUid);
  return selections;
};

const toCommandId = key => {
  const dotIndex = key.indexOf('.');
  return key.slice(dotIndex + 1);
};
const create$1 = () => {
  const states = Object.create(null);
  const commandMapRef = {};
  return {
    get(uid) {
      return states[uid];
    },
    set(uid, oldState, newState) {
      states[uid] = {
        oldState,
        newState
      };
    },
    dispose(uid) {
      delete states[uid];
    },
    getKeys() {
      return Object.keys(states).map(key => {
        return Number.parseInt(key);
      });
    },
    clear() {
      for (const key of Object.keys(states)) {
        delete states[key];
      }
    },
    wrapCommand(fn) {
      const wrapped = async (uid, ...args) => {
        const {
          oldState,
          newState
        } = states[uid];
        const newerState = await fn(newState, ...args);
        if (oldState === newerState || newState === newerState) {
          return;
        }
        const latest = states[uid];
        states[uid] = {
          oldState: latest.oldState,
          newState: newerState
        };
      };
      return wrapped;
    },
    wrapGetter(fn) {
      const wrapped = (uid, ...args) => {
        const {
          newState
        } = states[uid];
        return fn(newState, ...args);
      };
      return wrapped;
    },
    diff(uid, modules, numbers) {
      const {
        oldState,
        newState
      } = states[uid];
      const diffResult = [];
      for (let i = 0; i < modules.length; i++) {
        const fn = modules[i];
        if (!fn(oldState, newState)) {
          diffResult.push(numbers[i]);
        }
      }
      return diffResult;
    },
    getCommandIds() {
      const keys = Object.keys(commandMapRef);
      const ids = keys.map(toCommandId);
      return ids;
    },
    registerCommands(commandMap) {
      Object.assign(commandMapRef, commandMap);
    }
  };
};
const terminate = () => {
  globalThis.close();
};

const close$1 = async state => {
  const {
    editorUid
  } = state;
  // @ts-ignore
  await invoke('Editor.closeFind2', editorUid);
  return state;
};

const {
  dispose: dispose$1,
  get,
  getCommandIds,
  registerCommands,
  set,
  wrapCommand,
  wrapGetter
} = create$1();

const User = 1;
const Script = 2;
const Unknown = 0;

const create = (uid, x, y, width, height, parentUid) => {
  const state = {
    ariaAnnouncement: '',
    editorHeight: height,
    editorUid: parentUid,
    editorWidth: width,
    editorX: x,
    editorY: y,
    focus: 0,
    focused: false,
    focusSource: Unknown,
    height: 0,
    history: [],
    inputBorderWidth: 1,
    inputErrorMessage: '',
    inputGap: 3,
    inputLineHeight: 15,
    inputPaddingBottom: 4,
    inputPaddingTop: 4,
    inputSource: 0,
    lines: [],
    matchCase: false,
    matchCount: 0,
    matches: new Uint32Array(),
    matchIndex: -1,
    matchWholeWord: false,
    minWidth: 400,
    preserveCase: false,
    replaceExpanded: false,
    replacement: '',
    resizerPointerDown: false,
    searchInputHeight: 15,
    selections: [],
    uid,
    useRegularExpression: false,
    value: '',
    version: 0,
    width: 0,
    x: 0,
    y: 0
  };
  set(uid, state, state);
  return state;
};

const isEqual$8 = (oldState, newState) => {
  return oldState.x === newState.x && oldState.y === newState.y && oldState.width === newState.width && oldState.height === newState.height;
};

const isEqual$7 = (oldState, newState) => {
  return newState.width === newState.width && oldState.height === newState.height && oldState.x === newState.x && oldState.searchInputHeight === newState.searchInputHeight;
};

const isEqual$6 = (oldState, newState) => {
  return oldState.version === newState.version;
};

const isEqual$5 = (oldState, newState) => {
  return oldState.focused === newState.focused && oldState.focus === newState.focus;
};

const isEqual$4 = (oldState, newState) => {
  return oldState.focused === newState.focused;
};

const isEqual$3 = (oldState, newState) => {
  return oldState.inputErrorMessage === newState.inputErrorMessage && oldState.matchCase === newState.matchCase && oldState.matchCount === newState.matchCount && oldState.matchIndex === newState.matchIndex && oldState.matchWholeWord === newState.matchWholeWord && oldState.preserveCase === newState.preserveCase && oldState.replaceExpanded === newState.replaceExpanded && oldState.useRegularExpression === newState.useRegularExpression && oldState.version === newState.version;
};

const isEqual$2 = (oldState, newState) => {
  return oldState.version === newState.version;
};

const isEqual$1 = (oldState, newState) => {
  return newState.inputSource === User$1 || oldState.replacement === newState.replacement;
};

const RenderBounds = 8;
const RenderCss = 10;
const RenderEventListeners = 11;
const RenderUid = 12;
const RenderContent = 13;
const RenderFocusContext = 14;
const RenderFocus = 15;
const RenderValue = 16;
const RenderReplaceValue = 17;

const isEqual = (oldState, newState) => {
  return newState.inputSource === User$1 || oldState.value === newState.value;
};

const modules = [isEqual$6, isEqual$3, isEqual$8, isEqual$2, isEqual$4, isEqual$5, isEqual, isEqual$1, isEqual$7];
const numbers = [RenderEventListeners, RenderContent, RenderBounds, RenderUid, RenderFocusContext, RenderFocus, RenderValue, RenderReplaceValue, RenderCss];

const diff = (oldState, newState) => {
  const diffResult = [];
  for (let i = 0; i < modules.length; i++) {
    const fn = modules[i];
    if (!fn(oldState, newState)) {
      diffResult.push(numbers[i]);
    }
  }
  return diffResult;
};

const diff2 = uid => {
  const {
    newState,
    oldState
  } = get(uid);
  const diffResult = diff(oldState, newState);
  return diffResult;
};

const dispose = uid => {
  return dispose$1(uid);
};

const FindWidget$1 = 16;
const FocusFindWidgetCloseButton = 48;
const FocusFindWidgetReplace = 43;
const FocusFindWidgetReplaceAllButton = 47;
const FocusFindWidgetToggleReplace = 42;

const setFindWidgetFocus = (state, focusKey) => {
  if (state.focus === focusKey) {
    return state;
  }
  return {
    ...state,
    focus: focusKey,
    focusSource: Script
  };
};

const focusCloseButton = state => {
  return setFindWidgetFocus(state, FocusFindWidgetCloseButton);
};

const setSelections = async (editorUid, selections) => {
  // @ts-ignore
  await invoke('Editor.setSelections2', editorUid, selections);
};

const focusIndex = async (state, index) => {
  const {
    editorUid,
    matches,
    matchIndex
  } = state;
  if (index === matchIndex) {
    return state;
  }
  // // TODO find next match and highlight it
  const matchRowIndex = matches[index * 3];
  const matchColumnIndex = matches[index * 3 + 1];
  const matchLength = matches[index * 3 + 2];
  const newSelections = new Uint32Array([matchRowIndex, matchColumnIndex, matchRowIndex, matchColumnIndex + matchLength]);
  await setSelections(editorUid, newSelections);
  return {
    ...state,
    matchIndex: index,
    selections: [...newSelections]
  };
};
const focusFirst = state => {
  return focusIndex(state, 0);
};
const focusLast = state => {
  const {
    matchCount
  } = state;
  return focusIndex(state, matchCount - 1);
};
const focusNext = state => {
  const {
    matchCount,
    matchIndex
  } = state;
  if (matchIndex === matchCount - 1) {
    return focusFirst(state);
  }
  return focusIndex(state, matchIndex + 1);
};
const focusPrevious = state => {
  const {
    matchIndex
  } = state;
  if (matchIndex === 0) {
    return focusLast(state);
  }
  return focusIndex(state, matchIndex - 1);
};

const focusReplace = state => {
  return setFindWidgetFocus(state, FocusFindWidgetReplace);
};

const focusReplaceAllButton = state => {
  return setFindWidgetFocus(state, FocusFindWidgetReplaceAllButton);
};

const handleBlur = async state => {
  return {
    ...state,
    focus: 0,
    focused: false
  };
};

const escapeRegExpCharacters = value => {
  // @ts-ignore
  return RegExp.escape(value);
};

const buildRegex = (searchString, options) => {
  const {
    matchCase,
    matchWholeWord,
    useRegularExpression
  } = options;
  const flags = matchCase ? 'g' : 'gi';
  const pattern = useRegularExpression ? searchString : escapeRegExpCharacters(searchString);
  const wrapped = matchWholeWord ? `\\b(?:${pattern})\\b` : pattern;
  try {
    const regex = new RegExp(wrapped, flags);
    return {
      error: '',
      regex
    };
  } catch (error) {
    return {
      error: `${error}`,
      regex: new RegExp('')
    };
  }
};

const findRegexMatches = (lines, regex) => {
  if (!regex.global) {
    throw new Error('regex must be global');
  }
  const {
    length
  } = lines;
  const matches = [];
  for (let i = 0; i < length; i++) {
    const line = lines[i];
    let lastMatch;
    do {
      lastMatch = regex.exec(line);
      if (!lastMatch) {
        break;
      }
      matches.push(i, lastMatch.index, lastMatch[0].length);
    } while (true);
  }
  return new Uint32Array(matches);
};

const emptyMatches$1 = new Uint32Array([]);
const findMatches = (lines, searchString, options) => {
  if (searchString.length === 0) {
    return {
      error: '',
      matches: emptyMatches$1
    };
  }
  const {
    error,
    regex
  } = buildRegex(searchString, options);
  if (error) {
    return {
      error,
      matches: emptyMatches$1
    };
  }
  const matches = findRegexMatches(lines, regex);
  return {
    error: '',
    matches
  };
};

const getMatchCount = matches => {
  return matches.length / 3;
};

const measureTextHeight = (value, lineHeight) => {
  if (!value) {
    return lineHeight;
  }
  // TODO for single line width, can use offscreencanvas to measure text width
  // for multiline text, can ask renderer process to measure text height
  const lines = value.split('\n');
  return lines.length * lineHeight;
};

const measureInputHeight = (value, inputLineHeight, inputPaddingBottom, inputPaddingTop, inputBorderWidth, inputGap, replaceExpanded) => {
  const textHeight = measureTextHeight(value, inputLineHeight);
  const inputHeight = textHeight + inputPaddingBottom + inputPaddingTop + inputBorderWidth * 2;
  const replaceInputHeight = replaceExpanded ? inputHeight : 0; // TODO should be independent of input
  const actualGap = replaceExpanded ? inputGap : 0;
  // TODO use variables for margin
  const height = inputHeight + replaceInputHeight + 5 + actualGap;
  return {
    height,
    inputHeight,
    replaceInputHeight
  };
};

const refresh$1 = (state, value, inputSource) => {
  const {
    inputBorderWidth,
    inputGap,
    inputLineHeight,
    inputPaddingBottom,
    inputPaddingTop,
    lines,
    matchCase,
    matchWholeWord,
    replaceExpanded,
    useRegularExpression
  } = state;
  const options = {
    matchCase,
    matchWholeWord,
    useRegularExpression
  };
  const {
    error,
    matches
  } = findMatches(lines, value, options);
  const {
    height,
    inputHeight
  } = measureInputHeight(value, inputLineHeight, inputPaddingBottom, inputPaddingTop, inputBorderWidth, inputGap, replaceExpanded);
  if (error) {
    return {
      ...state,
      height,
      inputErrorMessage: error,
      searchInputHeight: inputHeight
    };
  }
  const matchCount = getMatchCount(matches);
  return {
    ...state,
    height,
    inputErrorMessage: error,
    inputSource,
    matchCount,
    matches,
    matchIndex: 0,
    searchInputHeight: inputHeight,
    value
  };
};

const refresh = (state, value = state.value, inputSource = User$1) => {
  return refresh$1(state, value, inputSource);
};

const toggleMatchCase = state => {
  const {
    matchCase
  } = state;
  const newState = {
    ...state,
    matchCase: !matchCase
  };
  return refresh(newState, newState.value, User$1);
};

const toggleMatchWholeWord = state => {
  const {
    matchWholeWord
  } = state;
  const newState = {
    ...state,
    matchWholeWord: !matchWholeWord
  };
  return refresh(newState, newState.value, User$1);
};

const togglePreserveCase = state => {
  const {
    preserveCase
  } = state;
  // TODO update search results
  return {
    ...state,
    preserveCase: !preserveCase
  };
};

const toggleUseRegularExpression = state => {
  const {
    useRegularExpression
  } = state;
  const newState = {
    ...state,
    useRegularExpression: !useRegularExpression
  };
  return refresh(newState, newState.value, User$1);
};

const Close$2 = 'Close';
const FocusNext = 'FocusNext';
const FocusPrevious = 'FocusPrevious';
const MatchCase$2 = 'MatchCase';
const MatchWholeWord$2 = 'MatchWholeWord';
const PreserveCase$1 = 'PreserveCase';
const Replace$2 = 'Replace';
const ReplaceAll$2 = 'ReplaceAll';
const ReplaceValue = 'replace-value';
const SearchValue = 'search-value';
const ToggleReplace$1 = 'ToggleReplace';
const UseRegularExpression$2 = 'UseRegularExpression';

const applyEdits = async (editorId, edits) => {
  // @ts-ignore
  await invoke('Editor.applyDocumentEdits', editorId, edits);
};

/**
 * Apply regex replacement with back-reference substitution ($1, $2, etc.)
 */
const applyRegexReplacement = (originalText, regex, replacement) => {
  // Create a non-global version of the regex to get capture groups
  const flags = regex.flags.replace('g', '');
  const nonGlobalRegex = new RegExp(regex.source, flags);
  const match = nonGlobalRegex.exec(originalText);
  if (!match) {
    return replacement;
  }

  // Replace $n back-references with captured groups
  let result = replacement;

  // Handle $& (entire match)
  result = result.replaceAll('$&', match[0]);

  // Handle $` (text before match) - in this context it's empty since we're matching the whole text
  result = result.replaceAll('$`', '');

  // Handle $' (text after match) - in this context it's empty since we're matching the whole text
  result = result.replaceAll("$'", '');

  // Handle $$ (literal $)
  result = result.replaceAll('$$', '\u0000DOLLAR\u0000');

  // Handle $n and $nn (numbered capture groups)
  result = result.replaceAll(/\$(\d{1,2})/g, (_match, groupNumber) => {
    const index = Number.parseInt(groupNumber, 10);
    if (index < match.length) {
      return match[index] ?? '';
    }
    return `$${groupNumber}`;
  });

  // Restore literal $
  result = result.replaceAll('\u0000DOLLAR\u0000', '$');
  return result;
};

/**
 * Preserves the case pattern of the original text when replacing.
 * Supports uppercase, lowercase, PascalCase, and camelCase patterns.
 */
const preserveCase$1 = (originalText, replacementText) => {
  if (originalText.length === 0 || replacementText.length === 0) {
    return replacementText;
  }

  // Check if original text is all uppercase
  if (originalText === originalText.toUpperCase()) {
    return replacementText.toUpperCase();
  }

  // Check if original text is all lowercase
  if (originalText === originalText.toLowerCase()) {
    return replacementText.toLowerCase();
  }

  // Check if original text is PascalCase (first letter uppercase, rest lowercase or mixed)
  if (originalText[0] === originalText[0].toUpperCase()) {
    // Check if it's pure PascalCase (first uppercase, rest lowercase)
    const restOfText = originalText.slice(1);
    if (restOfText === restOfText.toLowerCase()) {
      return replacementText[0].toUpperCase() + replacementText.slice(1).toLowerCase();
    }
    // Mixed case - preserve the pattern as much as possible
    return replacementText[0].toUpperCase() + replacementText.slice(1).toLowerCase();
  }

  // Check if original text is camelCase (first letter lowercase, rest mixed)
  if (originalText[0] === originalText[0].toLowerCase()) {
    return replacementText[0].toLowerCase() + replacementText.slice(1).toLowerCase();
  }

  // Default fallback - return replacement as-is
  return replacementText;
};

const getEdits = (matches, value, replacement, startIndex, replaceAll, lines, preserveCaseOption = false, options) => {
  if (value.length === 0 || matches.length === 0) {
    return [];
  }
  const edits = [];
  const totalMatches = Math.floor(matches.length / 3);
  const fromIndex = replaceAll ? 0 : Math.max(0, startIndex);
  const toIndex = replaceAll ? totalMatches : Math.min(totalMatches, fromIndex + 1);

  // Build regex once if using regular expressions
  let regex;
  if (options?.useRegularExpression) {
    const {
      error,
      regex: builtRegex
    } = buildRegex(value, options);
    if (!error) {
      regex = builtRegex;
    }
  }
  for (let i = fromIndex; i < toIndex; i++) {
    const rowIndex = matches[i * 3];
    const startColumnIndex = matches[i * 3 + 1];
    const matchLength = matches[i * 3 + 2];
    const endColumnIndex = startColumnIndex + matchLength;

    // Get the original text that was matched
    const originalText = lines[rowIndex].slice(startColumnIndex, endColumnIndex);

    // Apply regex replacement with back-references if enabled
    let finalReplacement;
    if (options?.useRegularExpression && regex) {
      finalReplacement = applyRegexReplacement(originalText, regex, replacement);
    } else {
      finalReplacement = replacement;
    }

    // Apply case preservation if enabled
    if (preserveCaseOption) {
      finalReplacement = preserveCase$1(originalText, finalReplacement);
    }

    // Convert row/column positions to character offsets
    let startOffset = 0;
    for (let row = 0; row < rowIndex; row++) {
      startOffset += lines[row].length + 1; // +1 for newline character
    }
    startOffset += startColumnIndex;
    let endOffset = 0;
    for (let row = 0; row < rowIndex; row++) {
      endOffset += lines[row].length + 1; // +1 for newline character
    }
    endOffset += endColumnIndex;
    edits.push({
      endOffset,
      inserted: finalReplacement,
      origin: 'find-widget.replace',
      startOffset
    });
  }
  return edits;
};

const getLines = async editorUid => {
  const lines = await getLines$1(editorUid);
  return lines;
};

const updateAfterReplace = async (state, matchIndex) => {
  const {
    editorUid,
    matchCase,
    matchWholeWord,
    useRegularExpression,
    value
  } = state;
  const options = {
    matchCase,
    matchWholeWord,
    useRegularExpression
  };
  const newLines = await getLines(editorUid);
  const {
    error,
    matches: newMatches
  } = findMatches(newLines, value, options);
  const newMatchCount = getMatchCount(newMatches);

  // Keep matchIndex in bounds, or reset to 0 if no matches remain
  const newMatchIndex = newMatchCount === 0 ? 0 : Math.min(matchIndex, newMatchCount - 1);
  return {
    ...state,
    inputErrorMessage: error,
    lines: newLines,
    matchCount: newMatchCount,
    matches: newMatches,
    matchIndex: newMatchIndex
  };
};

const replace$1 = async state => {
  const {
    editorUid,
    lines,
    matchCase,
    matches,
    matchIndex,
    matchWholeWord,
    preserveCase,
    replacement,
    useRegularExpression,
    value
  } = state;
  const options = {
    matchCase,
    matchWholeWord,
    useRegularExpression
  };
  const edits = getEdits(matches, value, replacement, matchIndex, false, lines, preserveCase, options);
  await applyEdits(editorUid, edits);
  return updateAfterReplace(state, matchIndex);
};

const replaceAll$1 = async state => {
  const {
    editorUid,
    lines,
    matchCase,
    matches,
    matchWholeWord,
    preserveCase,
    replacement,
    useRegularExpression,
    value
  } = state;
  const options = {
    matchCase,
    matchWholeWord,
    useRegularExpression
  };
  const edits = getEdits(matches, value, replacement, 0, true, lines, preserveCase, options);
  await applyEdits(editorUid, edits);
  return updateAfterReplace(state, 0);
};

const getClickHandler = name => {
  switch (name) {
    case MatchCase$2:
      return toggleMatchCase;
    case MatchWholeWord$2:
      return toggleMatchWholeWord;
    case PreserveCase$1:
      return togglePreserveCase;
    case Replace$2:
      return replace$1;
    case ReplaceAll$2:
      return replaceAll$1;
    case UseRegularExpression$2:
      return toggleUseRegularExpression;
    default:
      throw new Error(`unexpected click`);
  }
};

const handleClickButton = async (state, name) => {
  const fn = getClickHandler(name);
  return fn(state);
};

const handleClickClose = state => {
  return close$1(state);
};

const handleFindWidgetFocus = (state, focusKey) => {
  const {
    focus
  } = state;
  if (!focusKey || focus === focusKey) {
    return state;
  }
  return {
    ...state,
    focus: focusKey,
    focusSource: User
  };
};

const handleFindFocus = state => {
  return handleFindWidgetFocus(state, FindWidget$1);
};

// TODO maybe use one handleFocus function with a name parameter
const handleReplaceFocus = state => {
  return handleFindWidgetFocus(state, FocusFindWidgetReplace);
};

const handleResizerPointerDown = async (state, eventX, eventY) => {
  return {
    ...state,
    resizerPointerDown: true
  };
};

const getNewCoordinates = (oldWidth, oldX, eventX, minWidth) => {
  const oldXEnd = oldX + oldWidth;
  const newWidth = Math.max(oldXEnd - eventX, minWidth);
  return {
    newWidth,
    newX: eventX
  };
};
const handleResizerPointerMove = async (state, eventX, eventY) => {
  const {
    minWidth,
    resizerPointerDown,
    width,
    x
  } = state;
  if (!resizerPointerDown) {
    return state;
  }
  const {
    newWidth,
    newX
  } = getNewCoordinates(width, x, eventX, minWidth);
  return {
    ...state,
    width: newWidth,
    x: newX
  };
};

const handleResizerPointerUp = async (state, eventX, eventY) => {
  return {
    ...state,
    resizerPointerDown: false
  };
};

const handleToggleReplaceFocus = state => {
  return handleFindWidgetFocus(state, FocusFindWidgetToggleReplace);
};

const toggleReplace$1 = state => {
  const {
    inputBorderWidth,
    inputGap,
    inputLineHeight,
    inputPaddingBottom,
    inputPaddingTop,
    replaceExpanded,
    value
  } = state;
  const newExpanded = !replaceExpanded;
  const {
    height
  } = measureInputHeight(value, inputLineHeight, inputPaddingBottom, inputPaddingTop, inputBorderWidth, inputGap, newExpanded);
  return {
    ...state,
    height,
    replaceExpanded: newExpanded
  };
};

const focusElement = (state, whenExpression) => {
  return {
    ...state,
    focus: whenExpression,
    focusSource: Script$1
  };
};

const getNextFocus = (focus, replaceExpanded) => {
  switch (focus) {
    case FocusSearchExcludeInput:
      return FocusIgnoreFiles;
    case FocusSearchIncludeInput:
      return FocusSearchOpenEditors;
    case FocusSearchInput:
      if (replaceExpanded) {
        return FocusSearchReplaceInput;
      }
      return FocusSearchMatchCase;
    case FocusSearchMatchCase:
      return FocusSearchWholeWord;
    case FocusSearchOpenEditors:
      return FocusSearchExcludeInput;
    case FocusSearchPreserveCase:
      return FocusSearchReplaceAll;
    case FocusSearchRegex:
      if (replaceExpanded) {
        return FocusSearchPreserveCase;
      }
      return FocusFindWidgetCloseButton$1;
    case FocusSearchReplaceAll:
      return FocusToggleDetails;
    case FocusSearchReplaceInput:
      return FocusSearchMatchCase;
    case FocusSearchWholeWord:
      return FocusSearchRegex;
    case FocusToggleDetails:
      return FocusSearchIncludeInput;
    case FocusToggleReplace:
      return FocusSearchInput;
    default:
      return focus;
  }
};

const focusNextElement = state => {
  const {
    focus,
    replaceExpanded
  } = state;
  const nextFocus = getNextFocus(focus, replaceExpanded);
  return focusElement(state, nextFocus);
};

const getPreviousFocus = (focus, replaceExpanded) => {
  switch (focus) {
    case FocusFindWidgetCloseButton$1:
      return FocusSearchRegex;
    case FocusIgnoreFiles:
      return FocusSearchExcludeInput;
    case FocusSearchExcludeInput:
      return FocusSearchOpenEditors;
    case FocusSearchIncludeInput:
      return FocusToggleDetails;
    case FocusSearchInput:
      return FocusToggleReplace;
    case FocusSearchMatchCase:
      if (replaceExpanded) {
        return FocusSearchReplaceInput;
      }
      return FocusSearchInput;
    case FocusSearchOpenEditors:
      return FocusSearchIncludeInput;
    case FocusSearchPreserveCase:
      return FocusSearchRegex;
    case FocusSearchRegex:
      return FocusSearchWholeWord;
    case FocusSearchReplaceAll:
      return FocusSearchPreserveCase;
    case FocusSearchReplaceInput:
      return FocusSearchInput;
    case FocusSearchWholeWord:
      return FocusSearchMatchCase;
    case FocusToggleDetails:
      if (replaceExpanded) {
        return FocusSearchReplaceAll;
      }
      return FocusSearchRegex;
    default:
      return focus;
  }
};

const focusPreviousElement = state => {
  const {
    focus,
    replaceExpanded
  } = state;
  const previousFocus = getPreviousFocus(focus, replaceExpanded);
  return focusElement(state, previousFocus);
};

const getKeyBindings = () => {
  return [{
    command: 'FindWidget.focusNext',
    key: Enter,
    when: FocusFindWidget$1
  }, {
    command: 'FindWidget.preventDefaultBrowserFind',
    key: CtrlCmd | KeyF,
    when: FocusFindWidget$1
  }, {
    command: 'FindWidget.focusPrevious',
    key: Shift | F4,
    when: FocusFindWidget$1
  }, {
    command: 'FindWidget.focusNext',
    key: F4,
    when: FocusFindWidget$1
  }, {
    command: 'FindWidget.focusToggleReplace',
    key: Shift | Tab,
    when: FocusFindWidget$1
  }, {
    command: 'FindWidget.focusReplace',
    key: Tab,
    when: FocusFindWidget$1
  }, {
    command: 'FindWidget.focusPreviousMatchButton',
    key: Tab,
    when: FocusFindWidgetReplace$1
  }, {
    command: 'FindWidget.replace',
    key: Enter,
    when: FocusFindWidgetReplace$1
  }, {
    command: 'FindWidget.replaceAll',
    key: Alt | CtrlCmd | Enter,
    when: FocusFindWidgetReplace$1
  }, {
    command: 'FindWidget.focusNextMatchButton',
    key: Tab,
    when: FocusFindWidgetPreviousMatchButton
  }, {
    command: 'FindWidget.focusReplace',
    key: Shift | Tab,
    when: FocusFindWidgetPreviousMatchButton
  }, {
    command: 'FindWidget.focusPreviousMatchButton',
    key: Shift | Tab,
    when: FocusFindWidgetNextMatchButton
  }, {
    command: 'FindWidget.focusCloseButton',
    key: Tab,
    when: FocusFindWidgetNextMatchButton
  }, {
    command: 'FindWidget.focusNextMatchButton',
    key: Shift | Tab,
    when: FocusFindWidgetCloseButton$1
  }, {
    command: 'FindWidget.focusReplaceButton',
    key: Tab,
    when: FocusFindWidgetCloseButton$1
  }, {
    command: 'FindWidget.focusFind',
    key: Shift | Tab,
    when: FocusFindWidgetReplace$1
  }, {
    command: 'FindWidget.focusReplaceAllButton',
    key: Tab,
    when: FocusFindWidgetReplaceButton
  }, {
    command: 'FindWidget.focusCloseButton',
    key: Shift | Tab,
    when: FocusFindWidgetReplaceButton
  }, {
    command: 'FindWidget.focusReplaceButton',
    key: Shift | Tab,
    when: FocusFindWidgetReplaceAllButton$1
  }];
};

const handleInput = (state, value, inputSource = User$1) => {
  return refresh(state, value, inputSource);
};

const handleReplaceInput = (state, value, inputSource = User$1) => {
  return {
    ...state,
    inputSource,
    replacement: value
  };
};

const regexFlags = 'gi';
const getSearchRegex = searchString => {
  const escaped = escapeRegExpCharacters(searchString);
  return new RegExp(escaped, regexFlags);
};

const findMatchesCaseInsensitive = (lines, searchString) => {
  if (searchString.length === 0) {
    return new Uint32Array([]);
  }
  const regex = getSearchRegex(searchString);
  return findRegexMatches(lines, regex);
};

const getFindWidgetPosition = (editorX, editorY, editorWidth) => {
  const width = 300;
  const height = 30;
  const paddingTop = 10;
  const paddingRight = 20;
  const x = editorX + editorWidth - width - paddingRight;
  const y = editorY + paddingTop;
  return {
    height,
    width,
    x,
    y
  };
};

const getSelectedText = (lines, selections) => {
  if (selections.length === 0) {
    return '';
  }
  const startRowIndex = selections[0];
  const startColumnIndex = selections[1];
  const endColumnIndex = selections[3];
  const line = lines[startRowIndex];
  const value = line.slice(startColumnIndex, endColumnIndex);
  return value;
};

const getSelections = async editorUid => {
  const selections = await getSelections$1(editorUid);
  return selections;
};

const getSavedValue = savedState => {
  if (savedState && savedState.value) {
    return savedState.value;
  }
  return '';
};
const getSavedReplacement = savedState => {
  if (savedState && savedState.replacement) {
    return savedState.replacement;
  }
  return '';
};
const restoreState = savedState => {
  const value = getSavedValue(savedState);
  const replacement = getSavedReplacement(savedState);
  return {
    replacement,
    value
  };
};

const loadContent = async (state, savedState) => {
  const {
    editorUid,
    editorWidth,
    editorX,
    editorY,
    inputBorderWidth,
    inputGap,
    inputLineHeight,
    inputPaddingBottom,
    inputPaddingTop,
    replaceExpanded
  } = state;
  const {
    replacement,
    value
  } = restoreState(savedState);
  const lines = await getLines(editorUid);
  const selections = await getSelections(editorUid);
  const {
    width,
    x,
    y
  } = getFindWidgetPosition(editorX, editorY, editorWidth);
  if (lines.length === 0) {
    return state;
  }
  const actualValue = value || getSelectedText(lines, selections);
  const matches = findMatchesCaseInsensitive(lines, actualValue);
  const matchCount = getMatchCount(matches);
  const {
    height,
    inputHeight
  } = measureInputHeight(value, inputLineHeight, inputPaddingBottom, inputPaddingTop, inputBorderWidth, inputGap, replaceExpanded);
  return {
    ...state,
    focus: FocusSearchInput,
    focused: true,
    height,
    inputSource: Script$1,
    lines,
    matchCount,
    matches,
    matchIndex: 0,
    replacement,
    searchInputHeight: inputHeight,
    selections,
    value: actualValue,
    version: 1,
    width,
    x,
    y
  };
};

const preventDefaultBrowserFind = state => {
  return state;
};

const SetBounds = 'Viewlet.setBounds';
const SetDom2 = 'Viewlet.setDom2';
const SetUid = 'Viewlet.setUid';
const SetEventListeners = 'Viewlet.registerEventListeners';

const renderBounds = (oldState, newState) => {
  const {
    height,
    uid,
    width,
    x,
    y
  } = newState;
  return [SetBounds, uid, x, y, width, height];
};

const HandleBlur = 1;
const HandleClickButton = 2;
const HandleClickClose = 3;
const HandleClickNextMatch = 4;
const HandleClickPreviousMatch = 5;
const HandleClickReplace = 6;
const HandleClickReplaceAll = 7;
const HandleClickToggleReplace = 8;
const HandleFocus = 9;
const HandleFocusNext = 10;
const HandleFocusPrevious = 11;
const HandleInput = 12;
const HandleReplaceFocus = 13;
const HandleReplaceInput = 14;
const HandleResizerPointerDown = 15;
const HandleResizerPointerMove = 16;
const HandleResizerPointerUp = 17;
const HandleToggleReplaceFocus = 19;

const emptyObject = {};
const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
const i18nString = (key, placeholders = emptyObject) => {
  if (placeholders === emptyObject) {
    return key;
  }
  const replacer = (match, rest) => {
    return placeholders[rest];
  };
  return key.replaceAll(RE_PLACEHOLDER, replacer);
};

const MatchOf = '{PH1} of {PH2}';
const NoResults = 'No Results';
const PreserveCase = 'Preserve Case';
const Close$1 = 'Close';
const PreviousMatch = 'Previous Match';
const NextMatch = 'Next Match';
const Find$1 = 'Find';
const Replace$1 = 'Replace';
const ReplaceAll$1 = 'Replace All';
const MatchCase$1 = 'Match Case';
const MatchWholeWord$1 = 'Match Whole Word';
const UseRegularExpression$1 = 'Use Regular Expression';
const ToggleReplace = 'Toggle Replace';

const noResults = () => {
  return i18nString(NoResults);
};
const preserveCase = () => {
  return i18nString(PreserveCase);
};
const matchOf = (matchIndex, matchCount) => {
  return i18nString(MatchOf, {
    PH1: matchIndex,
    PH2: matchCount
  });
};
const previousMatch = () => {
  return i18nString(PreviousMatch);
};
const nextMatch = () => {
  return i18nString(NextMatch);
};
const close = () => {
  return i18nString(Close$1);
};
const find = () => {
  return i18nString(Find$1);
};
const replace = () => {
  return i18nString(Replace$1);
};
const replaceAll = () => {
  return i18nString(ReplaceAll$1);
};
const matchCase = () => {
  return i18nString(MatchCase$1);
};
const matchWholeWord = () => {
  return i18nString(MatchWholeWord$1);
};
const useRegularExpression = () => {
  return i18nString(UseRegularExpression$1);
};
const toggleReplace = () => {
  return i18nString(ToggleReplace);
};

const MatchCase = 'CaseSensitive';
const UseRegularExpression = 'Regex';
const MatchWholeWord = 'WholeWord';
const ArrowDown = 'ArrowDown';
const ArrowUp = 'ArrowUp';
const Close = 'Close';
const Replace = 'Replace';
const ReplaceAll = 'ReplaceAll';

const getFindWidgetButtons = (findButtonsEnabled, replaceButtonsEnabled, matchCase$1, matchWholeWord$1, useRegularExpression$1, preserveCase$1) => {
  const findFieldButtons = [{
    checked: matchCase$1,
    icon: MatchCase,
    name: MatchCase$2,
    onClick: HandleClickButton,
    title: matchCase()
  }, {
    checked: matchWholeWord$1,
    icon: MatchWholeWord,
    name: MatchWholeWord$2,
    onClick: HandleClickButton,
    title: matchWholeWord()
  }, {
    checked: useRegularExpression$1,
    icon: UseRegularExpression,
    name: UseRegularExpression$2,
    onClick: HandleClickButton,
    title: useRegularExpression()
  }];
  const replaceFieldButtons = [{
    checked: preserveCase$1,
    icon: 'PreserveCase',
    name: PreserveCase$1,
    onClick: HandleClickButton,
    title: preserveCase()
  }];
  const findButtons = [{
    disabled: !findButtonsEnabled,
    icon: ArrowUp,
    label: previousMatch(),
    name: FocusPrevious,
    onClick: HandleClickPreviousMatch
  }, {
    disabled: !findButtonsEnabled,
    icon: ArrowDown,
    label: nextMatch(),
    name: FocusNext,
    onClick: HandleClickNextMatch
  }, {
    disabled: false,
    icon: Close,
    label: close(),
    name: Close$2,
    onClick: HandleClickClose
  }];
  const replaceButtons = [{
    disabled: !replaceButtonsEnabled,
    icon: Replace,
    label: replace(),
    name: Replace$2,
    onClick: HandleClickButton
  }, {
    disabled: !replaceButtonsEnabled,
    icon: ReplaceAll,
    label: replaceAll(),
    name: ReplaceAll$2,
    onClick: HandleClickButton
  }];
  return {
    findButtons,
    findFieldButtons,
    replaceButtons,
    replaceFieldButtons
  };
};

const getFindWidgetButtonsEnabled = (matchCount, value) => {
  const findButtonsEnabled = matchCount > 0;
  const replaceButtonsEnabled = value.length > 0;
  return {
    findButtonsEnabled,
    replaceButtonsEnabled
  };
};

const mergeClassNames = (...classNames) => {
  return classNames.filter(Boolean).join(' ');
};

const text = data => {
  return {
    childCount: 0,
    text: data,
    type: Text
  };
};

const FindWidget = 'FindWidget';
const FindWidgetFind = 'FindWidgetFind';
const FindWidgetMatchCount = 'FindWidgetMatchCount';
const FindWidgetMatchCountEmpty = 'FindWidgetMatchCountEmpty';
const FindWidgetReplace = 'FindWidgetReplace';
const FindWidgetRight = 'FindWidgetRight';
const IconButton = 'IconButton';
const IconButtonDisabled = 'IconButtonDisabled';
const MaskIcon = 'MaskIcon';
const MaskIconChevronDown = 'MaskIconChevronDown';
const MaskIconChevronRight = 'MaskIconChevronRight';
const MultilineInputBox = 'MultilineInputBox';
const Resizer = 'Resizer';
const ResizerHighlight = 'ResizerHighlight';
const SearchField = 'SearchField';
const SearchFieldButton = 'SearchFieldButton';
const SearchFieldButtonChecked = 'SearchFieldButtonChecked';
const SearchFieldButtons = 'SearchFieldButtons';
const SearchFieldError = 'SearchFieldError';
const SearchFieldFocused = 'SearchFieldFocused';
const SearchToggleButton = 'SearchToggleButton';
const SearchToggleButtonExpanded = 'SearchToggleButtonExpanded';
const Viewlet = 'Viewlet';
const ViewletFind = 'ViewletFind';
const ViewletFindWidget = 'ViewletFindWidget';

const getIconVirtualDom = (icon, type = Div) => {
  return {
    childCount: 0,
    className: `${MaskIcon} MaskIcon${icon}`,
    role: None,
    type
  };
};

const getIconButtonVirtualDom = iconButton => {
  const {
    disabled,
    icon,
    label,
    name,
    onClick
  } = iconButton;
  let className = IconButton;
  if (disabled) {
    className += ' ' + IconButtonDisabled;
  }
  return [{
    ariaLabel: label,
    childCount: 1,
    className,
    disabled: disabled ? true : undefined,
    name,
    onClick,
    title: label,
    type: Button
  }, getIconVirtualDom(icon)];
};

const emptyMatches = mergeClassNames(FindWidgetMatchCount, FindWidgetMatchCountEmpty);
const getFindMatchCountClassName = (matchCount, hasValue) => {
  if (hasValue && matchCount === 0) {
    return emptyMatches;
  }
  return FindWidgetMatchCount;
};

const getMatchCountVirtualDom = (matchCountText, matchCount, hasValue) => {
  return [{
    childCount: 1,
    className: getFindMatchCountClassName(matchCount, hasValue),
    type: Div
  }, text(matchCountText)];
};

const checkedClassName = mergeClassNames(SearchFieldButton, SearchFieldButtonChecked);
const unCheckedClassName = SearchFieldButton;
const getSearchFieldButtonVirtualDom = button => {
  const {
    checked,
    icon,
    name,
    onClick,
    title
  } = button;
  return [{
    ariaChecked: checked,
    childCount: 1,
    className: checked ? checkedClassName : unCheckedClassName,
    name,
    onClick,
    role: CheckBox,
    tabIndex: 0,
    title,
    type: Button
  }, {
    childCount: 0,
    className: mergeClassNames(MaskIcon, `MaskIcon${icon}`),
    type: Div
  }];
};

const getSearchFieldVirtualDom = (name, placeholder, onInput, insideButtons, outsideButtons, onFocus, extraClassName) => {
  const dom = [{
    childCount: 2,
    className: mergeClassNames(SearchField, extraClassName),
    role: None,
    type: Div
  }, {
    autocapitalize: 'off',
    autocorrect: 'off',
    childCount: 0,
    className: MultilineInputBox,
    name,
    onFocus,
    onInput,
    placeholder,
    spellcheck: false,
    type: TextArea
  }, {
    childCount: insideButtons.length,
    className: SearchFieldButtons,
    type: Div
  }, ...insideButtons.flatMap(getSearchFieldButtonVirtualDom)];
  if (outsideButtons.length > 0) {
    throw new Error('outsideButtons are deprecated');
  }
  return dom;
};

const getExtraClassName = (hasError, inputFocused) => {
  if (hasError) {
    return SearchFieldError;
  }
  if (inputFocused) {
    return SearchFieldFocused;
  }
  return '';
};
const getFindWidgetFindVirtualDom = (matchCountText, buttons, fieldButtons, matchCount, hasValue, hasError, inputFocused) => {
  const extraClassName = getExtraClassName(hasError, inputFocused);
  return [{
    childCount: 2,
    className: FindWidgetFind,
    type: Div
  }, ...getSearchFieldVirtualDom(SearchValue, find(), HandleInput, fieldButtons, [], HandleFocus, extraClassName), {
    childCount: 1 + buttons.length,
    className: 'FindWidgetActions',
    type: Div
  }, ...getMatchCountVirtualDom(matchCountText, matchCount, hasValue), ...buttons.flatMap(getIconButtonVirtualDom)];
};

const getFindWidgetReplaceVirtualDom = (replaceExpanded, replaceButtons, replaceFieldButtons, replaceInputFocused) => {
  if (!replaceExpanded) {
    return [];
  }
  const extraClassName = replaceInputFocused ? SearchFieldFocused : '';
  return [{
    childCount: 1 + replaceButtons.length,
    className: FindWidgetReplace,
    type: Div
  }, ...getSearchFieldVirtualDom(ReplaceValue, replace(), HandleReplaceInput, [], [], HandleReplaceFocus, extraClassName), ...replaceButtons.flatMap(getIconButtonVirtualDom)];
};

const getResizerVirtualDom = () => {
  return [{
    childCount: 1,
    className: Resizer,
    onPointerDown: HandleResizerPointerDown,
    type: Div
  }, {
    childCount: 0,
    className: ResizerHighlight,
    type: Div
  }];
};

const getSearchToggleButtonVirtualDom = (replaceExpanded, onClick = '') => {
  const title = toggleReplace();
  return [{
    ariaExpanded: replaceExpanded,
    ariaLabel: title,
    childCount: 1,
    className: mergeClassNames(IconButton, SearchToggleButton, replaceExpanded ? SearchToggleButtonExpanded : ''),
    'data-command': 'toggleReplace',
    name: ToggleReplace$1,
    onClick,
    onFocus: HandleToggleReplaceFocus,
    title,
    type: Button
  }, {
    childCount: 0,
    className: mergeClassNames(MaskIcon, replaceExpanded ? MaskIconChevronDown : MaskIconChevronRight),
    type: Div
  }];
};

const parentNode = {
  childCount: 3,
  className: mergeClassNames(Viewlet, ViewletFind, ViewletFindWidget, FindWidget),
  role: Group,
  type: Div
};
const getFindWidgetVirtualDom = (matchCountText, replaceExpanded, findButtons, findFieldButtons, replaceButtons, replaceFieldButtons, matchCount, value, hasError, inputFocused, replaceInputFocused) => {
  return [parentNode, ...getResizerVirtualDom(), ...getSearchToggleButtonVirtualDom(replaceExpanded, 'handleClickToggleReplace'), {
    childCount: replaceExpanded ? 2 : 1,
    className: FindWidgetRight,
    type: Div
  }, ...getFindWidgetFindVirtualDom(matchCountText, findButtons, findFieldButtons, matchCount, Boolean(value), hasError, inputFocused), ...getFindWidgetReplaceVirtualDom(replaceExpanded, replaceButtons, replaceFieldButtons, replaceInputFocused)];
};

const getMatchCountText = (matchIndex, matchCount) => {
  if (matchCount === 0) {
    return noResults();
  }
  return matchOf(matchIndex + 1, matchCount);
};

const renderContent = (oldState, newState) => {
  const {
    focus,
    inputErrorMessage,
    matchCase,
    matchCount,
    matchWholeWord,
    preserveCase,
    replaceExpanded,
    uid,
    useRegularExpression,
    value
  } = newState;
  const matchCountText = getMatchCountText(newState.matchIndex, newState.matchCount);
  const {
    findButtonsEnabled,
    replaceButtonsEnabled
  } = getFindWidgetButtonsEnabled(matchCount, value);
  const {
    findButtons,
    findFieldButtons,
    replaceButtons,
    replaceFieldButtons
  } = getFindWidgetButtons(findButtonsEnabled, replaceButtonsEnabled, matchCase, matchWholeWord, useRegularExpression, preserveCase);
  const hasError = Boolean(inputErrorMessage);
  const inputFocused = focus === FocusSearchInput;
  const replaceInputFocused = focus === FocusSearchReplaceInput;
  const dom = getFindWidgetVirtualDom(matchCountText, replaceExpanded, findButtons, findFieldButtons, replaceButtons, replaceFieldButtons, matchCount, value, hasError, inputFocused, replaceInputFocused);
  return [SetDom2, uid, dom];
};

const renderCss = (oldState, newState) => {
  const {
    height,
    searchInputHeight: inputHeight,
    uid,
    width,
    x,
    y
  } = newState;
  const css = `:root {
  --FindWidgetWidth: ${width}px;
  --FindWidgetHeight: ${height}px;
  --FindWidgetX: ${x}px;
  --FindWidgetY: ${y}px;
  --FindWidgetInputHeight: ${inputHeight}px;
}`;
  return [SetCss, uid, css];
};

const getEventListeners = (uid, widgetId) => {
  return [{
    name: HandleInput,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleInput', 0, widgetId, TargetValue]
  }, {
    name: HandleClickClose,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleClickClose', 0, widgetId]
  }, {
    name: HandleClickPreviousMatch,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.focusPrevious', 0, widgetId]
  }, {
    name: HandleClickNextMatch,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.focusNext', 0, widgetId]
  }, {
    name: HandleClickReplace,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleClickReplace', 0, widgetId]
  }, {
    name: HandleClickReplace,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleClickReplaceAll', 0, widgetId]
  }, {
    name: HandleClickToggleReplace,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.toggleReplace', 0, widgetId]
  }, {
    name: HandleBlur,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleBlur', 0, widgetId]
  }, {
    name: HandleReplaceInput,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleReplaceInput', 0, widgetId, TargetValue]
  }, {
    name: HandleReplaceFocus,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleReplaceFocus', 0, widgetId]
  }, {
    name: HandleFocusPrevious,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleFocusPrevious', 0, widgetId]
  }, {
    name: HandleFocusNext,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleFocusNext', 0, widgetId]
  }, {
    name: HandleToggleReplaceFocus,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleToggleReplaceFocus', 0, widgetId]
  }, {
    name: HandleClickReplaceAll,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleClickReplaceAll', 0, widgetId]
  }, {
    name: HandleClickButton,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleClickButton', 0, widgetId, TargetName]
  }, {
    name: HandleResizerPointerDown,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleResizerPointerDown', 0, widgetId, ClientX, ClientY],
    trackPointerEvents: [HandleResizerPointerMove, HandleResizerPointerUp]
  }, {
    name: HandleResizerPointerMove,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleResizerPointerMove', 0, widgetId, ClientX, ClientY]
  }, {
    name: HandleResizerPointerUp,
    params: ['executeWidgetCommand', 'FindWidget', 'FindWidget.handleResizerPointerUp', 0, widgetId, ClientX, ClientY]
  }];
};

const Find = 5;

const renderEventListeners = state => {
  const {
    uid
  } = state;
  const eventListeners = getEventListeners(uid, Find);
  return [SetEventListeners, uid, eventListeners];
};

const getFocusSelector = focusKey => {
  switch (focusKey) {
    case FocusFindWidgetCloseButton$1:
      return Close$2;
    case FocusSearchInput:
      return SearchValue;
    case FocusSearchMatchCase:
      return MatchCase$2;
    case FocusSearchPreserveCase:
      return PreserveCase$1;
    case FocusSearchRegex:
      return UseRegularExpression$2;
    case FocusSearchReplaceAll:
      return ReplaceAll$2;
    case FocusSearchReplaceInput:
      return ReplaceValue;
    case FocusSearchWholeWord:
      return MatchWholeWord$2;
    case FocusToggleReplace:
      return ToggleReplace$1;
    default:
      return '';
  }
};

const renderFocus = (oldState, newState) => {
  const {
    focus,
    uid
  } = newState;
  const name = getFocusSelector(focus);
  const selector = `[name="${name}"]`;
  return [FocusSelector, uid, selector];
};

const FocusFindWidget = 16;

const renderFocusContext = (oldState, newState) => {
  return [/* method */SetFocusContext, FocusFindWidget];
};

const renderReplaceValue = (oldState, newState) => {
  const {
    replacement,
    uid
  } = newState;
  return [SetValueByName, uid, ReplaceValue, replacement];
};

const renderUid = (oldState, newState) => {
  const {
    editorUid,
    uid
  } = newState;
  return [SetUid, uid, editorUid];
};

const renderValue = (oldState, newState) => {
  const {
    uid,
    value
  } = newState;
  return [SetValueByName, uid, SearchValue, value];
};

const getRenderer = diffType => {
  switch (diffType) {
    case RenderBounds:
      return renderBounds;
    case RenderContent:
      return renderContent;
    case RenderCss:
      return renderCss;
    case RenderEventListeners:
      return renderEventListeners;
    case RenderFocus:
      return renderFocus;
    case RenderFocusContext:
      return renderFocusContext;
    case RenderReplaceValue:
      return renderReplaceValue;
    case RenderUid:
      return renderUid;
    case RenderValue:
      return renderValue;
    default:
      throw new Error('unknown renderer');
  }
};

const applyRender = (oldState, newState, diffResult) => {
  const commands = [];
  for (const item of diffResult) {
    const fn = getRenderer(item);
    commands.push(fn(oldState, newState));
  }
  return commands;
};

const render2 = (uid, diffResult) => {
  const {
    newState,
    oldState
  } = get(uid);
  set(uid, newState, newState);
  const commands = applyRender(oldState, newState, diffResult);
  return commands;
};

const resize = async (state, dimensions) => {
  return state;
};

const saveState = state => {
  const {
    matchCase,
    matchWholeWord,
    replaceExpanded,
    replacement,
    useRegularExpression,
    value,
    width
  } = state;
  return {
    matchCase,
    matchWholeWord,
    replaceExpanded,
    replacement,
    useRegularExpression,
    value,
    width
  };
};

const commandMap = {
  'FindWidget.close': wrapCommand(close$1),
  'FindWidget.create': create,
  'FindWidget.diff2': diff2,
  'FindWidget.dispose': dispose,
  'FindWidget.focusCloseButton': wrapCommand(focusCloseButton),
  'FindWidget.focusElement': wrapCommand(focusElement),
  'FindWidget.focusFirst': wrapCommand(focusFirst),
  'FindWidget.focusIndex': wrapCommand(focusIndex),
  'FindWidget.focusLast': wrapCommand(focusLast),
  'FindWidget.focusNext': wrapCommand(focusNext),
  'FindWidget.focusNextElement': wrapCommand(focusNextElement),
  'FindWidget.focusPrevious': wrapCommand(focusPrevious),
  'FindWidget.focusPreviousElement': wrapCommand(focusPreviousElement),
  'FindWidget.focusReplace': wrapCommand(focusReplace),
  'FindWidget.focusReplaceAllButton': wrapCommand(focusReplaceAllButton),
  'FindWidget.getCommandIds': getCommandIds,
  'FindWidget.getKeyBindings': getKeyBindings,
  'FindWidget.handleBlur': wrapCommand(handleBlur),
  'FindWidget.handleClickButton': wrapCommand(handleClickButton),
  'FindWidget.handleClickClose': wrapCommand(handleClickClose),
  'FindWidget.handleFocus': wrapCommand(handleFindFocus),
  'FindWidget.handleInput': wrapCommand(handleInput),
  'FindWidget.handleReplaceFocus': wrapCommand(handleReplaceFocus),
  'FindWidget.handleReplaceInput': wrapCommand(handleReplaceInput),
  'FindWidget.handleResizerPointerDown': wrapCommand(handleResizerPointerDown),
  'FindWidget.handleResizerPointerMove': wrapCommand(handleResizerPointerMove),
  'FindWidget.handleResizerPointerUp': wrapCommand(handleResizerPointerUp),
  'FindWidget.handleToggleReplaceFocus': wrapCommand(handleToggleReplaceFocus),
  'FindWidget.loadContent': wrapCommand(loadContent),
  'FindWidget.preventDefaultBrowserFind': wrapCommand(preventDefaultBrowserFind),
  'FindWidget.render2': render2,
  'FindWidget.replace': wrapCommand(replace$1),
  'FindWidget.replaceAll': wrapCommand(replaceAll$1),
  'FindWidget.resize': wrapCommand(resize),
  'FindWidget.saveState': wrapGetter(saveState),
  'FindWidget.terminate': terminate,
  'FindWidget.toggleMatchCase': wrapCommand(toggleMatchCase),
  'FindWidget.toggleMatchWholeWord': wrapCommand(toggleMatchWholeWord),
  'FindWidget.togglePreserveCase': wrapCommand(togglePreserveCase),
  'FindWidget.toggleReplace': wrapCommand(toggleReplace$1),
  'FindWidget.toggleUseRegularExpression': wrapCommand(toggleUseRegularExpression)
};

const listen = async () => {
  registerCommands(commandMap);
  const rpc = await WebWorkerRpcClient.create({
    commandMap: commandMap
  });
  set$1(rpc);
};

const main = async () => {
  await listen();
};

main();
