# Block Loader

`UicBlockLoader` 是可阻擋整個頁面或單一物件的 Vanilla JavaScript 元件。它使用獨立的 Block Loader 遮罩與 CSS Orbit indicator，不依賴 daisyUI Modal、jQuery、doTimeout 或 prefixfree。

## 全頁模式

將程式放在 `<body>` 開始後即可立即建立全頁 Loader；若需要等待圖片、字型等資源，使用 `window.load` 取消：

```html
<script src="/assets/vendor/ui-components/block-loader.js"></script>
<body>
   <script>
   const oPageLoader = UicBlockLoader.show(document.body, {
      text: 'Loading'
   });

   window.addEventListener('load', () => {
      oPageLoader.hide();
   }, { once: true });
   </script>
```

## 局部模式

```javascript
const oPanel = document.querySelector('#data-panel');
const oPanelLoader = UicBlockLoader.show(oPanel, {
   text: '更新資料中'
});

try {
   await LoadPanelData();
} finally {
   await oPanelLoader.hide();
}
```

目標必須是 DOM `Element`。傳入 `document.body` 或 `document.documentElement` 時會自動使用全頁模式；其他元素使用局部模式。

## API

### `UicBlockLoader.show(oTarget, oOptions)`

顯示 Loader 並回傳 handle：

```javascript
const oLoaderHandle = UicBlockLoader.show(oTarget, {
   text: 'Loading',
   page: false
});

await oLoaderHandle.hide();
```

- `text`：畫面中央與輔助科技讀取的狀態文字，預設為 `Loading`。
- `page`：設為 `true` 時強制使用全頁 fixed 遮罩。
- 同一目標重複呼叫 `show()` 只會保留一個遮罩；每個 handle 都完成 `hide()` 後才會移除。

### `UicBlockLoader.hide(oTarget)`

強制清除指定目標目前的 Loader，不等待其他 handle：

```javascript
await UicBlockLoader.hide(oTarget);
```

### `UicBlockLoader.isActive(oTarget)`

```javascript
const bIsLoading = UicBlockLoader.isActive(oTarget);
```

## 色彩與主題

Orbit 動畫保留原始固定色，不會跟著 daisyUI 主題改變：

| 變數 | 預設值 |
| --- | --- |
| `--uic-orbit-blue` | `#3369e8` |
| `--uic-orbit-red` | `#d50f25` |
| `--uic-orbit-green` | `#009925` |
| `--uic-orbit-yellow` | `#eeb211` |

遮罩與文字使用 daisyUI 主題變數：

| 變數 | 預設值 |
| --- | --- |
| `--uic-block-loader-backdrop` | `color-mix(... var(--color-base-100) ...)` |
| `--uic-block-loader-content` | `var(--color-base-content)` |
| `--uic-block-loader-z-index` | `1000`；全頁模式為 `1100` |

## 行為與無障礙

- 顯示時設定目標的 `aria-busy="true"`，移除時還原原始值。
- Loader 使用 `role="status"`、`aria-live="polite"` 與可見狀態文字。
- 目標的其他直接子元素暫時套用 `inert`，新增的直接子元素也會被阻擋，移除 Loader 後還原。
- Loader 顯示前若焦點位於目標內，移除後會嘗試還原焦點。
- 全頁模式會暫停頁面捲動。
- `prefers-reduced-motion: reduce` 時停止 Orbit 動畫，保留四色靜態位置。
- 列印與 forced colors 模式不顯示遮罩。
