@moontra/moonui 6.17.0 → 6.18.0

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.mjs CHANGED
@@ -4061,23 +4061,49 @@ function DataTableBasic({
4061
4061
  ] }) }),
4062
4062
  /* @__PURE__ */ jsx("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxs(Table, { children: [
4063
4063
  /* @__PURE__ */ jsx(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx(TableRow, { children: headerGroup.headers.map((header) => {
4064
- return /* @__PURE__ */ jsx(TableHead, { children: header.isPlaceholder ? null : /* @__PURE__ */ jsxs(
4065
- "div",
4064
+ const canSort = enableSorting && header.column.getCanSort();
4065
+ const sorted = header.column.getIsSorted();
4066
+ const headerDef = header.column.columnDef.header;
4067
+ return /* @__PURE__ */ jsx(
4068
+ TableHead,
4066
4069
  {
4067
- className: cn(
4068
- "flex items-center gap-2",
4069
- header.column.getCanSort() && "cursor-pointer select-none"
4070
- ),
4071
- onClick: header.column.getToggleSortingHandler(),
4072
- children: [
4073
- flexRender(
4074
- header.column.columnDef.header,
4075
- header.getContext()
4076
- ),
4077
- enableSorting && header.column.getCanSort() && /* @__PURE__ */ jsx("div", { className: "ml-auto", children: header.column.getIsSorted() === "desc" ? /* @__PURE__ */ jsx(ArrowDown, { className: "h-4 w-4" }) : header.column.getIsSorted() === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ArrowUpDown, { className: "h-4 w-4 opacity-50" }) })
4078
- ]
4079
- }
4080
- ) }, header.id);
4070
+ "aria-sort": canSort ? sorted === "asc" ? "ascending" : sorted === "desc" ? "descending" : "none" : void 0,
4071
+ children: header.isPlaceholder ? null : /* @__PURE__ */ jsxs(
4072
+ "div",
4073
+ {
4074
+ className: cn(
4075
+ "flex items-center gap-2",
4076
+ canSort && "cursor-pointer select-none"
4077
+ ),
4078
+ onClick: canSort ? header.column.getToggleSortingHandler() : void 0,
4079
+ children: [
4080
+ flexRender(
4081
+ header.column.columnDef.header,
4082
+ header.getContext()
4083
+ ),
4084
+ canSort && /* #366: sıralama kontrolü yalnız fareyle çalışıyordu
4085
+ (dosyada `tabIndex`/`onKeyDown` grep'i 0 idi).
4086
+ Gerçek <button> ile Tab + Enter/Space native
4087
+ gelir; görünür odak focus-visible ring ile. */
4088
+ /* @__PURE__ */ jsx(
4089
+ "button",
4090
+ {
4091
+ type: "button",
4092
+ onClick: (event) => {
4093
+ event.stopPropagation();
4094
+ header.column.getToggleSortingHandler()?.(event);
4095
+ },
4096
+ "aria-label": `Sort by ${typeof headerDef === "string" ? headerDef : header.column.id}`,
4097
+ className: "ml-auto inline-flex items-center rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-ring",
4098
+ children: sorted === "desc" ? /* @__PURE__ */ jsx(ArrowDown, { className: "h-4 w-4" }) : sorted === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ArrowUpDown, { className: "h-4 w-4 opacity-50" })
4099
+ }
4100
+ )
4101
+ ]
4102
+ }
4103
+ )
4104
+ },
4105
+ header.id
4106
+ );
4081
4107
  }) }, headerGroup.id)) }),
