@wcstack/upload 1.10.0 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +101 -16
- package/README.md +101 -16
- package/dist/index.d.ts +17 -1
- package/dist/index.esm.js +67 -6
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/package.json +1 -1
package/README.ja.md
CHANGED
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
|
|
14
14
|
つまり、ファイルアップロードを場当たり的な `XMLHttpRequest` のグルーコードではなく、状態遷移と DOM バインディングとして扱えます。
|
|
15
15
|
|
|
16
|
-
`@wcstack/upload` は
|
|
16
|
+
`@wcstack/upload` は [CSBC](https://github.com/csbc-dev/arch/blob/main/README.md)(Core / Shell / Binding Contract)アーキテクチャに従います。
|
|
17
17
|
|
|
18
18
|
- **Core** (`UploadCore`) が XHR アップロード、進捗追跡、abort、非同期状態を処理
|
|
19
|
-
- **Shell** (`<wcs-upload>`) がその状態をカスタム要素と
|
|
20
|
-
-
|
|
19
|
+
- **Shell** (`<wcs-upload>`) がその状態をカスタム要素と DOM 向けランタイムサーフェスとして公開
|
|
20
|
+
- **Binding Contract** (`static wcBindable`) が観測可能な `properties`、書き込み可能な `inputs`、呼び出し可能な `commands` を宣言
|
|
21
21
|
|
|
22
22
|
## なぜこれが存在するのか
|
|
23
23
|
|
|
@@ -106,6 +106,8 @@ npm install @wcstack/upload
|
|
|
106
106
|
- 完了後に自動で `false` へ戻る
|
|
107
107
|
- そのリセット時に `wcs-upload:trigger-changed` を発火
|
|
108
108
|
|
|
109
|
+
観測できるのは `false` へのリセットのみです。`true` 遷移(アップロード開始)は `wcs-upload:trigger-changed` を発火しません。バインディングシステムは `true` を書き込んで開始し、唯一の `false` エッジを観測してコマンドの完了を知ります。これは `@wcstack/fetch` の `trigger` と同じトレードオフです。
|
|
110
|
+
|
|
109
111
|
### 3. 宣言的なトリガーターゲット
|
|
110
112
|
|
|
111
113
|
自動トリガーが有効な場合、クリック可能な要素から id で `<wcs-upload>` を参照できます。
|
|
@@ -189,7 +191,7 @@ npm install @wcstack/upload
|
|
|
189
191
|
| `url` | `string` | `""` | アップロード先エンドポイント |
|
|
190
192
|
| `method` | `string` | `"POST"` | HTTP メソッド |
|
|
191
193
|
| `field-name` | `string` | `"file"` | FormData のフィールド名 |
|
|
192
|
-
| `multiple` | `boolean` | `false` |
|
|
194
|
+
| `multiple` | `boolean` | `false` | 複数ファイル対応を表す宣言用フラグのみ。ファイル数を強制しない(`multiple` の有無に関わらず `files` のファイルはすべて送信される) |
|
|
193
195
|
| `max-size` | `number` | `Infinity` | 許容最大ファイルサイズ(byte) |
|
|
194
196
|
| `accept` | `string` | `""` | 許可する MIME type または拡張子 |
|
|
195
197
|
| `manual` | `boolean` | `false` | `files` 代入時の自動アップロードを無効化 |
|
|
@@ -207,11 +209,23 @@ npm install @wcstack/upload
|
|
|
207
209
|
#### `upload()`
|
|
208
210
|
|
|
209
211
|
現在の `files` を使ってアップロードを開始し、promise を返します。
|
|
210
|
-
|
|
212
|
+
|
|
213
|
+
この promise はすべての終了ケースで **resolve** し、reject しません。
|
|
214
|
+
|
|
215
|
+
- 成功 → パース済みレスポンスボディ(`value`)で resolve
|
|
216
|
+
- ファイル未指定 / `url` 未指定 → `null` で resolve(no-op。リクエストは開始されずエラーも発火しない)
|
|
217
|
+
- バリデーション失敗 → `null` で resolve(`wcs-upload:error` を発火)
|
|
218
|
+
- HTTP エラー(status >= 400)→ `null` で resolve(エラー内容は `error` / `wcs-upload:error` で取得)
|
|
219
|
+
- ネットワークエラー → `null` で resolve(エラー内容は `error` / `wcs-upload:error` で取得)
|
|
220
|
+
- 中断(abort)→ `null` で resolve
|
|
221
|
+
|
|
222
|
+
`null` は正常な resolve 値でもあるため、失敗判定に resolve 値を使わないでください。代わりに `error` / `status`(または `wcs-upload:error` / `wcs-upload:response` イベント)を観測します。これは `@wcstack/fetch` と同じ設計で、エラーは promise の reject ではなく状態として流れます。
|
|
223
|
+
|
|
224
|
+
> ヘッドレス Core についての注記: `UploadCore.upload(url, files)` は `async` で、同期的に検出できる引数エラー(`url` 欠落・`files` が空)は `[@wcstack/upload] ...` を throw して **reject** します。Shell の `upload()` は `url` 未指定・ファイル未指定を no-op として扱い `null` を返します(Shell が `url`/ファイルのライフサイクルを所有しており「送信先無し」「ファイル無し」をエラーではなく無操作とみなすため)。これにより Shell は Core の throw に到達せず reject しません。
|
|
211
225
|
|
|
212
226
|
#### `abort()`
|
|
213
227
|
|
|
214
|
-
現在のリクエストを中断します。
|
|
228
|
+
現在のリクエストを中断します。loading の解除はリクエストの abort 経路を通じて行われます(`@wcstack/fetch` と一貫)。
|
|
215
229
|
|
|
216
230
|
## イベント
|
|
217
231
|
|
|
@@ -231,21 +245,92 @@ npm install @wcstack/upload
|
|
|
231
245
|
- `max-size` は指定 byte 数を超えるファイルを拒否
|
|
232
246
|
- `accept` は `image/*` のような MIME 範囲、`application/pdf` のような厳密 MIME、`.pdf` のような拡張子をサポート
|
|
233
247
|
|
|
248
|
+
`type` が空のファイル(OS が MIME を判定できなかったファイル)は MIME パターンと照合できません。この場合、`accept` に一致する拡張子パターン(例: `.png`)が含まれていれば受理されます。`accept` が MIME パターンのみの場合は、型を確認できないため空 type のファイルは拒否されます。
|
|
249
|
+
|
|
234
250
|
バリデーションに失敗すると `wcs-upload:error` を発火し、リクエストは開始されません。
|
|
235
251
|
|
|
236
|
-
|
|
252
|
+
### 状態サーフェスにおける error と response
|
|
253
|
+
|
|
254
|
+
成功レスポンス(status 2xx)では `value` と `status` の両方が `wcs-upload:response` 経由で更新されます。HTTP エラー(status >= 400)では `error` のみが(`wcs-upload:error` 経由で)更新され、**エラー時に `status` は状態サーフェスへ伝播しません**。これは `status` が `wcs-upload:response` イベントにバインドされており、エラー時はそのイベントが発火しないためです。HTTP ステータスコードは `error` オブジェクト内(`error.status`)で取得できます。これは `@wcstack/fetch` と同じトレードオフで、エラー詳細は response/error に分散させず単一の `error` チャネルに集約します。
|
|
255
|
+
|
|
256
|
+
> `core.status` / `el.status` を直接読むと、`413` や `500` などのエラーステータスも含め、直近レスポンスの HTTP ステータスが返ります(getter は生の XHR ステータスを反映するため)。これはバインド経路の `status`(`wcs-upload:response` 駆動)とは異なり、バインド経路はエラー時には前回値のまま据え置かれます。したがって getter を命令的に直接読むコードと `status` にバインドするコードでは、HTTP エラー後に観測値が食い違います。どちらか一方の経路に統一してください。これは `@wcstack/fetch` と同じ構造です。
|
|
257
|
+
|
|
258
|
+
### エラー時の progress
|
|
259
|
+
|
|
260
|
+
`progress` は各アップロード開始時に `0` へリセットされ、成功時に `100` へ設定されるだけです。HTTP・ネットワーク・abort のエラー時は、**`progress` は意図的に直前の値(例: `70`)のまま据え置かれます**。これは転送がどこで止まったかを UI が示せるようにするためです。失敗の検出には `progress` ではなく `error` / `loading` を使い、古い値を表示したくない場合は `wcs-upload:error` に応じて UI 側で進捗表示をリセット / 非表示にしてください。次回の `upload()` で `progress` は再び `0` にリセットされます。
|
|
237
261
|
|
|
238
|
-
|
|
262
|
+
## wc-bindable-protocol
|
|
263
|
+
|
|
264
|
+
`UploadCore` と `<wcs-upload>` はいずれも `wc-bindable-protocol` 準拠を宣言しており、プロトコルをサポートするあらゆるフレームワークやコンポーネントと相互運用できます。
|
|
265
|
+
|
|
266
|
+
宣言は wc-bindable インターフェースモデルの全体に従い、3 つの独立したサーフェスを持ちます。
|
|
267
|
+
|
|
268
|
+
- **`properties`** — `bind()` が購読する観測可能な出力(`value`, `loading`, `progress`, `error`, `status`、および Shell の `trigger` / `files`)
|
|
269
|
+
- **`inputs`** — 設定可能サーフェス(`url`, `method`, `fieldName`, …)。ツール・codegen・リモートプロキシが読む記述的メタデータ
|
|
270
|
+
- **`commands`** — 呼び出し可能メソッド(`upload`, `abort`)。`@wcstack/state` のようなバインディングシステムが名前で呼び出せる
|
|
271
|
+
|
|
272
|
+
プロトコル上、コアの `bind()` が解釈するのは `properties` のみです。`inputs` / `commands`(および `attribute` / `async` ヒント)は記述的であり、暗黙の双方向データフローを生成しません。
|
|
273
|
+
|
|
274
|
+
### Core (`UploadCore`)
|
|
275
|
+
|
|
276
|
+
`UploadCore` は、任意のランタイムが購読できるバインド可能な非同期状態に加え、移植可能な入力 / コマンドサーフェスを宣言します。
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
static wcBindable = {
|
|
280
|
+
protocol: "wc-bindable",
|
|
281
|
+
version: 1,
|
|
282
|
+
properties: [
|
|
283
|
+
{ name: "value", event: "wcs-upload:response",
|
|
284
|
+
getter: (e) => e.detail.value },
|
|
285
|
+
{ name: "loading", event: "wcs-upload:loading-changed" },
|
|
286
|
+
{ name: "progress", event: "wcs-upload:progress" },
|
|
287
|
+
{ name: "error", event: "wcs-upload:error" },
|
|
288
|
+
{ name: "status", event: "wcs-upload:response",
|
|
289
|
+
getter: (e) => e.detail.status },
|
|
290
|
+
],
|
|
291
|
+
inputs: [
|
|
292
|
+
{ name: "url" },
|
|
293
|
+
{ name: "method" },
|
|
294
|
+
{ name: "fieldName" },
|
|
295
|
+
],
|
|
296
|
+
commands: [
|
|
297
|
+
{ name: "upload", async: true },
|
|
298
|
+
{ name: "abort" },
|
|
299
|
+
],
|
|
300
|
+
};
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Headless 利用では `core.upload(url, files)` を直接呼び出します(`trigger` は不要)。
|
|
304
|
+
|
|
305
|
+
### Shell (`<wcs-upload>`)
|
|
306
|
+
|
|
307
|
+
Shell は Core の宣言を継承し、`trigger` / `files` 出力と DOM 駆動の入力サーフェスを追加します。`commands`(`upload` / `abort`)は spread でそのまま継承されます。
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
static wcBindable = {
|
|
311
|
+
...UploadCore.wcBindable,
|
|
312
|
+
properties: [
|
|
313
|
+
...UploadCore.wcBindable.properties,
|
|
314
|
+
{ name: "trigger", event: "wcs-upload:trigger-changed" },
|
|
315
|
+
{ name: "files", event: "wcs-upload:files-changed" },
|
|
316
|
+
],
|
|
317
|
+
inputs: [
|
|
318
|
+
{ name: "url" },
|
|
319
|
+
{ name: "method" },
|
|
320
|
+
{ name: "fieldName" },
|
|
321
|
+
{ name: "multiple" },
|
|
322
|
+
{ name: "maxSize" },
|
|
323
|
+
{ name: "accept" },
|
|
324
|
+
{ name: "manual" },
|
|
325
|
+
{ name: "files" },
|
|
326
|
+
{ name: "trigger" },
|
|
327
|
+
],
|
|
328
|
+
};
|
|
329
|
+
```
|
|
239
330
|
|
|
240
|
-
|
|
241
|
-
- `loading`
|
|
242
|
-
- `progress`
|
|
243
|
-
- `error`
|
|
244
|
-
- `status`
|
|
245
|
-
- `trigger`
|
|
246
|
-
- `files`
|
|
331
|
+
Shell の inputs は意図的に `attribute` ヒントを持ちません。属性に紐づく各 setter(`url`, `method`, `fieldName`, `multiple`, `maxSize`, `accept`, `manual`)はすでに自身で属性へ反映するため、`inputs[].attribute` をミラーするバインディングシステムが属性を二重に設定してしまうのを避けるためです。
|
|
247
332
|
|
|
248
|
-
これにより、`@wcstack/state`
|
|
333
|
+
これにより、`@wcstack/state` を含むあらゆる wc-bindable 対応システムから利用できます。
|
|
249
334
|
|
|
250
335
|
## Headless API
|
|
251
336
|
|
package/README.md
CHANGED
|
@@ -13,11 +13,11 @@ With `@wcstack/state`, `<wcs-upload>` exposes a small async state surface:
|
|
|
13
13
|
|
|
14
14
|
This means file upload can be expressed as state transitions and DOM bindings instead of ad-hoc `XMLHttpRequest` glue code.
|
|
15
15
|
|
|
16
|
-
`@wcstack/upload` follows the
|
|
16
|
+
`@wcstack/upload` follows the [CSBC](https://github.com/csbc-dev/arch/blob/main/README.md) (Core / Shell / Binding Contract) architecture:
|
|
17
17
|
|
|
18
18
|
- **Core** (`UploadCore`) handles XHR upload, progress tracking, abort, and async state
|
|
19
|
-
- **Shell** (`<wcs-upload>`) exposes that state as a custom element and
|
|
20
|
-
-
|
|
19
|
+
- **Shell** (`<wcs-upload>`) exposes that state as a custom element and DOM-facing runtime surface
|
|
20
|
+
- **Binding Contract** (`static wcBindable`) declares observable `properties`, writable `inputs`, and callable `commands`
|
|
21
21
|
|
|
22
22
|
## Why this exists
|
|
23
23
|
|
|
@@ -106,6 +106,8 @@ Use `manual` when you want to choose files first and upload later.
|
|
|
106
106
|
- after completion it resets itself to `false`
|
|
107
107
|
- that reset dispatches `wcs-upload:trigger-changed`
|
|
108
108
|
|
|
109
|
+
Only the `false` reset is observable: the `true` transition (upload start) does **not** dispatch `wcs-upload:trigger-changed`. A binding system writes `true` to start and observes the single `false` edge to know the command finished. This is the same trade-off as `@wcstack/fetch`'s `trigger`.
|
|
110
|
+
|
|
109
111
|
### 3. Declarative trigger target
|
|
110
112
|
|
|
111
113
|
When auto trigger is enabled, a clickable element can point at a `<wcs-upload>` by id.
|
|
@@ -189,7 +191,7 @@ In this setup, upload becomes a bindable async node:
|
|
|
189
191
|
| `url` | `string` | `""` | Upload endpoint |
|
|
190
192
|
| `method` | `string` | `"POST"` | HTTP method |
|
|
191
193
|
| `field-name` | `string` | `"file"` | FormData field name |
|
|
192
|
-
| `multiple` | `boolean` | `false` |
|
|
194
|
+
| `multiple` | `boolean` | `false` | Declarative marker only — it advertises multi-file intent but does not enforce file count (any number of files in `files` is sent regardless) |
|
|
193
195
|
| `max-size` | `number` | `Infinity` | Maximum allowed file size in bytes |
|
|
194
196
|
| `accept` | `string` | `""` | Accepted MIME types or file extensions |
|
|
195
197
|
| `manual` | `boolean` | `false` | Disables auto upload on `files` assignment |
|
|
@@ -207,11 +209,23 @@ In this setup, upload becomes a bindable async node:
|
|
|
207
209
|
#### `upload()`
|
|
208
210
|
|
|
209
211
|
Starts upload with the current `files` and returns a promise.
|
|
210
|
-
|
|
212
|
+
|
|
213
|
+
The promise **resolves** in every terminal case and never rejects:
|
|
214
|
+
|
|
215
|
+
- success → resolves to the parsed response body (`value`)
|
|
216
|
+
- no files / no `url` → resolves to `null` (no-op; no request is started and no error is dispatched)
|
|
217
|
+
- validation failure → resolves to `null` (and dispatches `wcs-upload:error`)
|
|
218
|
+
- HTTP error (status >= 400) → resolves to `null` (the error object is exposed on `error` / `wcs-upload:error`)
|
|
219
|
+
- network error → resolves to `null` (the error is exposed on `error` / `wcs-upload:error`)
|
|
220
|
+
- abort → resolves to `null`
|
|
221
|
+
|
|
222
|
+
Because `null` is also a valid resolved value, do not use the resolved value to detect failure — observe `error` / `status` (or the `wcs-upload:error` / `wcs-upload:response` events) instead. This mirrors `@wcstack/fetch`, where errors flow through state rather than promise rejection.
|
|
223
|
+
|
|
224
|
+
> Note on the headless Core: `UploadCore.upload(url, files)` is `async` and **rejects** synchronously-detectable argument errors (missing `url` or empty `files`) by throwing `[@wcstack/upload] ...`. The Shell's `upload()` instead returns `null` for a missing `url` or missing files (it owns the `url`/file lifecycle and treats "no destination" / "no files" as a no-op rather than an error), so the Shell never reaches the Core's throw and never rejects.
|
|
211
225
|
|
|
212
226
|
#### `abort()`
|
|
213
227
|
|
|
214
|
-
Aborts the current request.
|
|
228
|
+
Aborts the current request. Loading is cleared through the request's abort path (consistent with `@wcstack/fetch`).
|
|
215
229
|
|
|
216
230
|
## Events
|
|
217
231
|
|
|
@@ -231,21 +245,92 @@ Aborts the current request.
|
|
|
231
245
|
- `max-size` rejects files larger than the configured byte size
|
|
232
246
|
- `accept` supports MIME types like `image/*`, exact MIME types like `application/pdf`, and extensions like `.pdf`
|
|
233
247
|
|
|
248
|
+
Files whose `type` is empty (the OS could not determine a MIME type) cannot be matched against MIME patterns. Such files are accepted only if `accept` contains a matching extension pattern (e.g. `.png`); if `accept` lists MIME patterns exclusively, an empty-type file is rejected because its type cannot be verified.
|
|
249
|
+
|
|
234
250
|
Validation failure dispatches `wcs-upload:error` and the request is not started.
|
|
235
251
|
|
|
236
|
-
|
|
252
|
+
### Error vs response on the state surface
|
|
253
|
+
|
|
254
|
+
On a successful response (status 2xx), both `value` and `status` are updated via `wcs-upload:response`. On an HTTP error (status >= 400), only `error` is updated (via `wcs-upload:error`) — **`status` is not propagated to the state surface in the error case**, because `status` is bound to the `wcs-upload:response` event, which is not dispatched for errors. The HTTP status code is still available inside the `error` object (`error.status`). This is the same trade-off as `@wcstack/fetch`: error details flow through the single `error` channel rather than splitting across response/error events.
|
|
255
|
+
|
|
256
|
+
> Reading `core.status` / `el.status` directly returns the HTTP status of the last response, including error statuses such as `413` or `500` (the getter reflects the raw XHR status). This differs from the bound `status` path (driven by `wcs-upload:response`), which stays at its previous value on an error. Code that reads the getter imperatively and code that binds to `status` therefore observe different values after an HTTP error; prefer one path consistently. This is the same structure as `@wcstack/fetch`.
|
|
257
|
+
|
|
258
|
+
### Progress on error
|
|
259
|
+
|
|
260
|
+
`progress` is only reset to `0` at the start of each upload and set to `100` on success. On an HTTP, network, or abort error, **`progress` is intentionally left at its last value** (e.g. `70`) so the UI can show where the transfer stopped. Use `error` / `loading` (not `progress`) to detect failure, and reset or hide the progress indicator from your UI in response to `wcs-upload:error` if you do not want a stale value displayed. A subsequent `upload()` resets `progress` back to `0`.
|
|
237
261
|
|
|
238
|
-
|
|
262
|
+
## wc-bindable-protocol
|
|
263
|
+
|
|
264
|
+
Both `UploadCore` and `<wcs-upload>` declare `wc-bindable-protocol` compliance, making them interoperable with any framework or component that supports the protocol.
|
|
265
|
+
|
|
266
|
+
The declaration follows the full wc-bindable interface model — three independent surfaces:
|
|
267
|
+
|
|
268
|
+
- **`properties`** — observable outputs that `bind()` subscribes to (`value`, `loading`, `progress`, `error`, `status`, and the Shell's `trigger` / `files`)
|
|
269
|
+
- **`inputs`** — the settable surface (`url`, `method`, `fieldName`, …); declarative metadata that tooling, codegen, and remote proxying read
|
|
270
|
+
- **`commands`** — invocable methods (`upload`, `abort`); a binding system such as `@wcstack/state` can invoke them by name
|
|
271
|
+
|
|
272
|
+
Per the protocol, only `properties` is interpreted by core `bind()`; `inputs` / `commands` (and the `attribute` / `async` hints) are descriptive. They do **not** create implicit two-way data flow.
|
|
273
|
+
|
|
274
|
+
### Core (`UploadCore`)
|
|
275
|
+
|
|
276
|
+
`UploadCore` declares the bindable async state that any runtime can subscribe to, plus its portable input/command surface:
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
static wcBindable = {
|
|
280
|
+
protocol: "wc-bindable",
|
|
281
|
+
version: 1,
|
|
282
|
+
properties: [
|
|
283
|
+
{ name: "value", event: "wcs-upload:response",
|
|
284
|
+
getter: (e) => e.detail.value },
|
|
285
|
+
{ name: "loading", event: "wcs-upload:loading-changed" },
|
|
286
|
+
{ name: "progress", event: "wcs-upload:progress" },
|
|
287
|
+
{ name: "error", event: "wcs-upload:error" },
|
|
288
|
+
{ name: "status", event: "wcs-upload:response",
|
|
289
|
+
getter: (e) => e.detail.status },
|
|
290
|
+
],
|
|
291
|
+
inputs: [
|
|
292
|
+
{ name: "url" },
|
|
293
|
+
{ name: "method" },
|
|
294
|
+
{ name: "fieldName" },
|
|
295
|
+
],
|
|
296
|
+
commands: [
|
|
297
|
+
{ name: "upload", async: true },
|
|
298
|
+
{ name: "abort" },
|
|
299
|
+
],
|
|
300
|
+
};
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Headless consumers call `core.upload(url, files)` directly — no `trigger` needed.
|
|
304
|
+
|
|
305
|
+
### Shell (`<wcs-upload>`)
|
|
306
|
+
|
|
307
|
+
The Shell extends the Core declaration with the `trigger` / `files` outputs and the DOM-driven input surface; `commands` (`upload` / `abort`) are inherited unchanged:
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
static wcBindable = {
|
|
311
|
+
...UploadCore.wcBindable,
|
|
312
|
+
properties: [
|
|
313
|
+
...UploadCore.wcBindable.properties,
|
|
314
|
+
{ name: "trigger", event: "wcs-upload:trigger-changed" },
|
|
315
|
+
{ name: "files", event: "wcs-upload:files-changed" },
|
|
316
|
+
],
|
|
317
|
+
inputs: [
|
|
318
|
+
{ name: "url" },
|
|
319
|
+
{ name: "method" },
|
|
320
|
+
{ name: "fieldName" },
|
|
321
|
+
{ name: "multiple" },
|
|
322
|
+
{ name: "maxSize" },
|
|
323
|
+
{ name: "accept" },
|
|
324
|
+
{ name: "manual" },
|
|
325
|
+
{ name: "files" },
|
|
326
|
+
{ name: "trigger" },
|
|
327
|
+
],
|
|
328
|
+
};
|
|
329
|
+
```
|
|
239
330
|
|
|
240
|
-
- `
|
|
241
|
-
- `loading`
|
|
242
|
-
- `progress`
|
|
243
|
-
- `error`
|
|
244
|
-
- `status`
|
|
245
|
-
- `trigger`
|
|
246
|
-
- `files`
|
|
331
|
+
The Shell's inputs intentionally carry no `attribute` hint: each attribute-backed setter (`url`, `method`, `fieldName`, `multiple`, `maxSize`, `accept`, `manual`) already reflects to its attribute, so a binding system that mirrors `inputs[].attribute` would set the attribute twice.
|
|
247
332
|
|
|
248
|
-
This makes the element consumable from wc-bindable-aware
|
|
333
|
+
This makes the element consumable from any wc-bindable-aware system, including `@wcstack/state`.
|
|
249
334
|
|
|
250
335
|
## Headless API
|
|
251
336
|
|
package/dist/index.d.ts
CHANGED
|
@@ -19,10 +19,20 @@ interface IWcBindableProperty {
|
|
|
19
19
|
readonly event: string;
|
|
20
20
|
readonly getter?: (event: Event) => any;
|
|
21
21
|
}
|
|
22
|
+
interface IWcBindableInput {
|
|
23
|
+
readonly name: string;
|
|
24
|
+
readonly attribute?: string;
|
|
25
|
+
}
|
|
26
|
+
interface IWcBindableCommand {
|
|
27
|
+
readonly name: string;
|
|
28
|
+
readonly async?: boolean;
|
|
29
|
+
}
|
|
22
30
|
interface IWcBindable {
|
|
23
31
|
readonly protocol: "wc-bindable";
|
|
24
|
-
readonly version:
|
|
32
|
+
readonly version: 1;
|
|
25
33
|
readonly properties: IWcBindableProperty[];
|
|
34
|
+
readonly inputs?: readonly IWcBindableInput[];
|
|
35
|
+
readonly commands?: readonly IWcBindableCommand[];
|
|
26
36
|
}
|
|
27
37
|
/**
|
|
28
38
|
* Upload error object.
|
|
@@ -45,6 +55,12 @@ interface WcsUploadCoreValues<T = unknown> {
|
|
|
45
55
|
}
|
|
46
56
|
/**
|
|
47
57
|
* Value types for the Shell (`<wcs-upload>`) — extends Core with `trigger` and `files`.
|
|
58
|
+
*
|
|
59
|
+
* `trigger` is a write-only command surface declared as an observable property mapped to
|
|
60
|
+
* `wcs-upload:trigger-changed`. Only the `false` reset (after an upload settles) is
|
|
61
|
+
* observable — the `true` transition (upload start) is intentionally NOT notified. This is
|
|
62
|
+
* the same pub/sub trade-off as `@wcstack/fetch`'s `trigger`: a binding system writes `true`
|
|
63
|
+
* to start and observes the single `false` edge to know the command has completed.
|
|
48
64
|
*/
|
|
49
65
|
interface WcsUploadValues<T = unknown> extends WcsUploadCoreValues<T> {
|
|
50
66
|
trigger: boolean;
|
package/dist/index.esm.js
CHANGED
|
@@ -24,6 +24,11 @@ function deepClone(obj) {
|
|
|
24
24
|
return clone;
|
|
25
25
|
}
|
|
26
26
|
let frozenConfig = null;
|
|
27
|
+
// `config` は内部用のライブビュー(live view)。setConfig() の更新が即座に反映される
|
|
28
|
+
// 実体 `_config` をそのまま公開しており、凍結もクローンもしていない。autoTrigger /
|
|
29
|
+
// components など同パッケージ内のモジュールが最新値を読むための窓口であり、
|
|
30
|
+
// 「変更不可なスナップショット」が必要な外部利用には getConfig()(凍結クローンを返す)
|
|
31
|
+
// を使うこと。型が readonly なのは内部からの誤書き換えを抑止するための表明にすぎない。
|
|
27
32
|
const config = _config;
|
|
28
33
|
function getConfig() {
|
|
29
34
|
if (!frozenConfig) {
|
|
@@ -59,6 +64,15 @@ class UploadCore extends EventTarget {
|
|
|
59
64
|
{ name: "error", event: "wcs-upload:error" },
|
|
60
65
|
{ name: "status", event: "wcs-upload:response", getter: (e) => e.detail.status },
|
|
61
66
|
],
|
|
67
|
+
inputs: [
|
|
68
|
+
{ name: "url" },
|
|
69
|
+
{ name: "method" },
|
|
70
|
+
{ name: "fieldName" },
|
|
71
|
+
],
|
|
72
|
+
commands: [
|
|
73
|
+
{ name: "upload", async: true },
|
|
74
|
+
{ name: "abort" },
|
|
75
|
+
],
|
|
62
76
|
};
|
|
63
77
|
_target;
|
|
64
78
|
_value = null;
|
|
@@ -122,12 +136,18 @@ class UploadCore extends EventTarget {
|
|
|
122
136
|
}
|
|
123
137
|
// --- Public API ---
|
|
124
138
|
abort() {
|
|
139
|
+
// `_xhr` は send() の直前に同期で代入されるため、send 前に外部から abort が
|
|
140
|
+
// 割り込む余地はない(割り込み点となる await が存在しない)。よって XHR.abort()
|
|
141
|
+
// は常に進行中のリクエストに対して呼ばれ、abort イベントが発火して loading を
|
|
142
|
+
// 解除する。loading の解除を abort イベントハンドラに集約しているのは、
|
|
143
|
+
// ネットワークエラー/HTTP エラー/正常完了/中断のすべてで解除経路を一本化し、
|
|
144
|
+
// FetchCore.abort() と挙動を揃えるため。
|
|
125
145
|
if (this._xhr) {
|
|
126
146
|
this._xhr.abort();
|
|
127
147
|
this._xhr = null;
|
|
128
148
|
}
|
|
129
149
|
}
|
|
130
|
-
upload(url, files, options = {}) {
|
|
150
|
+
async upload(url, files, options = {}) {
|
|
131
151
|
if (!url) {
|
|
132
152
|
raiseError("url is required.");
|
|
133
153
|
}
|
|
@@ -245,7 +265,28 @@ class WcsUpload extends HTMLElement {
|
|
|
245
265
|
{ name: "trigger", event: "wcs-upload:trigger-changed" },
|
|
246
266
|
{ name: "files", event: "wcs-upload:files-changed" },
|
|
247
267
|
],
|
|
268
|
+
// Shell-level input surface. The Core declares only the portable `url` / `method` /
|
|
269
|
+
// `fieldName`; the Shell adds the DOM-driven settable surface. No `attribute` hints
|
|
270
|
+
// are given: the `url` / `method` / `fieldName` / `multiple` / `maxSize` / `accept` /
|
|
271
|
+
// `manual` setters already reflect to their attributes, so a binding system that
|
|
272
|
+
// mirrors inputs[].attribute would set the attribute twice (`files` / `trigger` are
|
|
273
|
+
// not attribute-backed). `commands` (upload / abort) are inherited unchanged from the
|
|
274
|
+
// Core via the spread above.
|
|
275
|
+
inputs: [
|
|
276
|
+
{ name: "url" },
|
|
277
|
+
{ name: "method" },
|
|
278
|
+
{ name: "fieldName" },
|
|
279
|
+
{ name: "multiple" },
|
|
280
|
+
{ name: "maxSize" },
|
|
281
|
+
{ name: "accept" },
|
|
282
|
+
{ name: "manual" },
|
|
283
|
+
{ name: "files" },
|
|
284
|
+
{ name: "trigger" },
|
|
285
|
+
],
|
|
248
286
|
};
|
|
287
|
+
// `url` を観測するのは FetchCore のシェルと構造を揃えるためだが、upload は
|
|
288
|
+
// url 変更だけでは送信できない(files が必須)。そのため attributeChangedCallback は
|
|
289
|
+
// 意図的に何もしない。url 変更で自動送信しないことは仕様であり、テストで担保している。
|
|
249
290
|
static get observedAttributes() { return ["url"]; }
|
|
250
291
|
_core;
|
|
251
292
|
_files = null;
|
|
@@ -286,7 +327,14 @@ class WcsUpload extends HTMLElement {
|
|
|
286
327
|
}
|
|
287
328
|
get maxSize() {
|
|
288
329
|
const attr = this.getAttribute("max-size");
|
|
289
|
-
|
|
330
|
+
if (attr === null) {
|
|
331
|
+
return Infinity;
|
|
332
|
+
}
|
|
333
|
+
// 不正値(NaN になる "abc" など)や負数は「制限なし」(Infinity) として扱う。
|
|
334
|
+
// NaN を返すと `size > NaN` が常に false になりサイズ検証が無言で無効化され、
|
|
335
|
+
// 負数を返すと全ファイルが拒否されるため、いずれも安全側の Infinity に丸める。
|
|
336
|
+
const n = parseInt(attr, 10);
|
|
337
|
+
return Number.isFinite(n) && n >= 0 ? n : Infinity;
|
|
290
338
|
}
|
|
291
339
|
set maxSize(value) {
|
|
292
340
|
this.setAttribute("max-size", String(value));
|
|
@@ -332,6 +380,10 @@ class WcsUpload extends HTMLElement {
|
|
|
332
380
|
return this._trigger;
|
|
333
381
|
}
|
|
334
382
|
set trigger(value) {
|
|
383
|
+
// 進行中に再度 trigger=true が来ても再入ガードはしない(FetchCore シェルと同一)。
|
|
384
|
+
// upload() → _core.upload() が先頭で既存リクエストを abort し新規開始するため、
|
|
385
|
+
// 連続トリガは「前回を中止して新しいアップロードを開始する」挙動になる。
|
|
386
|
+
// 各 upload() の settle ごとに trigger-changed(false) が 1 回発火する。
|
|
335
387
|
const v = !!value;
|
|
336
388
|
if (v) {
|
|
337
389
|
this._trigger = true;
|
|
@@ -374,14 +426,18 @@ class WcsUpload extends HTMLElement {
|
|
|
374
426
|
const file = files[i];
|
|
375
427
|
const fileType = file.type.toLowerCase();
|
|
376
428
|
const fileName = file.name.toLowerCase();
|
|
429
|
+
// file.type が空文字(OS が MIME を判定できないファイル)の場合、MIME 系
|
|
430
|
+
// パターン(`image/*` / 厳密 MIME)は一致しない。その場合でも accept に
|
|
431
|
+
// 拡張子パターン(`.pdf` 等)が含まれ拡張子が一致すれば受理される。
|
|
432
|
+
// accept が MIME 系のみのときは型を確認できないため拒否する(安全側)。
|
|
377
433
|
const matched = acceptList.some(pattern => {
|
|
378
434
|
if (pattern.startsWith(".")) {
|
|
379
435
|
return fileName.endsWith(pattern);
|
|
380
436
|
}
|
|
381
437
|
if (pattern.endsWith("/*")) {
|
|
382
|
-
return fileType.startsWith(pattern.slice(0, -1));
|
|
438
|
+
return fileType !== "" && fileType.startsWith(pattern.slice(0, -1));
|
|
383
439
|
}
|
|
384
|
-
return fileType === pattern;
|
|
440
|
+
return fileType !== "" && fileType === pattern;
|
|
385
441
|
});
|
|
386
442
|
if (!matched) {
|
|
387
443
|
return { message: `File "${file.name}" does not match accepted types: ${accept}` };
|
|
@@ -396,7 +452,11 @@ class WcsUpload extends HTMLElement {
|
|
|
396
452
|
}
|
|
397
453
|
async upload() {
|
|
398
454
|
const files = this._files;
|
|
399
|
-
|
|
455
|
+
// url 未設定は no-op(null)。Core は url 空で throw するが、Shell は url/files の
|
|
456
|
+
// ライフサイクルを所有しており「送信先が無い」を「ファイル無し」と同じ無操作として扱う。
|
|
457
|
+
// これにより set trigger / set files の fire-and-forget 経路で unhandled rejection が
|
|
458
|
+
// 発生せず、README の「upload() は全終了ケースで resolve し never reject」契約とも整合する。
|
|
459
|
+
if (!files || files.length === 0 || !this.url) {
|
|
400
460
|
return null;
|
|
401
461
|
}
|
|
402
462
|
const validationError = this._validate(files);
|
|
@@ -424,7 +484,8 @@ class WcsUpload extends HTMLElement {
|
|
|
424
484
|
}
|
|
425
485
|
// --- Lifecycle ---
|
|
426
486
|
attributeChangedCallback(_name, _oldValue, _newValue) {
|
|
427
|
-
//
|
|
487
|
+
// 意図的に空。url 変更ではアップロードを自動実行しない(files が必要なため)。
|
|
488
|
+
// observedAttributes のコメント参照。
|
|
428
489
|
}
|
|
429
490
|
connectedCallback() {
|
|
430
491
|
this.style.display = "none";
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/raiseError.ts","../src/core/UploadCore.ts","../src/autoTrigger.ts","../src/components/Upload.ts","../src/registerComponents.ts","../src/bootstrapUpload.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n upload: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-uploadtarget\",\n tagNames: {\n upload: \"wcs-upload\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","export function raiseError(message: string): never {\n throw new Error(`[@wcstack/upload] ${message}`);\n}\n","import { raiseError } from \"../raiseError.js\";\nimport { IWcBindable } from \"../types.js\";\n\nexport interface UploadRequestOptions {\n method?: string;\n headers?: Record<string, string>;\n fieldName?: string;\n}\n\nexport class UploadCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"value\", event: \"wcs-upload:response\", getter: (e: Event) => (e as CustomEvent).detail.value },\n { name: \"loading\", event: \"wcs-upload:loading-changed\" },\n { name: \"progress\", event: \"wcs-upload:progress\" },\n { name: \"error\", event: \"wcs-upload:error\" },\n { name: \"status\", event: \"wcs-upload:response\", getter: (e: Event) => (e as CustomEvent).detail.status },\n ],\n };\n\n private _target: EventTarget;\n private _value: any = null;\n private _loading: boolean = false;\n private _progress: number = 0;\n private _error: any = null;\n private _status: number = 0;\n private _xhr: XMLHttpRequest | null = null;\n private _promise: Promise<any> = Promise.resolve(null);\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get value(): any {\n return this._value;\n }\n\n get loading(): boolean {\n return this._loading;\n }\n\n get progress(): number {\n return this._progress;\n }\n\n get error(): any {\n return this._error;\n }\n\n get status(): number {\n return this._status;\n }\n\n get promise(): Promise<any> {\n return this._promise;\n }\n\n // --- State setters with event dispatch ---\n\n private _setLoading(loading: boolean): void {\n this._loading = loading;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:loading-changed\", {\n detail: loading,\n bubbles: true,\n }));\n }\n\n private _setProgress(progress: number): void {\n this._progress = progress;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:progress\", {\n detail: progress,\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n private _setResponse(value: any, status: number): void {\n this._value = value;\n this._status = status;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:response\", {\n detail: { value, status },\n bubbles: true,\n }));\n }\n\n // --- Public API ---\n\n abort(): void {\n if (this._xhr) {\n this._xhr.abort();\n this._xhr = null;\n }\n }\n\n upload(url: string, files: FileList | File[], options: UploadRequestOptions = {}): Promise<any> {\n if (!url) {\n raiseError(\"url is required.\");\n }\n if (!files || files.length === 0) {\n raiseError(\"files are required.\");\n }\n\n const p = this._doUpload(url, files, options);\n this._promise = p;\n return p;\n }\n\n // --- Internal ---\n\n private _doUpload(url: string, files: FileList | File[], options: UploadRequestOptions): Promise<any> {\n // 既存のアップロードを中止\n this.abort();\n\n this._setLoading(true);\n this._setProgress(0);\n this._setError(null);\n\n const {\n method = \"POST\",\n headers = {},\n fieldName = \"file\",\n } = options;\n\n const formData = new FormData();\n for (let i = 0; i < files.length; i++) {\n formData.append(fieldName, files[i]);\n }\n\n return new Promise<any>((resolve) => {\n const xhr = new XMLHttpRequest();\n this._xhr = xhr;\n\n xhr.upload.addEventListener(\"progress\", (event: ProgressEvent) => {\n if (event.lengthComputable) {\n const percent = Math.round((event.loaded / event.total) * 100);\n this._setProgress(percent);\n }\n });\n\n xhr.addEventListener(\"load\", () => {\n this._xhr = null;\n this._status = xhr.status;\n\n if (xhr.status >= 200 && xhr.status < 300) {\n let value: any = xhr.responseText;\n const contentType = xhr.getResponseHeader(\"Content-Type\") || \"\";\n if (contentType.includes(\"application/json\")) {\n try {\n value = JSON.parse(xhr.responseText);\n } catch {\n // テキストのまま\n }\n }\n this._setProgress(100);\n this._setResponse(value, xhr.status);\n this._setLoading(false);\n resolve(value);\n } else {\n const error = {\n status: xhr.status,\n statusText: xhr.statusText,\n body: xhr.responseText,\n };\n this._setError(error);\n this._setLoading(false);\n resolve(null);\n }\n });\n\n xhr.addEventListener(\"error\", () => {\n this._xhr = null;\n this._setError({ message: \"Network error\" });\n this._setLoading(false);\n resolve(null);\n });\n\n xhr.addEventListener(\"abort\", () => {\n this._xhr = null;\n this._setLoading(false);\n resolve(null);\n });\n\n xhr.open(method, url);\n\n for (const [name, value] of Object.entries(headers)) {\n xhr.setRequestHeader(name, value);\n }\n\n xhr.send(formData);\n });\n }\n}\n","import { config } from \"./config.js\";\nimport { WcsUpload } from \"./components/Upload.js\";\n\nlet registered = false;\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const uploadId = triggerElement.getAttribute(config.triggerAttribute);\n if (!uploadId) return;\n\n const uploadElement = document.getElementById(uploadId) as WcsUpload | null;\n if (!uploadElement || !(uploadElement instanceof WcsUpload)) return;\n\n // ファイルと URL が揃っている場合のみ既定動作を抑止\n if (uploadElement.files && uploadElement.files.length > 0 && uploadElement.url) {\n event.preventDefault();\n }\n uploadElement.upload();\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","import { config } from \"../config.js\";\nimport { IWcBindable, WcsUploadError } from \"../types.js\";\nimport { UploadCore } from \"../core/UploadCore.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\nexport class WcsUpload extends HTMLElement {\n static hasConnectedCallbackPromise = false;\n static wcBindable: IWcBindable = {\n ...UploadCore.wcBindable,\n properties: [\n ...UploadCore.wcBindable.properties,\n { name: \"trigger\", event: \"wcs-upload:trigger-changed\" },\n { name: \"files\", event: \"wcs-upload:files-changed\" },\n ],\n };\n static get observedAttributes(): string[] { return [\"url\"]; }\n\n private _core: UploadCore;\n private _files: FileList | File[] | null = null;\n private _trigger: boolean = false;\n\n constructor() {\n super();\n this._core = new UploadCore(this);\n }\n\n // --- Attribute accessors ---\n\n get url(): string {\n return this.getAttribute(\"url\") || \"\";\n }\n\n set url(value: string) {\n this.setAttribute(\"url\", value);\n }\n\n get method(): string {\n return (this.getAttribute(\"method\") || \"POST\").toUpperCase();\n }\n\n set method(value: string) {\n this.setAttribute(\"method\", value);\n }\n\n get fieldName(): string {\n return this.getAttribute(\"field-name\") || \"file\";\n }\n\n set fieldName(value: string) {\n this.setAttribute(\"field-name\", value);\n }\n\n get multiple(): boolean {\n return this.hasAttribute(\"multiple\");\n }\n\n set multiple(value: boolean) {\n if (value) {\n this.setAttribute(\"multiple\", \"\");\n } else {\n this.removeAttribute(\"multiple\");\n }\n }\n\n get maxSize(): number {\n const attr = this.getAttribute(\"max-size\");\n return attr ? parseInt(attr, 10) : Infinity;\n }\n\n set maxSize(value: number) {\n this.setAttribute(\"max-size\", String(value));\n }\n\n get accept(): string {\n return this.getAttribute(\"accept\") || \"\";\n }\n\n set accept(value: string) {\n this.setAttribute(\"accept\", value);\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get value(): any {\n return this._core.value;\n }\n\n get loading(): boolean {\n return this._core.loading;\n }\n\n get progress(): number {\n return this._core.progress;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n get status(): number {\n return this._core.status;\n }\n\n get promise(): Promise<any> {\n return this._core.promise;\n }\n\n // --- Command properties ---\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n const v = !!value;\n if (v) {\n this._trigger = true;\n this.upload().finally(() => {\n this._trigger = false;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:trigger-changed\", {\n detail: false,\n bubbles: true,\n }));\n });\n }\n }\n\n get files(): FileList | File[] | null {\n return this._files;\n }\n\n set files(value: FileList | File[] | null) {\n this._files = value;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\n detail: value,\n bubbles: true,\n }));\n if (!this.manual && this.url && value && value.length > 0) {\n this.upload();\n }\n }\n\n // --- Validation ---\n\n private _validate(files: FileList | File[]): WcsUploadError | null {\n const maxSize = this.maxSize;\n if (maxSize !== Infinity) {\n for (let i = 0; i < files.length; i++) {\n if (files[i].size > maxSize) {\n return { message: `File \"${files[i].name}\" exceeds maximum size of ${maxSize} bytes.` };\n }\n }\n }\n\n const accept = this.accept;\n if (accept) {\n const acceptList = accept.split(\",\").map(s => s.trim().toLowerCase());\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n const fileType = file.type.toLowerCase();\n const fileName = file.name.toLowerCase();\n const matched = acceptList.some(pattern => {\n if (pattern.startsWith(\".\")) {\n return fileName.endsWith(pattern);\n }\n if (pattern.endsWith(\"/*\")) {\n return fileType.startsWith(pattern.slice(0, -1));\n }\n return fileType === pattern;\n });\n if (!matched) {\n return { message: `File \"${file.name}\" does not match accepted types: ${accept}` };\n }\n }\n }\n\n return null;\n }\n\n // --- Public methods ---\n\n abort(): void {\n this._core.abort();\n }\n\n async upload(): Promise<any> {\n const files = this._files;\n if (!files || files.length === 0) {\n return null;\n }\n\n const validationError = this._validate(files);\n if (validationError) {\n this.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\n detail: validationError,\n bubbles: true,\n }));\n return null;\n }\n\n const result = await this._core.upload(this.url, files, {\n method: this.method,\n fieldName: this.fieldName,\n });\n\n // 自分が開始したアップロードのファイルだけをリセット\n // (途中で新しい files がセットされていたら触らない)\n if (this._files === files) {\n this._files = null;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\n detail: null,\n bubbles: true,\n }));\n }\n\n return result;\n }\n\n // --- Lifecycle ---\n\n attributeChangedCallback(_name: string, _oldValue: string | null, _newValue: string | null): void {\n // URL変更ではアップロードを自動実行しない(ファイルが必要なため)\n }\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n }\n\n disconnectedCallback(): void {\n this._core.abort();\n }\n}\n","import { WcsUpload } from \"./components/Upload.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.upload)) {\n customElements.define(config.tagNames.upload, WcsUpload);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapUpload(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/raiseError.ts","../src/core/UploadCore.ts","../src/autoTrigger.ts","../src/components/Upload.ts","../src/registerComponents.ts","../src/bootstrapUpload.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n upload: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-uploadtarget\",\n tagNames: {\n upload: \"wcs-upload\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\n// `config` は内部用のライブビュー(live view)。setConfig() の更新が即座に反映される\n// 実体 `_config` をそのまま公開しており、凍結もクローンもしていない。autoTrigger /\n// components など同パッケージ内のモジュールが最新値を読むための窓口であり、\n// 「変更不可なスナップショット」が必要な外部利用には getConfig()(凍結クローンを返す)\n// を使うこと。型が readonly なのは内部からの誤書き換えを抑止するための表明にすぎない。\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","export function raiseError(message: string): never {\n throw new Error(`[@wcstack/upload] ${message}`);\n}\n","import { raiseError } from \"../raiseError.js\";\nimport { IWcBindable } from \"../types.js\";\n\nexport interface UploadRequestOptions {\n method?: string;\n headers?: Record<string, string>;\n fieldName?: string;\n}\n\nexport class UploadCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"value\", event: \"wcs-upload:response\", getter: (e: Event) => (e as CustomEvent).detail.value },\n { name: \"loading\", event: \"wcs-upload:loading-changed\" },\n { name: \"progress\", event: \"wcs-upload:progress\" },\n { name: \"error\", event: \"wcs-upload:error\" },\n { name: \"status\", event: \"wcs-upload:response\", getter: (e: Event) => (e as CustomEvent).detail.status },\n ],\n inputs: [\n { name: \"url\" },\n { name: \"method\" },\n { name: \"fieldName\" },\n ],\n commands: [\n { name: \"upload\", async: true },\n { name: \"abort\" },\n ],\n };\n\n private _target: EventTarget;\n private _value: any = null;\n private _loading: boolean = false;\n private _progress: number = 0;\n private _error: any = null;\n private _status: number = 0;\n private _xhr: XMLHttpRequest | null = null;\n private _promise: Promise<any> = Promise.resolve(null);\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get value(): any {\n return this._value;\n }\n\n get loading(): boolean {\n return this._loading;\n }\n\n get progress(): number {\n return this._progress;\n }\n\n get error(): any {\n return this._error;\n }\n\n get status(): number {\n return this._status;\n }\n\n get promise(): Promise<any> {\n return this._promise;\n }\n\n // --- State setters with event dispatch ---\n\n private _setLoading(loading: boolean): void {\n this._loading = loading;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:loading-changed\", {\n detail: loading,\n bubbles: true,\n }));\n }\n\n private _setProgress(progress: number): void {\n this._progress = progress;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:progress\", {\n detail: progress,\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n private _setResponse(value: any, status: number): void {\n this._value = value;\n this._status = status;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:response\", {\n detail: { value, status },\n bubbles: true,\n }));\n }\n\n // --- Public API ---\n\n abort(): void {\n // `_xhr` は send() の直前に同期で代入されるため、send 前に外部から abort が\n // 割り込む余地はない(割り込み点となる await が存在しない)。よって XHR.abort()\n // は常に進行中のリクエストに対して呼ばれ、abort イベントが発火して loading を\n // 解除する。loading の解除を abort イベントハンドラに集約しているのは、\n // ネットワークエラー/HTTP エラー/正常完了/中断のすべてで解除経路を一本化し、\n // FetchCore.abort() と挙動を揃えるため。\n if (this._xhr) {\n this._xhr.abort();\n this._xhr = null;\n }\n }\n\n async upload(url: string, files: FileList | File[], options: UploadRequestOptions = {}): Promise<any> {\n if (!url) {\n raiseError(\"url is required.\");\n }\n if (!files || files.length === 0) {\n raiseError(\"files are required.\");\n }\n\n const p = this._doUpload(url, files, options);\n this._promise = p;\n return p;\n }\n\n // --- Internal ---\n\n private _doUpload(url: string, files: FileList | File[], options: UploadRequestOptions): Promise<any> {\n // 既存のアップロードを中止\n this.abort();\n\n this._setLoading(true);\n this._setProgress(0);\n this._setError(null);\n\n const {\n method = \"POST\",\n headers = {},\n fieldName = \"file\",\n } = options;\n\n const formData = new FormData();\n for (let i = 0; i < files.length; i++) {\n formData.append(fieldName, files[i]);\n }\n\n return new Promise<any>((resolve) => {\n const xhr = new XMLHttpRequest();\n this._xhr = xhr;\n\n xhr.upload.addEventListener(\"progress\", (event: ProgressEvent) => {\n if (event.lengthComputable) {\n const percent = Math.round((event.loaded / event.total) * 100);\n this._setProgress(percent);\n }\n });\n\n xhr.addEventListener(\"load\", () => {\n this._xhr = null;\n this._status = xhr.status;\n\n if (xhr.status >= 200 && xhr.status < 300) {\n let value: any = xhr.responseText;\n const contentType = xhr.getResponseHeader(\"Content-Type\") || \"\";\n if (contentType.includes(\"application/json\")) {\n try {\n value = JSON.parse(xhr.responseText);\n } catch {\n // テキストのまま\n }\n }\n this._setProgress(100);\n this._setResponse(value, xhr.status);\n this._setLoading(false);\n resolve(value);\n } else {\n const error = {\n status: xhr.status,\n statusText: xhr.statusText,\n body: xhr.responseText,\n };\n this._setError(error);\n this._setLoading(false);\n resolve(null);\n }\n });\n\n xhr.addEventListener(\"error\", () => {\n this._xhr = null;\n this._setError({ message: \"Network error\" });\n this._setLoading(false);\n resolve(null);\n });\n\n xhr.addEventListener(\"abort\", () => {\n this._xhr = null;\n this._setLoading(false);\n resolve(null);\n });\n\n xhr.open(method, url);\n\n for (const [name, value] of Object.entries(headers)) {\n xhr.setRequestHeader(name, value);\n }\n\n xhr.send(formData);\n });\n }\n}\n","import { config } from \"./config.js\";\nimport { WcsUpload } from \"./components/Upload.js\";\n\nlet registered = false;\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const uploadId = triggerElement.getAttribute(config.triggerAttribute);\n if (!uploadId) return;\n\n const uploadElement = document.getElementById(uploadId) as WcsUpload | null;\n if (!uploadElement || !(uploadElement instanceof WcsUpload)) return;\n\n // ファイルと URL が揃っている場合のみ既定動作を抑止\n if (uploadElement.files && uploadElement.files.length > 0 && uploadElement.url) {\n event.preventDefault();\n }\n uploadElement.upload();\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","import { config } from \"../config.js\";\nimport { IWcBindable, WcsUploadError } from \"../types.js\";\nimport { UploadCore } from \"../core/UploadCore.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\nexport class WcsUpload extends HTMLElement {\n static hasConnectedCallbackPromise = false;\n static wcBindable: IWcBindable = {\n ...UploadCore.wcBindable,\n properties: [\n ...UploadCore.wcBindable.properties,\n { name: \"trigger\", event: \"wcs-upload:trigger-changed\" },\n { name: \"files\", event: \"wcs-upload:files-changed\" },\n ],\n // Shell-level input surface. The Core declares only the portable `url` / `method` /\n // `fieldName`; the Shell adds the DOM-driven settable surface. No `attribute` hints\n // are given: the `url` / `method` / `fieldName` / `multiple` / `maxSize` / `accept` /\n // `manual` setters already reflect to their attributes, so a binding system that\n // mirrors inputs[].attribute would set the attribute twice (`files` / `trigger` are\n // not attribute-backed). `commands` (upload / abort) are inherited unchanged from the\n // Core via the spread above.\n inputs: [\n { name: \"url\" },\n { name: \"method\" },\n { name: \"fieldName\" },\n { name: \"multiple\" },\n { name: \"maxSize\" },\n { name: \"accept\" },\n { name: \"manual\" },\n { name: \"files\" },\n { name: \"trigger\" },\n ],\n };\n // `url` を観測するのは FetchCore のシェルと構造を揃えるためだが、upload は\n // url 変更だけでは送信できない(files が必須)。そのため attributeChangedCallback は\n // 意図的に何もしない。url 変更で自動送信しないことは仕様であり、テストで担保している。\n static get observedAttributes(): string[] { return [\"url\"]; }\n\n private _core: UploadCore;\n private _files: FileList | File[] | null = null;\n private _trigger: boolean = false;\n\n constructor() {\n super();\n this._core = new UploadCore(this);\n }\n\n // --- Attribute accessors ---\n\n get url(): string {\n return this.getAttribute(\"url\") || \"\";\n }\n\n set url(value: string) {\n this.setAttribute(\"url\", value);\n }\n\n get method(): string {\n return (this.getAttribute(\"method\") || \"POST\").toUpperCase();\n }\n\n set method(value: string) {\n this.setAttribute(\"method\", value);\n }\n\n get fieldName(): string {\n return this.getAttribute(\"field-name\") || \"file\";\n }\n\n set fieldName(value: string) {\n this.setAttribute(\"field-name\", value);\n }\n\n get multiple(): boolean {\n return this.hasAttribute(\"multiple\");\n }\n\n set multiple(value: boolean) {\n if (value) {\n this.setAttribute(\"multiple\", \"\");\n } else {\n this.removeAttribute(\"multiple\");\n }\n }\n\n get maxSize(): number {\n const attr = this.getAttribute(\"max-size\");\n if (attr === null) {\n return Infinity;\n }\n // 不正値(NaN になる \"abc\" など)や負数は「制限なし」(Infinity) として扱う。\n // NaN を返すと `size > NaN` が常に false になりサイズ検証が無言で無効化され、\n // 負数を返すと全ファイルが拒否されるため、いずれも安全側の Infinity に丸める。\n const n = parseInt(attr, 10);\n return Number.isFinite(n) && n >= 0 ? n : Infinity;\n }\n\n set maxSize(value: number) {\n this.setAttribute(\"max-size\", String(value));\n }\n\n get accept(): string {\n return this.getAttribute(\"accept\") || \"\";\n }\n\n set accept(value: string) {\n this.setAttribute(\"accept\", value);\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get value(): any {\n return this._core.value;\n }\n\n get loading(): boolean {\n return this._core.loading;\n }\n\n get progress(): number {\n return this._core.progress;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n get status(): number {\n return this._core.status;\n }\n\n get promise(): Promise<any> {\n return this._core.promise;\n }\n\n // --- Command properties ---\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n // 進行中に再度 trigger=true が来ても再入ガードはしない(FetchCore シェルと同一)。\n // upload() → _core.upload() が先頭で既存リクエストを abort し新規開始するため、\n // 連続トリガは「前回を中止して新しいアップロードを開始する」挙動になる。\n // 各 upload() の settle ごとに trigger-changed(false) が 1 回発火する。\n const v = !!value;\n if (v) {\n this._trigger = true;\n this.upload().finally(() => {\n this._trigger = false;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:trigger-changed\", {\n detail: false,\n bubbles: true,\n }));\n });\n }\n }\n\n get files(): FileList | File[] | null {\n return this._files;\n }\n\n set files(value: FileList | File[] | null) {\n this._files = value;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\n detail: value,\n bubbles: true,\n }));\n if (!this.manual && this.url && value && value.length > 0) {\n this.upload();\n }\n }\n\n // --- Validation ---\n\n private _validate(files: FileList | File[]): WcsUploadError | null {\n const maxSize = this.maxSize;\n if (maxSize !== Infinity) {\n for (let i = 0; i < files.length; i++) {\n if (files[i].size > maxSize) {\n return { message: `File \"${files[i].name}\" exceeds maximum size of ${maxSize} bytes.` };\n }\n }\n }\n\n const accept = this.accept;\n if (accept) {\n const acceptList = accept.split(\",\").map(s => s.trim().toLowerCase());\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n const fileType = file.type.toLowerCase();\n const fileName = file.name.toLowerCase();\n // file.type が空文字(OS が MIME を判定できないファイル)の場合、MIME 系\n // パターン(`image/*` / 厳密 MIME)は一致しない。その場合でも accept に\n // 拡張子パターン(`.pdf` 等)が含まれ拡張子が一致すれば受理される。\n // accept が MIME 系のみのときは型を確認できないため拒否する(安全側)。\n const matched = acceptList.some(pattern => {\n if (pattern.startsWith(\".\")) {\n return fileName.endsWith(pattern);\n }\n if (pattern.endsWith(\"/*\")) {\n return fileType !== \"\" && fileType.startsWith(pattern.slice(0, -1));\n }\n return fileType !== \"\" && fileType === pattern;\n });\n if (!matched) {\n return { message: `File \"${file.name}\" does not match accepted types: ${accept}` };\n }\n }\n }\n\n return null;\n }\n\n // --- Public methods ---\n\n abort(): void {\n this._core.abort();\n }\n\n async upload(): Promise<any> {\n const files = this._files;\n // url 未設定は no-op(null)。Core は url 空で throw するが、Shell は url/files の\n // ライフサイクルを所有しており「送信先が無い」を「ファイル無し」と同じ無操作として扱う。\n // これにより set trigger / set files の fire-and-forget 経路で unhandled rejection が\n // 発生せず、README の「upload() は全終了ケースで resolve し never reject」契約とも整合する。\n if (!files || files.length === 0 || !this.url) {\n return null;\n }\n\n const validationError = this._validate(files);\n if (validationError) {\n this.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\n detail: validationError,\n bubbles: true,\n }));\n return null;\n }\n\n const result = await this._core.upload(this.url, files, {\n method: this.method,\n fieldName: this.fieldName,\n });\n\n // 自分が開始したアップロードのファイルだけをリセット\n // (途中で新しい files がセットされていたら触らない)\n if (this._files === files) {\n this._files = null;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\n detail: null,\n bubbles: true,\n }));\n }\n\n return result;\n }\n\n // --- Lifecycle ---\n\n attributeChangedCallback(_name: string, _oldValue: string | null, _newValue: string | null): void {\n // 意図的に空。url 変更ではアップロードを自動実行しない(files が必要なため)。\n // observedAttributes のコメント参照。\n }\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n }\n\n disconnectedCallback(): void {\n this._core.abort();\n }\n}\n","import { WcsUpload } from \"./components/Upload.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.upload)) {\n customElements.define(config.tagNames.upload, WcsUpload);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapUpload(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n"],"names":[],"mappings":"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"}
|
package/dist/index.esm.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const t={autoTrigger:!0,triggerAttribute:"data-uploadtarget",tagNames:{upload:"wcs-upload"}};function e(t){if(null===t||"object"!=typeof t)return t;Object.freeze(t);for(const s of Object.keys(t))e(t[s]);return t}function s(t){if(null===t||"object"!=typeof t)return t;const e={};for(const r of Object.keys(t))e[r]=s(t[r]);return e}let r=null;const i=t;function n(){return r||(r=e(s(t))),r}function a(t){throw new Error(`[@wcstack/upload] ${t}`)}class o extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"value",event:"wcs-upload:response",getter:t=>t.detail.value},{name:"loading",event:"wcs-upload:loading-changed"},{name:"progress",event:"wcs-upload:progress"},{name:"error",event:"wcs-upload:error"},{name:"status",event:"wcs-upload:response",getter:t=>t.detail.status}]};_target;_value=null;_loading=!1;_progress=0;_error=null;_status=0;_xhr=null;_promise=Promise.resolve(null);constructor(t){super(),this._target=t??this}get value(){return this._value}get loading(){return this._loading}get progress(){return this._progress}get error(){return this._error}get status(){return this._status}get promise(){return this._promise}_setLoading(t){this._loading=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:loading-changed",{detail:t,bubbles:!0}))}_setProgress(t){this._progress=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:progress",{detail:t,bubbles:!0}))}_setError(t){this._error=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:error",{detail:t,bubbles:!0}))}_setResponse(t,e){this._value=t,this._status=e,this._target.dispatchEvent(new CustomEvent("wcs-upload:response",{detail:{value:t,status:e},bubbles:!0}))}abort(){this._xhr&&(this._xhr.abort(),this._xhr=null)}upload(t,e,s={}){t||a("url is required."),e&&0!==e.length||a("files are required.");const r=this._doUpload(t,e,s);return this._promise=r,r}_doUpload(t,e,s){this.abort(),this._setLoading(!0),this._setProgress(0),this._setError(null);const{method:r="POST",headers:i={},fieldName:n="file"}=s,a=new FormData;for(let t=0;t<e.length;t++)a.append(n,e[t]);return new Promise(e=>{const s=new XMLHttpRequest;this._xhr=s,s.upload.addEventListener("progress",t=>{if(t.lengthComputable){const e=Math.round(t.loaded/t.total*100);this._setProgress(e)}}),s.addEventListener("load",()=>{if(this._xhr=null,this._status=s.status,s.status>=200&&s.status<300){let t=s.responseText;if((s.getResponseHeader("Content-Type")||"").includes("application/json"))try{t=JSON.parse(s.responseText)}catch{}this._setProgress(100),this._setResponse(t,s.status),this._setLoading(!1),e(t)}else{const t={status:s.status,statusText:s.statusText,body:s.responseText};this._setError(t),this._setLoading(!1),e(null)}}),s.addEventListener("error",()=>{this._xhr=null,this._setError({message:"Network error"}),this._setLoading(!1),e(null)}),s.addEventListener("abort",()=>{this._xhr=null,this._setLoading(!1),e(null)}),s.open(r,t);for(const[t,e]of Object.entries(i))s.setRequestHeader(t,e);s.send(a)})}}let l=!1;function u(t){const e=t.target;if(!(e instanceof Element))return;const s=e.closest(`[${i.triggerAttribute}]`);if(!s)return;const r=s.getAttribute(i.triggerAttribute);if(!r)return;const n=document.getElementById(r);n&&n instanceof h&&(n.files&&n.files.length>0&&n.url&&t.preventDefault(),n.upload())}class h extends HTMLElement{static hasConnectedCallbackPromise=!1;static wcBindable={...o.wcBindable,properties:[...o.wcBindable.properties,{name:"trigger",event:"wcs-upload:trigger-changed"},{name:"files",event:"wcs-upload:files-changed"}]};static get observedAttributes(){return["url"]}_core;_files=null;_trigger=!1;constructor(){super(),this._core=new o(this)}get url(){return this.getAttribute("url")||""}set url(t){this.setAttribute("url",t)}get method(){return(this.getAttribute("method")||"POST").toUpperCase()}set method(t){this.setAttribute("method",t)}get fieldName(){return this.getAttribute("field-name")||"file"}set fieldName(t){this.setAttribute("field-name",t)}get multiple(){return this.hasAttribute("multiple")}set multiple(t){t?this.setAttribute("multiple",""):this.removeAttribute("multiple")}get maxSize(){const t=this.getAttribute("max-size");return
|
|
1
|
+
const t={autoTrigger:!0,triggerAttribute:"data-uploadtarget",tagNames:{upload:"wcs-upload"}};function e(t){if(null===t||"object"!=typeof t)return t;Object.freeze(t);for(const s of Object.keys(t))e(t[s]);return t}function s(t){if(null===t||"object"!=typeof t)return t;const e={};for(const r of Object.keys(t))e[r]=s(t[r]);return e}let r=null;const i=t;function n(){return r||(r=e(s(t))),r}function a(t){throw new Error(`[@wcstack/upload] ${t}`)}class o extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"value",event:"wcs-upload:response",getter:t=>t.detail.value},{name:"loading",event:"wcs-upload:loading-changed"},{name:"progress",event:"wcs-upload:progress"},{name:"error",event:"wcs-upload:error"},{name:"status",event:"wcs-upload:response",getter:t=>t.detail.status}],inputs:[{name:"url"},{name:"method"},{name:"fieldName"}],commands:[{name:"upload",async:!0},{name:"abort"}]};_target;_value=null;_loading=!1;_progress=0;_error=null;_status=0;_xhr=null;_promise=Promise.resolve(null);constructor(t){super(),this._target=t??this}get value(){return this._value}get loading(){return this._loading}get progress(){return this._progress}get error(){return this._error}get status(){return this._status}get promise(){return this._promise}_setLoading(t){this._loading=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:loading-changed",{detail:t,bubbles:!0}))}_setProgress(t){this._progress=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:progress",{detail:t,bubbles:!0}))}_setError(t){this._error=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:error",{detail:t,bubbles:!0}))}_setResponse(t,e){this._value=t,this._status=e,this._target.dispatchEvent(new CustomEvent("wcs-upload:response",{detail:{value:t,status:e},bubbles:!0}))}abort(){this._xhr&&(this._xhr.abort(),this._xhr=null)}async upload(t,e,s={}){t||a("url is required."),e&&0!==e.length||a("files are required.");const r=this._doUpload(t,e,s);return this._promise=r,r}_doUpload(t,e,s){this.abort(),this._setLoading(!0),this._setProgress(0),this._setError(null);const{method:r="POST",headers:i={},fieldName:n="file"}=s,a=new FormData;for(let t=0;t<e.length;t++)a.append(n,e[t]);return new Promise(e=>{const s=new XMLHttpRequest;this._xhr=s,s.upload.addEventListener("progress",t=>{if(t.lengthComputable){const e=Math.round(t.loaded/t.total*100);this._setProgress(e)}}),s.addEventListener("load",()=>{if(this._xhr=null,this._status=s.status,s.status>=200&&s.status<300){let t=s.responseText;if((s.getResponseHeader("Content-Type")||"").includes("application/json"))try{t=JSON.parse(s.responseText)}catch{}this._setProgress(100),this._setResponse(t,s.status),this._setLoading(!1),e(t)}else{const t={status:s.status,statusText:s.statusText,body:s.responseText};this._setError(t),this._setLoading(!1),e(null)}}),s.addEventListener("error",()=>{this._xhr=null,this._setError({message:"Network error"}),this._setLoading(!1),e(null)}),s.addEventListener("abort",()=>{this._xhr=null,this._setLoading(!1),e(null)}),s.open(r,t);for(const[t,e]of Object.entries(i))s.setRequestHeader(t,e);s.send(a)})}}let l=!1;function u(t){const e=t.target;if(!(e instanceof Element))return;const s=e.closest(`[${i.triggerAttribute}]`);if(!s)return;const r=s.getAttribute(i.triggerAttribute);if(!r)return;const n=document.getElementById(r);n&&n instanceof h&&(n.files&&n.files.length>0&&n.url&&t.preventDefault(),n.upload())}class h extends HTMLElement{static hasConnectedCallbackPromise=!1;static wcBindable={...o.wcBindable,properties:[...o.wcBindable.properties,{name:"trigger",event:"wcs-upload:trigger-changed"},{name:"files",event:"wcs-upload:files-changed"}],inputs:[{name:"url"},{name:"method"},{name:"fieldName"},{name:"multiple"},{name:"maxSize"},{name:"accept"},{name:"manual"},{name:"files"},{name:"trigger"}]};static get observedAttributes(){return["url"]}_core;_files=null;_trigger=!1;constructor(){super(),this._core=new o(this)}get url(){return this.getAttribute("url")||""}set url(t){this.setAttribute("url",t)}get method(){return(this.getAttribute("method")||"POST").toUpperCase()}set method(t){this.setAttribute("method",t)}get fieldName(){return this.getAttribute("field-name")||"file"}set fieldName(t){this.setAttribute("field-name",t)}get multiple(){return this.hasAttribute("multiple")}set multiple(t){t?this.setAttribute("multiple",""):this.removeAttribute("multiple")}get maxSize(){const t=this.getAttribute("max-size");if(null===t)return 1/0;const e=parseInt(t,10);return Number.isFinite(e)&&e>=0?e:1/0}set maxSize(t){this.setAttribute("max-size",String(t))}get accept(){return this.getAttribute("accept")||""}set accept(t){this.setAttribute("accept",t)}get manual(){return this.hasAttribute("manual")}set manual(t){t?this.setAttribute("manual",""):this.removeAttribute("manual")}get value(){return this._core.value}get loading(){return this._core.loading}get progress(){return this._core.progress}get error(){return this._core.error}get status(){return this._core.status}get promise(){return this._core.promise}get trigger(){return this._trigger}set trigger(t){!!t&&(this._trigger=!0,this.upload().finally(()=>{this._trigger=!1,this.dispatchEvent(new CustomEvent("wcs-upload:trigger-changed",{detail:!1,bubbles:!0}))}))}get files(){return this._files}set files(t){this._files=t,this.dispatchEvent(new CustomEvent("wcs-upload:files-changed",{detail:t,bubbles:!0})),!this.manual&&this.url&&t&&t.length>0&&this.upload()}_validate(t){const e=this.maxSize;if(e!==1/0)for(let s=0;s<t.length;s++)if(t[s].size>e)return{message:`File "${t[s].name}" exceeds maximum size of ${e} bytes.`};const s=this.accept;if(s){const e=s.split(",").map(t=>t.trim().toLowerCase());for(let r=0;r<t.length;r++){const i=t[r],n=i.type.toLowerCase(),a=i.name.toLowerCase();if(!e.some(t=>t.startsWith(".")?a.endsWith(t):t.endsWith("/*")?""!==n&&n.startsWith(t.slice(0,-1)):""!==n&&n===t))return{message:`File "${i.name}" does not match accepted types: ${s}`}}}return null}abort(){this._core.abort()}async upload(){const t=this._files;if(!t||0===t.length||!this.url)return null;const e=this._validate(t);if(e)return this.dispatchEvent(new CustomEvent("wcs-upload:error",{detail:e,bubbles:!0})),null;const s=await this._core.upload(this.url,t,{method:this.method,fieldName:this.fieldName});return this._files===t&&(this._files=null,this.dispatchEvent(new CustomEvent("wcs-upload:files-changed",{detail:null,bubbles:!0}))),s}attributeChangedCallback(t,e,s){}connectedCallback(){this.style.display="none",i.autoTrigger&&(l||(l=!0,document.addEventListener("click",u)))}disconnectedCallback(){this._core.abort()}}function d(e){var s;e&&("boolean"==typeof(s=e).autoTrigger&&(t.autoTrigger=s.autoTrigger),"string"==typeof s.triggerAttribute&&(t.triggerAttribute=s.triggerAttribute),s.tagNames&&Object.assign(t.tagNames,s.tagNames),r=null),customElements.get(i.tagNames.upload)||customElements.define(i.tagNames.upload,h)}export{o as UploadCore,h as WcsUpload,d as bootstrapUpload,n as getConfig};
|
|
2
2
|
//# sourceMappingURL=index.esm.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/raiseError.ts","../src/core/UploadCore.ts","../src/autoTrigger.ts","../src/components/Upload.ts","../src/bootstrapUpload.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n upload: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-uploadtarget\",\n tagNames: {\n upload: \"wcs-upload\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","export function raiseError(message: string): never {\n throw new Error(`[@wcstack/upload] ${message}`);\n}\n","import { raiseError } from \"../raiseError.js\";\nimport { IWcBindable } from \"../types.js\";\n\nexport interface UploadRequestOptions {\n method?: string;\n headers?: Record<string, string>;\n fieldName?: string;\n}\n\nexport class UploadCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"value\", event: \"wcs-upload:response\", getter: (e: Event) => (e as CustomEvent).detail.value },\n { name: \"loading\", event: \"wcs-upload:loading-changed\" },\n { name: \"progress\", event: \"wcs-upload:progress\" },\n { name: \"error\", event: \"wcs-upload:error\" },\n { name: \"status\", event: \"wcs-upload:response\", getter: (e: Event) => (e as CustomEvent).detail.status },\n ],\n };\n\n private _target: EventTarget;\n private _value: any = null;\n private _loading: boolean = false;\n private _progress: number = 0;\n private _error: any = null;\n private _status: number = 0;\n private _xhr: XMLHttpRequest | null = null;\n private _promise: Promise<any> = Promise.resolve(null);\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get value(): any {\n return this._value;\n }\n\n get loading(): boolean {\n return this._loading;\n }\n\n get progress(): number {\n return this._progress;\n }\n\n get error(): any {\n return this._error;\n }\n\n get status(): number {\n return this._status;\n }\n\n get promise(): Promise<any> {\n return this._promise;\n }\n\n // --- State setters with event dispatch ---\n\n private _setLoading(loading: boolean): void {\n this._loading = loading;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:loading-changed\", {\n detail: loading,\n bubbles: true,\n }));\n }\n\n private _setProgress(progress: number): void {\n this._progress = progress;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:progress\", {\n detail: progress,\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n private _setResponse(value: any, status: number): void {\n this._value = value;\n this._status = status;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:response\", {\n detail: { value, status },\n bubbles: true,\n }));\n }\n\n // --- Public API ---\n\n abort(): void {\n if (this._xhr) {\n this._xhr.abort();\n this._xhr = null;\n }\n }\n\n upload(url: string, files: FileList | File[], options: UploadRequestOptions = {}): Promise<any> {\n if (!url) {\n raiseError(\"url is required.\");\n }\n if (!files || files.length === 0) {\n raiseError(\"files are required.\");\n }\n\n const p = this._doUpload(url, files, options);\n this._promise = p;\n return p;\n }\n\n // --- Internal ---\n\n private _doUpload(url: string, files: FileList | File[], options: UploadRequestOptions): Promise<any> {\n // 既存のアップロードを中止\n this.abort();\n\n this._setLoading(true);\n this._setProgress(0);\n this._setError(null);\n\n const {\n method = \"POST\",\n headers = {},\n fieldName = \"file\",\n } = options;\n\n const formData = new FormData();\n for (let i = 0; i < files.length; i++) {\n formData.append(fieldName, files[i]);\n }\n\n return new Promise<any>((resolve) => {\n const xhr = new XMLHttpRequest();\n this._xhr = xhr;\n\n xhr.upload.addEventListener(\"progress\", (event: ProgressEvent) => {\n if (event.lengthComputable) {\n const percent = Math.round((event.loaded / event.total) * 100);\n this._setProgress(percent);\n }\n });\n\n xhr.addEventListener(\"load\", () => {\n this._xhr = null;\n this._status = xhr.status;\n\n if (xhr.status >= 200 && xhr.status < 300) {\n let value: any = xhr.responseText;\n const contentType = xhr.getResponseHeader(\"Content-Type\") || \"\";\n if (contentType.includes(\"application/json\")) {\n try {\n value = JSON.parse(xhr.responseText);\n } catch {\n // テキストのまま\n }\n }\n this._setProgress(100);\n this._setResponse(value, xhr.status);\n this._setLoading(false);\n resolve(value);\n } else {\n const error = {\n status: xhr.status,\n statusText: xhr.statusText,\n body: xhr.responseText,\n };\n this._setError(error);\n this._setLoading(false);\n resolve(null);\n }\n });\n\n xhr.addEventListener(\"error\", () => {\n this._xhr = null;\n this._setError({ message: \"Network error\" });\n this._setLoading(false);\n resolve(null);\n });\n\n xhr.addEventListener(\"abort\", () => {\n this._xhr = null;\n this._setLoading(false);\n resolve(null);\n });\n\n xhr.open(method, url);\n\n for (const [name, value] of Object.entries(headers)) {\n xhr.setRequestHeader(name, value);\n }\n\n xhr.send(formData);\n });\n }\n}\n","import { config } from \"./config.js\";\nimport { WcsUpload } from \"./components/Upload.js\";\n\nlet registered = false;\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const uploadId = triggerElement.getAttribute(config.triggerAttribute);\n if (!uploadId) return;\n\n const uploadElement = document.getElementById(uploadId) as WcsUpload | null;\n if (!uploadElement || !(uploadElement instanceof WcsUpload)) return;\n\n // ファイルと URL が揃っている場合のみ既定動作を抑止\n if (uploadElement.files && uploadElement.files.length > 0 && uploadElement.url) {\n event.preventDefault();\n }\n uploadElement.upload();\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","import { config } from \"../config.js\";\nimport { IWcBindable, WcsUploadError } from \"../types.js\";\nimport { UploadCore } from \"../core/UploadCore.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\nexport class WcsUpload extends HTMLElement {\n static hasConnectedCallbackPromise = false;\n static wcBindable: IWcBindable = {\n ...UploadCore.wcBindable,\n properties: [\n ...UploadCore.wcBindable.properties,\n { name: \"trigger\", event: \"wcs-upload:trigger-changed\" },\n { name: \"files\", event: \"wcs-upload:files-changed\" },\n ],\n };\n static get observedAttributes(): string[] { return [\"url\"]; }\n\n private _core: UploadCore;\n private _files: FileList | File[] | null = null;\n private _trigger: boolean = false;\n\n constructor() {\n super();\n this._core = new UploadCore(this);\n }\n\n // --- Attribute accessors ---\n\n get url(): string {\n return this.getAttribute(\"url\") || \"\";\n }\n\n set url(value: string) {\n this.setAttribute(\"url\", value);\n }\n\n get method(): string {\n return (this.getAttribute(\"method\") || \"POST\").toUpperCase();\n }\n\n set method(value: string) {\n this.setAttribute(\"method\", value);\n }\n\n get fieldName(): string {\n return this.getAttribute(\"field-name\") || \"file\";\n }\n\n set fieldName(value: string) {\n this.setAttribute(\"field-name\", value);\n }\n\n get multiple(): boolean {\n return this.hasAttribute(\"multiple\");\n }\n\n set multiple(value: boolean) {\n if (value) {\n this.setAttribute(\"multiple\", \"\");\n } else {\n this.removeAttribute(\"multiple\");\n }\n }\n\n get maxSize(): number {\n const attr = this.getAttribute(\"max-size\");\n return attr ? parseInt(attr, 10) : Infinity;\n }\n\n set maxSize(value: number) {\n this.setAttribute(\"max-size\", String(value));\n }\n\n get accept(): string {\n return this.getAttribute(\"accept\") || \"\";\n }\n\n set accept(value: string) {\n this.setAttribute(\"accept\", value);\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get value(): any {\n return this._core.value;\n }\n\n get loading(): boolean {\n return this._core.loading;\n }\n\n get progress(): number {\n return this._core.progress;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n get status(): number {\n return this._core.status;\n }\n\n get promise(): Promise<any> {\n return this._core.promise;\n }\n\n // --- Command properties ---\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n const v = !!value;\n if (v) {\n this._trigger = true;\n this.upload().finally(() => {\n this._trigger = false;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:trigger-changed\", {\n detail: false,\n bubbles: true,\n }));\n });\n }\n }\n\n get files(): FileList | File[] | null {\n return this._files;\n }\n\n set files(value: FileList | File[] | null) {\n this._files = value;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\n detail: value,\n bubbles: true,\n }));\n if (!this.manual && this.url && value && value.length > 0) {\n this.upload();\n }\n }\n\n // --- Validation ---\n\n private _validate(files: FileList | File[]): WcsUploadError | null {\n const maxSize = this.maxSize;\n if (maxSize !== Infinity) {\n for (let i = 0; i < files.length; i++) {\n if (files[i].size > maxSize) {\n return { message: `File \"${files[i].name}\" exceeds maximum size of ${maxSize} bytes.` };\n }\n }\n }\n\n const accept = this.accept;\n if (accept) {\n const acceptList = accept.split(\",\").map(s => s.trim().toLowerCase());\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n const fileType = file.type.toLowerCase();\n const fileName = file.name.toLowerCase();\n const matched = acceptList.some(pattern => {\n if (pattern.startsWith(\".\")) {\n return fileName.endsWith(pattern);\n }\n if (pattern.endsWith(\"/*\")) {\n return fileType.startsWith(pattern.slice(0, -1));\n }\n return fileType === pattern;\n });\n if (!matched) {\n return { message: `File \"${file.name}\" does not match accepted types: ${accept}` };\n }\n }\n }\n\n return null;\n }\n\n // --- Public methods ---\n\n abort(): void {\n this._core.abort();\n }\n\n async upload(): Promise<any> {\n const files = this._files;\n if (!files || files.length === 0) {\n return null;\n }\n\n const validationError = this._validate(files);\n if (validationError) {\n this.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\n detail: validationError,\n bubbles: true,\n }));\n return null;\n }\n\n const result = await this._core.upload(this.url, files, {\n method: this.method,\n fieldName: this.fieldName,\n });\n\n // 自分が開始したアップロードのファイルだけをリセット\n // (途中で新しい files がセットされていたら触らない)\n if (this._files === files) {\n this._files = null;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\n detail: null,\n bubbles: true,\n }));\n }\n\n return result;\n }\n\n // --- Lifecycle ---\n\n attributeChangedCallback(_name: string, _oldValue: string | null, _newValue: string | null): void {\n // URL変更ではアップロードを自動実行しない(ファイルが必要なため)\n }\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n }\n\n disconnectedCallback(): void {\n this._core.abort();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapUpload(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { WcsUpload } from \"./components/Upload.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.upload)) {\n customElements.define(config.tagNames.upload, WcsUpload);\n }\n}\n"],"names":["_config","autoTrigger","triggerAttribute","tagNames","upload","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","raiseError","message","Error","UploadCore","EventTarget","static","protocol","version","properties","name","event","getter","e","detail","value","status","_target","_value","_loading","_progress","_error","_status","_xhr","_promise","Promise","resolve","constructor","target","super","this","loading","progress","error","promise","_setLoading","dispatchEvent","CustomEvent","bubbles","_setProgress","_setError","_setResponse","abort","url","files","options","length","p","_doUpload","method","headers","fieldName","formData","FormData","i","append","xhr","XMLHttpRequest","addEventListener","lengthComputable","percent","Math","round","loaded","total","responseText","getResponseHeader","includes","JSON","parse","statusText","body","open","entries","setRequestHeader","send","registered","handleClick","Element","triggerElement","closest","uploadId","getAttribute","uploadElement","document","getElementById","WcsUpload","preventDefault","HTMLElement","wcBindable","observedAttributes","_core","_files","_trigger","setAttribute","toUpperCase","multiple","hasAttribute","removeAttribute","maxSize","attr","parseInt","Infinity","String","accept","manual","trigger","finally","_validate","size","acceptList","split","map","s","trim","toLowerCase","file","fileType","type","fileName","some","pattern","startsWith","endsWith","slice","validationError","result","attributeChangedCallback","_name","_oldValue","_newValue","connectedCallback","style","display","disconnectedCallback","bootstrapUpload","userConfig","partialConfig","assign","customElements","get","define"],"mappings":"AAUA,MAAMA,EAA2B,CAC/BC,aAAa,EACbC,iBAAkB,oBAClBC,SAAU,CACRC,OAAQ,eAIZ,SAASC,EAAcC,GACrB,GAAY,OAARA,GAA+B,iBAARA,EAAkB,OAAOA,EACpDC,OAAOC,OAAOF,GACd,IAAK,MAAMG,KAAOF,OAAOG,KAAKJ,GAC5BD,EAAYC,EAAgCG,IAE9C,OAAOH,CACT,CAEA,SAASK,EAAaL,GACpB,GAAY,OAARA,GAA+B,iBAARA,EAAkB,OAAOA,EACpD,MAAMM,EAAiC,CAAA,EACvC,IAAK,MAAMH,KAAOF,OAAOG,KAAKJ,GAC5BM,EAAMH,GAAOE,EAAWL,EAAgCG,IAE1D,OAAOG,CACT,CAEA,IAAIC,EAA+B,KAE5B,MAAMC,EAAkBd,WAEfe,IAId,OAHKF,IACHA,EAAeR,EAAWM,EAAUX,KAE/Ba,CACT,CC7CM,SAAUG,EAAWC,GACzB,MAAM,IAAIC,MAAM,qBAAqBD,IACvC,CCOM,MAAOE,UAAmBC,YAC9BC,kBAAiC,CAC/BC,SAAU,cACVC,QAAS,EACTC,WAAY,CACV,CAAEC,KAAM,QAASC,MAAO,sBAAuBC,OAASC,GAAcA,EAAkBC,OAAOC,OAC/F,CAAEL,KAAM,UAAWC,MAAO,8BAC1B,CAAED,KAAM,WAAYC,MAAO,uBAC3B,CAAED,KAAM,QAASC,MAAO,oBACxB,CAAED,KAAM,SAAUC,MAAO,sBAAuBC,OAASC,GAAcA,EAAkBC,OAAOE,UAI5FC,QACAC,OAAc,KACdC,UAAoB,EACpBC,UAAoB,EACpBC,OAAc,KACdC,QAAkB,EAClBC,KAA8B,KAC9BC,SAAyBC,QAAQC,QAAQ,MAEjD,WAAAC,CAAYC,GACVC,QACAC,KAAKb,QAAUW,GAAUE,IAC3B,CAEA,SAAIf,GACF,OAAOe,KAAKZ,MACd,CAEA,WAAIa,GACF,OAAOD,KAAKX,QACd,CAEA,YAAIa,GACF,OAAOF,KAAKV,SACd,CAEA,SAAIa,GACF,OAAOH,KAAKT,MACd,CAEA,UAAIL,GACF,OAAOc,KAAKR,OACd,CAEA,WAAIY,GACF,OAAOJ,KAAKN,QACd,CAIQ,WAAAW,CAAYJ,GAClBD,KAAKX,SAAWY,EAChBD,KAAKb,QAAQmB,cAAc,IAAIC,YAAY,6BAA8B,CACvEvB,OAAQiB,EACRO,SAAS,IAEb,CAEQ,YAAAC,CAAaP,GACnBF,KAAKV,UAAYY,EACjBF,KAAKb,QAAQmB,cAAc,IAAIC,YAAY,sBAAuB,CAChEvB,OAAQkB,EACRM,SAAS,IAEb,CAEQ,SAAAE,CAAUP,GAChBH,KAAKT,OAASY,EACdH,KAAKb,QAAQmB,cAAc,IAAIC,YAAY,mBAAoB,CAC7DvB,OAAQmB,EACRK,SAAS,IAEb,CAEQ,YAAAG,CAAa1B,EAAYC,GAC/Bc,KAAKZ,OAASH,EACde,KAAKR,QAAUN,EACfc,KAAKb,QAAQmB,cAAc,IAAIC,YAAY,sBAAuB,CAChEvB,OAAQ,CAAEC,QAAOC,UACjBsB,SAAS,IAEb,CAIA,KAAAI,GACMZ,KAAKP,OACPO,KAAKP,KAAKmB,QACVZ,KAAKP,KAAO,KAEhB,CAEA,MAAAlC,CAAOsD,EAAaC,EAA0BC,EAAgC,CAAA,GACvEF,GACH1C,EAAW,oBAER2C,GAA0B,IAAjBA,EAAME,QAClB7C,EAAW,uBAGb,MAAM8C,EAAIjB,KAAKkB,UAAUL,EAAKC,EAAOC,GAErC,OADAf,KAAKN,SAAWuB,EACTA,CACT,CAIQ,SAAAC,CAAUL,EAAaC,EAA0BC,GAEvDf,KAAKY,QAELZ,KAAKK,aAAY,GACjBL,KAAKS,aAAa,GAClBT,KAAKU,UAAU,MAEf,MAAMS,OACJA,EAAS,OAAMC,QACfA,EAAU,CAAA,EAAEC,UACZA,EAAY,QACVN,EAEEO,EAAW,IAAIC,SACrB,IAAK,IAAIC,EAAI,EAAGA,EAAIV,EAAME,OAAQQ,IAChCF,EAASG,OAAOJ,EAAWP,EAAMU,IAGnC,OAAO,IAAI7B,QAAcC,IACvB,MAAM8B,EAAM,IAAIC,eAChB3B,KAAKP,KAAOiC,EAEZA,EAAInE,OAAOqE,iBAAiB,WAAa/C,IACvC,GAAIA,EAAMgD,iBAAkB,CAC1B,MAAMC,EAAUC,KAAKC,MAAOnD,EAAMoD,OAASpD,EAAMqD,MAAS,KAC1DlC,KAAKS,aAAaqB,EACpB,IAGFJ,EAAIE,iBAAiB,OAAQ,KAI3B,GAHA5B,KAAKP,KAAO,KACZO,KAAKR,QAAUkC,EAAIxC,OAEfwC,EAAIxC,QAAU,KAAOwC,EAAIxC,OAAS,IAAK,CACzC,IAAID,EAAayC,EAAIS,aAErB,IADoBT,EAAIU,kBAAkB,iBAAmB,IAC7CC,SAAS,oBACvB,IACEpD,EAAQqD,KAAKC,MAAMb,EAAIS,aACzB,CAAE,MAEF,CAEFnC,KAAKS,aAAa,KAClBT,KAAKW,aAAa1B,EAAOyC,EAAIxC,QAC7Bc,KAAKK,aAAY,GACjBT,EAAQX,EACV,KAAO,CACL,MAAMkB,EAAQ,CACZjB,OAAQwC,EAAIxC,OACZsD,WAAYd,EAAIc,WAChBC,KAAMf,EAAIS,cAEZnC,KAAKU,UAAUP,GACfH,KAAKK,aAAY,GACjBT,EAAQ,KACV,IAGF8B,EAAIE,iBAAiB,QAAS,KAC5B5B,KAAKP,KAAO,KACZO,KAAKU,UAAU,CAAEtC,QAAS,kBAC1B4B,KAAKK,aAAY,GACjBT,EAAQ,QAGV8B,EAAIE,iBAAiB,QAAS,KAC5B5B,KAAKP,KAAO,KACZO,KAAKK,aAAY,GACjBT,EAAQ,QAGV8B,EAAIgB,KAAKvB,EAAQN,GAEjB,IAAK,MAAOjC,EAAMK,KAAUvB,OAAOiF,QAAQvB,GACzCM,EAAIkB,iBAAiBhE,EAAMK,GAG7ByC,EAAImB,KAAKvB,IAEb,ECrMF,IAAIwB,GAAa,EAEjB,SAASC,EAAYlE,GACnB,MAAMiB,EAASjB,EAAMiB,OACrB,KAAMA,aAAkBkD,SAAU,OAElC,MAAMC,EAAiBnD,EAAOoD,QAAiB,IAAIjF,EAAOZ,qBAC1D,IAAK4F,EAAgB,OAErB,MAAME,EAAWF,EAAeG,aAAanF,EAAOZ,kBACpD,IAAK8F,EAAU,OAEf,MAAME,EAAgBC,SAASC,eAAeJ,GACzCE,GAAmBA,aAAyBG,IAG7CH,EAAcvC,OAASuC,EAAcvC,MAAME,OAAS,GAAKqC,EAAcxC,KACzEhC,EAAM4E,iBAERJ,EAAc9F,SAChB,CClBM,MAAOiG,UAAkBE,YAC7BlF,oCAAqC,EACrCA,kBAAiC,IAC5BF,EAAWqF,WACdhF,WAAY,IACPL,EAAWqF,WAAWhF,WACzB,CAAEC,KAAM,UAAWC,MAAO,8BAC1B,CAAED,KAAM,QAASC,MAAO,8BAG5B,6BAAW+E,GAAiC,MAAO,CAAC,MAAQ,CAEpDC,MACAC,OAAmC,KACnCC,UAAoB,EAE5B,WAAAlE,GACEE,QACAC,KAAK6D,MAAQ,IAAIvF,EAAW0B,KAC9B,CAIA,OAAIa,GACF,OAAOb,KAAKoD,aAAa,QAAU,EACrC,CAEA,OAAIvC,CAAI5B,GACNe,KAAKgE,aAAa,MAAO/E,EAC3B,CAEA,UAAIkC,GACF,OAAQnB,KAAKoD,aAAa,WAAa,QAAQa,aACjD,CAEA,UAAI9C,CAAOlC,GACTe,KAAKgE,aAAa,SAAU/E,EAC9B,CAEA,aAAIoC,GACF,OAAOrB,KAAKoD,aAAa,eAAiB,MAC5C,CAEA,aAAI/B,CAAUpC,GACZe,KAAKgE,aAAa,aAAc/E,EAClC,CAEA,YAAIiF,GACF,OAAOlE,KAAKmE,aAAa,WAC3B,CAEA,YAAID,CAASjF,GACPA,EACFe,KAAKgE,aAAa,WAAY,IAE9BhE,KAAKoE,gBAAgB,WAEzB,CAEA,WAAIC,GACF,MAAMC,EAAOtE,KAAKoD,aAAa,YAC/B,OAAOkB,EAAOC,SAASD,EAAM,IAAME,GACrC,CAEA,WAAIH,CAAQpF,GACVe,KAAKgE,aAAa,WAAYS,OAAOxF,GACvC,CAEA,UAAIyF,GACF,OAAO1E,KAAKoD,aAAa,WAAa,EACxC,CAEA,UAAIsB,CAAOzF,GACTe,KAAKgE,aAAa,SAAU/E,EAC9B,CAEA,UAAI0F,GACF,OAAO3E,KAAKmE,aAAa,SAC3B,CAEA,UAAIQ,CAAO1F,GACLA,EACFe,KAAKgE,aAAa,SAAU,IAE5BhE,KAAKoE,gBAAgB,SAEzB,CAIA,SAAInF,GACF,OAAOe,KAAK6D,MAAM5E,KACpB,CAEA,WAAIgB,GACF,OAAOD,KAAK6D,MAAM5D,OACpB,CAEA,YAAIC,GACF,OAAOF,KAAK6D,MAAM3D,QACpB,CAEA,SAAIC,GACF,OAAOH,KAAK6D,MAAM1D,KACpB,CAEA,UAAIjB,GACF,OAAOc,KAAK6D,MAAM3E,MACpB,CAEA,WAAIkB,GACF,OAAOJ,KAAK6D,MAAMzD,OACpB,CAIA,WAAIwE,GACF,OAAO5E,KAAK+D,QACd,CAEA,WAAIa,CAAQ3F,KACEA,IAEVe,KAAK+D,UAAW,EAChB/D,KAAKzC,SAASsH,QAAQ,KACpB7E,KAAK+D,UAAW,EAChB/D,KAAKM,cAAc,IAAIC,YAAY,6BAA8B,CAC/DvB,QAAQ,EACRwB,SAAS,OAIjB,CAEA,SAAIM,GACF,OAAOd,KAAK8D,MACd,CAEA,SAAIhD,CAAM7B,GACRe,KAAK8D,OAAS7E,EACde,KAAKM,cAAc,IAAIC,YAAY,2BAA4B,CAC7DvB,OAAQC,EACRuB,SAAS,MAENR,KAAK2E,QAAU3E,KAAKa,KAAO5B,GAASA,EAAM+B,OAAS,GACtDhB,KAAKzC,QAET,CAIQ,SAAAuH,CAAUhE,GAChB,MAAMuD,EAAUrE,KAAKqE,QACrB,GAAIA,IAAYG,IACd,IAAK,IAAIhD,EAAI,EAAGA,EAAIV,EAAME,OAAQQ,IAChC,GAAIV,EAAMU,GAAGuD,KAAOV,EAClB,MAAO,CAAEjG,QAAS,SAAS0C,EAAMU,GAAG5C,iCAAiCyF,YAK3E,MAAMK,EAAS1E,KAAK0E,OACpB,GAAIA,EAAQ,CACV,MAAMM,EAAaN,EAAOO,MAAM,KAAKC,IAAIC,GAAKA,EAAEC,OAAOC,eACvD,IAAK,IAAI7D,EAAI,EAAGA,EAAIV,EAAME,OAAQQ,IAAK,CACrC,MAAM8D,EAAOxE,EAAMU,GACb+D,EAAWD,EAAKE,KAAKH,cACrBI,EAAWH,EAAK1G,KAAKyG,cAU3B,IATgBL,EAAWU,KAAKC,GAC1BA,EAAQC,WAAW,KACdH,EAASI,SAASF,GAEvBA,EAAQE,SAAS,MACZN,EAASK,WAAWD,EAAQG,MAAM,GAAG,IAEvCP,IAAaI,GAGpB,MAAO,CAAEvH,QAAS,SAASkH,EAAK1G,wCAAwC8F,IAE5E,CACF,CAEA,OAAO,IACT,CAIA,KAAA9D,GACEZ,KAAK6D,MAAMjD,OACb,CAEA,YAAMrD,GACJ,MAAMuD,EAAQd,KAAK8D,OACnB,IAAKhD,GAA0B,IAAjBA,EAAME,OAClB,OAAO,KAGT,MAAM+E,EAAkB/F,KAAK8E,UAAUhE,GACvC,GAAIiF,EAKF,OAJA/F,KAAKM,cAAc,IAAIC,YAAY,mBAAoB,CACrDvB,OAAQ+G,EACRvF,SAAS,KAEJ,KAGT,MAAMwF,QAAehG,KAAK6D,MAAMtG,OAAOyC,KAAKa,IAAKC,EAAO,CACtDK,OAAQnB,KAAKmB,OACbE,UAAWrB,KAAKqB,YAalB,OARIrB,KAAK8D,SAAWhD,IAClBd,KAAK8D,OAAS,KACd9D,KAAKM,cAAc,IAAIC,YAAY,2BAA4B,CAC7DvB,OAAQ,KACRwB,SAAS,MAINwF,CACT,CAIA,wBAAAC,CAAyBC,EAAeC,EAA0BC,GAElE,CAEA,iBAAAC,GACErG,KAAKsG,MAAMC,QAAU,OACjBtI,EAAOb,cDpNT0F,IACJA,GAAa,EACbQ,SAAS1B,iBAAiB,QAASmB,ICqNnC,CAEA,oBAAAyD,GACExG,KAAK6D,MAAMjD,OACb,ECjPI,SAAU6F,EAAgBC,GL2C1B,IAAoBC,EK1CpBD,IL2CqC,kBADjBC,EKzCZD,GL0CatJ,cACvBD,EAAQC,YAAcuJ,EAAcvJ,aAEQ,iBAAnCuJ,EAActJ,mBACvBF,EAAQE,iBAAmBsJ,EAActJ,kBAEvCsJ,EAAcrJ,UAChBI,OAAOkJ,OAAOzJ,EAAQG,SAAUqJ,EAAcrJ,UAEhDU,EAAe,MMrDV6I,eAAeC,IAAI7I,EAAOX,SAASC,SACtCsJ,eAAeE,OAAO9I,EAAOX,SAASC,OAAQiG,EDIlD"}
|
|
1
|
+
{"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/raiseError.ts","../src/core/UploadCore.ts","../src/autoTrigger.ts","../src/components/Upload.ts","../src/bootstrapUpload.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n upload: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-uploadtarget\",\n tagNames: {\n upload: \"wcs-upload\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\n// `config` は内部用のライブビュー(live view)。setConfig() の更新が即座に反映される\n// 実体 `_config` をそのまま公開しており、凍結もクローンもしていない。autoTrigger /\n// components など同パッケージ内のモジュールが最新値を読むための窓口であり、\n// 「変更不可なスナップショット」が必要な外部利用には getConfig()(凍結クローンを返す)\n// を使うこと。型が readonly なのは内部からの誤書き換えを抑止するための表明にすぎない。\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","export function raiseError(message: string): never {\n throw new Error(`[@wcstack/upload] ${message}`);\n}\n","import { raiseError } from \"../raiseError.js\";\nimport { IWcBindable } from \"../types.js\";\n\nexport interface UploadRequestOptions {\n method?: string;\n headers?: Record<string, string>;\n fieldName?: string;\n}\n\nexport class UploadCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"value\", event: \"wcs-upload:response\", getter: (e: Event) => (e as CustomEvent).detail.value },\n { name: \"loading\", event: \"wcs-upload:loading-changed\" },\n { name: \"progress\", event: \"wcs-upload:progress\" },\n { name: \"error\", event: \"wcs-upload:error\" },\n { name: \"status\", event: \"wcs-upload:response\", getter: (e: Event) => (e as CustomEvent).detail.status },\n ],\n inputs: [\n { name: \"url\" },\n { name: \"method\" },\n { name: \"fieldName\" },\n ],\n commands: [\n { name: \"upload\", async: true },\n { name: \"abort\" },\n ],\n };\n\n private _target: EventTarget;\n private _value: any = null;\n private _loading: boolean = false;\n private _progress: number = 0;\n private _error: any = null;\n private _status: number = 0;\n private _xhr: XMLHttpRequest | null = null;\n private _promise: Promise<any> = Promise.resolve(null);\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get value(): any {\n return this._value;\n }\n\n get loading(): boolean {\n return this._loading;\n }\n\n get progress(): number {\n return this._progress;\n }\n\n get error(): any {\n return this._error;\n }\n\n get status(): number {\n return this._status;\n }\n\n get promise(): Promise<any> {\n return this._promise;\n }\n\n // --- State setters with event dispatch ---\n\n private _setLoading(loading: boolean): void {\n this._loading = loading;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:loading-changed\", {\n detail: loading,\n bubbles: true,\n }));\n }\n\n private _setProgress(progress: number): void {\n this._progress = progress;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:progress\", {\n detail: progress,\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n private _setResponse(value: any, status: number): void {\n this._value = value;\n this._status = status;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:response\", {\n detail: { value, status },\n bubbles: true,\n }));\n }\n\n // --- Public API ---\n\n abort(): void {\n // `_xhr` は send() の直前に同期で代入されるため、send 前に外部から abort が\n // 割り込む余地はない(割り込み点となる await が存在しない)。よって XHR.abort()\n // は常に進行中のリクエストに対して呼ばれ、abort イベントが発火して loading を\n // 解除する。loading の解除を abort イベントハンドラに集約しているのは、\n // ネットワークエラー/HTTP エラー/正常完了/中断のすべてで解除経路を一本化し、\n // FetchCore.abort() と挙動を揃えるため。\n if (this._xhr) {\n this._xhr.abort();\n this._xhr = null;\n }\n }\n\n async upload(url: string, files: FileList | File[], options: UploadRequestOptions = {}): Promise<any> {\n if (!url) {\n raiseError(\"url is required.\");\n }\n if (!files || files.length === 0) {\n raiseError(\"files are required.\");\n }\n\n const p = this._doUpload(url, files, options);\n this._promise = p;\n return p;\n }\n\n // --- Internal ---\n\n private _doUpload(url: string, files: FileList | File[], options: UploadRequestOptions): Promise<any> {\n // 既存のアップロードを中止\n this.abort();\n\n this._setLoading(true);\n this._setProgress(0);\n this._setError(null);\n\n const {\n method = \"POST\",\n headers = {},\n fieldName = \"file\",\n } = options;\n\n const formData = new FormData();\n for (let i = 0; i < files.length; i++) {\n formData.append(fieldName, files[i]);\n }\n\n return new Promise<any>((resolve) => {\n const xhr = new XMLHttpRequest();\n this._xhr = xhr;\n\n xhr.upload.addEventListener(\"progress\", (event: ProgressEvent) => {\n if (event.lengthComputable) {\n const percent = Math.round((event.loaded / event.total) * 100);\n this._setProgress(percent);\n }\n });\n\n xhr.addEventListener(\"load\", () => {\n this._xhr = null;\n this._status = xhr.status;\n\n if (xhr.status >= 200 && xhr.status < 300) {\n let value: any = xhr.responseText;\n const contentType = xhr.getResponseHeader(\"Content-Type\") || \"\";\n if (contentType.includes(\"application/json\")) {\n try {\n value = JSON.parse(xhr.responseText);\n } catch {\n // テキストのまま\n }\n }\n this._setProgress(100);\n this._setResponse(value, xhr.status);\n this._setLoading(false);\n resolve(value);\n } else {\n const error = {\n status: xhr.status,\n statusText: xhr.statusText,\n body: xhr.responseText,\n };\n this._setError(error);\n this._setLoading(false);\n resolve(null);\n }\n });\n\n xhr.addEventListener(\"error\", () => {\n this._xhr = null;\n this._setError({ message: \"Network error\" });\n this._setLoading(false);\n resolve(null);\n });\n\n xhr.addEventListener(\"abort\", () => {\n this._xhr = null;\n this._setLoading(false);\n resolve(null);\n });\n\n xhr.open(method, url);\n\n for (const [name, value] of Object.entries(headers)) {\n xhr.setRequestHeader(name, value);\n }\n\n xhr.send(formData);\n });\n }\n}\n","import { config } from \"./config.js\";\nimport { WcsUpload } from \"./components/Upload.js\";\n\nlet registered = false;\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const uploadId = triggerElement.getAttribute(config.triggerAttribute);\n if (!uploadId) return;\n\n const uploadElement = document.getElementById(uploadId) as WcsUpload | null;\n if (!uploadElement || !(uploadElement instanceof WcsUpload)) return;\n\n // ファイルと URL が揃っている場合のみ既定動作を抑止\n if (uploadElement.files && uploadElement.files.length > 0 && uploadElement.url) {\n event.preventDefault();\n }\n uploadElement.upload();\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","import { config } from \"../config.js\";\nimport { IWcBindable, WcsUploadError } from \"../types.js\";\nimport { UploadCore } from \"../core/UploadCore.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\nexport class WcsUpload extends HTMLElement {\n static hasConnectedCallbackPromise = false;\n static wcBindable: IWcBindable = {\n ...UploadCore.wcBindable,\n properties: [\n ...UploadCore.wcBindable.properties,\n { name: \"trigger\", event: \"wcs-upload:trigger-changed\" },\n { name: \"files\", event: \"wcs-upload:files-changed\" },\n ],\n // Shell-level input surface. The Core declares only the portable `url` / `method` /\n // `fieldName`; the Shell adds the DOM-driven settable surface. No `attribute` hints\n // are given: the `url` / `method` / `fieldName` / `multiple` / `maxSize` / `accept` /\n // `manual` setters already reflect to their attributes, so a binding system that\n // mirrors inputs[].attribute would set the attribute twice (`files` / `trigger` are\n // not attribute-backed). `commands` (upload / abort) are inherited unchanged from the\n // Core via the spread above.\n inputs: [\n { name: \"url\" },\n { name: \"method\" },\n { name: \"fieldName\" },\n { name: \"multiple\" },\n { name: \"maxSize\" },\n { name: \"accept\" },\n { name: \"manual\" },\n { name: \"files\" },\n { name: \"trigger\" },\n ],\n };\n // `url` を観測するのは FetchCore のシェルと構造を揃えるためだが、upload は\n // url 変更だけでは送信できない(files が必須)。そのため attributeChangedCallback は\n // 意図的に何もしない。url 変更で自動送信しないことは仕様であり、テストで担保している。\n static get observedAttributes(): string[] { return [\"url\"]; }\n\n private _core: UploadCore;\n private _files: FileList | File[] | null = null;\n private _trigger: boolean = false;\n\n constructor() {\n super();\n this._core = new UploadCore(this);\n }\n\n // --- Attribute accessors ---\n\n get url(): string {\n return this.getAttribute(\"url\") || \"\";\n }\n\n set url(value: string) {\n this.setAttribute(\"url\", value);\n }\n\n get method(): string {\n return (this.getAttribute(\"method\") || \"POST\").toUpperCase();\n }\n\n set method(value: string) {\n this.setAttribute(\"method\", value);\n }\n\n get fieldName(): string {\n return this.getAttribute(\"field-name\") || \"file\";\n }\n\n set fieldName(value: string) {\n this.setAttribute(\"field-name\", value);\n }\n\n get multiple(): boolean {\n return this.hasAttribute(\"multiple\");\n }\n\n set multiple(value: boolean) {\n if (value) {\n this.setAttribute(\"multiple\", \"\");\n } else {\n this.removeAttribute(\"multiple\");\n }\n }\n\n get maxSize(): number {\n const attr = this.getAttribute(\"max-size\");\n if (attr === null) {\n return Infinity;\n }\n // 不正値(NaN になる \"abc\" など)や負数は「制限なし」(Infinity) として扱う。\n // NaN を返すと `size > NaN` が常に false になりサイズ検証が無言で無効化され、\n // 負数を返すと全ファイルが拒否されるため、いずれも安全側の Infinity に丸める。\n const n = parseInt(attr, 10);\n return Number.isFinite(n) && n >= 0 ? n : Infinity;\n }\n\n set maxSize(value: number) {\n this.setAttribute(\"max-size\", String(value));\n }\n\n get accept(): string {\n return this.getAttribute(\"accept\") || \"\";\n }\n\n set accept(value: string) {\n this.setAttribute(\"accept\", value);\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get value(): any {\n return this._core.value;\n }\n\n get loading(): boolean {\n return this._core.loading;\n }\n\n get progress(): number {\n return this._core.progress;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n get status(): number {\n return this._core.status;\n }\n\n get promise(): Promise<any> {\n return this._core.promise;\n }\n\n // --- Command properties ---\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n // 進行中に再度 trigger=true が来ても再入ガードはしない(FetchCore シェルと同一)。\n // upload() → _core.upload() が先頭で既存リクエストを abort し新規開始するため、\n // 連続トリガは「前回を中止して新しいアップロードを開始する」挙動になる。\n // 各 upload() の settle ごとに trigger-changed(false) が 1 回発火する。\n const v = !!value;\n if (v) {\n this._trigger = true;\n this.upload().finally(() => {\n this._trigger = false;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:trigger-changed\", {\n detail: false,\n bubbles: true,\n }));\n });\n }\n }\n\n get files(): FileList | File[] | null {\n return this._files;\n }\n\n set files(value: FileList | File[] | null) {\n this._files = value;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\n detail: value,\n bubbles: true,\n }));\n if (!this.manual && this.url && value && value.length > 0) {\n this.upload();\n }\n }\n\n // --- Validation ---\n\n private _validate(files: FileList | File[]): WcsUploadError | null {\n const maxSize = this.maxSize;\n if (maxSize !== Infinity) {\n for (let i = 0; i < files.length; i++) {\n if (files[i].size > maxSize) {\n return { message: `File \"${files[i].name}\" exceeds maximum size of ${maxSize} bytes.` };\n }\n }\n }\n\n const accept = this.accept;\n if (accept) {\n const acceptList = accept.split(\",\").map(s => s.trim().toLowerCase());\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n const fileType = file.type.toLowerCase();\n const fileName = file.name.toLowerCase();\n // file.type が空文字(OS が MIME を判定できないファイル)の場合、MIME 系\n // パターン(`image/*` / 厳密 MIME)は一致しない。その場合でも accept に\n // 拡張子パターン(`.pdf` 等)が含まれ拡張子が一致すれば受理される。\n // accept が MIME 系のみのときは型を確認できないため拒否する(安全側)。\n const matched = acceptList.some(pattern => {\n if (pattern.startsWith(\".\")) {\n return fileName.endsWith(pattern);\n }\n if (pattern.endsWith(\"/*\")) {\n return fileType !== \"\" && fileType.startsWith(pattern.slice(0, -1));\n }\n return fileType !== \"\" && fileType === pattern;\n });\n if (!matched) {\n return { message: `File \"${file.name}\" does not match accepted types: ${accept}` };\n }\n }\n }\n\n return null;\n }\n\n // --- Public methods ---\n\n abort(): void {\n this._core.abort();\n }\n\n async upload(): Promise<any> {\n const files = this._files;\n // url 未設定は no-op(null)。Core は url 空で throw するが、Shell は url/files の\n // ライフサイクルを所有しており「送信先が無い」を「ファイル無し」と同じ無操作として扱う。\n // これにより set trigger / set files の fire-and-forget 経路で unhandled rejection が\n // 発生せず、README の「upload() は全終了ケースで resolve し never reject」契約とも整合する。\n if (!files || files.length === 0 || !this.url) {\n return null;\n }\n\n const validationError = this._validate(files);\n if (validationError) {\n this.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\n detail: validationError,\n bubbles: true,\n }));\n return null;\n }\n\n const result = await this._core.upload(this.url, files, {\n method: this.method,\n fieldName: this.fieldName,\n });\n\n // 自分が開始したアップロードのファイルだけをリセット\n // (途中で新しい files がセットされていたら触らない)\n if (this._files === files) {\n this._files = null;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\n detail: null,\n bubbles: true,\n }));\n }\n\n return result;\n }\n\n // --- Lifecycle ---\n\n attributeChangedCallback(_name: string, _oldValue: string | null, _newValue: string | null): void {\n // 意図的に空。url 変更ではアップロードを自動実行しない(files が必要なため)。\n // observedAttributes のコメント参照。\n }\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n }\n\n disconnectedCallback(): void {\n this._core.abort();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapUpload(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { WcsUpload } from \"./components/Upload.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.upload)) {\n customElements.define(config.tagNames.upload, WcsUpload);\n }\n}\n"],"names":["_config","autoTrigger","triggerAttribute","tagNames","upload","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","raiseError","message","Error","UploadCore","EventTarget","static","protocol","version","properties","name","event","getter","e","detail","value","status","inputs","commands","async","_target","_value","_loading","_progress","_error","_status","_xhr","_promise","Promise","resolve","constructor","target","super","this","loading","progress","error","promise","_setLoading","dispatchEvent","CustomEvent","bubbles","_setProgress","_setError","_setResponse","abort","url","files","options","length","p","_doUpload","method","headers","fieldName","formData","FormData","i","append","xhr","XMLHttpRequest","addEventListener","lengthComputable","percent","Math","round","loaded","total","responseText","getResponseHeader","includes","JSON","parse","statusText","body","open","entries","setRequestHeader","send","registered","handleClick","Element","triggerElement","closest","uploadId","getAttribute","uploadElement","document","getElementById","WcsUpload","preventDefault","HTMLElement","wcBindable","observedAttributes","_core","_files","_trigger","setAttribute","toUpperCase","multiple","hasAttribute","removeAttribute","maxSize","attr","Infinity","n","parseInt","Number","isFinite","String","accept","manual","trigger","finally","_validate","size","acceptList","split","map","s","trim","toLowerCase","file","fileType","type","fileName","some","pattern","startsWith","endsWith","slice","validationError","result","attributeChangedCallback","_name","_oldValue","_newValue","connectedCallback","style","display","disconnectedCallback","bootstrapUpload","userConfig","partialConfig","assign","customElements","get","define"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wcstack/upload",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"description": "Declarative file upload component for Web Components. Framework-agnostic upload with progress tracking via wc-bindable-protocol.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.esm.js",
|