@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/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.d.ts CHANGED
@@ -19,10 +19,20 @@ interface IWcBindableProperty {
19
19
  readonly event: string;
20
20
  readonly getter?: (event: Event) => any;
21
21
  }
22
+ interface IWcBindableInput {
23
+ readonly name: string;
24
+ readonly attribute?: string;
25
+ }
26
+ interface IWcBindableCommand {
27
+ readonly name: string;
28
+ readonly async?: boolean;
29
+ }
22
30
  interface IWcBindable {
23
31
  readonly protocol: "wc-bindable";
24
- readonly version: number;
32
+ readonly version: 1;
25
33
  readonly properties: IWcBindableProperty[];
34
+ readonly inputs?: readonly IWcBindableInput[];
35
+ readonly commands?: readonly IWcBindableCommand[];
26
36
  }
27
37
  /**
28
38
  * Upload error object.
@@ -45,6 +55,12 @@ interface WcsUploadCoreValues<T = unknown> {
45
55
  }
46
56
  /**
47
57
  * Value types for the Shell (`<wcs-upload>`) — extends Core with `trigger` and `files`.
58
+ *
59
+ * `trigger` is a write-only command surface declared as an observable property mapped to
60
+ * `wcs-upload:trigger-changed`. Only the `false` reset (after an upload settles) is
61
+ * observable — the `true` transition (upload start) is intentionally NOT notified. This is
62
+ * the same pub/sub trade-off as `@wcstack/fetch`'s `trigger`: a binding system writes `true`
63
+ * to start and observes the single `false` edge to know the command has completed.
48
64
  */