4082
4108
  /* @__PURE__ */ jsx(TableBody, { children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(
4083
4109
  TableRow,
@@ -4845,7 +4871,20 @@ var progressIndicatorVariants = cva(
4845
4871
  variant: {
4846
4872
  default: "bg-foreground",
4847
4873
  primary: "bg-primary",
4848
- secondary: "bg-secondary",
4874
+ // #372: dolgu `bg-secondary` idi — track (`bg-secondary/20`) ile AYNI
4875
+ // yüzey token'ına basıyordu; %20 alfa track ile tam dolgu iki temada da
4876
+ // ~1.0 oranında kalıyor, bar görünmüyordu (light rgb(235,239,245) /
4877
+ // dark rgb(2,8,23)). `bg-secondary-foreground` BİLEREK seçilmedi:
4878
+ // light'ta --primary ile aynı hue/sat'ta yalnız ΔL=%2 (49 vs 51,
4879
+ // fill↔fill 1.07), dark'ta birebir --primary değeri (210 40% 98%) —
4880
+ // secondary varyantı primary'nin klonuna dönerdi. `--secondary-500`
4881
+ // (tokens.css slate skalası, RGB üçlüsü) iki temada da track'e ≥3:1
4882
+ // (WCAG 1.4.11) veren TEK kademe: light 4.63, dark 4.23 (gerçek kart
4883
+ // #111827 üstünde 3.83; 400 light'ta 2.50 ✗, 600 dark'ta 2.66 ✗).
4884
+ // Skala :root'ta tanımlı olduğundan tema değişiminde sabittir;
4885
+ // tüketici --secondary-500'ü ezerek özelleştirebilir.
4886
+ // Regresyon: __tests__/progress-secondary-contrast.test.ts
4887
+ secondary: "bg-[rgb(var(--secondary-500))]",
4849
4888
  success: "bg-success",
4850
4889
  warning: "bg-warning",
4851
4890
  error: "bg-error"
@@ -4939,6 +4978,26 @@ var formatFileSize = (bytes) => {
4939
4978
  const i = Math.floor(Math.log(bytes) / Math.log(k));
4940
4979
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
4941
4980
  };
4981
+ var matchesAcceptToken = (file, token) => {
4982
+ const normalized = token.trim().toLowerCase();
4983
+ if (!normalized)
4984
+ return false;
4985
+ if (normalized === "*" || normalized === "*/*")
4986
+ return true;
4987
+ if (normalized.startsWith(".")) {
4988
+ return file.name.toLowerCase().endsWith(normalized);
4989
+ }
4990
+ if (normalized.endsWith("/*")) {
4991
+ return file.type.toLowerCase().startsWith(normalized.slice(0, -1));
4992
+ }
4993
+ return file.type.toLowerCase() === normalized;
4994
+ };
4995
+ var isFileAccepted = (file, accept) => {
4996
+ const trimmed = accept.trim();
4997
+ if (trimmed === "" || trimmed === "*")
4998
+ return true;
4999
+ return trimmed.split(",").some((token) => matchesAcceptToken(file, token));
5000
+ };
4942
5001
  var FileItem = ({
4943
5002
  uploadedFile,
4944
5003
  onRemove
@@ -5017,13 +5076,7 @@ var FileUpload = React12__default.forwardRef(
5017
5076
  if (file.size > maxSize) {
5018
5077
  return `File size exceeds ${formatFileSize(maxSize)}`;
5019
5078
  }
5020
- if (accept !== "*" && !accept.split(",").some((type) => {
5021
- const cleanType = type.trim();
5022
- if (cleanType.includes("*")) {
5023
- return file.type.startsWith(cleanType.replace("*", ""));
5024
- }
5025
- return file.type === cleanType;
5026
- })) {
5079
+ if (!isFileAccepted(file, accept)) {
5027
5080
  return `File type not supported`;
5028
5081
  }
5029
5082
  return null;
@@ -5057,6 +5110,7 @@ var FileUpload = React12__default.forwardRef(
5057
5110
  preview: file.type.startsWith("image/") ? URL.createObjectURL(file) : void 0
5058
5111
  }));
5059
5112
  setUploadedFiles((prev) => [...prev, ...newUploadedFiles]);
5113
+ const progressIntervals = /* @__PURE__ */ new Map();
5060
5114
  for (const uploadedFile of newUploadedFiles) {
5061
5115
  let progress = 0;
5062
5116
  const interval = setInterval(() => {
@@ -5064,25 +5118,33 @@ var FileUpload = React12__default.forwardRef(
5064
5118
  if (progress >= 100) {
5065
5119
  progress = 100;
5066
5120
  clearInterval(interval);
5121
+ progressIntervals.delete(uploadedFile.id);
5067
5122
  setUploadedFiles(
5068
5123
  (prev) => prev.map(
5069
- (f) => f.id === uploadedFile.id ? { ...f, progress: 100, status: "success" } : f
5124
+ (f) => (
5125
+ // 'error'a düşmüş dosya simülasyonca geri 'success' yapılamaz —
5126
+ // error nihai durumdur (#378)
5127
+ f.id === uploadedFile.id && f.status === "uploading" ? { ...f, progress: 100, status: "success" } : f
5128
+ )
5070
5129
  )
5071
5130
  );
5072
5131
  } else {
5073
5132
  setUploadedFiles(
5074
5133
  (prev) => prev.map(
5075
- (f) => f.id === uploadedFile.id ? { ...f, progress } : f
5134
+ (f) => f.id === uploadedFile.id && f.status === "uploading" ? { ...f, progress } : f
5076
5135
  )
5077
5136
  );
5078
5137
  }
5079
5138
  }, 200);
5139
+ progressIntervals.set(uploadedFile.id, interval);
5080
5140
  }
5081
5141
  if (onUpload) {
5082
5142
  try {
5083
5143
  await onUpload(newUploadedFiles);
5084
5144
  } catch (error2) {
5085
5145
  console.error("Upload failed:", error2);
5146
+ progressIntervals.forEach((handle) => clearInterval(handle));
5147
+ progressIntervals.clear();
5086
5148
  setUploadedFiles(
5087
5149
  (prev) => prev.map(
5088
5150
  (f) => newUploadedFiles.some((nf) => nf.id === f.id) ? { ...f, status: "error" } : f