@moontra/moonui 6.17.0 → 6.19.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.js +114 -28
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +114 -28
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -5
- package/src/__tests__/cdn-iife-removed.test.ts +103 -0
- 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__/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/__tests__/slider-secondary-contrast.test.ts +375 -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/components/ui/slider.tsx +26 -2
- package/src/styles/tokens.css +30 -3
- package/dist/chunk-VXDFZPDA.global.js +0 -33
- package/dist/chunk-VXDFZPDA.global.js.map +0 -1
- package/dist/hooks/index.global.js +0 -33
- package/dist/hooks/index.global.js.map +0 -1
- package/dist/index.global.js +0 -980
- package/dist/index.global.js.map +0 -1
- package/dist/lib/theme.global.js +0 -54
- package/dist/lib/theme.global.js.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -2534,7 +2534,20 @@ var sliderRangeVariants = cva(
|
|
|
2534
2534
|
variant: {
|
|
2535
2535
|
default: "bg-foreground",
|
|
2536
2536
|
primary: "bg-primary",
|
|
2537
|
-
|
|
2537
|
+
// #389 (#372'nin birebir ardılı): range `bg-secondary` idi — track'in
|
|
2538
|
+
// (`bg-secondary/20`) AYNI yüzey token'ına basıyordu; %20 alfa track ile
|
|
2539
|
+
// tam dolgu iki temada da ~1.0 oranında kalıyor, dolu kısım görünmüyordu
|
|
2540
|
+
// (light rgb(235,239,245) → 1.12 · dark rgb(2,8,23) → 1.01).
|
|
2541
|
+
// `bg-secondary-foreground` BİLEREK seçilmedi: light'ta --primary ile aynı
|
|
2542
|
+
// hue/sat'ta yalnız ΔL=%2 (fill↔fill 1.07), dark'ta birebir --primary
|
|
2543
|
+
// değeri (210 40% 98%) — secondary varyantı primary klonuna dönerdi.
|
|
2544
|
+
// `--secondary-500` (tokens.css slate skalası, RGB üçlüsü) iki temada da
|
|
2545
|
+
// track'e ≥3:1 (WCAG 1.4.11) veren TEK kademe: light 4.63, dark 4.23
|
|
2546
|
+
// (gerçek kart #111827 üstünde 3.83; 400 light'ta 2.50 ✗, 600 dark'ta
|
|
2547
|
+
// 2.66 ✗). Skala :root'ta tanımlı olduğundan tema değişiminde sabittir;
|
|
2548
|
+
// tüketici --secondary-500'ü ezerek özelleştirebilir.
|
|
2549
|
+
// Regresyon: __tests__/slider-secondary-contrast.test.ts
|
|
2550
|
+
secondary: "bg-[rgb(var(--secondary-500))]",
|
|
2538
2551
|
accent: "bg-accent",
|
|
2539
2552
|
success: "bg-success",
|
|
2540
2553
|
warning: "bg-warning",
|
|
@@ -2553,7 +2566,18 @@ var sliderThumbVariants = cva(
|
|
|
2553
2566
|
variant: {
|
|
2554
2567
|
default: "border-foreground bg-background",
|
|
2555
2568
|
primary: "border-primary bg-background",
|
|
2556
|
-
|
|
2569
|
+
// #407 (P2, #389'un range eksenine EK ayrı eksen): tutamacın kenarlığı
|
|
2570
|
+
// `border-secondary`, dolgusu `bg-background` idi. Bu bileşen↔sayfa-zemini
|
|
2571
|
+
// ekseni: `--secondary` light'ta neredeyse beyaz (rgb(235,239,245)), dark'ta
|
|
2572
|
+
// `--background` ile neredeyse aynı → kenarlık 1.15 (light) / 1.01 (dark)
|
|
2573
|
+
// oranında kalıyor, secondary slider'ın tutamacı zeminde kayboluyordu.
|
|
2574
|
+
// #389'da bilerek kapsam dışıydı (mevcut kusuru testle "doğru" ilan etmemek için).
|
|
2575
|
+
// Non-text UI bileşeni → WCAG 1.4.11 ≥3:1. Skala taraması bu eksende de TEK
|
|
2576
|
+
// kademe bırakıyor — `--secondary-500`: light 4.76, dark 4.23 (gerçek kart
|
|
2577
|
+
// #111827 üstünde 3.73); 400 light'ta 2.56 ✗, 600 dark'ta 2.66 ✗. Range ile
|
|
2578
|
+
// aynı kademe: tutamaç ve dolgu tek renkte okunur.
|
|
2579
|
+
// Regresyon: __tests__/slider-secondary-contrast.test.ts
|
|
2580
|
+
secondary: "border-[rgb(var(--secondary-500))] bg-background",
|
|
2557
2581
|
accent: "border-accent bg-background",
|
|
2558
2582
|
success: "border-success bg-background",
|
|
2559
2583
|
warning: "border-warning bg-background",
|
|
@@ -4061,23 +4085,49 @@ function DataTableBasic({
|
|
|
4061
4085
|
] }) }),
|
|
4062
4086
|
/* @__PURE__ */ jsx("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxs(Table, { children: [
|
|
4063
4087
|
/* @__PURE__ */ jsx(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx(TableRow, { children: headerGroup.headers.map((header) => {
|
|
4064
|
-
|
|
4065
|
-
|
|
4088
|
+
const canSort = enableSorting && header.column.getCanSort();
|
|
4089
|
+
const sorted = header.column.getIsSorted();
|
|
4090
|
+
const headerDef = header.column.columnDef.header;
|
|
4091
|
+
return /* @__PURE__ */ jsx(
|
|
4092
|
+
TableHead,
|
|
4066
4093
|
{
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
header.
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4094
|
+
"aria-sort": canSort ? sorted === "asc" ? "ascending" : sorted === "desc" ? "descending" : "none" : void 0,
|
|
4095
|
+
children: header.isPlaceholder ? null : /* @__PURE__ */ jsxs(
|
|
4096
|
+
"div",
|
|
4097
|
+
{
|
|
4098
|
+
className: cn(
|
|
4099
|
+
"flex items-center gap-2",
|
|
4100
|
+
canSort && "cursor-pointer select-none"
|
|
4101
|
+
),
|
|
4102
|
+
onClick: canSort ? header.column.getToggleSortingHandler() : void 0,
|
|
4103
|
+
children: [
|
|
4104
|
+
flexRender(
|
|
4105
|
+
header.column.columnDef.header,
|
|
4106
|
+
header.getContext()
|
|
4107
|
+
),
|
|
4108
|
+
canSort && /* #366: sıralama kontrolü yalnız fareyle çalışıyordu
|
|
4109
|
+
(dosyada `tabIndex`/`onKeyDown` grep'i 0 idi).
|
|
4110
|
+
Gerçek <button> ile Tab + Enter/Space native
|
|
4111
|
+
gelir; görünür odak focus-visible ring ile. */
|
|
4112
|
+
/* @__PURE__ */ jsx(
|
|
4113
|
+
"button",
|
|
4114
|
+
{
|
|
4115
|
+
type: "button",
|
|
4116
|
+
onClick: (event) => {
|
|
4117
|
+
event.stopPropagation();
|
|
4118
|
+
header.column.getToggleSortingHandler()?.(event);
|
|
4119
|
+
},
|
|
4120
|
+
"aria-label": `Sort by ${typeof headerDef === "string" ? headerDef : header.column.id}`,
|
|
4121
|
+
className: "ml-auto inline-flex items-center rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
4122
|
+
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" })
|
|
4123
|
+
}
|
|
4124
|
+
)
|
|
4125
|
+
]
|
|
4126
|
+
}
|
|
4127
|
+
)
|
|
4128
|
+
},
|
|
4129
|
+
header.id
|
|
4130
|
+
);
|
|
4081
4131
|
}) }, headerGroup.id)) }),
|
|
4082
4132
|
/* @__PURE__ */ jsx(TableBody, { children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(
|
|
4083
4133
|
TableRow,
|
|
@@ -4845,7 +4895,20 @@ var progressIndicatorVariants = cva(
|
|
|
4845
4895
|
variant: {
|
|
4846
4896
|
default: "bg-foreground",
|
|
4847
4897
|
primary: "bg-primary",
|
|
4848
|
-
|
|
4898
|
+
// #372: dolgu `bg-secondary` idi — track (`bg-secondary/20`) ile AYNI
|
|
4899
|
+
// yüzey token'ına basıyordu; %20 alfa track ile tam dolgu iki temada da
|
|
4900
|
+
// ~1.0 oranında kalıyor, bar görünmüyordu (light rgb(235,239,245) /
|
|
4901
|
+
// dark rgb(2,8,23)). `bg-secondary-foreground` BİLEREK seçilmedi:
|
|
4902
|
+
// light'ta --primary ile aynı hue/sat'ta yalnız ΔL=%2 (49 vs 51,
|
|
4903
|
+
// fill↔fill 1.07), dark'ta birebir --primary değeri (210 40% 98%) —
|
|
4904
|
+
// secondary varyantı primary'nin klonuna dönerdi. `--secondary-500`
|
|
4905
|
+
// (tokens.css slate skalası, RGB üçlüsü) iki temada da track'e ≥3:1
|
|
4906
|
+
// (WCAG 1.4.11) veren TEK kademe: light 4.63, dark 4.23 (gerçek kart
|
|
4907
|
+
// #111827 üstünde 3.83; 400 light'ta 2.50 ✗, 600 dark'ta 2.66 ✗).
|
|
4908
|
+
// Skala :root'ta tanımlı olduğundan tema değişiminde sabittir;
|
|
4909
|
+
// tüketici --secondary-500'ü ezerek özelleştirebilir.
|
|
4910
|
+
// Regresyon: __tests__/progress-secondary-contrast.test.ts
|
|
4911
|
+
secondary: "bg-[rgb(var(--secondary-500))]",
|
|
4849
4912
|
success: "bg-success",
|
|
4850
4913
|
warning: "bg-warning",
|
|
4851
4914
|
error: "bg-error"
|
|
@@ -4939,6 +5002,26 @@ var formatFileSize = (bytes) => {
|
|
|
4939
5002
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
4940
5003
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
|
|
4941
5004
|
};
|
|
5005
|
+
var matchesAcceptToken = (file, token) => {
|
|
5006
|
+
const normalized = token.trim().toLowerCase();
|
|
5007
|
+
if (!normalized)
|
|
5008
|
+
return false;
|
|
5009
|
+
if (normalized === "*" || normalized === "*/*")
|
|
5010
|
+
return true;
|
|
5011
|
+
if (normalized.startsWith(".")) {
|
|
5012
|
+
return file.name.toLowerCase().endsWith(normalized);
|
|
5013
|
+
}
|
|
5014
|
+
if (normalized.endsWith("/*")) {
|
|
5015
|
+
return file.type.toLowerCase().startsWith(normalized.slice(0, -1));
|
|
5016
|
+
}
|
|
5017
|
+
return file.type.toLowerCase() === normalized;
|
|
5018
|
+
};
|
|
5019
|
+
var isFileAccepted = (file, accept) => {
|
|
5020
|
+
const trimmed = accept.trim();
|
|
5021
|
+
if (trimmed === "" || trimmed === "*")
|
|
5022
|
+
return true;
|
|
5023
|
+
return trimmed.split(",").some((token) => matchesAcceptToken(file, token));
|
|
5024
|
+
};
|
|
4942
5025
|
var FileItem = ({
|
|
4943
5026
|
uploadedFile,
|
|
4944
5027
|
onRemove
|
|
@@ -5017,13 +5100,7 @@ var FileUpload = React12__default.forwardRef(
|
|
|
5017
5100
|
if (file.size > maxSize) {
|
|
5018
5101
|
return `File size exceeds ${formatFileSize(maxSize)}`;
|
|
5019
5102
|
}
|
|
5020
|
-
if (
|
|
5021
|
-
const cleanType = type.trim();
|
|
5022
|
-
if (cleanType.includes("*")) {
|
|
5023
|
-
return file.type.startsWith(cleanType.replace("*", ""));
|
|
5024
|
-
}
|
|
5025
|
-
return file.type === cleanType;
|
|
5026
|
-
})) {
|
|
5103
|
+
if (!isFileAccepted(file, accept)) {
|
|
5027
5104
|
return `File type not supported`;
|
|
5028
5105
|
}
|
|
5029
5106
|
return null;
|
|
@@ -5057,6 +5134,7 @@ var FileUpload = React12__default.forwardRef(
|
|
|
5057
5134
|
preview: file.type.startsWith("image/") ? URL.createObjectURL(file) : void 0
|
|
5058
5135
|
}));
|
|
5059
5136
|
setUploadedFiles((prev) => [...prev, ...newUploadedFiles]);
|
|
5137
|
+
const progressIntervals = /* @__PURE__ */ new Map();
|
|
5060
5138
|
for (const uploadedFile of newUploadedFiles) {
|
|
5061
5139
|
let progress = 0;
|
|
5062
5140
|
const interval = setInterval(() => {
|
|
@@ -5064,25 +5142,33 @@ var FileUpload = React12__default.forwardRef(
|
|
|
5064
5142
|
if (progress >= 100) {
|
|
5065
5143
|
progress = 100;
|
|
5066
5144
|
clearInterval(interval);
|
|
5145
|
+
progressIntervals.delete(uploadedFile.id);
|
|
5067
5146
|
setUploadedFiles(
|
|
5068
5147
|
(prev) => prev.map(
|
|
5069
|
-
(f) =>
|
|
5148
|
+
(f) => (
|
|
5149
|
+
// 'error'a düşmüş dosya simülasyonca geri 'success' yapılamaz —
|
|
5150
|
+
// error nihai durumdur (#378)
|
|
5151
|
+
f.id === uploadedFile.id && f.status === "uploading" ? { ...f, progress: 100, status: "success" } : f
|
|
5152
|
+
)
|
|
5070
5153
|
)
|
|
5071
5154
|
);
|
|
5072
5155
|
} else {
|
|
5073
5156
|
setUploadedFiles(
|
|
5074
5157
|
(prev) => prev.map(
|
|
5075
|
-
(f) => f.id === uploadedFile.id ? { ...f, progress } : f
|
|
5158
|
+
(f) => f.id === uploadedFile.id && f.status === "uploading" ? { ...f, progress } : f
|
|
5076
5159
|
)
|
|
5077
5160
|
);
|
|
5078
5161
|
}
|
|
5079
5162
|
}, 200);
|
|
5163
|
+
progressIntervals.set(uploadedFile.id, interval);
|
|
5080
5164
|
}
|
|
5081
5165
|
if (onUpload) {
|
|
5082
5166
|
try {
|
|
5083
5167
|
await onUpload(newUploadedFiles);
|
|
5084
5168
|
} catch (error2) {
|
|
5085
5169
|
console.error("Upload failed:", error2);
|
|
5170
|
+
progressIntervals.forEach((handle) => clearInterval(handle));
|
|
5171
|
+
progressIntervals.clear();
|
|
5086
5172
|
setUploadedFiles(
|
|
5087
5173
|
(prev) => prev.map(
|
|
5088
5174
|
(f) => newUploadedFiles.some((nf) => nf.id === f.id) ? { ...f, status: "error" } : f
|