@moontra/moonui 6.16.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/README.md +189 -108
- package/dist/index.global.js +8 -8
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +88 -26
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +88 -26
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/ui/__tests__/dark-token-contrast.test.ts +162 -0
- package/src/components/ui/__tests__/data-table-basic.test.tsx +109 -0
- package/src/components/ui/__tests__/file-upload.issue-378.test.tsx +226 -0
- package/src/components/ui/__tests__/primary-subtle-token.test.ts +95 -0
- package/src/components/ui/__tests__/progress-secondary-contrast.test.ts +231 -0
- package/src/components/ui/__tests__/progress.test.tsx +4 -1
- package/src/components/ui/__tests__/responsive-color-invariance.test.ts +92 -0
- package/src/components/ui/data-table-basic.tsx +59 -8
- package/src/components/ui/file-upload.tsx +51 -16
- package/src/components/ui/progress.tsx +14 -1
- package/src/styles/tokens.css +47 -3
- package/tailwind-preset.js +7 -0
package/dist/index.js
CHANGED
|
@@ -4099,23 +4099,49 @@ function DataTableBasic({
|
|
|
4099
4099
|
] }) }),
|
|
4100
4100
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxRuntime.jsxs(Table, { children: [
|
|
4101
4101
|
/* @__PURE__ */ jsxRuntime.jsx(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsxRuntime.jsx(TableRow, { children: headerGroup.headers.map((header) => {
|
|
4102
|
-
|
|
4103
|
-
|
|
4102
|
+
const canSort = enableSorting && header.column.getCanSort();
|
|
4103
|
+
const sorted = header.column.getIsSorted();
|
|
4104
|
+
const headerDef = header.column.columnDef.header;
|
|
4105
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4106
|
+
TableHead,
|
|
4104
4107
|
{
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
header.
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4108
|
+
"aria-sort": canSort ? sorted === "asc" ? "ascending" : sorted === "desc" ? "descending" : "none" : void 0,
|
|
4109
|
+
children: header.isPlaceholder ? null : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4110
|
+
"div",
|
|
4111
|
+
{
|
|
4112
|
+
className: cn(
|
|
4113
|
+
"flex items-center gap-2",
|
|
4114
|
+
canSort && "cursor-pointer select-none"
|
|
4115
|
+
),
|
|
4116
|
+
onClick: canSort ? header.column.getToggleSortingHandler() : void 0,
|
|
4117
|
+
children: [
|
|
4118
|
+
reactTable.flexRender(
|
|
4119
|
+
header.column.columnDef.header,
|
|
4120
|
+
header.getContext()
|
|
4121
|
+
),
|
|
4122
|
+
canSort && /* #366: sıralama kontrolü yalnız fareyle çalışıyordu
|
|
4123
|
+
(dosyada `tabIndex`/`onKeyDown` grep'i 0 idi).
|
|
4124
|
+
Gerçek <button> ile Tab + Enter/Space native
|
|
4125
|
+
gelir; görünür odak focus-visible ring ile. */
|
|
4126
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4127
|
+
"button",
|
|
4128
|
+
{
|
|
4129
|
+
type: "button",
|
|
4130
|
+
onClick: (event) => {
|
|
4131
|
+
event.stopPropagation();
|
|
4132
|
+
header.column.getToggleSortingHandler()?.(event);
|
|
4133
|
+
},
|
|
4134
|
+
"aria-label": `Sort by ${typeof headerDef === "string" ? headerDef : header.column.id}`,
|
|
4135
|
+
className: "ml-auto inline-flex items-center rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
4136
|
+
children: sorted === "desc" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { className: "h-4 w-4" }) : sorted === "asc" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpDown, { className: "h-4 w-4 opacity-50" })
|
|
4137
|
+
}
|
|
4138
|
+
)
|
|
4139
|
+
]
|
|
4140
|
+
}
|
|
4141
|
+
)
|
|
4142
|
+
},
|
|
4143
|
+
header.id
|
|
4144
|
+
);
|
|
4119
4145
|
}) }, headerGroup.id)) }),
|
|
4120
4146
|
/* @__PURE__ */ jsxRuntime.jsx(TableBody, { children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4121
4147
|
TableRow,
|
|
@@ -4883,7 +4909,20 @@ var progressIndicatorVariants = classVarianceAuthority.cva(
|
|
|
4883
4909
|
variant: {
|
|
4884
4910
|
default: "bg-foreground",
|
|
4885
4911
|
primary: "bg-primary",
|
|
4886
|
-
|
|
4912
|
+
// #372: dolgu `bg-secondary` idi — track (`bg-secondary/20`) ile AYNI
|
|
4913
|
+
// yüzey token'ına basıyordu; %20 alfa track ile tam dolgu iki temada da
|
|
4914
|
+
// ~1.0 oranında kalıyor, bar görünmüyordu (light rgb(235,239,245) /
|
|
4915
|
+
// dark rgb(2,8,23)). `bg-secondary-foreground` BİLEREK seçilmedi:
|
|
4916
|
+
// light'ta --primary ile aynı hue/sat'ta yalnız ΔL=%2 (49 vs 51,
|
|
4917
|
+
// fill↔fill 1.07), dark'ta birebir --primary değeri (210 40% 98%) —
|
|
4918
|
+
// secondary varyantı primary'nin klonuna dönerdi. `--secondary-500`
|
|
4919
|
+
// (tokens.css slate skalası, RGB üçlüsü) iki temada da track'e ≥3:1
|
|
4920
|
+
// (WCAG 1.4.11) veren TEK kademe: light 4.63, dark 4.23 (gerçek kart
|
|
4921
|
+
// #111827 üstünde 3.83; 400 light'ta 2.50 ✗, 600 dark'ta 2.66 ✗).
|
|
4922
|
+
// Skala :root'ta tanımlı olduğundan tema değişiminde sabittir;
|
|
4923
|
+
// tüketici --secondary-500'ü ezerek özelleştirebilir.
|
|
4924
|
+
// Regresyon: __tests__/progress-secondary-contrast.test.ts
|
|
4925
|
+
secondary: "bg-[rgb(var(--secondary-500))]",
|
|
4887
4926
|
success: "bg-success",
|
|
4888
4927
|
warning: "bg-warning",
|
|
4889
4928
|
error: "bg-error"
|
|
@@ -4977,6 +5016,26 @@ var formatFileSize = (bytes) => {
|
|
|
4977
5016
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
4978
5017
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
|
|
4979
5018
|
};
|
|
5019
|
+
var matchesAcceptToken = (file, token) => {
|
|
5020
|
+
const normalized = token.trim().toLowerCase();
|
|
5021
|
+
if (!normalized)
|
|
5022
|
+
return false;
|
|
5023
|
+
if (normalized === "*" || normalized === "*/*")
|
|
5024
|
+
return true;
|
|
5025
|
+
if (normalized.startsWith(".")) {
|
|
5026
|
+
return file.name.toLowerCase().endsWith(normalized);
|
|
5027
|
+
}
|
|
5028
|
+
if (normalized.endsWith("/*")) {
|
|
5029
|
+
return file.type.toLowerCase().startsWith(normalized.slice(0, -1));
|
|
5030
|
+
}
|
|
5031
|
+
return file.type.toLowerCase() === normalized;
|
|
5032
|
+
};
|
|
5033
|
+
var isFileAccepted = (file, accept) => {
|
|
5034
|
+
const trimmed = accept.trim();
|
|
5035
|
+
if (trimmed === "" || trimmed === "*")
|
|
5036
|
+
return true;
|
|
5037
|
+
return trimmed.split(",").some((token) => matchesAcceptToken(file, token));
|
|
5038
|
+
};
|
|
4980
5039
|
var FileItem = ({
|
|
4981
5040
|
uploadedFile,
|
|
4982
5041
|
onRemove
|
|
@@ -5055,13 +5114,7 @@ var FileUpload = React12__namespace.default.forwardRef(
|
|
|
5055
5114
|
if (file.size > maxSize) {
|
|
5056
5115
|
return `File size exceeds ${formatFileSize(maxSize)}`;
|
|
5057
5116
|
}
|
|
5058
|
-
if (
|
|
5059
|
-
const cleanType = type.trim();
|
|
5060
|
-
if (cleanType.includes("*")) {
|
|
5061
|
-
return file.type.startsWith(cleanType.replace("*", ""));
|
|
5062
|
-
}
|
|
5063
|
-
return file.type === cleanType;
|
|
5064
|
-
})) {
|
|
5117
|
+
if (!isFileAccepted(file, accept)) {
|
|
5065
5118
|
return `File type not supported`;
|
|
5066
5119
|
}
|
|
5067
5120
|
return null;
|
|
@@ -5095,6 +5148,7 @@ var FileUpload = React12__namespace.default.forwardRef(
|
|
|
5095
5148
|
preview: file.type.startsWith("image/") ? URL.createObjectURL(file) : void 0
|
|
5096
5149
|
}));
|
|
5097
5150
|
setUploadedFiles((prev) => [...prev, ...newUploadedFiles]);
|
|
5151
|
+
const progressIntervals = /* @__PURE__ */ new Map();
|
|
5098
5152
|
for (const uploadedFile of newUploadedFiles) {
|
|
5099
5153
|
let progress = 0;
|
|
5100
5154
|
const interval = setInterval(() => {
|
|
@@ -5102,25 +5156,33 @@ var FileUpload = React12__namespace.default.forwardRef(
|
|
|
5102
5156
|
if (progress >= 100) {
|
|
5103
5157
|
progress = 100;
|
|
5104
5158
|
clearInterval(interval);
|
|
5159
|
+
progressIntervals.delete(uploadedFile.id);
|
|
5105
5160
|
setUploadedFiles(
|
|
5106
5161
|
(prev) => prev.map(
|
|
5107
|
-
(f) =>
|
|
5162
|
+
(f) => (
|
|
5163
|
+
// 'error'a düşmüş dosya simülasyonca geri 'success' yapılamaz —
|
|
5164
|
+
// error nihai durumdur (#378)
|
|
5165
|
+
f.id === uploadedFile.id && f.status === "uploading" ? { ...f, progress: 100, status: "success" } : f
|
|
5166
|
+
)
|
|
5108
5167
|
)
|
|
5109
5168
|
);
|
|
5110
5169
|
} else {
|
|
5111
5170
|
setUploadedFiles(
|
|
5112
5171
|
(prev) => prev.map(
|
|
5113
|
-
(f) => f.id === uploadedFile.id ? { ...f, progress } : f
|
|
5172
|
+
(f) => f.id === uploadedFile.id && f.status === "uploading" ? { ...f, progress } : f
|
|
5114
5173
|
)
|
|
5115
5174
|
);
|
|
5116
5175
|
}
|
|
5117
5176
|
}, 200);
|
|
5177
|
+
progressIntervals.set(uploadedFile.id, interval);
|
|
5118
5178
|
}
|
|
5119
5179
|
if (onUpload) {
|
|
5120
5180
|
try {
|
|
5121
5181
|
await onUpload(newUploadedFiles);
|
|
5122
5182
|
} catch (error2) {
|
|
5123
5183
|
console.error("Upload failed:", error2);
|
|
5184
|
+
progressIntervals.forEach((handle) => clearInterval(handle));
|
|
5185
|
+
progressIntervals.clear();
|
|
5124
5186
|
setUploadedFiles(
|
|
5125
5187
|
(prev) => prev.map(
|
|
5126
5188
|
(f) => newUploadedFiles.some((nf) => nf.id === f.id) ? { ...f, status: "error" } : f
|