A JavaScript window management library for building desktop-like interfaces in the browser.
ブラウザ上でデスクトップアプリのようなウィンドウUIを構築するための、JavaScript製ウィンドウ管理ライブラリです。
- ウィンドウの作成・管理
- ウィンドウの移動・リサイズ
- 最小化・最大化・復元
- フォーカス管理
- タスクバー
- HTML / iframe /
<template>によるコンテンツ表示 - ポップアップウィンドウ
- 非同期ポップアップ
- ウィンドウ内への子ウィンドウ作成
- タブ
- Split View
- ウィンドウ内検索
- メニュー・コンテキストメニュー
- カスタムコントロール
- ステータスバー
- ウィンドウイベント
- グローバルイベント
- テーマ
- ウィンドウアニメーション
- ウィンドウの仮想化
- ウィンドウのキャプチャ
- 印刷
- 不透明度変更
- ショートカットキー
- TypeScript型定義
winletでは、ブラウザ上に複数のウィンドウを持つデスクトップライクなUIを構築できます。
┌─────────────────────────────────────────────────────────────┐
│ Desktop │
│ │
│ ┌──────────────────────────┐ ┌──────────────────────┐ │
│ │ Hello │ │ Settings │ │
│ │ ──────────────────────── │ │ ──────────────────── │ │
│ │ │ │ │ │
│ │ Window content │ │ Settings │ │
│ │ │ │ │ │
│ └──────────────────────────┘ └──────────────────────┘ │
│ │
│ │
├─────────────────────────────────────────────────────────────┤
│ Hello Settings │
└─────────────────────────────────────────────────────────────┘
GitHubリポジトリをnpmの依存関係として直接インストールできます。
npm install github:hi2ma-bu4/winletimport WinLet from "winlet";リポジトリを直接取得してビルドすることもできます。
git clone https://github.com/hi2ma-bu4/winlet.git
cd winlet
npm install
npm run buildビルド済みのファイルはjsDelivr経由でも利用できます。
<script src="https://cdn.jsdelivr.net/gh/hi2ma-bu4/winlet/dist/winlet.js"></script>CDNから読み込んだ場合は、グローバルの WinLet からAPIを利用できます。
import WinLet from "winlet";
WinLet.init();
const win = WinLet.createWindow({
title: "Hello, WinLet",
width: 500,
height: 300,
content: {
html: "<h1>Hello, WinLet!</h1>"
}
});CDNの場合も同様です。
<script src="https://cdn.jsdelivr.net/gh/hi2ma-bu4/winlet/dist/winlet.js"></script>
<script>
WinLet.init();
const win = WinLet.createWindow({
title: "Hello, WinLet",
width: 500,
height: 300,
content: {
html: "<h1>Hello, WinLet!</h1>"
}
});
</script>WinLet.init() はDOMの準備ができた後に呼び出してください。
document.addEventListener("DOMContentLoaded", () => {
WinLet.init();
});基本的なウィンドウは createWindow() で作成できます。
const win = WinLet.createWindow({
title: "My Window",
width: 600,
height: 400,
content: {
html: `
<h1>Hello</h1>
<p>This is a WinLet window.</p>
`
}
});ウィンドウにIDを設定できます。
const win = WinLet.createWindow({
id: "settings",
title: "Settings"
});同じIDのウィンドウがすでに存在する場合の動作は ifExists で指定できます。
WinLet.createWindow({
id: "settings",
ifExists: "focus",
title: "Settings"
});利用できる値は以下の通りです。
| 値 | 動作 |
|---|---|
focus |
既存ウィンドウを復元してフォーカス |
prevent |
新しいウィンドウを作成しない |
create |
IDの重複を無視して新しく作成 |
デフォルトは focus です。
ウィンドウの位置とサイズを指定できます。
WinLet.createWindow({
x: 100,
y: 80,
width: 600,
height: 400
});位置には特定のキーワードも使用できます。
WinLet.createWindow({
x: "center",
y: "center"
});x:
number"center""left""right""auto"
y:
number"center""top""bottom""auto"
WinLet.createWindow({
width: 600,
height: 400,
minWidth: 300,
minHeight: 200
});作成後にも位置やサイズを変更できます。
win.setPosition(100, 100);
win.setSize(800, 600);現在の位置・サイズは取得できます。
const position = win.getPosition();
console.log(position.x);
console.log(position.y);
const size = win.getSize();
console.log(size.width);
console.log(size.height);ウィンドウの状態を操作できます。
win.minimize();
win.maximize();
win.restore();
win.toggleMaximize();
win.focus();
win.blur();
win.close();注意を引くためにウィンドウを揺らすこともできます。
win.shake();ウィンドウの操作機能を個別に設定できます。
WinLet.createWindow({
title: "Example",
windowOptions: {
movable: true,
resizableX: true,
resizableY: true,
closable: true,
minimizable: true,
maximizable: true,
maximizableOnDblClick: true,
focus: true,
alwaysOnTop: false,
useGhostWindow: false,
opacity: 1.0,
modal: false
}
});windowOptions: {
movable: true,
resizableX: true,
resizableY: true
}windowOptions: {
closable: true,
minimizable: true,
maximizable: true
}windowOptions: {
alwaysOnTop: true
}windowOptions: {
modal: true
}windowOptions: {
opacity: 0.8
}作成後に変更することもできます。
win.setOpacity(0.8);ウィンドウのコンテンツにはHTML、iframe、HTMLテンプレートを使用できます。
WinLet.createWindow({
title: "HTML",
content: {
html: `
<h1>Hello</h1>
<p>Window content.</p>
`
}
});WinLet.createWindow({
title: "Web Page",
content: {
iframe: {
src: "https://example.com",
loading: "lazy"
}
}
});iframeには以下のような設定を指定できます。
content: {
iframe: {
src: "https://example.com",
srcdoc: "",
allow: "",
referrerPolicy: "no-referrer",
loading: "lazy",
sandbox: ["allow-scripts", "allow-same-origin"]
}
}loadWinLet を有効にすると、srcdoc で生成されたiframe内にWinLet自身を読み込めます。
WinLet.createWindow({
title: "Embedded App",
content: {
iframe: {
srcdoc: `
<h1>Embedded App</h1>
`,
loadWinLet: true
}
}
});この機能を使用する場合は、グローバル設定で libraryPath を指定してください。
既存の <template> を利用できます。
<template id="my-template">
<h1>Template Content</h1>
<p>Hello from template.</p>
</template>WinLet.createWindow({
title: "Template",
content: {
template: "#my-template"
}
});ウィンドウのコンテンツ要素を取得できます。
const content = win.getContent();通常のHTMLコンテンツでは HTMLElement、iframeの場合は HTMLIFrameElement が返されます。
ウィンドウの内部に別のウィンドウを作成できます。
const parent = WinLet.createWindow({
title: "Parent",
width: 800,
height: 600
});
const child = parent.createWindow({
title: "Child",
width: 300,
height: 200,
content: {
html: "<p>Child window</p>"
}
});これにより、アプリケーションウィンドウの内部にさらにウィンドウを持つようなUIを構築できます。
ポップアップウィンドウを作成できます。
const popup = WinLet.createPopup({
title: "Popup",
width: 400,
height: 250,
content: {
html: "<p>Popup content</p>"
}
});ウィンドウから作成することもできます。
const popup = win.createPopup({
title: "Popup",
content: {
html: "<p>Hello</p>"
}
});非同期ポップアップを利用できます。
const result = await WinLet.createAsyncPopup({
title: "Confirm",
width: 400,
height: 250,
content: {
html: "<p>Continue?</p>"
}
});ポップアップの結果には、通常の終了結果とタイムアウト結果を区別するための定数が用意されています。
WinLet.POPUP_TIMEOUT_RESULT
WinLet.POPUP_CLOSE_BUTTON_RESULTウィンドウにタブを設定できます。
WinLet.createWindow({
title: "Tabbed Window",
tabs: [
{
title: "Home",
content: {
html: "<h1>Home</h1>"
}
},
{
title: "Settings",
content: {
html: "<h1>Settings</h1>"
}
}
]
});タブの動作は tabOptions で設定できます。
WinLet.createWindow({
title: "Tabs",
tabs: [
{
title: "Tab 1",
content: {
html: "<p>Tab 1</p>"
}
}
],
tabOptions: {
reorderable: true,
closable: true,
addable: true,
detachable: true,
mergeable: true,
allowIncomingMerge: true
}
});1つのウィンドウ内を複数のペインに分割できます。
WinLet.createWindow({
title: "Split View",
splitView: {
direction: "horizontal",
panes: [
{
id: "left",
size: "50%",
content: {
html: "<h2>Left</h2>"
}
},
{
id: "right",
size: "50%",
content: {
html: "<h2>Right</h2>"
}
}
]
}
});WinLet.createWindow({
title: "Split View",
splitView: {
direction: "vertical",
panes: [
{
id: "top",
size: "50%",
content: {
html: "<h2>Top</h2>"
}
},
{
id: "bottom",
size: "50%",
content: {
html: "<h2>Bottom</h2>"
}
}
]
}
});各ペインには最小サイズやリサイズ可否も設定できます。
{
id: "left",
size: "300px",
minSize: "200px",
resizable: true,
content: {
html: "<p>Left</p>"
}
}ウィンドウ内検索を利用できます。
WinLet.createWindow({
title: "Searchable",
search: {
enabled: true
},
content: {
html: `
<h1>Hello</h1>
<p>Search this content.</p>
`
}
});検索オプションでは、大文字小文字、正規表現、単語単位検索などのUIを設定できます。
search: {
enabled: true,
caseSensitive: false,
showCaseSensitiveButton: true,
showRegexButton: true,
showWholeWordButton: true
}検索対象をセレクタで限定することもできます。
search: {
enabled: true,
targetSelector: ".search-content"
}作成後に検索UIを操作することもできます。
win.openSearch();
win.closeSearch();ステータスバーを表示できます。
WinLet.createWindow({
title: "Status Bar",
statusBar: {
enabled: true,
text: "Ready"
},
content: {
html: "<p>Content</p>"
}
});HTMLを許可することもできます。
statusBar: {
enabled: true,
text: "<strong>Ready</strong>",
allowHTML: true
}作成後にテキストを変更できます。
win.setStatusBarText("Processing...");WinLetはウィンドウを管理するタスクバーを備えています。
デフォルトでは画面下部に表示されます。
グローバル設定から位置を変更できます。
WinLet.init({
taskbar: {
position: "bottom"
}
});タスクバー上のアイテム表示もウィンドウごとに設定できます。
WinLet.createWindow({
title: "Example",
taskbarOptions: {
showIconOnly: true
}
});ウィンドウにメニューを追加できます。
WinLet.createWindow({
title: "Menu Example",
menu: [
{
name: "File",
items: [
{
name: "New",
action: (win) => {
console.log("New", win);
}
},
{
name: "Open",
action: (win) => {
console.log("Open", win);
}
}
]
},
{
name: "Help",
action: (win) => {
console.log("Help", win);
}
}
]
});メニュー項目にはショートカットを表示できます。
{
name: "Save",
shortcut: "Ctrl+S",
action: (win) => {
// ...
}
}メニューはネストできます。
{
name: "File",
items: [
{
name: "Export",
items: [
{
name: "JSON",
action: (win) => {
// ...
}
}
]
}
]
}ウィンドウにコンテキストメニューを設定できます。
WinLet.createWindow({
title: "Context Menu",
contextMenu: [
{
name: "Reload",
action: (win) => {
win.reload();
}
},
{
separator: true
},
{
name: "Close",
action: (win) => {
win.close();
}
}
]
});タイトルバーに独自のコントロールを追加できます。
WinLet.createWindow({
title: "Custom Control",
customControls: [
{
name: "help",
html: "?",
title: "Help",
action: (win) => {
console.log("Help", win);
}
}
]
});標準のウィンドウコントロールは左右どちらにも配置できます。
WinLet.createWindow({
controlsPosition: "right"
});ウィンドウ単位でイベントを購読できます。
const win = WinLet.createWindow({
title: "Events"
});
win.on("focus", (win) => {
console.log("Focused:", win.id);
});
win.on("close", (win) => {
console.log("Closed:", win.id);
});利用できる主なイベントは以下です。
openclosebefore-closefocusblurmove-startmove-endmoveresize-startresize-endresizereload
before-close では閉じる処理をキャンセルできます。
win.on("before-close", () => {
return false;
});一度だけ実行するリスナーも設定できます。
win.on("open", (win) => {
console.log("Opened once:", win.id);
}, {
once: true
});リスナーは off() で解除できます。
const listener = (win) => {
console.log(win.id);
};
win.on("focus", listener);
win.off("focus", listener);WinLet全体のイベントも購読できます。
WinLet.on("window-created", (win) => {
console.log("Created:", win.id);
});
WinLet.on("window-destroyed", (win) => {
console.log("Destroyed:", win.id);
});IDからウィンドウを取得できます。
const win = WinLet.getWindow("settings");存在しない場合は undefined が返ります。
アクティブなウィンドウは以下から取得できます。
const activeWindow = WinLet.getActiveWindow();指定されたDOM要素を内包するウィンドウも取得できます。
const win = WinLet.getWindowFromElement(element);ウィンドウの状態は state から確認できます。
console.log(win.state);状態には以下があります。
"normal""minimized""maximized"
大量のウィンドウを扱う場合に備えて、ウィンドウの仮想化機能を備えています。
グローバル設定で有効・無効を切り替えられます。
WinLet.init({
enableVirtualization: true
});ウィンドウ単位でも仮想化対象かどうかを設定できます。
WinLet.createWindow({
title: "Virtualizable",
virtualizable: true
});仮想化には複数のレベルがあります。
nonefrozensuspendedunloaded
デフォルトでは、一定時間非アクティブなウィンドウを対象に仮想化が行われます。
WinLet.init({
virtualizationThreshold: 5,
virtualizationDelay: 10000
});ウィンドウの開閉・最小化・復元などにはアニメーションを利用できます。
WinLet.init({
enableAnimations: true
});アニメーションの基点も指定できます。
WinLet.createWindow({
title: "Animated",
animationOrigin: "#open-button"
});animationOrigin には以下を指定できます。
- DOMセレクタ
HTMLElementMouseEvent{ x, y }
例えばボタンを基点にできます。
const button = document.querySelector("#open-button");
WinLet.createWindow({
title: "Animated",
animationOrigin: button
});テーマを登録して切り替えることができます。
WinLet.registerTheme({
name: "my-theme"
});登録済みテーマは取得できます。
const themes = WinLet.getRegisteredThemes();
console.log(themes);テーマを切り替えます。
WinLet.setTheme("my-theme");現在のテーマは取得できます。
const theme = WinLet.getTheme();テーマオブジェクトを直接指定することもできます。
WinLet.setTheme({
name: "my-theme"
});ウィンドウを画像としてキャプチャできます。
const dataUrl = await win.capture();デフォルトではウィンドウ全体をキャプチャします。
コンテンツ部分のみをキャプチャすることもできます。
const dataUrl = await win.capture("content");返される値はPNG形式のData URLです。
キャプチャ機能では html2canvas を利用します。
ウィンドウのコンテンツを印刷できます。
win.print();ウィンドウを再読み込みできます。
win.reload();iframeコンテンツなどを再読み込みしたい場合にも利用できます。
ウィンドウ作成後に一部の設定を変更できます。
win.setOptions({
title: "Updated Title",
width: 800,
height: 600
});タイトルやアイコンは専用メソッドでも変更できます。
win.setTitle("New Title");
win.setIcon("/images/icon.png");WinLetにはウィンドウ切り替え用のショートカットがあります。
デフォルトでは、
Ctrl+`
が使用されます。
グローバル設定から変更できます。
WinLet.init({
windowSwitchShortcut: "Ctrl+Tab"
});ショートカット機能そのものをウィンドウ単位で無効化することもできます。
WinLet.createWindow({
title: "No Shortcuts",
enableShortcuts: false
});WinLet全体の動作を init() で設定できます。
WinLet.init({
windowSwitchShortcut: "Ctrl+`",
enableAnimations: true,
animateFromTaskbar: true,
enableFocusTrapping: true,
enableVirtualization: true,
indicateVirtualizationInTaskbar: true,
virtualizationThreshold: 5,
virtualizationDelay: 10000,
taskbar: {
position: "bottom"
},
autoDetectBootstrapTheme: true,
enableDebugMode: false
});また、初期化後に変更可能なグローバル設定は setGlobalConfig() から変更できます。
WinLet.setGlobalConfig({
enableAnimations: false
});ウィンドウのデフォルト設定は setDefaultConfig() で変更できます。
WinLet.setDefaultConfig({
width: 600,
height: 400,
windowOptions: {
resizableX: true,
resizableY: true
}
});これ以降に作成されるウィンドウへデフォルト設定として適用されます。
| API | 説明 |
|---|---|
init(options?) |
WinLetを初期化 |
createWindow(options?) |
ウィンドウを作成 |
createPopup(options) |
ポップアップを作成 |
createAsyncPopup(options) |
非同期ポップアップを作成 |
getWindow(id) |
IDからウィンドウを取得 |
getWindowFromElement(element) |
DOM要素からウィンドウを取得 |
getActiveWindow() |
アクティブなウィンドウを取得 |
updateTaskbarItem(win, state) |
タスクバー項目を更新 |
setDefaultConfig(options) |
ウィンドウのデフォルト設定を変更 |
setGlobalConfig(options) |
グローバル設定を変更 |
registerTheme(theme) |
テーマを登録 |
getRegisteredThemes() |
登録済みテーマを取得 |
setTheme(theme) |
テーマを変更 |
getTheme() |
現在のテーマを取得 |
on(event, listener, options?) |
グローバルイベントを購読 |
off(event, listener) |
グローバルイベントを解除 |
emit(event, ...args) |
グローバルイベントを発火 |
version |
WinLetのバージョン |
| API | 説明 |
|---|---|
close() |
ウィンドウを閉じる |
minimize(options?) |
最小化 |
maximize() |
最大化 |
restore(options?) |
復元 |
toggleMaximize() |
最大化/復元 |
focus() |
フォーカス |
blur() |
フォーカスを外す |
shake() |
ウィンドウを揺らす |
capture(mode?) |
ウィンドウを画像として取得 |
print() |
印刷 |
getTitle() |
タイトルを取得 |
setTitle(title) |
タイトルを変更 |
setIcon(icon) |
アイコンを変更 |
getPosition() |
位置を取得 |
setPosition(x, y) |
位置を変更 |
getSize() |
サイズを取得 |
setSize(width, height) |
サイズを変更 |
setOpacity(opacity) |
不透明度を変更 |
reload() |
再読み込み |
getContent() |
コンテンツ要素を取得 |
setStatusBarText(text) |
ステータスバーを変更 |
openSearch() |
検索UIを開く |
closeSearch() |
検索UIを閉じる |
createWindow(options?) |
子ウィンドウを作成 |
createPopup(options) |
子ポップアップを作成 |
createAsyncPopup(options) |
子非同期ポップアップを作成 |
setOptions(options) |
オプションを変更 |
on(event, listener, options?) |
ウィンドウイベントを購読 |
off(event, listener) |
ウィンドウイベントを解除 |
emit(event, ...args) |
ウィンドウイベントを発火 |
winletはTypeScriptで実装されており、型定義を提供しています。
import WinLet from "winlet";
const win = WinLet.createWindow({
title: "TypeScript",
width: 600,
height: 400
});
win.on("focus", (window) => {
console.log(window.id);
});ウィンドウ、イベント、メニュー、タブ、Split ViewなどのAPIに型が提供されています。
winletはブラウザ上で動作するウィンドウUIライブラリです。
CDNを利用する場合は、ビルド済みの dist/winlet.js を読み込めます。
<script src="https://cdn.jsdelivr.net/gh/hi2ma-bu4/winlet/dist/winlet.js"></script>minified版も利用できます。
<script src="https://cdn.jsdelivr.net/gh/hi2ma-bu4/winlet/dist/winlet.min.js"></script>リポジトリをcloneします。
git clone https://github.com/hi2ma-bu4/winlet.git
cd winlet依存関係をインストールします。
npm installビルドします。
npm run buildビルド済みファイルは dist/ に生成されます。