@idds/js 1.0.58 → 1.0.59

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.
@@ -998,18 +998,10 @@ var InaUI = (() => {
998
998
  filesContainer.className = `${PREFIX}-file-upload__files`;
999
999
  container.appendChild(filesContainer);
1000
1000
  }
1001
- let errorsContainer = container.querySelector(
1002
- `.${PREFIX}-file-upload__errors`
1003
- );
1004
- if (!errorsContainer) {
1005
- errorsContainer = document.createElement("div");
1006
- errorsContainer.className = `${PREFIX}-file-upload__errors`;
1007
- container.appendChild(errorsContainer);
1008
- }
1009
1001
  if (!input || !dropzone) return;
1010
1002
  const maxFiles = parseInt(container.getAttribute("data-max-files")) || 0;
1011
1003
  const maxSize = parseInt(container.getAttribute("data-max-size")) || 0;
1012
- const allowedExtensions = (container.getAttribute("data-allowed-extensions") || "").split(",").filter(Boolean);
1004
+ const allowedExtensions = (container.getAttribute("data-allowed-extensions") || "").toLowerCase().split(",").map((ext) => ext.trim()).filter(Boolean);
1013
1005
  const multiple = input.hasAttribute("multiple");
1014
1006
  let uploadedFiles = [];
1015
1007
  const formatFileSize = (bytes) => {
@@ -1023,7 +1015,7 @@ var InaUI = (() => {
1023
1015
  const validateFile = (file) => {
1024
1016
  if (allowedExtensions.length > 0) {
1025
1017
  const ext = file.name.split(".").pop().toLowerCase();
1026
- if (!allowedExtensions.includes(ext.toLowerCase())) {
1018
+ if (!allowedExtensions.includes(ext)) {
1027
1019
  return {
1028
1020
  valid: false,
1029
1021
  error: `Ekstensi file harus: ${allowedExtensions.join(", ")}`
@@ -1040,7 +1032,11 @@ var InaUI = (() => {
1040
1032
  };
1041
1033
  const renderFiles = () => {
1042
1034
  filesContainer.innerHTML = "";
1043
- errorsContainer.innerHTML = "";
1035
+ if (uploadedFiles.length > 0) {
1036
+ filesContainer.style.display = "flex";
1037
+ } else {
1038
+ filesContainer.style.display = "none";
1039
+ }
1044
1040
  uploadedFiles.forEach((f, index) => {
1045
1041
  const fileEl = document.createElement("div");
1046
1042
  fileEl.className = `${PREFIX}-file-upload__file`;
@@ -1085,59 +1081,63 @@ var InaUI = (() => {
1085
1081
  });
1086
1082
  };
1087
1083
  const addFiles = (newFiles) => {
1088
- const validNewFiles = [];
1089
- const errors = [];
1084
+ const addedFiles = [];
1090
1085
  Array.from(newFiles).forEach((file) => {
1091
1086
  const validation = validateFile(file);
1092
1087
  if (!validation.valid) {
1093
- errors.push({ file, error: validation.error });
1088
+ addedFiles.push({
1089
+ file,
1090
+ status: "error",
1091
+ error: validation.error,
1092
+ id: generateId()
1093
+ });
1094
1094
  } else {
1095
- validNewFiles.push({
1095
+ addedFiles.push({
1096
1096
  file,
1097
1097
  status: "idle",
1098
- // In vanilla we might simulate upload or just set success immediately
1099
1098
  id: generateId()
1100
1099
  });
1101
1100
  }
1102
1101
  });
1102
+ const existingValidCount = uploadedFiles.filter(
1103
+ (f) => f.status !== "error"
1104
+ ).length;
1105
+ const newValidCount = addedFiles.filter(
1106
+ (f) => f.status !== "error"
1107
+ ).length;
1103
1108
  if (multiple && maxFiles > 0) {
1104
- if (uploadedFiles.length + validNewFiles.length > maxFiles) {
1105
- const spaceLeft = maxFiles - uploadedFiles.length;
1106
- if (spaceLeft > 0) {
1107
- validNewFiles.splice(spaceLeft);
1108
- } else {
1109
- validNewFiles.length = 0;
1109
+ if (existingValidCount + newValidCount > maxFiles) {
1110
+ let validFiles = addedFiles.filter((f) => f.status !== "error");
1111
+ let errorFiles = addedFiles.filter((f) => f.status === "error");
1112
+ const spaceLeft = maxFiles - existingValidCount;
1113
+ if (spaceLeft < validFiles.length) {
1114
+ validFiles = validFiles.slice(0, spaceLeft);
1110
1115
  }
1116
+ const limitedAddedFiles = [...errorFiles, ...validFiles];
1111
1117
  }
1112
1118
  }
1113
1119
  if (!multiple) {
1114
- uploadedFiles = validNewFiles.slice(0, 1);
1120
+ uploadedFiles = addedFiles.slice(0, 1);
1115
1121
  } else {
1116
- uploadedFiles = [...uploadedFiles, ...validNewFiles];
1122
+ uploadedFiles = [...uploadedFiles, ...addedFiles];
1117
1123
  }
1118
- errorsContainer.innerHTML = "";
1119
- errors.forEach((err) => {
1120
- const errEl = document.createElement("div");
1121
- errEl.className = `${PREFIX}-file-upload__error-message`;
1122
- errEl.textContent = `${err.file.name}: ${err.error}`;
1123
- errorsContainer.appendChild(errEl);
1124
- });
1125
1124
  renderFiles();
1126
1125
  container.dispatchEvent(
1127
1126
  new CustomEvent("file-upload:change", {
1128
1127
  detail: {
1129
1128
  files: uploadedFiles.map((f) => f.file),
1130
- errors
1129
+ errors: uploadedFiles.filter((f) => f.status === "error").map((f) => ({ file: f.file, error: f.error }))
1131
1130
  },
1132
1131
  bubbles: true
1133
1132
  })
1134
1133
  );
1135
- validNewFiles.forEach((f) => {
1134
+ const filesToUpload = uploadedFiles.filter((f) => f.status === "idle");
1135
+ filesToUpload.forEach((f) => {
1136
1136
  f.status = "uploading";
1137
1137
  });
1138
1138
  renderFiles();
1139
1139
  setTimeout(() => {
1140
- validNewFiles.forEach((f) => {
1140
+ filesToUpload.forEach((f) => {
1141
1141
  f.status = "success";
1142
1142
  });
1143
1143
  renderFiles();
package/dist/index.js CHANGED
@@ -1001,18 +1001,10 @@ function initFileUpload(rootSelector = `.${PREFIX}-file-upload`) {
1001
1001
  filesContainer.className = `${PREFIX}-file-upload__files`;
1002
1002
  container.appendChild(filesContainer);
1003
1003
  }
1004
- let errorsContainer = container.querySelector(
1005
- `.${PREFIX}-file-upload__errors`
1006
- );
1007
- if (!errorsContainer) {
1008
- errorsContainer = document.createElement("div");
1009
- errorsContainer.className = `${PREFIX}-file-upload__errors`;
1010
- container.appendChild(errorsContainer);
1011
- }
1012
1004
  if (!input || !dropzone) return;
1013
1005
  const maxFiles = parseInt(container.getAttribute("data-max-files")) || 0;
1014
1006
  const maxSize = parseInt(container.getAttribute("data-max-size")) || 0;
1015
- const allowedExtensions = (container.getAttribute("data-allowed-extensions") || "").split(",").filter(Boolean);
1007
+ const allowedExtensions = (container.getAttribute("data-allowed-extensions") || "").toLowerCase().split(",").map((ext) => ext.trim()).filter(Boolean);
1016
1008
  const multiple = input.hasAttribute("multiple");
1017
1009
  let uploadedFiles = [];
1018
1010
  const formatFileSize = (bytes) => {
@@ -1026,7 +1018,7 @@ function initFileUpload(rootSelector = `.${PREFIX}-file-upload`) {
1026
1018
  const validateFile = (file) => {
1027
1019
  if (allowedExtensions.length > 0) {
1028
1020
  const ext = file.name.split(".").pop().toLowerCase();
1029
- if (!allowedExtensions.includes(ext.toLowerCase())) {
1021
+ if (!allowedExtensions.includes(ext)) {
1030
1022
  return {
1031
1023
  valid: false,
1032
1024
  error: `Ekstensi file harus: ${allowedExtensions.join(", ")}`
@@ -1043,7 +1035,11 @@ function initFileUpload(rootSelector = `.${PREFIX}-file-upload`) {
1043
1035
  };
1044
1036
  const renderFiles = () => {
1045
1037
  filesContainer.innerHTML = "";
1046
- errorsContainer.innerHTML = "";
1038
+ if (uploadedFiles.length > 0) {
1039
+ filesContainer.style.display = "flex";
1040
+ } else {
1041
+ filesContainer.style.display = "none";
1042
+ }
1047
1043
  uploadedFiles.forEach((f, index) => {
1048
1044
  const fileEl = document.createElement("div");
1049
1045
  fileEl.className = `${PREFIX}-file-upload__file`;
@@ -1088,59 +1084,63 @@ function initFileUpload(rootSelector = `.${PREFIX}-file-upload`) {
1088
1084
  });
1089
1085
  };
1090
1086
  const addFiles = (newFiles) => {
1091
- const validNewFiles = [];
1092
- const errors = [];
1087
+ const addedFiles = [];
1093
1088
  Array.from(newFiles).forEach((file) => {
1094
1089
  const validation = validateFile(file);
1095
1090
  if (!validation.valid) {
1096
- errors.push({ file, error: validation.error });
1091
+ addedFiles.push({
1092
+ file,
1093
+ status: "error",
1094
+ error: validation.error,
1095
+ id: generateId()
1096
+ });
1097
1097
  } else {
1098
- validNewFiles.push({
1098
+ addedFiles.push({
1099
1099
  file,
1100
1100
  status: "idle",
1101
- // In vanilla we might simulate upload or just set success immediately
1102
1101
  id: generateId()
1103
1102
  });
1104
1103
  }
1105
1104
  });
1105
+ const existingValidCount = uploadedFiles.filter(
1106
+ (f) => f.status !== "error"
1107
+ ).length;
1108
+ const newValidCount = addedFiles.filter(
1109
+ (f) => f.status !== "error"
1110
+ ).length;
1106
1111
  if (multiple && maxFiles > 0) {
1107
- if (uploadedFiles.length + validNewFiles.length > maxFiles) {
1108
- const spaceLeft = maxFiles - uploadedFiles.length;
1109
- if (spaceLeft > 0) {
1110
- validNewFiles.splice(spaceLeft);
1111
- } else {
1112
- validNewFiles.length = 0;
1112
+ if (existingValidCount + newValidCount > maxFiles) {
1113
+ let validFiles = addedFiles.filter((f) => f.status !== "error");
1114
+ let errorFiles = addedFiles.filter((f) => f.status === "error");
1115
+ const spaceLeft = maxFiles - existingValidCount;
1116
+ if (spaceLeft < validFiles.length) {
1117
+ validFiles = validFiles.slice(0, spaceLeft);
1113
1118
  }
1119
+ const limitedAddedFiles = [...errorFiles, ...validFiles];
1114
1120
  }
1115
1121
  }
1116
1122
  if (!multiple) {
1117
- uploadedFiles = validNewFiles.slice(0, 1);
1123
+ uploadedFiles = addedFiles.slice(0, 1);
1118
1124
  } else {
1119
- uploadedFiles = [...uploadedFiles, ...validNewFiles];
1125
+ uploadedFiles = [...uploadedFiles, ...addedFiles];
1120
1126
  }
1121
- errorsContainer.innerHTML = "";
1122
- errors.forEach((err) => {
1123
- const errEl = document.createElement("div");
1124
- errEl.className = `${PREFIX}-file-upload__error-message`;
1125
- errEl.textContent = `${err.file.name}: ${err.error}`;
1126
- errorsContainer.appendChild(errEl);
1127
- });
1128
1127
  renderFiles();
1129
1128
  container.dispatchEvent(
1130
1129
  new CustomEvent("file-upload:change", {
1131
1130
  detail: {
1132
1131
  files: uploadedFiles.map((f) => f.file),
1133
- errors
1132
+ errors: uploadedFiles.filter((f) => f.status === "error").map((f) => ({ file: f.file, error: f.error }))
1134
1133
  },
1135
1134
  bubbles: true
1136
1135
  })
1137
1136
  );
1138
- validNewFiles.forEach((f) => {
1137
+ const filesToUpload = uploadedFiles.filter((f) => f.status === "idle");
1138
+ filesToUpload.forEach((f) => {
1139
1139
  f.status = "uploading";
1140
1140
  });
1141
1141
  renderFiles();
1142
1142
  setTimeout(() => {
1143
- validNewFiles.forEach((f) => {
1143
+ filesToUpload.forEach((f) => {
1144
1144
  f.status = "success";
1145
1145
  });
1146
1146
  renderFiles();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idds/js",
3
- "version": "1.0.58",
3
+ "version": "1.0.59",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },