Repository: tauri-apps/tauri
File: packages/api/src/menu/submenu.ts (TypeScript)

Code before:
      // @ts-expect-error constructor is protected for external usage only, safe for us to use
      return new Submenu(rid, id)
    case 'Predefined':
      // @ts-expect-error constructor is protected for external usage only, safe for us to use
      return new PredefinedMenuItem(rid, id)
    case 'Check':
      // @ts-expect-error constructor is protected for external usage only, safe for us to use
      return new CheckMenuItem(rid, id)
    case 'Icon':
      // @ts-expect-error constructor is protected for external usage only, safe for us to use
      return new IconMenuItem(rid, id)
    case 'MenuItem':
    default:
      // @ts-expect-error constructor is protected for external usage only, safe for us to use
      return new MenuItem(rid, id)
  }
  /* eslint-enable @typescript-eslint/no-unsafe-return */
}

export type SubmenuOptions = (Omit<MenuItemOptions, 'accelerator' | 'action'>
  & MenuOptions) & {
  /**
   * Icon to be used for the submenu.
   * Note: you may need the `image-ico` or `image-png` Cargo features to use this API.
   */
  icon?: NativeIcon | string | Image | Uint8Array | ArrayBuffer | number[]
}

/** A type that is a submenu inside a {@linkcode Menu} or {@linkcode Submenu}. */
export class Submenu extends MenuItemBase {
  /** @ignore */
  protected constructor(rid: number, id: string) {
    super(rid, id, 'Submenu')
  }

  /** Create a new submenu. */
  static async new(opts: SubmenuOptions): Promise<Submenu> {
    return newMenu('Submenu', opts).then(([rid, id]) => new Submenu(rid, id))
  }

  /** Returns the text of this submenu. */
  async text(): Promise<string> {
    return invoke('plugin:menu|text', { rid: this.rid, kind: this.kind })
  }

  /** Sets the text for this submenu. */
  async setText(text: string): Promise<void> {
    return invoke('plugin:menu|set_text', {
      rid: this.rid,
      kind: this.kind,
      text

Review comment (refactor):
Maybe we can extract this to a type alias now (something like `MenuIcon`) with this being used in multiple places

Code after:
      return new Submenu(rid, id)
    case 'Predefined':
      // @ts-expect-error constructor is protected for external usage only, safe for us to use
      return new PredefinedMenuItem(rid, id)
    case 'Check':
      // @ts-expect-error constructor is protected for external usage only, safe for us to use
      return new CheckMenuItem(rid, id)
    case 'Icon':
      // @ts-expect-error constructor is protected for external usage only, safe for us to use
      return new IconMenuItem(rid, id)
    case 'MenuItem':
    default:
      // @ts-expect-error constructor is protected for external usage only, safe for us to use
      return new MenuItem(rid, id)
  }
  /* eslint-enable @typescript-eslint/no-unsafe-return */
}

export type SubmenuOptions = (Omit<MenuItemOptions, 'accelerator' | 'action'>
  & MenuOptions) & {
  /**
   * Icon to be used for the submenu.
   * Note: you may need the `image-ico` or `image-png` Cargo features to use this API.
   */
  icon?: MenuIcon
}

/** A type that is a submenu inside a {@linkcode Menu} or {@linkcode Submenu}. */
export class Submenu extends MenuItemBase {
  /** @ignore */
  protected constructor(rid: number, id: string) {
    super(rid, id, 'Submenu')
  }

  /** Create a new submenu. */
  static async new(opts: SubmenuOptions): Promise<Submenu> {
    return newMenu('Submenu', opts).then(([rid, id]) => new Submenu(rid, id))
  }

  /** Returns the text of this submenu. */
  async text(): Promise<string> {
    return invoke('plugin:menu|text', { rid: this.rid, kind: this.kind })
  }

  /** Sets the text for this submenu. */
  async setText(text: string): Promise<void> {
    return invoke('plugin:menu|set_text', {
      rid: this.rid,
      kind: this.kind,
      text
    })