@wcstack/upload 4.5.0 → 4.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -213,6 +213,7 @@ declare class WcsUpload extends HTMLElement {
213
213
  private _files;
214
214
  private _trigger;
215
215
  private _told;
216
+ private _waitingForUrl;
216
217
  private _connectedCallbackPromise;
217
218
  private _internals;
218
219
  constructor();
@@ -249,7 +250,7 @@ declare class WcsUpload extends HTMLElement {
249
250
  abort(): void;
250
251
  upload(): Promise<any>;
251
252
  private _warnNotReady;
252
- attributeChangedCallback(_name: string, _oldValue: string | null, _newValue: string | null): void;
253
+ attributeChangedCallback(_name: string, _oldValue: string | null, newValue: string | null): void;
253
254
  connectedCallback(): void;
254
255
  disconnectedCallback(): void;
255
256
  }
package/dist/index.esm.js CHANGED
@@ -830,6 +830,21 @@ function hasAccessorOnPrototype(target, name) {
830
830
  }
831
831
  return false;
832
832
  }
833
+ // 属性になってしまったオブジェクトの入力(`files="[object File]"`)を、要素ごとに 1 回だけ言う。
834
+ // React 19 は定義前の要素にプロパティが無いのでオブジェクトを属性に書き、Vue の `.attr` も
835
+ // 書く。要素はその入力をプロパティでしか読まないので、何も受け取らず、何も言わなかった
836
+ // (docs/seam-apps.md、fw-inventory)。
837
+ const toldObjectAttribute = new WeakSet();
838
+ function warnObjectAttribute(element, name, value) {
839
+ if (toldObjectAttribute.has(element))
840
+ return;
841
+ toldObjectAttribute.add(element);
842
+ const tag = element.localName ?? "element";
843
+ console.warn(`[wcs/input-as-attribute] <${tag}> has the attribute ${name}="${value}": an object was written as an ` +
844
+ `attribute, so the element did not receive it. A framework does that when the property is set before the ` +
845
+ `element's definition loads (React 19), or when told to (Vue's .attr). Load the definition before rendering, ` +
846
+ `or assign the property through a ref (Vue: .prop). (Said once per element.)`, element);
847
+ }
833
848
  /**
834
849
  * `connectedCallback` の先頭で呼ぶ。宣言済み input のうち upgrade 前の代入で
835
850
  * accessor をシャドウしている own プロパティを、delete → 再代入で setter に通し直す。
@@ -837,14 +852,19 @@ function hasAccessorOnPrototype(target, name) {
837
852
  * - 冪等: 再代入は accessor を通るので own プロパティは残らず、2 回目以降は no-op。
838
853
  * - 宣言に `inputs` が無い要素、`wcBindable` を持たない要素では何もしない。
839
854
  * - 値の意味は変えない。今まで捨てられていた代入が届くようになる一方向の変化。
855
+ * - 値が `[object …]` の属性(属性に書かれてしまったオブジェクトの入力)は、要素ごとに 1 回警告する。
840
856
  */