49
65
  interface WcsUploadValues<T = unknown> extends WcsUploadCoreValues<T> {
50
66
  trigger: boolean;
package/dist/index.esm.js CHANGED
@@ -24,6 +24,11 @@ function deepClone(obj) {
24
24
  return clone;
25
25
  }
26
26
  let frozenConfig = null;
27
+ // `config` は内部用のライブビュー(live view)。setConfig() の更新が即座に反映される
28
+ // 実体 `_config` をそのまま公開しており、凍結もクローンもしていない。autoTrigger /
29
+ // components など同パッケージ内のモジュールが最新値を読むための窓口であり、
30
+ // 「変更不可なスナップショット」が必要な外部利用には getConfig()(凍結クローンを返す)
31
+ // を使うこと。型が readonly なのは内部からの誤書き換えを抑止するための表明にすぎない。
27
32
  const config = _config;
28
33
  function getConfig() {
29
34
  if (!frozenConfig) {
@@ -59,6 +64,15 @@ class UploadCore extends EventTarget {
59
64
  { name: "error", event: "wcs-upload:error" },
60
65
  { name: "status", event: "wcs-upload:response", getter: (e) => e.detail.status },
61
66
  ],
67
+ inputs: [
68
+ { name: "url" },
69
+ { name: "method" },
70
+ { name: "fieldName" },
71
+ ],
72
+ commands: [
73
+ { name: "upload", async: true },
74
+ { name: "abort" },
75
+ ],
62
76
  };
63
77
  _target;
64
78
  _value = null;
@@ -122,12 +136,18 @@ class UploadCore extends EventTarget {
122
136
  }
123
137
  // --- Public API ---
124
138
  abort() {
139
+ // `_xhr` は send() の直前に同期で代入されるため、send 前に外部から abort が
140
+ // 割り込む余地はない(割り込み点となる await が存在しない)。よって XHR.abort()
141
+ // は常に進行中のリクエストに対して呼ばれ、abort イベントが発火して loading を
142
+ // 解除する。loading の解除を abort イベントハンドラに集約しているのは、
143
+ // ネットワークエラー/HTTP エラー/正常完了/中断のすべてで解除経路を一本化し、
144
+ // FetchCore.abort() と挙動を揃えるため。
125
145
  if (this._xhr) {
126
146
  this._xhr.abort();
127
147
  this._xhr = null;
128
148
  }
129
149
  }
130
- upload(url, files, options = {}) {
150
+ async upload(url, files, options = {}) {
131
151
  if (!url) {
132
152
  raiseError("url is required.");
133
153
  }
@@ -245,7 +265,28 @@ class WcsUpload extends HTMLElement {
245
265
  { name: "trigger", event: "wcs-upload:trigger-changed" },
246
266
  { name: "files", event: "wcs-upload:files-changed" },
247
267
  ],
268
+ // Shell-level input surface. The Core declares only the portable `url` / `method` /
269
+ // `fieldName`; the Shell adds the DOM-driven settable surface. No `attribute` hints
270
+ // are given: the `url` / `method` / `fieldName` / `multiple` / `maxSize` / `accept` /
271
+ // `manual` setters already reflect to their attributes, so a binding system that
272
+ // mirrors inputs[].attribute would set the attribute twice (`files` / `trigger` are
273
+ // not attribute-backed). `commands` (upload / abort) are inherited unchanged from the
274
+ // Core via the spread above.
275
+ inputs: [
276
+ { name: "url" },
277
+ { name: "method" },
278
+ { name: "fieldName" },
279
+ { name: "multiple" },
280
+ { name: "maxSize" },
281
+ { name: "accept" },
282
+ { name: "manual" },
283
+ { name: "files" },
284
+ { name: "trigger" },
285
+ ],
248
286
  };
287
+ // `url` を観測するのは FetchCore のシェルと構造を揃えるためだが、upload は
288
+ // url 変更だけでは送信できない(files が必須)。そのため attributeChangedCallback は
289
+ // 意図的に何もしない。url 変更で自動送信しないことは仕様であり、テストで担保している。
249
290
  static get observedAttributes() { return ["url"]; }
250
291
  _core;
251
292
  _files = null;
@@ -286,7 +327,14 @@ class WcsUpload extends HTMLElement {
286
327
  }
287
328
  get maxSize() {
288
329
  const attr = this.getAttribute("max-size");
289
- return attr ? parseInt(attr, 10) : Infinity;
330
+ if (attr === null) {
331
+ return Infinity;
332
+ }
333
+ // 不正値(NaN になる "abc" など)や負数は「制限なし」(Infinity) として扱う。
334
+ // NaN を返すと `size > NaN` が常に false になりサイズ検証が無言で無効化され、
335
+ // 負数を返すと全ファイルが拒否されるため、いずれも安全側の Infinity に丸める。
336
+ const n = parseInt(attr, 10);
337
+ return Number.isFinite(n) && n >= 0 ? n : Infinity;
290
338
  }
291
339
  set maxSize(value) {
292
340
  this.setAttribute("max-size", String(value));
@@ -332,6 +380,10 @@ class WcsUpload extends HTMLElement {
332
380
  return this._trigger;
333
381
  }
334
382
  set trigger(value) {
383
+ // 進行中に再度 trigger=true が来ても再入ガードはしない(FetchCore シェルと同一)。
384
+ // upload() → _core.upload() が先頭で既存リクエストを abort し新規開始するため、
385
+ // 連続トリガは「前回を中止して新しいアップロードを開始する」挙動になる。
386
+ // 各 upload() の settle ごとに trigger-changed(false) が 1 回発火する。
335
387
  const v = !!value;
336
388
  if (v) {
337
389
  this._trigger = true;
@@ -374,14 +426,18 @@ class WcsUpload extends HTMLElement {
374
426
  const file = files[i];
375
427
  const fileType = file.type.toLowerCase();
376
428
  const fileName = file.name.toLowerCase();
429
+ // file.type が空文字(OS が MIME を判定できないファイル)の場合、MIME 系
430
+ // パターン(`image/*` / 厳密 MIME)は一致しない。その場合でも accept に
431
+ // 拡張子パターン(`.pdf` 等)が含まれ拡張子が一致すれば受理される。
432
+ // accept が MIME 系のみのときは型を確認できないため拒否する(安全側)。
377
433
  const matched = acceptList.some(pattern => {
378
434
  if (pattern.startsWith(".")) {
379
435
  return fileName.endsWith(pattern);
380
436
  }
381
437
  if (pattern.endsWith("/*")) {
382
- return fileType.startsWith(pattern.slice(0, -1));
438
+ return fileType !== "" && fileType.startsWith(pattern.slice(0, -1));
383
439
  }
384
- return fileType === pattern;
440
+ return fileType !== "" && fileType === pattern;
385
441
  });
386
442
  if (!matched) {
387
443
  return { message: `File "${file.name}" does not match accepted types: ${accept}` };
@@ -396,7 +452,11 @@ class WcsUpload extends HTMLElement {
396
452
  }
397
453
  async upload() {
398
454
  const files = this._files;
399
- if (!files || files.length === 0) {
455
+ // url 未設定は no-op(null)。Core url 空で throw するが、Shell は url/files の
456
+ // ライフサイクルを所有しており「送信先が無い」を「ファイル無し」と同じ無操作として扱う。
457
+ // これにより set trigger / set files の fire-and-forget 経路で unhandled rejection が
458
+ // 発生せず、README の「upload() は全終了ケースで resolve し never reject」契約とも整合する。
459
+ if (!files || files.length === 0 || !this.url) {
400
460
  return null;
401
461
  }
402
462
  const validationError = this._validate(files);
@@ -424,7 +484,8 @@ class WcsUpload extends HTMLElement {
424
484
  }
425
485
  // --- Lifecycle ---
426
486
  attributeChangedCallback(_name, _oldValue, _newValue) {
427
- // URL変更ではアップロードを自動実行しない(ファイルが必要なため)
487
+ // 意図的に空。url 変更ではアップロードを自動実行しない(files が必要なため)。
488
+ // observedAttributes のコメント参照。
428
489
  }
429
490
  connectedCallback() {
430
491
  this.style.display = "none";
@@ -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\";\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
+ {"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/raiseError.ts","../src/core/UploadCore.ts","../src/autoTrigger.ts","../src/components/Upload.ts","../src/registerComponents.ts","../src/bootstrapUpload.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n upload: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-uploadtarget\",\n tagNames: {\n upload: \"wcs-upload\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\n// `config` は内部用のライブビュー(live view)。setConfig() の更新が即座に反映される\n// 実体 `_config` をそのまま公開しており、凍結もクローンもしていない。autoTrigger /\n// components など同パッケージ内のモジュールが最新値を読むための窓口であり、\n// 「変更不可なスナップショット」が必要な外部利用には getConfig()(凍結クローンを返す)\n// を使うこと。型が readonly なのは内部からの誤書き換えを抑止するための表明にすぎない。\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","export function raiseError(message: string): never {\n throw new Error(`[@wcstack/upload] ${message}`);\n}\n","import { raiseError } from \"../raiseError.js\";\nimport { IWcBindable } from \"../types.js\";\n\nexport interface UploadRequestOptions {\n method?: string;\n headers?: Record<string, string>;\n fieldName?: string;\n}\n\nexport class UploadCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"value\", event: \"wcs-upload:response\", getter: (e: Event) => (e as CustomEvent).detail.value },\n { name: \"loading\", event: \"wcs-upload:loading-changed\" },\n { name: \"progress\", event: \"wcs-upload:progress\" },\n { name: \"error\", event: \"wcs-upload:error\" },\n { name: \"status\", event: \"wcs-upload:response\", getter: (e: Event) => (e as CustomEvent).detail.status },\n ],\n inputs: [\n { name: \"url\" },\n { name: \"method\" },\n { name: \"fieldName\" },\n ],\n commands: [\n { name: \"upload\", async: true },\n { name: \"abort\" },\n ],\n };\n\n private _target: EventTarget;\n private _value: any = null;\n private _loading: boolean = false;\n private _progress: number = 0;\n private _error: any = null;\n private _status: number = 0;\n private _xhr: XMLHttpRequest | null = null;\n private _promise: Promise<any> = Promise.resolve(null);\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get value(): any {\n return this._value;\n }\n\n get loading(): boolean {\n return this._loading;\n }\n\n get progress(): number {\n return this._progress;\n }\n\n get error(): any {\n return this._error;\n }\n\n get status(): number {\n return this._status;\n }\n\n get promise(): Promise<any> {\n return this._promise;\n }\n\n // --- State setters with event dispatch ---\n\n private _setLoading(loading: boolean): void {\n this._loading = loading;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:loading-changed\", {\n detail: loading,\n bubbles: true,\n }));\n }\n\n private _setProgress(progress: number): void {\n this._progress = progress;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:progress\", {\n detail: progress,\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n private _setResponse(value: any, status: number): void {\n this._value = value;\n this._status = status;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:response\", {\n detail: { value, status },\n bubbles: true,\n }));\n }\n\n // --- Public API ---\n\n abort(): void {\n // `_xhr` は send() の直前に同期で代入されるため、send 前に外部から abort が\n // 割り込む余地はない(割り込み点となる await が存在しない)。よって XHR.abort()\n // は常に進行中のリクエストに対して呼ばれ、abort イベントが発火して loading を\n // 解除する。loading の解除を abort イベントハンドラに集約しているのは、\n // ネットワークエラー/HTTP エラー/正常完了/中断のすべてで解除経路を一本化し、\n // FetchCore.abort() と挙動を揃えるため。\n if (this._xhr) {\n this._xhr.abort();\n this._xhr = null;\n }\n }\n\n async upload(url: string, files: FileList | File[], options: UploadRequestOptions = {}): Promise<any> {\n if (!url) {\n raiseError(\"url is required.\");\n }\n if (!files || files.length === 0) {\n raiseError(\"files are required.\");\n }\n\n const p = this._doUpload(url, files, options);\n this._promise = p;\n return p;\n }\n\n // --- Internal ---\n\n private _doUpload(url: string, files: FileList | File[], options: UploadRequestOptions): Promise<any> {\n // 既存のアップロードを中止\n this.abort();\n\n this._setLoading(true);\n this._setProgress(0);\n this._setError(null);\n\n const {\n method = \"POST\",\n headers = {},\n fieldName = \"file\",\n } = options;\n\n const formData = new FormData();\n for (let i = 0; i < files.length; i++) {\n formData.append(fieldName, files[i]);\n }\n\n return new Promise<any>((resolve) => {\n const xhr = new XMLHttpRequest();\n this._xhr = xhr;\n\n xhr.upload.addEventListener(\"progress\", (event: ProgressEvent) => {\n if (event.lengthComputable) {\n const percent = Math.round((event.loaded / event.total) * 100);\n this._setProgress(percent);\n }\n });\n\n xhr.addEventListener(\"load\", () => {\n this._xhr = null;\n this._status = xhr.status;\n\n if (xhr.status >= 200 && xhr.status < 300) {\n let value: any = xhr.responseText;\n const contentType = xhr.getResponseHeader(\"Content-Type\") || \"\";\n if (contentType.includes(\"application/json\")) {\n try {\n value = JSON.parse(xhr.responseText);\n } catch {\n // テキストのまま\n }\n }\n this._setProgress(100);\n this._setResponse(value, xhr.status);\n this._setLoading(false);\n resolve(value);\n } else {\n const error = {\n status: xhr.status,\n statusText: xhr.statusText,\n body: xhr.responseText,\n };\n this._setError(error);\n this._setLoading(false);\n resolve(null);\n }\n });\n\n xhr.addEventListener(\"error\", () => {\n this._xhr = null;\n this._setError({ message: \"Network error\" });\n this._setLoading(false);\n resolve(null);\n });\n\n xhr.addEventListener(\"abort\", () => {\n this._xhr = null;\n this._setLoading(false);\n resolve(null);\n });\n\n xhr.open(method, url);\n\n for (const [name, value] of Object.entries(headers)) {\n xhr.setRequestHeader(name, value);\n }\n\n xhr.send(formData);\n });\n }\n}\n","import { config } from \"./config.js\";\nimport { WcsUpload } from \"./components/Upload.js\";\n\nlet registered = false;\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const uploadId = triggerElement.getAttribute(config.triggerAttribute);\n if (!uploadId) return;\n\n const uploadElement = document.getElementById(uploadId) as WcsUpload | null;\n if (!uploadElement || !(uploadElement instanceof WcsUpload)) return;\n\n // ファイルと URL が揃っている場合のみ既定動作を抑止\n if (uploadElement.files && uploadElement.files.length > 0 && uploadElement.url) {\n event.preventDefault();\n }\n uploadElement.upload();\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","import { config } from \"../config.js\";\nimport { IWcBindable, WcsUploadError } from \"../types.js\";\nimport { UploadCore } from \"../core/UploadCore.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\nexport class WcsUpload extends HTMLElement {\n static hasConnectedCallbackPromise = false;\n static wcBindable: IWcBindable = {\n ...UploadCore.wcBindable,\n properties: [\n ...UploadCore.wcBindable.properties,\n { name: \"trigger\", event: \"wcs-upload:trigger-changed\" },\n { name: \"files\", event: \"wcs-upload:files-changed\" },\n ],\n // Shell-level input surface. The Core declares only the portable `url` / `method` /\n // `fieldName`; the Shell adds the DOM-driven settable surface. No `attribute` hints\n // are given: the `url` / `method` / `fieldName` / `multiple` / `maxSize` / `accept` /\n // `manual` setters already reflect to their attributes, so a binding system that\n // mirrors inputs[].attribute would set the attribute twice (`files` / `trigger` are\n // not attribute-backed). `commands` (upload / abort) are inherited unchanged from the\n // Core via the spread above.\n inputs: [\n { name: \"url\" },\n { name: \"method\" },\n { name: \"fieldName\" },\n { name: \"multiple\" },\n { name: \"maxSize\" },\n { name: \"accept\" },\n { name: \"manual\" },\n { name: \"files\" },\n { name: \"trigger\" },\n ],\n };\n // `url` を観測するのは FetchCore のシェルと構造を揃えるためだが、upload は\n // url 変更だけでは送信できない(files が必須)。そのため attributeChangedCallback は\n // 意図的に何もしない。url 変更で自動送信しないことは仕様であり、テストで担保している。\n static get observedAttributes(): string[] { return [\"url\"]; }\n\n private _core: UploadCore;\n private _files: FileList | File[] | null = null;\n private _trigger: boolean = false;\n\n constructor() {\n super();\n this._core = new UploadCore(this);\n }\n\n // --- Attribute accessors ---\n\n get url(): string {\n return this.getAttribute(\"url\") || \"\";\n }\n\n set url(value: string) {\n this.setAttribute(\"url\", value);\n }\n\n get method(): string {\n return (this.getAttribute(\"method\") || \"POST\").toUpperCase();\n }\n\n set method(value: string) {\n this.setAttribute(\"method\", value);\n }\n\n get fieldName(): string {\n return this.getAttribute(\"field-name\") || \"file\";\n }\n\n set fieldName(value: string) {\n this.setAttribute(\"field-name\", value);\n }\n\n get multiple(): boolean {\n return this.hasAttribute(\"multiple\");\n }\n\n set multiple(value: boolean) {\n if (value) {\n this.setAttribute(\"multiple\", \"\");\n } else {\n this.removeAttribute(\"multiple\");\n }\n }\n\n get maxSize(): number {\n const attr = this.getAttribute(\"max-size\");\n if (attr === null) {\n return Infinity;\n }\n // 不正値(NaN になる \"abc\" など)や負数は「制限なし」(Infinity) として扱う。\n // NaN を返すと `size > NaN` が常に false になりサイズ検証が無言で無効化され、\n // 負数を返すと全ファイルが拒否されるため、いずれも安全側の Infinity に丸める。\n const n = parseInt(attr, 10);\n return Number.isFinite(n) && n >= 0 ? n : Infinity;\n }\n\n set maxSize(value: number) {\n this.setAttribute(\"max-size\", String(value));\n }\n\n get accept(): string {\n return this.getAttribute(\"accept\") || \"\";\n }\n\n set accept(value: string) {\n this.setAttribute(\"accept\", value);\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get value(): any {\n return this._core.value;\n }\n\n get loading(): boolean {\n return this._core.loading;\n }\n\n get progress(): number {\n return this._core.progress;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n get status(): number {\n return this._core.status;\n }\n\n get promise(): Promise<any> {\n return this._core.promise;\n }\n\n // --- Command properties ---\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n // 進行中に再度 trigger=true が来ても再入ガードはしない(FetchCore シェルと同一)。\n // upload() → _core.upload() が先頭で既存リクエストを abort し新規開始するため、\n // 連続トリガは「前回を中止して新しいアップロードを開始する」挙動になる。\n // 各 upload() の settle ごとに trigger-changed(false) が 1 回発火する。\n const v = !!value;\n if (v) {\n this._trigger = true;\n this.upload().finally(() => {\n this._trigger = false;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:trigger-changed\", {\n detail: false,\n bubbles: true,\n }));\n });\n }\n }\n\n get files(): FileList | File[] | null {\n return this._files;\n }\n\n set files(value: FileList | File[] | null) {\n this._files = value;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\n detail: value,\n bubbles: true,\n }));\n if (!this.manual && this.url && value && value.length > 0) {\n this.upload();\n }\n }\n\n // --- Validation ---\n\n private _validate(files: FileList | File[]): WcsUploadError | null {\n const maxSize = this.maxSize;\n if (maxSize !== Infinity) {\n for (let i = 0; i < files.length; i++) {\n if (files[i].size > maxSize) {\n return { message: `File \"${files[i].name}\" exceeds maximum size of ${maxSize} bytes.` };\n }\n }\n }\n\n const accept = this.accept;\n if (accept) {\n const acceptList = accept.split(\",\").map(s => s.trim().toLowerCase());\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n const fileType = file.type.toLowerCase();\n const fileName = file.name.toLowerCase();\n // file.type が空文字(OS が MIME を判定できないファイル)の場合、MIME 系\n // パターン(`image/*` / 厳密 MIME)は一致しない。その場合でも accept に\n // 拡張子パターン(`.pdf` 等)が含まれ拡張子が一致すれば受理される。\n // accept が MIME 系のみのときは型を確認できないため拒否する(安全側)。\n const matched = acceptList.some(pattern => {\n if (pattern.startsWith(\".\")) {\n return fileName.endsWith(pattern);\n }\n if (pattern.endsWith(\"/*\")) {\n return fileType !== \"\" && fileType.startsWith(pattern.slice(0, -1));\n }\n return fileType !== \"\" && fileType === pattern;\n });\n if (!matched) {\n return { message: `File \"${file.name}\" does not match accepted types: ${accept}` };\n }\n }\n }\n\n return null;\n }\n\n // --- Public methods ---\n\n abort(): void {\n this._core.abort();\n }\n\n async upload(): Promise<any> {\n const files = this._files;\n // url 未設定は no-op(null)。Core は url 空で throw するが、Shell は url/files の\n // ライフサイクルを所有しており「送信先が無い」を「ファイル無し」と同じ無操作として扱う。\n // これにより set trigger / set files の fire-and-forget 経路で unhandled rejection が\n // 発生せず、README の「upload() は全終了ケースで resolve し never reject」契約とも整合する。\n if (!files || files.length === 0 || !this.url) {\n return null;\n }\n\n const validationError = this._validate(files);\n if (validationError) {\n this.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\n detail: validationError,\n bubbles: true,\n }));\n return null;\n }\n\n const result = await this._core.upload(this.url, files, {\n method: this.method,\n fieldName: this.fieldName,\n });\n\n // 自分が開始したアップロードのファイルだけをリセット\n // (途中で新しい files がセットされていたら触らない)\n if (this._files === files) {\n this._files = null;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\n detail: null,\n bubbles: true,\n }));\n }\n\n return result;\n }\n\n // --- Lifecycle ---\n\n attributeChangedCallback(_name: string, _oldValue: string | null, _newValue: string | null): void {\n // 意図的に空。url 変更ではアップロードを自動実行しない(files が必要なため)。\n // observedAttributes のコメント参照。\n }\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n }\n\n disconnectedCallback(): void {\n this._core.abort();\n }\n}\n","import { WcsUpload } from \"./components/Upload.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.upload)) {\n customElements.define(config.tagNames.upload, WcsUpload);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapUpload(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const t={autoTrigger:!0,triggerAttribute:"data-uploadtarget",tagNames:{upload:"wcs-upload"}};function e(t){if(null===t||"object"!=typeof t)return t;Object.freeze(t);for(const s of Object.keys(t))e(t[s]);return t}function s(t){if(null===t||"object"!=typeof t)return t;const e={};for(const r of Object.keys(t))e[r]=s(t[r]);return e}let r=null;const i=t;function n(){return r||(r=e(s(t))),r}function a(t){throw new Error(`[@wcstack/upload] ${t}`)}class o extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"value",event:"wcs-upload:response",getter:t=>t.detail.value},{name:"loading",event:"wcs-upload:loading-changed"},{name:"progress",event:"wcs-upload:progress"},{name:"error",event:"wcs-upload:error"},{name:"status",event:"wcs-upload:response",getter:t=>t.detail.status}]};_target;_value=null;_loading=!1;_progress=0;_error=null;_status=0;_xhr=null;_promise=Promise.resolve(null);constructor(t){super(),this._target=t??this}get value(){return this._value}get loading(){return this._loading}get progress(){return this._progress}get error(){return this._error}get status(){return this._status}get promise(){return this._promise}_setLoading(t){this._loading=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:loading-changed",{detail:t,bubbles:!0}))}_setProgress(t){this._progress=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:progress",{detail:t,bubbles:!0}))}_setError(t){this._error=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:error",{detail:t,bubbles:!0}))}_setResponse(t,e){this._value=t,this._status=e,this._target.dispatchEvent(new CustomEvent("wcs-upload:response",{detail:{value:t,status:e},bubbles:!0}))}abort(){this._xhr&&(this._xhr.abort(),this._xhr=null)}upload(t,e,s={}){t||a("url is required."),e&&0!==e.length||a("files are required.");const r=this._doUpload(t,e,s);return this._promise=r,r}_doUpload(t,e,s){this.abort(),this._setLoading(!0),this._setProgress(0),this._setError(null);const{method:r="POST",headers:i={},fieldName:n="file"}=s,a=new FormData;for(let t=0;t<e.length;t++)a.append(n,e[t]);return new Promise(e=>{const s=new XMLHttpRequest;this._xhr=s,s.upload.addEventListener("progress",t=>{if(t.lengthComputable){const e=Math.round(t.loaded/t.total*100);this._setProgress(e)}}),s.addEventListener("load",()=>{if(this._xhr=null,this._status=s.status,s.status>=200&&s.status<300){let t=s.responseText;if((s.getResponseHeader("Content-Type")||"").includes("application/json"))try{t=JSON.parse(s.responseText)}catch{}this._setProgress(100),this._setResponse(t,s.status),this._setLoading(!1),e(t)}else{const t={status:s.status,statusText:s.statusText,body:s.responseText};this._setError(t),this._setLoading(!1),e(null)}}),s.addEventListener("error",()=>{this._xhr=null,this._setError({message:"Network error"}),this._setLoading(!1),e(null)}),s.addEventListener("abort",()=>{this._xhr=null,this._setLoading(!1),e(null)}),s.open(r,t);for(const[t,e]of Object.entries(i))s.setRequestHeader(t,e);s.send(a)})}}let l=!1;function u(t){const e=t.target;if(!(e instanceof Element))return;const s=e.closest(`[${i.triggerAttribute}]`);if(!s)return;const r=s.getAttribute(i.triggerAttribute);if(!r)return;const n=document.getElementById(r);n&&n instanceof h&&(n.files&&n.files.length>0&&n.url&&t.preventDefault(),n.upload())}class h extends HTMLElement{static hasConnectedCallbackPromise=!1;static wcBindable={...o.wcBindable,properties:[...o.wcBindable.properties,{name:"trigger",event:"wcs-upload:trigger-changed"},{name:"files",event:"wcs-upload:files-changed"}]};static get observedAttributes(){return["url"]}_core;_files=null;_trigger=!1;constructor(){super(),this._core=new o(this)}get url(){return this.getAttribute("url")||""}set url(t){this.setAttribute("url",t)}get method(){return(this.getAttribute("method")||"POST").toUpperCase()}set method(t){this.setAttribute("method",t)}get fieldName(){return this.getAttribute("field-name")||"file"}set fieldName(t){this.setAttribute("field-name",t)}get multiple(){return this.hasAttribute("multiple")}set multiple(t){t?this.setAttribute("multiple",""):this.removeAttribute("multiple")}get maxSize(){const t=this.getAttribute("max-size");return t?parseInt(t,10):1/0}set maxSize(t){this.setAttribute("max-size",String(t))}get accept(){return this.getAttribute("accept")||""}set accept(t){this.setAttribute("accept",t)}get manual(){return this.hasAttribute("manual")}set manual(t){t?this.setAttribute("manual",""):this.removeAttribute("manual")}get value(){return this._core.value}get loading(){return this._core.loading}get progress(){return this._core.progress}get error(){return this._core.error}get status(){return this._core.status}get promise(){return this._core.promise}get trigger(){return this._trigger}set trigger(t){!!t&&(this._trigger=!0,this.upload().finally(()=>{this._trigger=!1,this.dispatchEvent(new CustomEvent("wcs-upload:trigger-changed",{detail:!1,bubbles:!0}))}))}get files(){return this._files}set files(t){this._files=t,this.dispatchEvent(new CustomEvent("wcs-upload:files-changed",{detail:t,bubbles:!0})),!this.manual&&this.url&&t&&t.length>0&&this.upload()}_validate(t){const e=this.maxSize;if(e!==1/0)for(let s=0;s<t.length;s++)if(t[s].size>e)return{message:`File "${t[s].name}" exceeds maximum size of ${e} bytes.`};const s=this.accept;if(s){const e=s.split(",").map(t=>t.trim().toLowerCase());for(let r=0;r<t.length;r++){const i=t[r],n=i.type.toLowerCase(),a=i.name.toLowerCase();if(!e.some(t=>t.startsWith(".")?a.endsWith(t):t.endsWith("/*")?n.startsWith(t.slice(0,-1)):n===t))return{message:`File "${i.name}" does not match accepted types: ${s}`}}}return null}abort(){this._core.abort()}async upload(){const t=this._files;if(!t||0===t.length)return null;const e=this._validate(t);if(e)return this.dispatchEvent(new CustomEvent("wcs-upload:error",{detail:e,bubbles:!0})),null;const s=await this._core.upload(this.url,t,{method:this.method,fieldName:this.fieldName});return this._files===t&&(this._files=null,this.dispatchEvent(new CustomEvent("wcs-upload:files-changed",{detail:null,bubbles:!0}))),s}attributeChangedCallback(t,e,s){}connectedCallback(){this.style.display="none",i.autoTrigger&&(l||(l=!0,document.addEventListener("click",u)))}disconnectedCallback(){this._core.abort()}}function g(e){var s;e&&("boolean"==typeof(s=e).autoTrigger&&(t.autoTrigger=s.autoTrigger),"string"==typeof s.triggerAttribute&&(t.triggerAttribute=s.triggerAttribute),s.tagNames&&Object.assign(t.tagNames,s.tagNames),r=null),customElements.get(i.tagNames.upload)||customElements.define(i.tagNames.upload,h)}export{o as UploadCore,h as WcsUpload,g as bootstrapUpload,n as getConfig};
1
+ const t={autoTrigger:!0,triggerAttribute:"data-uploadtarget",tagNames:{upload:"wcs-upload"}};function e(t){if(null===t||"object"!=typeof t)return t;Object.freeze(t);for(const s of Object.keys(t))e(t[s]);return t}function s(t){if(null===t||"object"!=typeof t)return t;const e={};for(const r of Object.keys(t))e[r]=s(t[r]);return e}let r=null;const i=t;function n(){return r||(r=e(s(t))),r}function a(t){throw new Error(`[@wcstack/upload] ${t}`)}class o extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"value",event:"wcs-upload:response",getter:t=>t.detail.value},{name:"loading",event:"wcs-upload:loading-changed"},{name:"progress",event:"wcs-upload:progress"},{name:"error",event:"wcs-upload:error"},{name:"status",event:"wcs-upload:response",getter:t=>t.detail.status}],inputs:[{name:"url"},{name:"method"},{name:"fieldName"}],commands:[{name:"upload",async:!0},{name:"abort"}]};_target;_value=null;_loading=!1;_progress=0;_error=null;_status=0;_xhr=null;_promise=Promise.resolve(null);constructor(t){super(),this._target=t??this}get value(){return this._value}get loading(){return this._loading}get progress(){return this._progress}get error(){return this._error}get status(){return this._status}get promise(){return this._promise}_setLoading(t){this._loading=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:loading-changed",{detail:t,bubbles:!0}))}_setProgress(t){this._progress=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:progress",{detail:t,bubbles:!0}))}_setError(t){this._error=t,this._target.dispatchEvent(new CustomEvent("wcs-upload:error",{detail:t,bubbles:!0}))}_setResponse(t,e){this._value=t,this._status=e,this._target.dispatchEvent(new CustomEvent("wcs-upload:response",{detail:{value:t,status:e},bubbles:!0}))}abort(){this._xhr&&(this._xhr.abort(),this._xhr=null)}async upload(t,e,s={}){t||a("url is required."),e&&0!==e.length||a("files are required.");const r=this._doUpload(t,e,s);return this._promise=r,r}_doUpload(t,e,s){this.abort(),this._setLoading(!0),this._setProgress(0),this._setError(null);const{method:r="POST",headers:i={},fieldName:n="file"}=s,a=new FormData;for(let t=0;t<e.length;t++)a.append(n,e[t]);return new Promise(e=>{const s=new XMLHttpRequest;this._xhr=s,s.upload.addEventListener("progress",t=>{if(t.lengthComputable){const e=Math.round(t.loaded/t.total*100);this._setProgress(e)}}),s.addEventListener("load",()=>{if(this._xhr=null,this._status=s.status,s.status>=200&&s.status<300){let t=s.responseText;if((s.getResponseHeader("Content-Type")||"").includes("application/json"))try{t=JSON.parse(s.responseText)}catch{}this._setProgress(100),this._setResponse(t,s.status),this._setLoading(!1),e(t)}else{const t={status:s.status,statusText:s.statusText,body:s.responseText};this._setError(t),this._setLoading(!1),e(null)}}),s.addEventListener("error",()=>{this._xhr=null,this._setError({message:"Network error"}),this._setLoading(!1),e(null)}),s.addEventListener("abort",()=>{this._xhr=null,this._setLoading(!1),e(null)}),s.open(r,t);for(const[t,e]of Object.entries(i))s.setRequestHeader(t,e);s.send(a)})}}let l=!1;function u(t){const e=t.target;if(!(e instanceof Element))return;const s=e.closest(`[${i.triggerAttribute}]`);if(!s)return;const r=s.getAttribute(i.triggerAttribute);if(!r)return;const n=document.getElementById(r);n&&n instanceof h&&(n.files&&n.files.length>0&&n.url&&t.preventDefault(),n.upload())}class h extends HTMLElement{static hasConnectedCallbackPromise=!1;static wcBindable={...o.wcBindable,properties:[...o.wcBindable.properties,{name:"trigger",event:"wcs-upload:trigger-changed"},{name:"files",event:"wcs-upload:files-changed"}],inputs:[{name:"url"},{name:"method"},{name:"fieldName"},{name:"multiple"},{name:"maxSize"},{name:"accept"},{name:"manual"},{name:"files"},{name:"trigger"}]};static get observedAttributes(){return["url"]}_core;_files=null;_trigger=!1;constructor(){super(),this._core=new o(this)}get url(){return this.getAttribute("url")||""}set url(t){this.setAttribute("url",t)}get method(){return(this.getAttribute("method")||"POST").toUpperCase()}set method(t){this.setAttribute("method",t)}get fieldName(){return this.getAttribute("field-name")||"file"}set fieldName(t){this.setAttribute("field-name",t)}get multiple(){return this.hasAttribute("multiple")}set multiple(t){t?this.setAttribute("multiple",""):this.removeAttribute("multiple")}get maxSize(){const t=this.getAttribute("max-size");if(null===t)return 1/0;const e=parseInt(t,10);return Number.isFinite(e)&&e>=0?e:1/0}set maxSize(t){this.setAttribute("max-size",String(t))}get accept(){return this.getAttribute("accept")||""}set accept(t){this.setAttribute("accept",t)}get manual(){return this.hasAttribute("manual")}set manual(t){t?this.setAttribute("manual",""):this.removeAttribute("manual")}get value(){return this._core.value}get loading(){return this._core.loading}get progress(){return this._core.progress}get error(){return this._core.error}get status(){return this._core.status}get promise(){return this._core.promise}get trigger(){return this._trigger}set trigger(t){!!t&&(this._trigger=!0,this.upload().finally(()=>{this._trigger=!1,this.dispatchEvent(new CustomEvent("wcs-upload:trigger-changed",{detail:!1,bubbles:!0}))}))}get files(){return this._files}set files(t){this._files=t,this.dispatchEvent(new CustomEvent("wcs-upload:files-changed",{detail:t,bubbles:!0})),!this.manual&&this.url&&t&&t.length>0&&this.upload()}_validate(t){const e=this.maxSize;if(e!==1/0)for(let s=0;s<t.length;s++)if(t[s].size>e)return{message:`File "${t[s].name}" exceeds maximum size of ${e} bytes.`};const s=this.accept;if(s){const e=s.split(",").map(t=>t.trim().toLowerCase());for(let r=0;r<t.length;r++){const i=t[r],n=i.type.toLowerCase(),a=i.name.toLowerCase();if(!e.some(t=>t.startsWith(".")?a.endsWith(t):t.endsWith("/*")?""!==n&&n.startsWith(t.slice(0,-1)):""!==n&&n===t))return{message:`File "${i.name}" does not match accepted types: ${s}`}}}return null}abort(){this._core.abort()}async upload(){const t=this._files;if(!t||0===t.length||!this.url)return null;const e=this._validate(t);if(e)return this.dispatchEvent(new CustomEvent("wcs-upload:error",{detail:e,bubbles:!0})),null;const s=await this._core.upload(this.url,t,{method:this.method,fieldName:this.fieldName});return this._files===t&&(this._files=null,this.dispatchEvent(new CustomEvent("wcs-upload:files-changed",{detail:null,bubbles:!0}))),s}attributeChangedCallback(t,e,s){}connectedCallback(){this.style.display="none",i.autoTrigger&&(l||(l=!0,document.addEventListener("click",u)))}disconnectedCallback(){this._core.abort()}}function d(e){var s;e&&("boolean"==typeof(s=e).autoTrigger&&(t.autoTrigger=s.autoTrigger),"string"==typeof s.triggerAttribute&&(t.triggerAttribute=s.triggerAttribute),s.tagNames&&Object.assign(t.tagNames,s.tagNames),r=null),customElements.get(i.tagNames.upload)||customElements.define(i.tagNames.upload,h)}export{o as UploadCore,h as WcsUpload,d as bootstrapUpload,n as getConfig};
2
2
  //# sourceMappingURL=index.esm.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/raiseError.ts","../src/core/UploadCore.ts","../src/autoTrigger.ts","../src/components/Upload.ts","../src/bootstrapUpload.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\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":"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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\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n upload: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-uploadtarget\",\n tagNames: {\n upload: \"wcs-upload\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\n// `config` は内部用のライブビュー(live view)。setConfig() の更新が即座に反映される\n// 実体 `_config` をそのまま公開しており、凍結もクローンもしていない。autoTrigger /\n// components など同パッケージ内のモジュールが最新値を読むための窓口であり、\n// 「変更不可なスナップショット」が必要な外部利用には getConfig()(凍結クローンを返す)\n// を使うこと。型が readonly なのは内部からの誤書き換えを抑止するための表明にすぎない。\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","export function raiseError(message: string): never {\n throw new Error(`[@wcstack/upload] ${message}`);\n}\n","import { raiseError } from \"../raiseError.js\";\nimport { IWcBindable } from \"../types.js\";\n\nexport interface UploadRequestOptions {\n method?: string;\n headers?: Record<string, string>;\n fieldName?: string;\n}\n\nexport class UploadCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"value\", event: \"wcs-upload:response\", getter: (e: Event) => (e as CustomEvent).detail.value },\n { name: \"loading\", event: \"wcs-upload:loading-changed\" },\n { name: \"progress\", event: \"wcs-upload:progress\" },\n { name: \"error\", event: \"wcs-upload:error\" },\n { name: \"status\", event: \"wcs-upload:response\", getter: (e: Event) => (e as CustomEvent).detail.status },\n ],\n inputs: [\n { name: \"url\" },\n { name: \"method\" },\n { name: \"fieldName\" },\n ],\n commands: [\n { name: \"upload\", async: true },\n { name: \"abort\" },\n ],\n };\n\n private _target: EventTarget;\n private _value: any = null;\n private _loading: boolean = false;\n private _progress: number = 0;\n private _error: any = null;\n private _status: number = 0;\n private _xhr: XMLHttpRequest | null = null;\n private _promise: Promise<any> = Promise.resolve(null);\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get value(): any {\n return this._value;\n }\n\n get loading(): boolean {\n return this._loading;\n }\n\n get progress(): number {\n return this._progress;\n }\n\n get error(): any {\n return this._error;\n }\n\n get status(): number {\n return this._status;\n }\n\n get promise(): Promise<any> {\n return this._promise;\n }\n\n // --- State setters with event dispatch ---\n\n private _setLoading(loading: boolean): void {\n this._loading = loading;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:loading-changed\", {\n detail: loading,\n bubbles: true,\n }));\n }\n\n private _setProgress(progress: number): void {\n this._progress = progress;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:progress\", {\n detail: progress,\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n private _setResponse(value: any, status: number): void {\n this._value = value;\n this._status = status;\n this._target.dispatchEvent(new CustomEvent(\"wcs-upload:response\", {\n detail: { value, status },\n bubbles: true,\n }));\n }\n\n // --- Public API ---\n\n abort(): void {\n // `_xhr` は send() の直前に同期で代入されるため、send 前に外部から abort が\n // 割り込む余地はない(割り込み点となる await が存在しない)。よって XHR.abort()\n // は常に進行中のリクエストに対して呼ばれ、abort イベントが発火して loading を\n // 解除する。loading の解除を abort イベントハンドラに集約しているのは、\n // ネットワークエラー/HTTP エラー/正常完了/中断のすべてで解除経路を一本化し、\n // FetchCore.abort() と挙動を揃えるため。\n if (this._xhr) {\n this._xhr.abort();\n this._xhr = null;\n }\n }\n\n async upload(url: string, files: FileList | File[], options: UploadRequestOptions = {}): Promise<any> {\n if (!url) {\n raiseError(\"url is required.\");\n }\n if (!files || files.length === 0) {\n raiseError(\"files are required.\");\n }\n\n const p = this._doUpload(url, files, options);\n this._promise = p;\n return p;\n }\n\n // --- Internal ---\n\n private _doUpload(url: string, files: FileList | File[], options: UploadRequestOptions): Promise<any> {\n // 既存のアップロードを中止\n this.abort();\n\n this._setLoading(true);\n this._setProgress(0);\n this._setError(null);\n\n const {\n method = \"POST\",\n headers = {},\n fieldName = \"file\",\n } = options;\n\n const formData = new FormData();\n for (let i = 0; i < files.length; i++) {\n formData.append(fieldName, files[i]);\n }\n\n return new Promise<any>((resolve) => {\n const xhr = new XMLHttpRequest();\n this._xhr = xhr;\n\n xhr.upload.addEventListener(\"progress\", (event: ProgressEvent) => {\n if (event.lengthComputable) {\n const percent = Math.round((event.loaded / event.total) * 100);\n this._setProgress(percent);\n }\n });\n\n xhr.addEventListener(\"load\", () => {\n this._xhr = null;\n this._status = xhr.status;\n\n if (xhr.status >= 200 && xhr.status < 300) {\n let value: any = xhr.responseText;\n const contentType = xhr.getResponseHeader(\"Content-Type\") || \"\";\n if (contentType.includes(\"application/json\")) {\n try {\n value = JSON.parse(xhr.responseText);\n } catch {\n // テキストのまま\n }\n }\n this._setProgress(100);\n this._setResponse(value, xhr.status);\n this._setLoading(false);\n resolve(value);\n } else {\n const error = {\n status: xhr.status,\n statusText: xhr.statusText,\n body: xhr.responseText,\n };\n this._setError(error);\n this._setLoading(false);\n resolve(null);\n }\n });\n\n xhr.addEventListener(\"error\", () => {\n this._xhr = null;\n this._setError({ message: \"Network error\" });\n this._setLoading(false);\n resolve(null);\n });\n\n xhr.addEventListener(\"abort\", () => {\n this._xhr = null;\n this._setLoading(false);\n resolve(null);\n });\n\n xhr.open(method, url);\n\n for (const [name, value] of Object.entries(headers)) {\n xhr.setRequestHeader(name, value);\n }\n\n xhr.send(formData);\n });\n }\n}\n","import { config } from \"./config.js\";\nimport { WcsUpload } from \"./components/Upload.js\";\n\nlet registered = false;\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const uploadId = triggerElement.getAttribute(config.triggerAttribute);\n if (!uploadId) return;\n\n const uploadElement = document.getElementById(uploadId) as WcsUpload | null;\n if (!uploadElement || !(uploadElement instanceof WcsUpload)) return;\n\n // ファイルと URL が揃っている場合のみ既定動作を抑止\n if (uploadElement.files && uploadElement.files.length > 0 && uploadElement.url) {\n event.preventDefault();\n }\n uploadElement.upload();\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","import { config } from \"../config.js\";\nimport { IWcBindable, WcsUploadError } from \"../types.js\";\nimport { UploadCore } from \"../core/UploadCore.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\nexport class WcsUpload extends HTMLElement {\n static hasConnectedCallbackPromise = false;\n static wcBindable: IWcBindable = {\n ...UploadCore.wcBindable,\n properties: [\n ...UploadCore.wcBindable.properties,\n { name: \"trigger\", event: \"wcs-upload:trigger-changed\" },\n { name: \"files\", event: \"wcs-upload:files-changed\" },\n ],\n // Shell-level input surface. The Core declares only the portable `url` / `method` /\n // `fieldName`; the Shell adds the DOM-driven settable surface. No `attribute` hints\n // are given: the `url` / `method` / `fieldName` / `multiple` / `maxSize` / `accept` /\n // `manual` setters already reflect to their attributes, so a binding system that\n // mirrors inputs[].attribute would set the attribute twice (`files` / `trigger` are\n // not attribute-backed). `commands` (upload / abort) are inherited unchanged from the\n // Core via the spread above.\n inputs: [\n { name: \"url\" },\n { name: \"method\" },\n { name: \"fieldName\" },\n { name: \"multiple\" },\n { name: \"maxSize\" },\n { name: \"accept\" },\n { name: \"manual\" },\n { name: \"files\" },\n { name: \"trigger\" },\n ],\n };\n // `url` を観測するのは FetchCore のシェルと構造を揃えるためだが、upload は\n // url 変更だけでは送信できない(files が必須)。そのため attributeChangedCallback は\n // 意図的に何もしない。url 変更で自動送信しないことは仕様であり、テストで担保している。\n static get observedAttributes(): string[] { return [\"url\"]; }\n\n private _core: UploadCore;\n private _files: FileList | File[] | null = null;\n private _trigger: boolean = false;\n\n constructor() {\n super();\n this._core = new UploadCore(this);\n }\n\n // --- Attribute accessors ---\n\n get url(): string {\n return this.getAttribute(\"url\") || \"\";\n }\n\n set url(value: string) {\n this.setAttribute(\"url\", value);\n }\n\n get method(): string {\n return (this.getAttribute(\"method\") || \"POST\").toUpperCase();\n }\n\n set method(value: string) {\n this.setAttribute(\"method\", value);\n }\n\n get fieldName(): string {\n return this.getAttribute(\"field-name\") || \"file\";\n }\n\n set fieldName(value: string) {\n this.setAttribute(\"field-name\", value);\n }\n\n get multiple(): boolean {\n return this.hasAttribute(\"multiple\");\n }\n\n set multiple(value: boolean) {\n if (value) {\n this.setAttribute(\"multiple\", \"\");\n } else {\n this.removeAttribute(\"multiple\");\n }\n }\n\n get maxSize(): number {\n const attr = this.getAttribute(\"max-size\");\n if (attr === null) {\n return Infinity;\n }\n // 不正値(NaN になる \"abc\" など)や負数は「制限なし」(Infinity) として扱う。\n // NaN を返すと `size > NaN` が常に false になりサイズ検証が無言で無効化され、\n // 負数を返すと全ファイルが拒否されるため、いずれも安全側の Infinity に丸める。\n const n = parseInt(attr, 10);\n return Number.isFinite(n) && n >= 0 ? n : Infinity;\n }\n\n set maxSize(value: number) {\n this.setAttribute(\"max-size\", String(value));\n }\n\n get accept(): string {\n return this.getAttribute(\"accept\") || \"\";\n }\n\n set accept(value: string) {\n this.setAttribute(\"accept\", value);\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get value(): any {\n return this._core.value;\n }\n\n get loading(): boolean {\n return this._core.loading;\n }\n\n get progress(): number {\n return this._core.progress;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n get status(): number {\n return this._core.status;\n }\n\n get promise(): Promise<any> {\n return this._core.promise;\n }\n\n // --- Command properties ---\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n // 進行中に再度 trigger=true が来ても再入ガードはしない(FetchCore シェルと同一)。\n // upload() → _core.upload() が先頭で既存リクエストを abort し新規開始するため、\n // 連続トリガは「前回を中止して新しいアップロードを開始する」挙動になる。\n // 各 upload() の settle ごとに trigger-changed(false) が 1 回発火する。\n const v = !!value;\n if (v) {\n this._trigger = true;\n this.upload().finally(() => {\n this._trigger = false;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:trigger-changed\", {\n detail: false,\n bubbles: true,\n }));\n });\n }\n }\n\n get files(): FileList | File[] | null {\n return this._files;\n }\n\n set files(value: FileList | File[] | null) {\n this._files = value;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\n detail: value,\n bubbles: true,\n }));\n if (!this.manual && this.url && value && value.length > 0) {\n this.upload();\n }\n }\n\n // --- Validation ---\n\n private _validate(files: FileList | File[]): WcsUploadError | null {\n const maxSize = this.maxSize;\n if (maxSize !== Infinity) {\n for (let i = 0; i < files.length; i++) {\n if (files[i].size > maxSize) {\n return { message: `File \"${files[i].name}\" exceeds maximum size of ${maxSize} bytes.` };\n }\n }\n }\n\n const accept = this.accept;\n if (accept) {\n const acceptList = accept.split(\",\").map(s => s.trim().toLowerCase());\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n const fileType = file.type.toLowerCase();\n const fileName = file.name.toLowerCase();\n // file.type が空文字(OS が MIME を判定できないファイル)の場合、MIME 系\n // パターン(`image/*` / 厳密 MIME)は一致しない。その場合でも accept に\n // 拡張子パターン(`.pdf` 等)が含まれ拡張子が一致すれば受理される。\n // accept が MIME 系のみのときは型を確認できないため拒否する(安全側)。\n const matched = acceptList.some(pattern => {\n if (pattern.startsWith(\".\")) {\n return fileName.endsWith(pattern);\n }\n if (pattern.endsWith(\"/*\")) {\n return fileType !== \"\" && fileType.startsWith(pattern.slice(0, -1));\n }\n return fileType !== \"\" && fileType === pattern;\n });\n if (!matched) {\n return { message: `File \"${file.name}\" does not match accepted types: ${accept}` };\n }\n }\n }\n\n return null;\n }\n\n // --- Public methods ---\n\n abort(): void {\n this._core.abort();\n }\n\n async upload(): Promise<any> {\n const files = this._files;\n // url 未設定は no-op(null)。Core は url 空で throw するが、Shell は url/files の\n // ライフサイクルを所有しており「送信先が無い」を「ファイル無し」と同じ無操作として扱う。\n // これにより set trigger / set files の fire-and-forget 経路で unhandled rejection が\n // 発生せず、README の「upload() は全終了ケースで resolve し never reject」契約とも整合する。\n if (!files || files.length === 0 || !this.url) {\n return null;\n }\n\n const validationError = this._validate(files);\n if (validationError) {\n this.dispatchEvent(new CustomEvent(\"wcs-upload:error\", {\n detail: validationError,\n bubbles: true,\n }));\n return null;\n }\n\n const result = await this._core.upload(this.url, files, {\n method: this.method,\n fieldName: this.fieldName,\n });\n\n // 自分が開始したアップロードのファイルだけをリセット\n // (途中で新しい files がセットされていたら触らない)\n if (this._files === files) {\n this._files = null;\n this.dispatchEvent(new CustomEvent(\"wcs-upload:files-changed\", {\n detail: null,\n bubbles: true,\n }));\n }\n\n return result;\n }\n\n // --- Lifecycle ---\n\n attributeChangedCallback(_name: string, _oldValue: string | null, _newValue: string | null): void {\n // 意図的に空。url 変更ではアップロードを自動実行しない(files が必要なため)。\n // observedAttributes のコメント参照。\n }\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n }\n\n disconnectedCallback(): void {\n this._core.abort();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapUpload(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { WcsUpload } from \"./components/Upload.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.upload)) {\n customElements.define(config.tagNames.upload, WcsUpload);\n }\n}\n"],"names":["_config","autoTrigger","triggerAttribute","tagNames","upload","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","raiseError","message","Error","UploadCore","EventTarget","static","protocol","version","properties","name","event","getter","e","detail","value","status","inputs","commands","async","_target","_value","_loading","_progress","_error","_status","_xhr","_promise","Promise","resolve","constructor","target","super","this","loading","progress","error","promise","_setLoading","dispatchEvent","CustomEvent","bubbles","_setProgress","_setError","_setResponse","abort","url","files","options","length","p","_doUpload","method","headers","fieldName","formData","FormData","i","append","xhr","XMLHttpRequest","addEventListener","lengthComputable","percent","Math","round","loaded","total","responseText","getResponseHeader","includes","JSON","parse","statusText","body","open","entries","setRequestHeader","send","registered","handleClick","Element","triggerElement","closest","uploadId","getAttribute","uploadElement","document","getElementById","WcsUpload","preventDefault","HTMLElement","wcBindable","observedAttributes","_core","_files","_trigger","setAttribute","toUpperCase","multiple","hasAttribute","removeAttribute","maxSize","attr","Infinity","n","parseInt","Number","isFinite","String","accept","manual","trigger","finally","_validate","size","acceptList","split","map","s","trim","toLowerCase","file","fileType","type","fileName","some","pattern","startsWith","endsWith","slice","validationError","result","attributeChangedCallback","_name","_oldValue","_newValue","connectedCallback","style","display","disconnectedCallback","bootstrapUpload","userConfig","partialConfig","assign","customElements","get","define"],"mappings":"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"}