@wcstack/upload 1.9.1 → 1.10.4
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 +367 -282
- package/README.md +367 -282
- package/dist/auto.js +3 -3
- package/dist/auto.min.js +3 -3
- package/dist/index.d.ts +17 -1
- package/dist/index.esm.js +67 -6
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/package.json +71 -71
package/README.ja.md
CHANGED
|
@@ -1,283 +1,368 @@
|
|
|
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` は
|
|
17
|
-
|
|
18
|
-
- **Core** (`UploadCore`) が XHR アップロード、進捗追跡、abort、非同期状態を処理
|
|
19
|
-
- **Shell** (`<wcs-upload>`) がその状態をカスタム要素と
|
|
20
|
-
-
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
<
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
input.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
<
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
<
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
<
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
input.
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
|
190
|
-
|
|
191
|
-
| `
|
|
192
|
-
| `
|
|
193
|
-
| `
|
|
194
|
-
| `
|
|
195
|
-
| `
|
|
196
|
-
| `
|
|
197
|
-
| `
|
|
198
|
-
| `
|
|
199
|
-
| `
|
|
200
|
-
| `
|
|
201
|
-
| `
|
|
202
|
-
| `
|
|
203
|
-
| `
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
-
|
|
244
|
-
|
|
245
|
-
- `
|
|
246
|
-
- `
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
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` は [CSBC](https://github.com/csbc-dev/arch/blob/main/README.md)(Core / Shell / Binding Contract)アーキテクチャに従います。
|
|
17
|
+
|
|
18
|
+
- **Core** (`UploadCore`) が XHR アップロード、進捗追跡、abort、非同期状態を処理
|
|
19
|
+
- **Shell** (`<wcs-upload>`) がその状態をカスタム要素と DOM 向けランタイムサーフェスとして公開
|
|
20
|
+
- **Binding Contract** (`static wcBindable`) が観測可能な `properties`、書き込み可能な `inputs`、呼び出し可能な `commands` を宣言
|
|
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
|
+
観測できるのは `false` へのリセットのみです。`true` 遷移(アップロード開始)は `wcs-upload:trigger-changed` を発火しません。バインディングシステムは `true` を書き込んで開始し、唯一の `false` エッジを観測してコマンドの完了を知ります。これは `@wcstack/fetch` の `trigger` と同じトレードオフです。
|
|
110
|
+
|
|
111
|
+
### 3. 宣言的なトリガーターゲット
|
|
112
|
+
|
|
113
|
+
自動トリガーが有効な場合、クリック可能な要素から id で `<wcs-upload>` を参照できます。
|
|
114
|
+
|
|
115
|
+
```html
|
|
116
|
+
<script type="module" src="https://esm.run/@wcstack/upload/auto"></script>
|
|
117
|
+
|
|
118
|
+
<wcs-upload id="photo-upload" url="/api/upload" manual></wcs-upload>
|
|
119
|
+
<input id="photo-input" type="file">
|
|
120
|
+
<button data-uploadtarget="photo-upload">Upload</button>
|
|
121
|
+
|
|
122
|
+
<script type="module">
|
|
123
|
+
const upload = document.getElementById("photo-upload");
|
|
124
|
+
const input = document.getElementById("photo-input");
|
|
125
|
+
|
|
126
|
+
input.addEventListener("change", () => {
|
|
127
|
+
upload.files = input.files;
|
|
128
|
+
});
|
|
129
|
+
</script>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
デフォルトのトリガー属性名は `data-uploadtarget` です。
|
|
133
|
+
|
|
134
|
+
### 4. `@wcstack/state` と組み合わせる
|
|
135
|
+
|
|
136
|
+
```html
|
|
137
|
+
<script type="module" src="https://esm.run/@wcstack/state/auto"></script>
|
|
138
|
+
<script type="module" src="https://esm.run/@wcstack/upload/auto"></script>
|
|
139
|
+
|
|
140
|
+
<wcs-state>
|
|
141
|
+
<script type="module">
|
|
142
|
+
export default {
|
|
143
|
+
uploadResult: null,
|
|
144
|
+
uploadLoading: false,
|
|
145
|
+
uploadProgress: 0,
|
|
146
|
+
uploadError: null,
|
|
147
|
+
};
|
|
148
|
+
</script>
|
|
149
|
+
|
|
150
|
+
<wcs-upload
|
|
151
|
+
id="state-upload"
|
|
152
|
+
url="/api/upload"
|
|
153
|
+
manual
|
|
154
|
+
data-wcs="
|
|
155
|
+
value: uploadResult;
|
|
156
|
+
loading: uploadLoading;
|
|
157
|
+
progress: uploadProgress;
|
|
158
|
+
error: uploadError
|
|
159
|
+
">
|
|
160
|
+
</wcs-upload>
|
|
161
|
+
|
|
162
|
+
<input id="state-upload-input" type="file">
|
|
163
|
+
<button data-uploadtarget="state-upload">Upload</button>
|
|
164
|
+
|
|
165
|
+
<progress max="100" data-wcs="value: uploadProgress"></progress>
|
|
166
|
+
<p data-wcs="textContent: uploadLoading"></p>
|
|
167
|
+
|
|
168
|
+
<script type="module">
|
|
169
|
+
const upload = document.getElementById("state-upload");
|
|
170
|
+
const input = document.getElementById("state-upload-input");
|
|
171
|
+
|
|
172
|
+
input.addEventListener("change", () => {
|
|
173
|
+
upload.files = input.files;
|
|
174
|
+
});
|
|
175
|
+
</script>
|
|
176
|
+
</wcs-state>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
この構成では、アップロードはバインド可能な非同期ノードになります。
|
|
180
|
+
|
|
181
|
+
- 要素がリクエストを実行
|
|
182
|
+
- 非同期状態が `value`, `loading`, `progress`, `error`, `status` として返る
|
|
183
|
+
- UI はそれらのパスへ宣言的にバインド
|
|
184
|
+
|
|
185
|
+
## 公開 API
|
|
186
|
+
|
|
187
|
+
### 要素属性とプロパティ
|
|
188
|
+
|
|
189
|
+
| 名前 | 型 | デフォルト | 説明 |
|
|
190
|
+
|---|---|---|---|
|
|
191
|
+
| `url` | `string` | `""` | アップロード先エンドポイント |
|
|
192
|
+
| `method` | `string` | `"POST"` | HTTP メソッド |
|
|
193
|
+
| `field-name` | `string` | `"file"` | FormData のフィールド名 |
|
|
194
|
+
| `multiple` | `boolean` | `false` | 複数ファイル対応を表す宣言用フラグのみ。ファイル数を強制しない(`multiple` の有無に関わらず `files` のファイルはすべて送信される) |
|
|
195
|
+
| `max-size` | `number` | `Infinity` | 許容最大ファイルサイズ(byte) |
|
|
196
|
+
| `accept` | `string` | `""` | 許可する MIME type または拡張子 |
|
|
197
|
+
| `manual` | `boolean` | `false` | `files` 代入時の自動アップロードを無効化 |
|
|
198
|
+
| `files` | `FileList \| File[] \| null` | `null` | アップロード対象ファイル |
|
|
199
|
+
| `trigger` | `boolean` | `false` | 手動アップロード用の書き込みコマンド面 |
|
|
200
|
+
| `value` | `any` | `null` | パース済みレスポンスまたはレスポンステキスト |
|
|
201
|
+
| `loading` | `boolean` | `false` | アップロード中フラグ |
|
|
202
|
+
| `progress` | `number` | `0` | `0` から `100` の進捗率 |
|
|
203
|
+
| `error` | `any` | `null` | バリデーション、ネットワーク、レスポンスのエラー |
|
|
204
|
+
| `status` | `number` | `0` | HTTP レスポンスステータス |
|
|
205
|
+
| `promise` | `Promise<any>` | resolved `null` | 現在のアップロード Promise |
|
|
206
|
+
|
|
207
|
+
### メソッド
|
|
208
|
+
|
|
209
|
+
#### `upload()`
|
|
210
|
+
|
|
211
|
+
現在の `files` を使ってアップロードを開始し、promise を返します。
|
|
212
|
+
|
|
213
|
+
この promise はすべての終了ケースで **resolve** し、reject しません。
|
|
214
|
+
|
|
215
|
+
- 成功 → パース済みレスポンスボディ(`value`)で resolve
|
|
216
|
+
- ファイル未指定 / `url` 未指定 → `null` で resolve(no-op。リクエストは開始されずエラーも発火しない)
|
|
217
|
+
- バリデーション失敗 → `null` で resolve(`wcs-upload:error` を発火)
|
|
218
|
+
- HTTP エラー(status >= 400)→ `null` で resolve(エラー内容は `error` / `wcs-upload:error` で取得)
|
|
219
|
+
- ネットワークエラー → `null` で resolve(エラー内容は `error` / `wcs-upload:error` で取得)
|
|
220
|
+
- 中断(abort)→ `null` で resolve
|
|
221
|
+
|
|
222
|
+
`null` は正常な resolve 値でもあるため、失敗判定に resolve 値を使わないでください。代わりに `error` / `status`(または `wcs-upload:error` / `wcs-upload:response` イベント)を観測します。これは `@wcstack/fetch` と同じ設計で、エラーは promise の reject ではなく状態として流れます。
|
|
223
|
+
|
|
224
|
+
> ヘッドレス Core についての注記: `UploadCore.upload(url, files)` は `async` で、同期的に検出できる引数エラー(`url` 欠落・`files` が空)は `[@wcstack/upload] ...` を throw して **reject** します。Shell の `upload()` は `url` 未指定・ファイル未指定を no-op として扱い `null` を返します(Shell が `url`/ファイルのライフサイクルを所有しており「送信先無し」「ファイル無し」をエラーではなく無操作とみなすため)。これにより Shell は Core の throw に到達せず reject しません。
|
|
225
|
+
|
|
226
|
+
#### `abort()`
|
|
227
|
+
|
|
228
|
+
現在のリクエストを中断します。loading の解除はリクエストの abort 経路を通じて行われます(`@wcstack/fetch` と一貫)。
|
|
229
|
+
|
|
230
|
+
## イベント
|
|
231
|
+
|
|
232
|
+
| イベント | `detail` | 説明 |
|
|
233
|
+
|---|---|---|
|
|
234
|
+
| `wcs-upload:files-changed` | `FileList \| File[] \| null` | `files` 変更時に発火 |
|
|
235
|
+
| `wcs-upload:trigger-changed` | `boolean` | `trigger` が `false` に戻るとき発火 |
|
|
236
|
+
| `wcs-upload:loading-changed` | `boolean` | loading 状態変更時に発火 |
|
|
237
|
+
| `wcs-upload:progress` | `number` | アップロード進捗更新時に発火 |
|
|
238
|
+
| `wcs-upload:error` | error object | バリデーション、ネットワーク、HTTP エラー時に発火 |
|
|
239
|
+
| `wcs-upload:response` | `{ value, status }` | HTTP 成功レスポンス時に発火 |
|
|
240
|
+
|
|
241
|
+
## バリデーション
|
|
242
|
+
|
|
243
|
+
`<wcs-upload>` は送信前にファイルを検証します。
|
|
244
|
+
|
|
245
|
+
- `max-size` は指定 byte 数を超えるファイルを拒否
|
|
246
|
+
- `accept` は `image/*` のような MIME 範囲、`application/pdf` のような厳密 MIME、`.pdf` のような拡張子をサポート
|
|
247
|
+
|
|
248
|
+
`type` が空のファイル(OS が MIME を判定できなかったファイル)は MIME パターンと照合できません。この場合、`accept` に一致する拡張子パターン(例: `.png`)が含まれていれば受理されます。`accept` が MIME パターンのみの場合は、型を確認できないため空 type のファイルは拒否されます。
|
|
249
|
+
|
|
250
|
+
バリデーションに失敗すると `wcs-upload:error` を発火し、リクエストは開始されません。
|
|
251
|
+
|
|
252
|
+
### 状態サーフェスにおける error と response
|
|
253
|
+
|
|
254
|
+
成功レスポンス(status 2xx)では `value` と `status` の両方が `wcs-upload:response` 経由で更新されます。HTTP エラー(status >= 400)では `error` のみが(`wcs-upload:error` 経由で)更新され、**エラー時に `status` は状態サーフェスへ伝播しません**。これは `status` が `wcs-upload:response` イベントにバインドされており、エラー時はそのイベントが発火しないためです。HTTP ステータスコードは `error` オブジェクト内(`error.status`)で取得できます。これは `@wcstack/fetch` と同じトレードオフで、エラー詳細は response/error に分散させず単一の `error` チャネルに集約します。
|
|
255
|
+
|
|
256
|
+
> `core.status` / `el.status` を直接読むと、`413` や `500` などのエラーステータスも含め、直近レスポンスの HTTP ステータスが返ります(getter は生の XHR ステータスを反映するため)。これはバインド経路の `status`(`wcs-upload:response` 駆動)とは異なり、バインド経路はエラー時には前回値のまま据え置かれます。したがって getter を命令的に直接読むコードと `status` にバインドするコードでは、HTTP エラー後に観測値が食い違います。どちらか一方の経路に統一してください。これは `@wcstack/fetch` と同じ構造です。
|
|
257
|
+
|
|
258
|
+
### エラー時の progress
|
|
259
|
+
|
|
260
|
+
`progress` は各アップロード開始時に `0` へリセットされ、成功時に `100` へ設定されるだけです。HTTP・ネットワーク・abort のエラー時は、**`progress` は意図的に直前の値(例: `70`)のまま据え置かれます**。これは転送がどこで止まったかを UI が示せるようにするためです。失敗の検出には `progress` ではなく `error` / `loading` を使い、古い値を表示したくない場合は `wcs-upload:error` に応じて UI 側で進捗表示をリセット / 非表示にしてください。次回の `upload()` で `progress` は再び `0` にリセットされます。
|
|
261
|
+
|
|
262
|
+
## wc-bindable-protocol
|
|
263
|
+
|
|
264
|
+
`UploadCore` と `<wcs-upload>` はいずれも `wc-bindable-protocol` 準拠を宣言しており、プロトコルをサポートするあらゆるフレームワークやコンポーネントと相互運用できます。
|
|
265
|
+
|
|
266
|
+
宣言は wc-bindable インターフェースモデルの全体に従い、3 つの独立したサーフェスを持ちます。
|
|
267
|
+
|
|
268
|
+
- **`properties`** — `bind()` が購読する観測可能な出力(`value`, `loading`, `progress`, `error`, `status`、および Shell の `trigger` / `files`)
|
|
269
|
+
- **`inputs`** — 設定可能サーフェス(`url`, `method`, `fieldName`, …)。ツール・codegen・リモートプロキシが読む記述的メタデータ
|
|
270
|
+
- **`commands`** — 呼び出し可能メソッド(`upload`, `abort`)。`@wcstack/state` のようなバインディングシステムが名前で呼び出せる
|
|
271
|
+
|
|
272
|
+
プロトコル上、コアの `bind()` が解釈するのは `properties` のみです。`inputs` / `commands`(および `attribute` / `async` ヒント)は記述的であり、暗黙の双方向データフローを生成しません。
|
|
273
|
+
|
|
274
|
+
### Core (`UploadCore`)
|
|
275
|
+
|
|
276
|
+
`UploadCore` は、任意のランタイムが購読できるバインド可能な非同期状態に加え、移植可能な入力 / コマンドサーフェスを宣言します。
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
static wcBindable = {
|
|
280
|
+
protocol: "wc-bindable",
|
|
281
|
+
version: 1,
|
|
282
|
+
properties: [
|
|
283
|
+
{ name: "value", event: "wcs-upload:response",
|
|
284
|
+
getter: (e) => e.detail.value },
|
|
285
|
+
{ name: "loading", event: "wcs-upload:loading-changed" },
|
|
286
|
+
{ name: "progress", event: "wcs-upload:progress" },
|
|
287
|
+
{ name: "error", event: "wcs-upload:error" },
|
|
288
|
+
{ name: "status", event: "wcs-upload:response",
|
|
289
|
+
getter: (e) => e.detail.status },
|
|
290
|
+
],
|
|
291
|
+
inputs: [
|
|
292
|
+
{ name: "url" },
|
|
293
|
+
{ name: "method" },
|
|
294
|
+
{ name: "fieldName" },
|
|
295
|
+
],
|
|
296
|
+
commands: [
|
|
297
|
+
{ name: "upload", async: true },
|
|
298
|
+
{ name: "abort" },
|
|
299
|
+
],
|
|
300
|
+
};
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Headless 利用では `core.upload(url, files)` を直接呼び出します(`trigger` は不要)。
|
|
304
|
+
|
|
305
|
+
### Shell (`<wcs-upload>`)
|
|
306
|
+
|
|
307
|
+
Shell は Core の宣言を継承し、`trigger` / `files` 出力と DOM 駆動の入力サーフェスを追加します。`commands`(`upload` / `abort`)は spread でそのまま継承されます。
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
static wcBindable = {
|
|
311
|
+
...UploadCore.wcBindable,
|
|
312
|
+
properties: [
|
|
313
|
+
...UploadCore.wcBindable.properties,
|
|
314
|
+
{ name: "trigger", event: "wcs-upload:trigger-changed" },
|
|
315
|
+
{ name: "files", event: "wcs-upload:files-changed" },
|
|
316
|
+
],
|
|
317
|
+
inputs: [
|
|
318
|
+
{ name: "url" },
|
|
319
|
+
{ name: "method" },
|
|
320
|
+
{ name: "fieldName" },
|
|
321
|
+
{ name: "multiple" },
|
|
322
|
+
{ name: "maxSize" },
|
|
323
|
+
{ name: "accept" },
|
|
324
|
+
{ name: "manual" },
|
|
325
|
+
{ name: "files" },
|
|
326
|
+
{ name: "trigger" },
|
|
327
|
+
],
|
|
328
|
+
};
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Shell の inputs は意図的に `attribute` ヒントを持ちません。属性に紐づく各 setter(`url`, `method`, `fieldName`, `multiple`, `maxSize`, `accept`, `manual`)はすでに自身で属性へ反映するため、`inputs[].attribute` をミラーするバインディングシステムが属性を二重に設定してしまうのを避けるためです。
|
|
332
|
+
|
|
333
|
+
これにより、`@wcstack/state` を含むあらゆる wc-bindable 対応システムから利用できます。
|
|
334
|
+
|
|
335
|
+
## Headless API
|
|
336
|
+
|
|
337
|
+
カスタム要素の shell が不要な場合は、`UploadCore` を直接使えます。
|
|
338
|
+
|
|
339
|
+
```ts
|
|
340
|
+
import { UploadCore } from "@wcstack/upload";
|
|
341
|
+
|
|
342
|
+
const core = new UploadCore();
|
|
343
|
+
const result = await core.upload("/api/upload", files, {
|
|
344
|
+
method: "PUT",
|
|
345
|
+
fieldName: "attachment",
|
|
346
|
+
headers: {
|
|
347
|
+
Authorization: "Bearer token",
|
|
348
|
+
},
|
|
349
|
+
});
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
`UploadCore` は同じ非同期状態をプロパティとして公開し、同じイベントを発火します。
|
|
353
|
+
|
|
354
|
+
## 手動 bootstrap
|
|
355
|
+
|
|
356
|
+
```ts
|
|
357
|
+
import { bootstrapUpload } from "@wcstack/upload";
|
|
358
|
+
|
|
359
|
+
bootstrapUpload({
|
|
360
|
+
autoTrigger: true,
|
|
361
|
+
triggerAttribute: "data-uploadtarget",
|
|
362
|
+
tagNames: {
|
|
363
|
+
upload: "wcs-upload",
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
```
|
|
367
|
+
|
|
283
368
|
`@wcstack/upload/auto` に頼らず、タグ名やトリガー属性名をカスタマイズしたい場合に使います。
|