@wcstack/upload 1.8.6 → 1.9.1
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 +283 -0
- package/README.md +283 -0
- package/dist/auto.js +3 -3
- package/dist/auto.min.js +3 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/package.json +71 -71
package/README.ja.md
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
# @wcstack/upload
|
|
2
|
+
|
|
3
|
+
`@wcstack/upload` は wcstack エコシステム向けの宣言的ファイルアップロードコンポーネントです。
|
|
4
|
+
|
|
5
|
+
視覚的な UI ウィジェットではありません。
|
|
6
|
+
ファイルアップロードをバインド可能な状態へ変換する、隠れた **upload I/O ノード** です。
|
|
7
|
+
|
|
8
|
+
`@wcstack/state` と組み合わせると、`<wcs-upload>` は次のような小さな非同期ステートサーフェスを公開します。
|
|
9
|
+
|
|
10
|
+
- 入力 / コマンドサーフェス: `files`, `trigger`
|
|
11
|
+
- 設定サーフェス: `url`, `method`, `field-name`, `accept`, `max-size`, `manual`, `multiple`
|
|
12
|
+
- 出力ステートサーフェス: `value`, `loading`, `progress`, `error`, `status`
|
|
13
|
+
|
|
14
|
+
つまり、ファイルアップロードを場当たり的な `XMLHttpRequest` のグルーコードではなく、状態遷移と DOM バインディングとして扱えます。
|
|
15
|
+
|
|
16
|
+
`@wcstack/upload` は wcstack の他の I/O パッケージと同様に、HAWC 的な分割に従います。
|
|
17
|
+
|
|
18
|
+
- **Core** (`UploadCore`) が XHR アップロード、進捗追跡、abort、非同期状態を処理
|
|
19
|
+
- **Shell** (`<wcs-upload>`) がその状態をカスタム要素と `wc-bindable` サーフェスとして公開
|
|
20
|
+
- フレームワークやバインディングシステムは `wc-bindable-protocol` 経由で利用
|
|
21
|
+
|
|
22
|
+
## なぜこれが存在するのか
|
|
23
|
+
|
|
24
|
+
ファイルアップロードは、実際には複数の関心事に分散しがちです。
|
|
25
|
+
|
|
26
|
+
- ファイル入力の取得
|
|
27
|
+
- `FormData` の組み立て
|
|
28
|
+
- progress イベント
|
|
29
|
+
- loading フラグ
|
|
30
|
+
- エラー処理
|
|
31
|
+
- 切断時の abort
|
|
32
|
+
|
|
33
|
+
`@wcstack/upload` はそのロジックを再利用可能なコンポーネントへ移し、結果をバインド可能な状態として公開します。
|
|
34
|
+
|
|
35
|
+
## インストール
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install @wcstack/upload
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## クイックスタート
|
|
42
|
+
|
|
43
|
+
### 1. `files` を代入すると自動アップロード
|
|
44
|
+
|
|
45
|
+
```html
|
|
46
|
+
<script type="module" src="https://esm.run/@wcstack/upload/auto"></script>
|
|
47
|
+
|
|
48
|
+
<wcs-upload id="avatar-upload" url="/api/upload"></wcs-upload>
|
|
49
|
+
<input id="avatar-input" type="file" accept="image/*">
|
|
50
|
+
|
|
51
|
+
<script type="module">
|
|
52
|
+
const upload = document.getElementById("avatar-upload");
|
|
53
|
+
const input = document.getElementById("avatar-input");
|
|
54
|
+
|
|
55
|
+
input.addEventListener("change", () => {
|
|
56
|
+
upload.files = input.files;
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
upload.addEventListener("wcs-upload:progress", (event) => {
|
|
60
|
+
console.log("progress", event.detail);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
upload.addEventListener("wcs-upload:response", (event) => {
|
|
64
|
+
console.log("uploaded", event.detail.value);
|
|
65
|
+
});
|
|
66
|
+
</script>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
デフォルト動作は次のとおりです。
|
|
70
|
+
|
|
71
|
+
- `files` を代入すると即座にアップロード開始
|
|
72
|
+
- 送信形式は `multipart/form-data`
|
|
73
|
+
- リクエストメソッドのデフォルトは `POST`
|
|
74
|
+
- フィールド名のデフォルトは `file`
|
|
75
|
+
|
|
76
|
+
### 2. `trigger` による手動アップロード
|
|
77
|
+
|
|
78
|
+
先にファイルを選び、後からアップロードしたい場合は `manual` を使います。
|
|
79
|
+
|
|
80
|
+
```html
|
|
81
|
+
<script type="module" src="https://esm.run/@wcstack/upload/auto"></script>
|
|
82
|
+
|
|
83
|
+
<wcs-upload id="resume-upload" url="/api/upload" manual></wcs-upload>
|
|
84
|
+
|
|
85
|
+
<input id="resume-input" type="file">
|
|
86
|
+
<button id="resume-button">Upload</button>
|
|
87
|
+
|
|
88
|
+
<script type="module">
|
|
89
|
+
const upload = document.getElementById("resume-upload");
|
|
90
|
+
const input = document.getElementById("resume-input");
|
|
91
|
+
const button = document.getElementById("resume-button");
|
|
92
|
+
|
|
93
|
+
input.addEventListener("change", () => {
|
|
94
|
+
upload.files = input.files;
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
button.addEventListener("click", () => {
|
|
98
|
+
upload.trigger = true;
|
|
99
|
+
});
|
|
100
|
+
</script>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`trigger` は単方向のコマンドサーフェスです。
|
|
104
|
+
|
|
105
|
+
- `true` を書き込むと `upload()` を開始
|
|
106
|
+
- 完了後に自動で `false` へ戻る
|
|
107
|
+
- そのリセット時に `wcs-upload:trigger-changed` を発火
|
|
108
|
+
|
|
109
|
+
### 3. 宣言的なトリガーターゲット
|
|
110
|
+
|
|
111
|
+
自動トリガーが有効な場合、クリック可能な要素から id で `<wcs-upload>` を参照できます。
|
|
112
|
+
|
|
113
|
+
```html
|
|
114
|
+
<script type="module" src="https://esm.run/@wcstack/upload/auto"></script>
|
|
115
|
+
|
|
116
|
+
<wcs-upload id="photo-upload" url="/api/upload" manual></wcs-upload>
|
|
117
|
+
<input id="photo-input" type="file">
|
|
118
|
+
<button data-uploadtarget="photo-upload">Upload</button>
|
|
119
|
+
|
|
120
|
+
<script type="module">
|
|
121
|
+
const upload = document.getElementById("photo-upload");
|
|
122
|
+
const input = document.getElementById("photo-input");
|
|
123
|
+
|
|
124
|
+
input.addEventListener("change", () => {
|
|
125
|
+
upload.files = input.files;
|
|
126
|
+
});
|
|
127
|
+
</script>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
デフォルトのトリガー属性名は `data-uploadtarget` です。
|
|
131
|
+
|
|
132
|
+
### 4. `@wcstack/state` と組み合わせる
|
|
133
|
+
|
|
134
|
+
```html
|
|
135
|
+
<script type="module" src="https://esm.run/@wcstack/state/auto"></script>
|
|
136
|
+
<script type="module" src="https://esm.run/@wcstack/upload/auto"></script>
|
|
137
|
+
|
|
138
|
+
<wcs-state>
|
|
139
|
+
<script type="module">
|
|
140
|
+
export default {
|
|
141
|
+
uploadResult: null,
|
|
142
|
+
uploadLoading: false,
|
|
143
|
+
uploadProgress: 0,
|
|
144
|
+
uploadError: null,
|
|
145
|
+
};
|
|
146
|
+
</script>
|
|
147
|
+
|
|
148
|
+
<wcs-upload
|
|
149
|
+
id="state-upload"
|
|
150
|
+
url="/api/upload"
|
|
151
|
+
manual
|
|
152
|
+
data-wcs="
|
|
153
|
+
value: uploadResult;
|
|
154
|
+
loading: uploadLoading;
|
|
155
|
+
progress: uploadProgress;
|
|
156
|
+
error: uploadError
|
|
157
|
+
">
|
|
158
|
+
</wcs-upload>
|
|
159
|
+
|
|
160
|
+
<input id="state-upload-input" type="file">
|
|
161
|
+
<button data-uploadtarget="state-upload">Upload</button>
|
|
162
|
+
|
|
163
|
+
<progress max="100" data-wcs="value: uploadProgress"></progress>
|
|
164
|
+
<p data-wcs="textContent: uploadLoading"></p>
|
|
165
|
+
|
|
166
|
+
<script type="module">
|
|
167
|
+
const upload = document.getElementById("state-upload");
|
|
168
|
+
const input = document.getElementById("state-upload-input");
|
|
169
|
+
|
|
170
|
+
input.addEventListener("change", () => {
|
|
171
|
+
upload.files = input.files;
|
|
172
|
+
});
|
|
173
|
+
</script>
|
|
174
|
+
</wcs-state>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
この構成では、アップロードはバインド可能な非同期ノードになります。
|
|
178
|
+
|
|
179
|
+
- 要素がリクエストを実行
|
|
180
|
+
- 非同期状態が `value`, `loading`, `progress`, `error`, `status` として返る
|
|
181
|
+
- UI はそれらのパスへ宣言的にバインド
|
|
182
|
+
|
|
183
|
+
## 公開 API
|
|
184
|
+
|
|
185
|
+
### 要素属性とプロパティ
|
|
186
|
+
|
|
187
|
+
| 名前 | 型 | デフォルト | 説明 |
|
|
188
|
+
|---|---|---|---|
|
|
189
|
+
| `url` | `string` | `""` | アップロード先エンドポイント |
|
|
190
|
+
| `method` | `string` | `"POST"` | HTTP メソッド |
|
|
191
|
+
| `field-name` | `string` | `"file"` | FormData のフィールド名 |
|
|
192
|
+
| `multiple` | `boolean` | `false` | 複数ファイル対応を表すフラグ |
|
|
193
|
+
| `max-size` | `number` | `Infinity` | 許容最大ファイルサイズ(byte) |
|
|
194
|
+
| `accept` | `string` | `""` | 許可する MIME type または拡張子 |
|
|
195
|
+
| `manual` | `boolean` | `false` | `files` 代入時の自動アップロードを無効化 |
|
|
196
|
+
| `files` | `FileList \| File[] \| null` | `null` | アップロード対象ファイル |
|
|
197
|
+
| `trigger` | `boolean` | `false` | 手動アップロード用の書き込みコマンド面 |
|
|
198
|
+
| `value` | `any` | `null` | パース済みレスポンスまたはレスポンステキスト |
|
|
199
|
+
| `loading` | `boolean` | `false` | アップロード中フラグ |
|
|
200
|
+
| `progress` | `number` | `0` | `0` から `100` の進捗率 |
|
|
201
|
+
| `error` | `any` | `null` | バリデーション、ネットワーク、レスポンスのエラー |
|
|
202
|
+
| `status` | `number` | `0` | HTTP レスポンスステータス |
|
|
203
|
+
| `promise` | `Promise<any>` | resolved `null` | 現在のアップロード Promise |
|
|
204
|
+
|
|
205
|
+
### メソッド
|
|
206
|
+
|
|
207
|
+
#### `upload()`
|
|
208
|
+
|
|
209
|
+
現在の `files` を使ってアップロードを開始し、promise を返します。
|
|
210
|
+
ファイル未指定またはバリデーション失敗時は `null` を返します。
|
|
211
|
+
|
|
212
|
+
#### `abort()`
|
|
213
|
+
|
|
214
|
+
現在のリクエストを中断します。
|
|
215
|
+
|
|
216
|
+
## イベント
|
|
217
|
+
|
|
218
|
+
| イベント | `detail` | 説明 |
|
|
219
|
+
|---|---|---|
|
|
220
|
+
| `wcs-upload:files-changed` | `FileList \| File[] \| null` | `files` 変更時に発火 |
|
|
221
|
+
| `wcs-upload:trigger-changed` | `boolean` | `trigger` が `false` に戻るとき発火 |
|
|
222
|
+
| `wcs-upload:loading-changed` | `boolean` | loading 状態変更時に発火 |
|
|
223
|
+
| `wcs-upload:progress` | `number` | アップロード進捗更新時に発火 |
|
|
224
|
+
| `wcs-upload:error` | error object | バリデーション、ネットワーク、HTTP エラー時に発火 |
|
|
225
|
+
| `wcs-upload:response` | `{ value, status }` | HTTP 成功レスポンス時に発火 |
|
|
226
|
+
|
|
227
|
+
## バリデーション
|
|
228
|
+
|
|
229
|
+
`<wcs-upload>` は送信前にファイルを検証します。
|
|
230
|
+
|
|
231
|
+
- `max-size` は指定 byte 数を超えるファイルを拒否
|
|
232
|
+
- `accept` は `image/*` のような MIME 範囲、`application/pdf` のような厳密 MIME、`.pdf` のような拡張子をサポート
|
|
233
|
+
|
|
234
|
+
バリデーションに失敗すると `wcs-upload:error` を発火し、リクエストは開始されません。
|
|
235
|
+
|
|
236
|
+
## wc-bindable サーフェス
|
|
237
|
+
|
|
238
|
+
`<wcs-upload>` は次の bindable property を持つ `wcBindable` 定義を公開します。
|
|
239
|
+
|
|
240
|
+
- `value`
|
|
241
|
+
- `loading`
|
|
242
|
+
- `progress`
|
|
243
|
+
- `error`
|
|
244
|
+
- `status`
|
|
245
|
+
- `trigger`
|
|
246
|
+
- `files`
|
|
247
|
+
|
|
248
|
+
これにより、`@wcstack/state` を含む wc-bindable 対応システムから利用できます。
|
|
249
|
+
|
|
250
|
+
## Headless API
|
|
251
|
+
|
|
252
|
+
カスタム要素の shell が不要な場合は、`UploadCore` を直接使えます。
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
import { UploadCore } from "@wcstack/upload";
|
|
256
|
+
|
|
257
|
+
const core = new UploadCore();
|
|
258
|
+
const result = await core.upload("/api/upload", files, {
|
|
259
|
+
method: "PUT",
|
|
260
|
+
fieldName: "attachment",
|
|
261
|
+
headers: {
|
|
262
|
+
Authorization: "Bearer token",
|
|
263
|
+
},
|
|
264
|
+
});
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
`UploadCore` は同じ非同期状態をプロパティとして公開し、同じイベントを発火します。
|
|
268
|
+
|
|
269
|
+
## 手動 bootstrap
|
|
270
|
+
|
|
271
|
+
```ts
|
|
272
|
+
import { bootstrapUpload } from "@wcstack/upload";
|
|
273
|
+
|
|
274
|
+
bootstrapUpload({
|
|
275
|
+
autoTrigger: true,
|
|
276
|
+
triggerAttribute: "data-uploadtarget",
|
|
277
|
+
tagNames: {
|
|
278
|
+
upload: "wcs-upload",
|
|
279
|
+
},
|
|
280
|
+
});
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
`@wcstack/upload/auto` に頼らず、タグ名やトリガー属性名をカスタマイズしたい場合に使います。
|
package/README.md
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
# @wcstack/upload
|
|
2
|
+
|
|
3
|
+
`@wcstack/upload` is a declarative file upload component for the wcstack ecosystem.
|
|
4
|
+
|
|
5
|
+
It is not a visible UI widget.
|
|
6
|
+
It is a hidden **upload I/O node** that turns file upload into bindable state.
|
|
7
|
+
|
|
8
|
+
With `@wcstack/state`, `<wcs-upload>` exposes a small async state surface:
|
|
9
|
+
|
|
10
|
+
- input / command surface: `files`, `trigger`
|
|
11
|
+
- configuration surface: `url`, `method`, `field-name`, `accept`, `max-size`, `manual`, `multiple`
|
|
12
|
+
- output state surface: `value`, `loading`, `progress`, `error`, `status`
|
|
13
|
+
|
|
14
|
+
This means file upload can be expressed as state transitions and DOM bindings instead of ad-hoc `XMLHttpRequest` glue code.
|
|
15
|
+
|
|
16
|
+
`@wcstack/upload` follows the same HAWC-style split as other wcstack I/O packages:
|
|
17
|
+
|
|
18
|
+
- **Core** (`UploadCore`) handles XHR upload, progress tracking, abort, and async state
|
|
19
|
+
- **Shell** (`<wcs-upload>`) exposes that state as a custom element and `wc-bindable` surface
|
|
20
|
+
- frameworks and binding systems consume it through `wc-bindable-protocol`
|
|
21
|
+
|
|
22
|
+
## Why this exists
|
|
23
|
+
|
|
24
|
+
File upload usually spreads across too many places:
|
|
25
|
+
|
|
26
|
+
- file input handling
|
|
27
|
+
- `FormData` creation
|
|
28
|
+
- progress events
|
|
29
|
+
- loading flags
|
|
30
|
+
- error handling
|
|
31
|
+
- abort on disconnect
|
|
32
|
+
|
|
33
|
+
`@wcstack/upload` moves that logic into a reusable component and exposes the result as bindable state.
|
|
34
|
+
|
|
35
|
+
## Install
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install @wcstack/upload
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
### 1. Auto upload when files are assigned
|
|
44
|
+
|
|
45
|
+
```html
|
|
46
|
+
<script type="module" src="https://esm.run/@wcstack/upload/auto"></script>
|
|
47
|
+
|
|
48
|
+
<wcs-upload id="avatar-upload" url="/api/upload"></wcs-upload>
|
|
49
|
+
<input id="avatar-input" type="file" accept="image/*">
|
|
50
|
+
|
|
51
|
+
<script type="module">
|
|
52
|
+
const upload = document.getElementById("avatar-upload");
|
|
53
|
+
const input = document.getElementById("avatar-input");
|
|
54
|
+
|
|
55
|
+
input.addEventListener("change", () => {
|
|
56
|
+
upload.files = input.files;
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
upload.addEventListener("wcs-upload:progress", (event) => {
|
|
60
|
+
console.log("progress", event.detail);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
upload.addEventListener("wcs-upload:response", (event) => {
|
|
64
|
+
console.log("uploaded", event.detail.value);
|
|
65
|
+
});
|
|
66
|
+
</script>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Default behavior:
|
|
70
|
+
|
|
71
|
+
- assigning `files` starts upload immediately
|
|
72
|
+
- files are sent as `multipart/form-data`
|
|
73
|
+
- request method defaults to `POST`
|
|
74
|
+
- field name defaults to `file`
|
|
75
|
+
|
|
76
|
+
### 2. Manual upload with `trigger`
|
|
77
|
+
|
|
78
|
+
Use `manual` when you want to choose files first and upload later.
|
|
79
|
+
|
|
80
|
+
```html
|
|
81
|
+
<script type="module" src="https://esm.run/@wcstack/upload/auto"></script>
|
|
82
|
+
|
|
83
|
+
<wcs-upload id="resume-upload" url="/api/upload" manual></wcs-upload>
|
|
84
|
+
|
|
85
|
+
<input id="resume-input" type="file">
|
|
86
|
+
<button id="resume-button">Upload</button>
|
|
87
|
+
|
|
88
|
+
<script type="module">
|
|
89
|
+
const upload = document.getElementById("resume-upload");
|
|
90
|
+
const input = document.getElementById("resume-input");
|
|
91
|
+
const button = document.getElementById("resume-button");
|
|
92
|
+
|
|
93
|
+
input.addEventListener("change", () => {
|
|
94
|
+
upload.files = input.files;
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
button.addEventListener("click", () => {
|
|
98
|
+
upload.trigger = true;
|
|
99
|
+
});
|
|
100
|
+
</script>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`trigger` is a one-way command surface:
|
|
104
|
+
|
|
105
|
+
- writing `true` starts `upload()`
|
|
106
|
+
- after completion it resets itself to `false`
|
|
107
|
+
- that reset dispatches `wcs-upload:trigger-changed`
|
|
108
|
+
|
|
109
|
+
### 3. Declarative trigger target
|
|
110
|
+
|
|
111
|
+
When auto trigger is enabled, a clickable element can point at a `<wcs-upload>` by id.
|
|
112
|
+
|
|
113
|
+
```html
|
|
114
|
+
<script type="module" src="https://esm.run/@wcstack/upload/auto"></script>
|
|
115
|
+
|
|
116
|
+
<wcs-upload id="photo-upload" url="/api/upload" manual></wcs-upload>
|
|
117
|
+
<input id="photo-input" type="file">
|
|
118
|
+
<button data-uploadtarget="photo-upload">Upload</button>
|
|
119
|
+
|
|
120
|
+
<script type="module">
|
|
121
|
+
const upload = document.getElementById("photo-upload");
|
|
122
|
+
const input = document.getElementById("photo-input");
|
|
123
|
+
|
|
124
|
+
input.addEventListener("change", () => {
|
|
125
|
+
upload.files = input.files;
|
|
126
|
+
});
|
|
127
|
+
</script>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
By default, the trigger attribute is `data-uploadtarget`.
|
|
131
|
+
|
|
132
|
+
### 4. With `@wcstack/state`
|
|
133
|
+
|
|
134
|
+
```html
|
|
135
|
+
<script type="module" src="https://esm.run/@wcstack/state/auto"></script>
|
|
136
|
+
<script type="module" src="https://esm.run/@wcstack/upload/auto"></script>
|
|
137
|
+
|
|
138
|
+
<wcs-state>
|
|
139
|
+
<script type="module">
|
|
140
|
+
export default {
|
|
141
|
+
uploadResult: null,
|
|
142
|
+
uploadLoading: false,
|
|
143
|
+
uploadProgress: 0,
|
|
144
|
+
uploadError: null,
|
|
145
|
+
};
|
|
146
|
+
</script>
|
|
147
|
+
|
|
148
|
+
<wcs-upload
|
|
149
|
+
id="state-upload"
|
|
150
|
+
url="/api/upload"
|
|
151
|
+
manual
|
|
152
|
+
data-wcs="
|
|
153
|
+
value: uploadResult;
|
|
154
|
+
loading: uploadLoading;
|
|
155
|
+
progress: uploadProgress;
|
|
156
|
+
error: uploadError
|
|
157
|
+
">
|
|
158
|
+
</wcs-upload>
|
|
159
|
+
|
|
160
|
+
<input id="state-upload-input" type="file">
|
|
161
|
+
<button data-uploadtarget="state-upload">Upload</button>
|
|
162
|
+
|
|
163
|
+
<progress max="100" data-wcs="value: uploadProgress"></progress>
|
|
164
|
+
<p data-wcs="textContent: uploadLoading"></p>
|
|
165
|
+
|
|
166
|
+
<script type="module">
|
|
167
|
+
const upload = document.getElementById("state-upload");
|
|
168
|
+
const input = document.getElementById("state-upload-input");
|
|
169
|
+
|
|
170
|
+
input.addEventListener("change", () => {
|
|
171
|
+
upload.files = input.files;
|
|
172
|
+
});
|
|
173
|
+
</script>
|
|
174
|
+
</wcs-state>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
In this setup, upload becomes a bindable async node:
|
|
178
|
+
|
|
179
|
+
- the element performs the request
|
|
180
|
+
- async state flows back as `value`, `loading`, `progress`, `error`, `status`
|
|
181
|
+
- the UI binds to those paths declaratively
|
|
182
|
+
|
|
183
|
+
## Public API
|
|
184
|
+
|
|
185
|
+
### Element attributes and properties
|
|
186
|
+
|
|
187
|
+
| Name | Type | Default | Description |
|
|
188
|
+
|---|---|---|---|
|
|
189
|
+
| `url` | `string` | `""` | Upload endpoint |
|
|
190
|
+
| `method` | `string` | `"POST"` | HTTP method |
|
|
191
|
+
| `field-name` | `string` | `"file"` | FormData field name |
|
|
192
|
+
| `multiple` | `boolean` | `false` | Marks the element as multi-file capable |
|
|
193
|
+
| `max-size` | `number` | `Infinity` | Maximum allowed file size in bytes |
|
|
194
|
+
| `accept` | `string` | `""` | Accepted MIME types or file extensions |
|
|
195
|
+
| `manual` | `boolean` | `false` | Disables auto upload on `files` assignment |
|
|
196
|
+
| `files` | `FileList \| File[] \| null` | `null` | Files to upload |
|
|
197
|
+
| `trigger` | `boolean` | `false` | Write-only command surface for manual upload |
|
|
198
|
+
| `value` | `any` | `null` | Parsed response body or response text |
|
|
199
|
+
| `loading` | `boolean` | `false` | Upload state flag |
|
|
200
|
+
| `progress` | `number` | `0` | Upload progress from `0` to `100` |
|
|
201
|
+
| `error` | `any` | `null` | Validation, network, or response error |
|
|
202
|
+
| `status` | `number` | `0` | HTTP response status |
|
|
203
|
+
| `promise` | `Promise<any>` | resolved `null` | Current upload promise |
|
|
204
|
+
|
|
205
|
+
### Methods
|
|
206
|
+
|
|
207
|
+
#### `upload()`
|
|
208
|
+
|
|
209
|
+
Starts upload with the current `files` and returns a promise.
|
|
210
|
+
Returns `null` when there are no files or validation fails.
|
|
211
|
+
|
|
212
|
+
#### `abort()`
|
|
213
|
+
|
|
214
|
+
Aborts the current request.
|
|
215
|
+
|
|
216
|
+
## Events
|
|
217
|
+
|
|
218
|
+
| Event | `detail` | Description |
|
|
219
|
+
|---|---|---|
|
|
220
|
+
| `wcs-upload:files-changed` | `FileList \| File[] \| null` | Fired when `files` changes |
|
|
221
|
+
| `wcs-upload:trigger-changed` | `boolean` | Fired when `trigger` resets to `false` |
|
|
222
|
+
| `wcs-upload:loading-changed` | `boolean` | Fired when loading state changes |
|
|
223
|
+
| `wcs-upload:progress` | `number` | Fired on upload progress updates |
|
|
224
|
+
| `wcs-upload:error` | error object | Fired on validation, network, or HTTP error |
|
|
225
|
+
| `wcs-upload:response` | `{ value, status }` | Fired on successful HTTP response |
|
|
226
|
+
|
|
227
|
+
## Validation
|
|
228
|
+
|
|
229
|
+
`<wcs-upload>` validates files before sending:
|
|
230
|
+
|
|
231
|
+
- `max-size` rejects files larger than the configured byte size
|
|
232
|
+
- `accept` supports MIME types like `image/*`, exact MIME types like `application/pdf`, and extensions like `.pdf`
|
|
233
|
+
|
|
234
|
+
Validation failure dispatches `wcs-upload:error` and the request is not started.
|
|
235
|
+
|
|
236
|
+
## wc-bindable surface
|
|
237
|
+
|
|
238
|
+
`<wcs-upload>` exposes a `wcBindable` definition with these bindable properties:
|
|
239
|
+
|
|
240
|
+
- `value`
|
|
241
|
+
- `loading`
|
|
242
|
+
- `progress`
|
|
243
|
+
- `error`
|
|
244
|
+
- `status`
|
|
245
|
+
- `trigger`
|
|
246
|
+
- `files`
|
|
247
|
+
|
|
248
|
+
This makes the element consumable from wc-bindable-aware systems, including `@wcstack/state`.
|
|
249
|
+
|
|
250
|
+
## Headless API
|
|
251
|
+
|
|
252
|
+
If you do not need the custom element shell, you can use `UploadCore` directly:
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
import { UploadCore } from "@wcstack/upload";
|
|
256
|
+
|
|
257
|
+
const core = new UploadCore();
|
|
258
|
+
const result = await core.upload("/api/upload", files, {
|
|
259
|
+
method: "PUT",
|
|
260
|
+
fieldName: "attachment",
|
|
261
|
+
headers: {
|
|
262
|
+
Authorization: "Bearer token",
|
|
263
|
+
},
|
|
264
|
+
});
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
`UploadCore` exposes the same async state as properties and dispatches the same events.
|
|
268
|
+
|
|
269
|
+
## Manual bootstrap
|
|
270
|
+
|
|
271
|
+
```ts
|
|
272
|
+
import { bootstrapUpload } from "@wcstack/upload";
|
|
273
|
+
|
|
274
|
+
bootstrapUpload({
|
|
275
|
+
autoTrigger: true,
|
|
276
|
+
triggerAttribute: "data-uploadtarget",
|
|
277
|
+
tagNames: {
|
|
278
|
+
upload: "wcs-upload",
|
|
279
|
+
},
|
|
280
|
+
});
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Use this when you want to customize the tag name or trigger attribute instead of relying on `@wcstack/upload/auto`.
|
package/dist/auto.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { bootstrapUpload } from "./index.esm.js";
|
|
2
|
-
|
|
3
|
-
bootstrapUpload();
|
|
1
|
+
import { bootstrapUpload } from "./index.esm.js";
|
|
2
|
+
|
|
3
|
+
bootstrapUpload();
|
package/dist/auto.min.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { bootstrapUpload } from "./index.esm.min.js";
|
|
2
|
-
|
|
3
|
-
bootstrapUpload();
|
|
1
|
+
import { bootstrapUpload } from "./index.esm.min.js";
|
|
2
|
+
|
|
3
|
+
bootstrapUpload();
|
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\";\r\n\r\ninterface IInternalConfig extends IConfig {\r\n autoTrigger: boolean;\r\n triggerAttribute: string;\r\n tagNames: {\r\n upload: string;\r\n };\r\n}\r\n\r\nconst _config: IInternalConfig = {\r\n autoTrigger: true,\r\n triggerAttribute: \"data-uploadtarget\",\r\n tagNames: {\r\n upload: \"wcs-upload\",\r\n },\r\n};\r\n\r\nfunction deepFreeze<T>(obj: T): T {\r\n if (obj === null || typeof obj !== \"object\") return obj;\r\n Object.freeze(obj);\r\n for (const key of Object.keys(obj)) {\r\n deepFreeze((obj as Record<string, unknown>)[key]);\r\n }\r\n return obj;\r\n}\r\n\r\nfunction deepClone<T>(obj: T): T {\r\n if (obj === null || typeof obj !== \"object\") return obj;\r\n const clone: Record<string, unknown> = {};\r\n for (const key of Object.keys(obj)) {\r\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\r\n }\r\n return clone as T;\r\n}\r\n\r\nlet frozenConfig: IConfig | null = null;\r\n\r\nexport const config: IConfig = _config as IConfig;\r\n\r\nexport function getConfig(): IConfig {\r\n if (!frozenConfig) {\r\n frozenConfig = deepFreeze(deepClone(_config));\r\n }\r\n return frozenConfig;\r\n}\r\n\r\nexport function setConfig(partialConfig: IWritableConfig): void {\r\n if (typeof partialConfig.autoTrigger === \"boolean\") {\r\n _config.autoTrigger = partialConfig.autoTrigger;\r\n }\r\n if (typeof partialConfig.triggerAttribute === \"string\") {\r\n _config.triggerAttribute = partialConfig.triggerAttribute;\r\n }\r\n if (partialConfig.tagNames) {\r\n Object.assign(_config.tagNames, partialConfig.tagNames);\r\n }\r\n frozenConfig = null;\r\n}\r\n","export function raiseError(message: string): never {\r\n throw new Error(`[@wcstack/upload] ${message}`);\r\n}\r\n","import { raiseError } from \"../raiseError.js\";\r\nimport { IWcBindable } from \"../types.js\";\r\n\r\nexport interface UploadRequestOptions {\r\n method?: string;\r\n headers?: Record<string, string>;\r\n fieldName?: string;\r\n}\r\n\r\nexport class UploadCore extends EventTarget {\r\n static wcBindable: IWcBindable = {\r\n protocol: \"wc-bindable\",\r\n version: 1,\r\n properties: [\r\n { name: \"value\", event: \"wcs-upload:response\", getter: (e: Event) => (e as CustomEvent).detail.value },\r\n { name: \"loading\", event: \"wcs-upload:loading-changed\" },\r\n { name: \"progress\", event: \"wcs-upload:progress\" },\r\n { name: \"error\", event: \"wcs-upload:error\" },\r\n { name: \"status\", event: \"wcs-upload:response\", getter: (e: Event) => (e as CustomEvent).detail.status },\r\n ],\r\n };\r\n\r\n private _target: EventTarget;\r\n private _value: any = null;\r\n private _loading: boolean = false;\r\n private _progress: number = 0;\r\n private _error: any = null;\r\n private _status: number = 0;\r\n private _xhr: XMLHttpRequest | null = null;\r\n private _promise: Promise<any> = Promise.resolve(null);\r\n\r\n constructor(target?: EventTarget) {\r\n super();\r\n this._target = target ?? this;\r\n }\r\n\r\n get value(): any {\r\n return this._value;\r\n }\r\n\r\n get loading(): boolean {\r\n return this._loading;\r\n }\r\n\r\n get progress(): number {\r\n return this._progress;\r\n }\r\n\r\n get error(): any {\r\n return this._error;\r\n }\r\n\r\n get status(): number {\r\n return this._status;\r\n }\r\n\r\n get promise(): Promise<any> {\r\n return this._promise;\r\n }\r\n\r\n // --- State setters with event dispatch ---\r\n\r\n private _setLoading(loading: boolean): void {\r\n this._loading = loading;\r\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:loading-changed\", {\r\n detail: loading,\r\n bubbles: true,\r\n }));\r\n }\r\n\r\n private _setProgress(progress: number): void {\r\n this._progress = progress;\r\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:progress\", {\r\n detail: progress,\r\n bubbles: true,\r\n }));\r\n }\r\n\r\n private _setError(error: any): void {\r\n this._error = error;\r\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\r\n detail: error,\r\n bubbles: true,\r\n }));\r\n }\r\n\r\n private _setResponse(value: any, status: number): void {\r\n this._value = value;\r\n this._status = status;\r\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:response\", {\r\n detail: { value, status },\r\n bubbles: true,\r\n }));\r\n }\r\n\r\n // --- Public API ---\r\n\r\n abort(): void {\r\n if (this._xhr) {\r\n this._xhr.abort();\r\n this._xhr = null;\r\n }\r\n }\r\n\r\n upload(url: string, files: FileList | File[], options: UploadRequestOptions = {}): Promise<any> {\r\n if (!url) {\r\n raiseError(\"url is required.\");\r\n }\r\n if (!files || files.length === 0) {\r\n raiseError(\"files are required.\");\r\n }\r\n\r\n const p = this._doUpload(url, files, options);\r\n this._promise = p;\r\n return p;\r\n }\r\n\r\n // --- Internal ---\r\n\r\n private _doUpload(url: string, files: FileList | File[], options: UploadRequestOptions): Promise<any> {\r\n // 既存のアップロードを中止\r\n this.abort();\r\n\r\n this._setLoading(true);\r\n this._setProgress(0);\r\n this._setError(null);\r\n\r\n const {\r\n method = \"POST\",\r\n headers = {},\r\n fieldName = \"file\",\r\n } = options;\r\n\r\n const formData = new FormData();\r\n for (let i = 0; i < files.length; i++) {\r\n formData.append(fieldName, files[i]);\r\n }\r\n\r\n return new Promise<any>((resolve) => {\r\n const xhr = new XMLHttpRequest();\r\n this._xhr = xhr;\r\n\r\n xhr.upload.addEventListener(\"progress\", (event: ProgressEvent) => {\r\n if (event.lengthComputable) {\r\n const percent = Math.round((event.loaded / event.total) * 100);\r\n this._setProgress(percent);\r\n }\r\n });\r\n\r\n xhr.addEventListener(\"load\", () => {\r\n this._xhr = null;\r\n this._status = xhr.status;\r\n\r\n if (xhr.status >= 200 && xhr.status < 300) {\r\n let value: any = xhr.responseText;\r\n const contentType = xhr.getResponseHeader(\"Content-Type\") || \"\";\r\n if (contentType.includes(\"application/json\")) {\r\n try {\r\n value = JSON.parse(xhr.responseText);\r\n } catch {\r\n // テキストのまま\r\n }\r\n }\r\n this._setProgress(100);\r\n this._setResponse(value, xhr.status);\r\n this._setLoading(false);\r\n resolve(value);\r\n } else {\r\n const error = {\r\n status: xhr.status,\r\n statusText: xhr.statusText,\r\n body: xhr.responseText,\r\n };\r\n this._setError(error);\r\n this._setLoading(false);\r\n resolve(null);\r\n }\r\n });\r\n\r\n xhr.addEventListener(\"error\", () => {\r\n this._xhr = null;\r\n this._setError({ message: \"Network error\" });\r\n this._setLoading(false);\r\n resolve(null);\r\n });\r\n\r\n xhr.addEventListener(\"abort\", () => {\r\n this._xhr = null;\r\n this._setLoading(false);\r\n resolve(null);\r\n });\r\n\r\n xhr.open(method, url);\r\n\r\n for (const [name, value] of Object.entries(headers)) {\r\n xhr.setRequestHeader(name, value);\r\n }\r\n\r\n xhr.send(formData);\r\n });\r\n }\r\n}\r\n","import { config } from \"./config.js\";\r\nimport { WcsUpload } from \"./components/Upload.js\";\r\n\r\nlet registered = false;\r\n\r\nfunction handleClick(event: Event): void {\r\n const target = event.target;\r\n if (!(target instanceof Element)) return;\r\n\r\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\r\n if (!triggerElement) return;\r\n\r\n const uploadId = triggerElement.getAttribute(config.triggerAttribute);\r\n if (!uploadId) return;\r\n\r\n const uploadElement = document.getElementById(uploadId) as WcsUpload | null;\r\n if (!uploadElement || !(uploadElement instanceof WcsUpload)) return;\r\n\r\n // ファイルと URL が揃っている場合のみ既定動作を抑止\r\n if (uploadElement.files && uploadElement.files.length > 0 && uploadElement.url) {\r\n event.preventDefault();\r\n }\r\n uploadElement.upload();\r\n}\r\n\r\nexport function registerAutoTrigger(): void {\r\n if (registered) return;\r\n registered = true;\r\n document.addEventListener(\"click\", handleClick);\r\n}\r\n\r\nexport function unregisterAutoTrigger(): void {\r\n if (!registered) return;\r\n registered = false;\r\n document.removeEventListener(\"click\", handleClick);\r\n}\r\n","import { config } from \"../config.js\";\r\nimport { IWcBindable, WcsUploadError } from \"../types.js\";\r\nimport { UploadCore } from \"../core/UploadCore.js\";\r\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\r\n\r\nexport class WcsUpload extends HTMLElement {\r\n static hasConnectedCallbackPromise = false;\r\n static wcBindable: IWcBindable = {\r\n ...UploadCore.wcBindable,\r\n properties: [\r\n ...UploadCore.wcBindable.properties,\r\n { name: \"trigger\", event: \"wcs-upload:trigger-changed\" },\r\n { name: \"files\", event: \"wcs-upload:files-changed\" },\r\n ],\r\n };\r\n static get observedAttributes(): string[] { return [\"url\"]; }\r\n\r\n private _core: UploadCore;\r\n private _files: FileList | File[] | null = null;\r\n private _trigger: boolean = false;\r\n\r\n constructor() {\r\n super();\r\n this._core = new UploadCore(this);\r\n }\r\n\r\n // --- Attribute accessors ---\r\n\r\n get url(): string {\r\n return this.getAttribute(\"url\") || \"\";\r\n }\r\n\r\n set url(value: string) {\r\n this.setAttribute(\"url\", value);\r\n }\r\n\r\n get method(): string {\r\n return (this.getAttribute(\"method\") || \"POST\").toUpperCase();\r\n }\r\n\r\n set method(value: string) {\r\n this.setAttribute(\"method\", value);\r\n }\r\n\r\n get fieldName(): string {\r\n return this.getAttribute(\"field-name\") || \"file\";\r\n }\r\n\r\n set fieldName(value: string) {\r\n this.setAttribute(\"field-name\", value);\r\n }\r\n\r\n get multiple(): boolean {\r\n return this.hasAttribute(\"multiple\");\r\n }\r\n\r\n set multiple(value: boolean) {\r\n if (value) {\r\n this.setAttribute(\"multiple\", \"\");\r\n } else {\r\n this.removeAttribute(\"multiple\");\r\n }\r\n }\r\n\r\n get maxSize(): number {\r\n const attr = this.getAttribute(\"max-size\");\r\n return attr ? parseInt(attr, 10) : Infinity;\r\n }\r\n\r\n set maxSize(value: number) {\r\n this.setAttribute(\"max-size\", String(value));\r\n }\r\n\r\n get accept(): string {\r\n return this.getAttribute(\"accept\") || \"\";\r\n }\r\n\r\n set accept(value: string) {\r\n this.setAttribute(\"accept\", value);\r\n }\r\n\r\n get manual(): boolean {\r\n return this.hasAttribute(\"manual\");\r\n }\r\n\r\n set manual(value: boolean) {\r\n if (value) {\r\n this.setAttribute(\"manual\", \"\");\r\n } else {\r\n this.removeAttribute(\"manual\");\r\n }\r\n }\r\n\r\n // --- Core delegated getters ---\r\n\r\n get value(): any {\r\n return this._core.value;\r\n }\r\n\r\n get loading(): boolean {\r\n return this._core.loading;\r\n }\r\n\r\n get progress(): number {\r\n return this._core.progress;\r\n }\r\n\r\n get error(): any {\r\n return this._core.error;\r\n }\r\n\r\n get status(): number {\r\n return this._core.status;\r\n }\r\n\r\n get promise(): Promise<any> {\r\n return this._core.promise;\r\n }\r\n\r\n // --- Command properties ---\r\n\r\n get trigger(): boolean {\r\n return this._trigger;\r\n }\r\n\r\n set trigger(value: boolean) {\r\n const v = !!value;\r\n if (v) {\r\n this._trigger = true;\r\n this.upload().finally(() => {\r\n this._trigger = false;\r\n this.dispatchEvent(new CustomEvent(\"wcs-upload:trigger-changed\", {\r\n detail: false,\r\n bubbles: true,\r\n }));\r\n });\r\n }\r\n }\r\n\r\n get files(): FileList | File[] | null {\r\n return this._files;\r\n }\r\n\r\n set files(value: FileList | File[] | null) {\r\n this._files = value;\r\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\r\n detail: value,\r\n bubbles: true,\r\n }));\r\n if (!this.manual && this.url && value && value.length > 0) {\r\n this.upload();\r\n }\r\n }\r\n\r\n // --- Validation ---\r\n\r\n private _validate(files: FileList | File[]): WcsUploadError | null {\r\n const maxSize = this.maxSize;\r\n if (maxSize !== Infinity) {\r\n for (let i = 0; i < files.length; i++) {\r\n if (files[i].size > maxSize) {\r\n return { message: `File \"${files[i].name}\" exceeds maximum size of ${maxSize} bytes.` };\r\n }\r\n }\r\n }\r\n\r\n const accept = this.accept;\r\n if (accept) {\r\n const acceptList = accept.split(\",\").map(s => s.trim().toLowerCase());\r\n for (let i = 0; i < files.length; i++) {\r\n const file = files[i];\r\n const fileType = file.type.toLowerCase();\r\n const fileName = file.name.toLowerCase();\r\n const matched = acceptList.some(pattern => {\r\n if (pattern.startsWith(\".\")) {\r\n return fileName.endsWith(pattern);\r\n }\r\n if (pattern.endsWith(\"/*\")) {\r\n return fileType.startsWith(pattern.slice(0, -1));\r\n }\r\n return fileType === pattern;\r\n });\r\n if (!matched) {\r\n return { message: `File \"${file.name}\" does not match accepted types: ${accept}` };\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n // --- Public methods ---\r\n\r\n abort(): void {\r\n this._core.abort();\r\n }\r\n\r\n async upload(): Promise<any> {\r\n const files = this._files;\r\n if (!files || files.length === 0) {\r\n return null;\r\n }\r\n\r\n const validationError = this._validate(files);\r\n if (validationError) {\r\n this.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\r\n detail: validationError,\r\n bubbles: true,\r\n }));\r\n return null;\r\n }\r\n\r\n const result = await this._core.upload(this.url, files, {\r\n method: this.method,\r\n fieldName: this.fieldName,\r\n });\r\n\r\n // 自分が開始したアップロードのファイルだけをリセット\r\n // (途中で新しい files がセットされていたら触らない)\r\n if (this._files === files) {\r\n this._files = null;\r\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\r\n detail: null,\r\n bubbles: true,\r\n }));\r\n }\r\n\r\n return result;\r\n }\r\n\r\n // --- Lifecycle ---\r\n\r\n attributeChangedCallback(_name: string, _oldValue: string | null, _newValue: string | null): void {\r\n // URL変更ではアップロードを自動実行しない(ファイルが必要なため)\r\n }\r\n\r\n connectedCallback(): void {\r\n this.style.display = \"none\";\r\n if (config.autoTrigger) {\r\n registerAutoTrigger();\r\n }\r\n }\r\n\r\n disconnectedCallback(): void {\r\n this._core.abort();\r\n }\r\n}\r\n","import { WcsUpload } from \"./components/Upload.js\";\r\nimport { config } from \"./config.js\";\r\n\r\nexport function registerComponents(): void {\r\n if (!customElements.get(config.tagNames.upload)) {\r\n customElements.define(config.tagNames.upload, WcsUpload);\r\n }\r\n}\r\n","import { setConfig } from \"./config.js\";\r\nimport { registerComponents } from \"./registerComponents.js\";\r\nimport { IWritableConfig } from \"./types.js\";\r\n\r\nexport function bootstrapUpload(userConfig?: IWritableConfig): void {\r\n if (userConfig) {\r\n setConfig(userConfig);\r\n }\r\n registerComponents();\r\n}\r\n"],"names":[],"mappings":"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"}
|
|
@@ -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":"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"}
|
|
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\";\r\n\r\ninterface IInternalConfig extends IConfig {\r\n autoTrigger: boolean;\r\n triggerAttribute: string;\r\n tagNames: {\r\n upload: string;\r\n };\r\n}\r\n\r\nconst _config: IInternalConfig = {\r\n autoTrigger: true,\r\n triggerAttribute: \"data-uploadtarget\",\r\n tagNames: {\r\n upload: \"wcs-upload\",\r\n },\r\n};\r\n\r\nfunction deepFreeze<T>(obj: T): T {\r\n if (obj === null || typeof obj !== \"object\") return obj;\r\n Object.freeze(obj);\r\n for (const key of Object.keys(obj)) {\r\n deepFreeze((obj as Record<string, unknown>)[key]);\r\n }\r\n return obj;\r\n}\r\n\r\nfunction deepClone<T>(obj: T): T {\r\n if (obj === null || typeof obj !== \"object\") return obj;\r\n const clone: Record<string, unknown> = {};\r\n for (const key of Object.keys(obj)) {\r\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\r\n }\r\n return clone as T;\r\n}\r\n\r\nlet frozenConfig: IConfig | null = null;\r\n\r\nexport const config: IConfig = _config as IConfig;\r\n\r\nexport function getConfig(): IConfig {\r\n if (!frozenConfig) {\r\n frozenConfig = deepFreeze(deepClone(_config));\r\n }\r\n return frozenConfig;\r\n}\r\n\r\nexport function setConfig(partialConfig: IWritableConfig): void {\r\n if (typeof partialConfig.autoTrigger === \"boolean\") {\r\n _config.autoTrigger = partialConfig.autoTrigger;\r\n }\r\n if (typeof partialConfig.triggerAttribute === \"string\") {\r\n _config.triggerAttribute = partialConfig.triggerAttribute;\r\n }\r\n if (partialConfig.tagNames) {\r\n Object.assign(_config.tagNames, partialConfig.tagNames);\r\n }\r\n frozenConfig = null;\r\n}\r\n","export function raiseError(message: string): never {\r\n throw new Error(`[@wcstack/upload] ${message}`);\r\n}\r\n","import { raiseError } from \"../raiseError.js\";\r\nimport { IWcBindable } from \"../types.js\";\r\n\r\nexport interface UploadRequestOptions {\r\n method?: string;\r\n headers?: Record<string, string>;\r\n fieldName?: string;\r\n}\r\n\r\nexport class UploadCore extends EventTarget {\r\n static wcBindable: IWcBindable = {\r\n protocol: \"wc-bindable\",\r\n version: 1,\r\n properties: [\r\n { name: \"value\", event: \"wcs-upload:response\", getter: (e: Event) => (e as CustomEvent).detail.value },\r\n { name: \"loading\", event: \"wcs-upload:loading-changed\" },\r\n { name: \"progress\", event: \"wcs-upload:progress\" },\r\n { name: \"error\", event: \"wcs-upload:error\" },\r\n { name: \"status\", event: \"wcs-upload:response\", getter: (e: Event) => (e as CustomEvent).detail.status },\r\n ],\r\n };\r\n\r\n private _target: EventTarget;\r\n private _value: any = null;\r\n private _loading: boolean = false;\r\n private _progress: number = 0;\r\n private _error: any = null;\r\n private _status: number = 0;\r\n private _xhr: XMLHttpRequest | null = null;\r\n private _promise: Promise<any> = Promise.resolve(null);\r\n\r\n constructor(target?: EventTarget) {\r\n super();\r\n this._target = target ?? this;\r\n }\r\n\r\n get value(): any {\r\n return this._value;\r\n }\r\n\r\n get loading(): boolean {\r\n return this._loading;\r\n }\r\n\r\n get progress(): number {\r\n return this._progress;\r\n }\r\n\r\n get error(): any {\r\n return this._error;\r\n }\r\n\r\n get status(): number {\r\n return this._status;\r\n }\r\n\r\n get promise(): Promise<any> {\r\n return this._promise;\r\n }\r\n\r\n // --- State setters with event dispatch ---\r\n\r\n private _setLoading(loading: boolean): void {\r\n this._loading = loading;\r\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:loading-changed\", {\r\n detail: loading,\r\n bubbles: true,\r\n }));\r\n }\r\n\r\n private _setProgress(progress: number): void {\r\n this._progress = progress;\r\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:progress\", {\r\n detail: progress,\r\n bubbles: true,\r\n }));\r\n }\r\n\r\n private _setError(error: any): void {\r\n this._error = error;\r\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\r\n detail: error,\r\n bubbles: true,\r\n }));\r\n }\r\n\r\n private _setResponse(value: any, status: number): void {\r\n this._value = value;\r\n this._status = status;\r\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:response\", {\r\n detail: { value, status },\r\n bubbles: true,\r\n }));\r\n }\r\n\r\n // --- Public API ---\r\n\r\n abort(): void {\r\n if (this._xhr) {\r\n this._xhr.abort();\r\n this._xhr = null;\r\n }\r\n }\r\n\r\n upload(url: string, files: FileList | File[], options: UploadRequestOptions = {}): Promise<any> {\r\n if (!url) {\r\n raiseError(\"url is required.\");\r\n }\r\n if (!files || files.length === 0) {\r\n raiseError(\"files are required.\");\r\n }\r\n\r\n const p = this._doUpload(url, files, options);\r\n this._promise = p;\r\n return p;\r\n }\r\n\r\n // --- Internal ---\r\n\r\n private _doUpload(url: string, files: FileList | File[], options: UploadRequestOptions): Promise<any> {\r\n // 既存のアップロードを中止\r\n this.abort();\r\n\r\n this._setLoading(true);\r\n this._setProgress(0);\r\n this._setError(null);\r\n\r\n const {\r\n method = \"POST\",\r\n headers = {},\r\n fieldName = \"file\",\r\n } = options;\r\n\r\n const formData = new FormData();\r\n for (let i = 0; i < files.length; i++) {\r\n formData.append(fieldName, files[i]);\r\n }\r\n\r\n return new Promise<any>((resolve) => {\r\n const xhr = new XMLHttpRequest();\r\n this._xhr = xhr;\r\n\r\n xhr.upload.addEventListener(\"progress\", (event: ProgressEvent) => {\r\n if (event.lengthComputable) {\r\n const percent = Math.round((event.loaded / event.total) * 100);\r\n this._setProgress(percent);\r\n }\r\n });\r\n\r\n xhr.addEventListener(\"load\", () => {\r\n this._xhr = null;\r\n this._status = xhr.status;\r\n\r\n if (xhr.status >= 200 && xhr.status < 300) {\r\n let value: any = xhr.responseText;\r\n const contentType = xhr.getResponseHeader(\"Content-Type\") || \"\";\r\n if (contentType.includes(\"application/json\")) {\r\n try {\r\n value = JSON.parse(xhr.responseText);\r\n } catch {\r\n // テキストのまま\r\n }\r\n }\r\n this._setProgress(100);\r\n this._setResponse(value, xhr.status);\r\n this._setLoading(false);\r\n resolve(value);\r\n } else {\r\n const error = {\r\n status: xhr.status,\r\n statusText: xhr.statusText,\r\n body: xhr.responseText,\r\n };\r\n this._setError(error);\r\n this._setLoading(false);\r\n resolve(null);\r\n }\r\n });\r\n\r\n xhr.addEventListener(\"error\", () => {\r\n this._xhr = null;\r\n this._setError({ message: \"Network error\" });\r\n this._setLoading(false);\r\n resolve(null);\r\n });\r\n\r\n xhr.addEventListener(\"abort\", () => {\r\n this._xhr = null;\r\n this._setLoading(false);\r\n resolve(null);\r\n });\r\n\r\n xhr.open(method, url);\r\n\r\n for (const [name, value] of Object.entries(headers)) {\r\n xhr.setRequestHeader(name, value);\r\n }\r\n\r\n xhr.send(formData);\r\n });\r\n }\r\n}\r\n","import { config } from \"./config.js\";\r\nimport { WcsUpload } from \"./components/Upload.js\";\r\n\r\nlet registered = false;\r\n\r\nfunction handleClick(event: Event): void {\r\n const target = event.target;\r\n if (!(target instanceof Element)) return;\r\n\r\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\r\n if (!triggerElement) return;\r\n\r\n const uploadId = triggerElement.getAttribute(config.triggerAttribute);\r\n if (!uploadId) return;\r\n\r\n const uploadElement = document.getElementById(uploadId) as WcsUpload | null;\r\n if (!uploadElement || !(uploadElement instanceof WcsUpload)) return;\r\n\r\n // ファイルと URL が揃っている場合のみ既定動作を抑止\r\n if (uploadElement.files && uploadElement.files.length > 0 && uploadElement.url) {\r\n event.preventDefault();\r\n }\r\n uploadElement.upload();\r\n}\r\n\r\nexport function registerAutoTrigger(): void {\r\n if (registered) return;\r\n registered = true;\r\n document.addEventListener(\"click\", handleClick);\r\n}\r\n\r\nexport function unregisterAutoTrigger(): void {\r\n if (!registered) return;\r\n registered = false;\r\n document.removeEventListener(\"click\", handleClick);\r\n}\r\n","import { config } from \"../config.js\";\r\nimport { IWcBindable, WcsUploadError } from \"../types.js\";\r\nimport { UploadCore } from \"../core/UploadCore.js\";\r\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\r\n\r\nexport class WcsUpload extends HTMLElement {\r\n static hasConnectedCallbackPromise = false;\r\n static wcBindable: IWcBindable = {\r\n ...UploadCore.wcBindable,\r\n properties: [\r\n ...UploadCore.wcBindable.properties,\r\n { name: \"trigger\", event: \"wcs-upload:trigger-changed\" },\r\n { name: \"files\", event: \"wcs-upload:files-changed\" },\r\n ],\r\n };\r\n static get observedAttributes(): string[] { return [\"url\"]; }\r\n\r\n private _core: UploadCore;\r\n private _files: FileList | File[] | null = null;\r\n private _trigger: boolean = false;\r\n\r\n constructor() {\r\n super();\r\n this._core = new UploadCore(this);\r\n }\r\n\r\n // --- Attribute accessors ---\r\n\r\n get url(): string {\r\n return this.getAttribute(\"url\") || \"\";\r\n }\r\n\r\n set url(value: string) {\r\n this.setAttribute(\"url\", value);\r\n }\r\n\r\n get method(): string {\r\n return (this.getAttribute(\"method\") || \"POST\").toUpperCase();\r\n }\r\n\r\n set method(value: string) {\r\n this.setAttribute(\"method\", value);\r\n }\r\n\r\n get fieldName(): string {\r\n return this.getAttribute(\"field-name\") || \"file\";\r\n }\r\n\r\n set fieldName(value: string) {\r\n this.setAttribute(\"field-name\", value);\r\n }\r\n\r\n get multiple(): boolean {\r\n return this.hasAttribute(\"multiple\");\r\n }\r\n\r\n set multiple(value: boolean) {\r\n if (value) {\r\n this.setAttribute(\"multiple\", \"\");\r\n } else {\r\n this.removeAttribute(\"multiple\");\r\n }\r\n }\r\n\r\n get maxSize(): number {\r\n const attr = this.getAttribute(\"max-size\");\r\n return attr ? parseInt(attr, 10) : Infinity;\r\n }\r\n\r\n set maxSize(value: number) {\r\n this.setAttribute(\"max-size\", String(value));\r\n }\r\n\r\n get accept(): string {\r\n return this.getAttribute(\"accept\") || \"\";\r\n }\r\n\r\n set accept(value: string) {\r\n this.setAttribute(\"accept\", value);\r\n }\r\n\r\n get manual(): boolean {\r\n return this.hasAttribute(\"manual\");\r\n }\r\n\r\n set manual(value: boolean) {\r\n if (value) {\r\n this.setAttribute(\"manual\", \"\");\r\n } else {\r\n this.removeAttribute(\"manual\");\r\n }\r\n }\r\n\r\n // --- Core delegated getters ---\r\n\r\n get value(): any {\r\n return this._core.value;\r\n }\r\n\r\n get loading(): boolean {\r\n return this._core.loading;\r\n }\r\n\r\n get progress(): number {\r\n return this._core.progress;\r\n }\r\n\r\n get error(): any {\r\n return this._core.error;\r\n }\r\n\r\n get status(): number {\r\n return this._core.status;\r\n }\r\n\r\n get promise(): Promise<any> {\r\n return this._core.promise;\r\n }\r\n\r\n // --- Command properties ---\r\n\r\n get trigger(): boolean {\r\n return this._trigger;\r\n }\r\n\r\n set trigger(value: boolean) {\r\n const v = !!value;\r\n if (v) {\r\n this._trigger = true;\r\n this.upload().finally(() => {\r\n this._trigger = false;\r\n this.dispatchEvent(new CustomEvent(\"wcs-upload:trigger-changed\", {\r\n detail: false,\r\n bubbles: true,\r\n }));\r\n });\r\n }\r\n }\r\n\r\n get files(): FileList | File[] | null {\r\n return this._files;\r\n }\r\n\r\n set files(value: FileList | File[] | null) {\r\n this._files = value;\r\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\r\n detail: value,\r\n bubbles: true,\r\n }));\r\n if (!this.manual && this.url && value && value.length > 0) {\r\n this.upload();\r\n }\r\n }\r\n\r\n // --- Validation ---\r\n\r\n private _validate(files: FileList | File[]): WcsUploadError | null {\r\n const maxSize = this.maxSize;\r\n if (maxSize !== Infinity) {\r\n for (let i = 0; i < files.length; i++) {\r\n if (files[i].size > maxSize) {\r\n return { message: `File \"${files[i].name}\" exceeds maximum size of ${maxSize} bytes.` };\r\n }\r\n }\r\n }\r\n\r\n const accept = this.accept;\r\n if (accept) {\r\n const acceptList = accept.split(\",\").map(s => s.trim().toLowerCase());\r\n for (let i = 0; i < files.length; i++) {\r\n const file = files[i];\r\n const fileType = file.type.toLowerCase();\r\n const fileName = file.name.toLowerCase();\r\n const matched = acceptList.some(pattern => {\r\n if (pattern.startsWith(\".\")) {\r\n return fileName.endsWith(pattern);\r\n }\r\n if (pattern.endsWith(\"/*\")) {\r\n return fileType.startsWith(pattern.slice(0, -1));\r\n }\r\n return fileType === pattern;\r\n });\r\n if (!matched) {\r\n return { message: `File \"${file.name}\" does not match accepted types: ${accept}` };\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n // --- Public methods ---\r\n\r\n abort(): void {\r\n this._core.abort();\r\n }\r\n\r\n async upload(): Promise<any> {\r\n const files = this._files;\r\n if (!files || files.length === 0) {\r\n return null;\r\n }\r\n\r\n const validationError = this._validate(files);\r\n if (validationError) {\r\n this.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\r\n detail: validationError,\r\n bubbles: true,\r\n }));\r\n return null;\r\n }\r\n\r\n const result = await this._core.upload(this.url, files, {\r\n method: this.method,\r\n fieldName: this.fieldName,\r\n });\r\n\r\n // 自分が開始したアップロードのファイルだけをリセット\r\n // (途中で新しい files がセットされていたら触らない)\r\n if (this._files === files) {\r\n this._files = null;\r\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\r\n detail: null,\r\n bubbles: true,\r\n }));\r\n }\r\n\r\n return result;\r\n }\r\n\r\n // --- Lifecycle ---\r\n\r\n attributeChangedCallback(_name: string, _oldValue: string | null, _newValue: string | null): void {\r\n // URL変更ではアップロードを自動実行しない(ファイルが必要なため)\r\n }\r\n\r\n connectedCallback(): void {\r\n this.style.display = \"none\";\r\n if (config.autoTrigger) {\r\n registerAutoTrigger();\r\n }\r\n }\r\n\r\n disconnectedCallback(): void {\r\n this._core.abort();\r\n }\r\n}\r\n","import { setConfig } from \"./config.js\";\r\nimport { registerComponents } from \"./registerComponents.js\";\r\nimport { IWritableConfig } from \"./types.js\";\r\n\r\nexport function bootstrapUpload(userConfig?: IWritableConfig): void {\r\n if (userConfig) {\r\n setConfig(userConfig);\r\n }\r\n registerComponents();\r\n}\r\n","import { WcsUpload } from \"./components/Upload.js\";\r\nimport { config } from \"./config.js\";\r\n\r\nexport function registerComponents(): void {\r\n if (!customElements.get(config.tagNames.upload)) {\r\n customElements.define(config.tagNames.upload, WcsUpload);\r\n }\r\n}\r\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"}
|
package/package.json
CHANGED
|
@@ -1,71 +1,71 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@wcstack/upload",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Declarative file upload component for Web Components. Framework-agnostic upload with progress tracking via wc-bindable-protocol.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./dist/index.esm.js",
|
|
7
|
-
"module": "./dist/index.esm.js",
|
|
8
|
-
"types": "./dist/index.d.ts",
|
|
9
|
-
"exports": {
|
|
10
|
-
".": {
|
|
11
|
-
"types": "./dist/index.d.ts",
|
|
12
|
-
"import": "./dist/index.esm.js"
|
|
13
|
-
},
|
|
14
|
-
"./auto": "./dist/auto.min.js"
|
|
15
|
-
},
|
|
16
|
-
"files": [
|
|
17
|
-
"dist"
|
|
18
|
-
],
|
|
19
|
-
"scripts": {
|
|
20
|
-
"clean": "rimraf dist .tsc-out",
|
|
21
|
-
"build": "rimraf dist .tsc-out && tsc && rollup -c",
|
|
22
|
-
"test": "vitest run",
|
|
23
|
-
"test:watch": "vitest",
|
|
24
|
-
"test:coverage": "vitest run --coverage",
|
|
25
|
-
"lint": "eslint src",
|
|
26
|
-
"version:patch": "npm version patch",
|
|
27
|
-
"version:minor": "npm version minor",
|
|
28
|
-
"version:major": "npm version major",
|
|
29
|
-
"prepublishOnly": "npm run build && npm run test:coverage"
|
|
30
|
-
},
|
|
31
|
-
"keywords": [
|
|
32
|
-
"web-components",
|
|
33
|
-
"upload",
|
|
34
|
-
"file-upload",
|
|
35
|
-
"custom-elements",
|
|
36
|
-
"wc-bindable",
|
|
37
|
-
"declarative",
|
|
38
|
-
"progress",
|
|
39
|
-
"zero-dependencies",
|
|
40
|
-
"framework-agnostic"
|
|
41
|
-
],
|
|
42
|
-
"author": "mogera551",
|
|
43
|
-
"homepage": "https://wcstack.github.io",
|
|
44
|
-
"repository": {
|
|
45
|
-
"type": "git",
|
|
46
|
-
"url": "https://github.com/wcstack/wcstack.git",
|
|
47
|
-
"directory": "packages/upload"
|
|
48
|
-
},
|
|
49
|
-
"bugs": {
|
|
50
|
-
"url": "https://github.com/wcstack/wcstack/issues"
|
|
51
|
-
},
|
|
52
|
-
"license": "MIT",
|
|
53
|
-
"devDependencies": {
|
|
54
|
-
"@eslint/js": "^9.39.1",
|
|
55
|
-
"@rollup/plugin-terser": "^0.4.4",
|
|
56
|
-
"@rollup/plugin-typescript": "^11.1.6",
|
|
57
|
-
"@vitest/coverage-v8": "^4.0.15",
|
|
58
|
-
"@vitest/ui": "^4.0.15",
|
|
59
|
-
"eslint": "^9.39.1",
|
|
60
|
-
"globals": "^16.5.0",
|
|
61
|
-
"happy-dom": "^20.0.11",
|
|
62
|
-
"rimraf": "^6.0.1",
|
|
63
|
-
"rollup": "^4.22.4",
|
|
64
|
-
"rollup-plugin-dts": "^6.1.1",
|
|
65
|
-
"rollup-plugin-copy": "^3.5.0",
|
|
66
|
-
"tslib": "^2.8.1",
|
|
67
|
-
"typescript": "^5.9.3",
|
|
68
|
-
"typescript-eslint": "^8.49.0",
|
|
69
|
-
"vitest": "^4.0.15"
|
|
70
|
-
}
|
|
71
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@wcstack/upload",
|
|
3
|
+
"version": "1.9.1",
|
|
4
|
+
"description": "Declarative file upload component for Web Components. Framework-agnostic upload with progress tracking via wc-bindable-protocol.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.esm.js",
|
|
7
|
+
"module": "./dist/index.esm.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.esm.js"
|
|
13
|
+
},
|
|
14
|
+
"./auto": "./dist/auto.min.js"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"clean": "rimraf dist .tsc-out",
|
|
21
|
+
"build": "rimraf dist .tsc-out && tsc && rollup -c",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"test:watch": "vitest",
|
|
24
|
+
"test:coverage": "vitest run --coverage",
|
|
25
|
+
"lint": "eslint src",
|
|
26
|
+
"version:patch": "npm version patch",
|
|
27
|
+
"version:minor": "npm version minor",
|
|
28
|
+
"version:major": "npm version major",
|
|
29
|
+
"prepublishOnly": "npm run build && npm run test:coverage"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"web-components",
|
|
33
|
+
"upload",
|
|
34
|
+
"file-upload",
|
|
35
|
+
"custom-elements",
|
|
36
|
+
"wc-bindable",
|
|
37
|
+
"declarative",
|
|
38
|
+
"progress",
|
|
39
|
+
"zero-dependencies",
|
|
40
|
+
"framework-agnostic"
|
|
41
|
+
],
|
|
42
|
+
"author": "mogera551",
|
|
43
|
+
"homepage": "https://wcstack.github.io",
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "https://github.com/wcstack/wcstack.git",
|
|
47
|
+
"directory": "packages/upload"
|
|
48
|
+
},
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://github.com/wcstack/wcstack/issues"
|
|
51
|
+
},
|
|
52
|
+
"license": "MIT",
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@eslint/js": "^9.39.1",
|
|
55
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
56
|
+
"@rollup/plugin-typescript": "^11.1.6",
|
|
57
|
+
"@vitest/coverage-v8": "^4.0.15",
|
|
58
|
+
"@vitest/ui": "^4.0.15",
|
|
59
|
+
"eslint": "^9.39.1",
|
|
60
|
+
"globals": "^16.5.0",
|
|
61
|
+
"happy-dom": "^20.0.11",
|
|
62
|
+
"rimraf": "^6.0.1",
|
|
63
|
+
"rollup": "^4.22.4",
|
|
64
|
+
"rollup-plugin-dts": "^6.1.1",
|
|
65
|
+
"rollup-plugin-copy": "^3.5.0",
|
|
66
|
+
"tslib": "^2.8.1",
|
|
67
|
+
"typescript": "^5.9.3",
|
|
68
|
+
"typescript-eslint": "^8.49.0",
|
|
69
|
+
"vitest": "^4.0.15"
|
|
70
|
+
}
|
|
71
|
+
}
|