841
857
  function upgradeProperties(element) {
842
858
  const declaration = element.constructor?.wcBindable;
843
859
  const inputs = declaration?.inputs;
844
860
  if (inputs === undefined)
845
861
  return;
862
+ const getAttribute = element.getAttribute;
846
863
  for (const input of inputs) {
847
864
  const name = input.name;
865
+ const attribute = typeof getAttribute === "function" ? getAttribute.call(element, name.toLowerCase()) : null;
866
+ if (attribute !== null && attribute.startsWith("[object "))
867
+ warnObjectAttribute(element, name, attribute);
848
868
  if (!Object.prototype.hasOwnProperty.call(element, name))
849
869
  continue;
850
870
  if (!hasAccessorOnPrototype(element, name))
@@ -939,9 +959,10 @@ class WcsUpload extends HTMLElement {
939
959
  { name: "trigger" },
940
960
  ],
941
961
  };
942
- // `url` を観測するのは FetchCore のシェルと構造を揃えるためだが、upload は
943
- // url 変更だけでは送信できない(files が必須)。そのため attributeChangedCallback は
944
- // 意図的に何もしない。url 変更で自動送信しないことは仕様であり、テストで担保している。
962
+ // `url` を観測するのは、url の無いうちに自動送信の files を受けたとき、url が来たらその
963
+ // files を送るため(4.5 までは url を待たずに黙って何もしなかった。JSX の props や data-wcs の
964
+ // 束縛は書いた順に当たるので、files を url より前に書くと送られなかった — docs/seam-apps.md、
965
+ // state-field-report と fw-inventory)。それ以外の url の変更では送らない。
945
966
  static get observedAttributes() { return ["url"]; }
946
967
  _core;
947
968
  _files = null;
@@ -949,6 +970,8 @@ class WcsUpload extends HTMLElement {
949
970
  // The reasons `[wcs/command-not-ready]` was said for, once each per element
950
971
  // (docs/v4-direction-2026-10.md §5.1, the I/O command policy).
951
972
  _told = null;
973
+ // automatic-mode files assigned while there was no url: sent when the url arrives
974
+ _waitingForUrl = false;
952
975
  _connectedCallbackPromise = Promise.resolve();
953
976
  _internals = null;
954
977
  constructor() {
@@ -1122,12 +1145,10 @@ class WcsUpload extends HTMLElement {
1122
1145
  detail: files,
1123
1146
  bubbles: true,
1124
1147
  }));
1125
- if (!this.manual && files && files.length > 0) {
1126
- if (this.url)
1127
- this.upload();
1128
- else
1129
- this._warnNotReady("files were assigned while there is no url");
1130
- }
1148
+ // files that arrive before the url wait for it (automatic mode only)
1149
+ this._waitingForUrl = !this.manual && !!files && files.length > 0 && !this.url;
1150
+ if (!this.manual && files && files.length > 0 && this.url)
1151
+ this.upload();
1131
1152
  }
1132
1153
  // --- Validation ---
1133
1154
  _validate(files) {
@@ -1207,20 +1228,26 @@ class WcsUpload extends HTMLElement {
1207
1228
  return result;
1208
1229
  }
1209
1230
  // A refused upload sent nothing and said nothing (no `error`, by design): a `trigger`
1210
- // written before `url` / `files` in one `data-wcs` (bindings apply in the order
1211
- // written), a retry after the files were used up, files picked before the url is known.
1231
+ // written before `url` / `files` (`data-wcs` bindings and a framework's props are applied in
1232
+ // the order written), a retry after the files were used up.
1212
1233
  _warnNotReady(reason) {
1213
1234
  if (this._told?.has(reason))
1214
1235
  return;
1215
1236
  (this._told ??= new Set()).add(reason);
1216
1237
  console.warn(`[@wcstack/upload] [wcs/command-not-ready] The upload was refused: ${reason}, so nothing is sent. ` +
1217
- "Write url and files before trigger (bindings apply in the order written), and assign files again " +
1218
- "for each retry: an upload uses them up. (Said once per element and reason.)", this);
1238
+ "Write url and files before trigger (data-wcs bindings and a framework's props are applied in the order " +
1239
+ "written), and assign files again for each retry: an upload uses them up. (Said once per element and reason.)", this);
1219
1240
  }
1220
1241
  // --- Lifecycle ---
1221
- attributeChangedCallback(_name, _oldValue, _newValue) {
1222
- // 意図的に空。url 変更ではアップロードを自動実行しない(files が必要なため)。
1223
- // observedAttributes のコメント参照。
1242
+ attributeChangedCallback(_name, _oldValue, newValue) {
1243
+ // url だけの変更では送らない。url の無いうちに受けた自動送信の files は、url が来たら送る。
1244
+ // 接続は問わない: React 19 は要素を文書に入れる前に props を当てる(files の setter も、url が
1245
+ // あれば接続の前に送る)。
1246
+ if (!this._waitingForUrl || !newValue || this.manual)
1247
+ return;
1248
+ // (waiting means files were assigned and not replaced since: the setter resets it)
1249
+ this._waitingForUrl = false;
1250
+ this.upload();
1224
1251
  }
1225
1252
  connectedCallback() {
1226
1253
  // upgrade 前に代入された input を取り込み直す(doc 13 §1.2 / Phase A1)