@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.js
CHANGED
|
@@ -2572,7 +2572,20 @@ var sliderRangeVariants = classVarianceAuthority.cva(
|
|
|
2572
2572
|
variant: {
|
|
2573
2573
|
default: "bg-foreground",
|
|
2574
2574
|
primary: "bg-primary",
|
|
2575
|
-
|
|
2575
|
+
// #389 (#372'nin birebir ardılı): range `bg-secondary` idi — track'in
|
|
2576
|
+
// (`bg-secondary/20`) AYNI yüzey token'ına basıyordu; %20 alfa track ile
|
|
2577
|
+
// tam dolgu iki temada da ~1.0 oranında kalıyor, dolu kısım görünmüyordu
|
|
2578
|
+
// (light rgb(235,239,245) → 1.12 · dark rgb(2,8,23) → 1.01).
|
|
2579
|
+
// `bg-secondary-foreground` BİLEREK seçilmedi: light'ta --primary ile aynı
|
|
2580
|
+
// hue/sat'ta yalnız ΔL=%2 (fill↔fill 1.07), dark'ta birebir --primary
|
|
2581
|
+
// değeri (210 40% 98%) — secondary varyantı primary klonuna dönerdi.
|
|
2582
|
+
// `--secondary-500` (tokens.css slate skalası, RGB üçlüsü) iki temada da
|
|
2583
|
+
// track'e ≥3:1 (WCAG 1.4.11) veren TEK kademe: light 4.63, dark 4.23
|
|
2584
|
+
// (gerçek kart #111827 üstünde 3.83; 400 light'ta 2.50 ✗, 600 dark'ta
|
|
2585
|
+
// 2.66 ✗). Skala :root'ta tanımlı olduğundan tema değişiminde sabittir;
|
|
2586
|
+
// tüketici --secondary-500'ü ezerek özelleştirebilir.
|
|
2587
|
+
// Regresyon: __tests__/slider-secondary-contrast.test.ts
|
|
2588
|
+
secondary: "bg-[rgb(var(--secondary-500))]",
|
|
2576
2589
|
accent: "bg-accent",
|
|
2577
2590
|
success: "bg-success",
|
|
2578
2591
|
warning: "bg-warning",
|
|
@@ -2591,7 +2604,18 @@ var sliderThumbVariants = classVarianceAuthority.cva(
|
|
|
2591
2604
|
variant: {
|
|
2592
2605
|
default: "border-foreground bg-background",
|
|
2593
2606
|
primary: "border-primary bg-background",
|
|
2594
|
-
|
|
2607
|
+
// #407 (P2, #389'un range eksenine EK ayrı eksen): tutamacın kenarlığı
|
|
2608
|
+
// `border-secondary`, dolgusu `bg-background` idi. Bu bileşen↔sayfa-zemini
|
|
2609
|
+
// ekseni: `--secondary` light'ta neredeyse beyaz (rgb(235,239,245)), dark'ta
|
|
2610
|
+
// `--background` ile neredeyse aynı → kenarlık 1.15 (light) / 1.01 (dark)
|
|
2611
|
+
// oranında kalıyor, secondary slider'ın tutamacı zeminde kayboluyordu.
|
|
2612
|
+
// #389'da bilerek kapsam dışıydı (mevcut kusuru testle "doğru" ilan etmemek için).
|
|
2613
|
+
// Non-text UI bileşeni → WCAG 1.4.11 ≥3:1. Skala taraması bu eksende de TEK
|
|
2614
|
+
// kademe bırakıyor — `--secondary-500`: light 4.76, dark 4.23 (gerçek kart
|
|
2615
|
+
// #111827 üstünde 3.73); 400 light'ta 2.56 ✗, 600 dark'ta 2.66 ✗. Range ile
|
|
2616
|
+
// aynı kademe: tutamaç ve dolgu tek renkte okunur.
|
|
2617
|
+
// Regresyon: __tests__/slider-secondary-contrast.test.ts
|
|
2618
|
+
secondary: "border-[rgb(var(--secondary-500))] bg-background",
|
|
2595
2619
|
accent: "border-accent bg-background",
|
|
2596
2620
|
success: "border-success bg-background",
|
|
2597
2621
|
warning: "border-warning bg-background",
|
|
@@ -4099,23 +4123,49 @@ function DataTableBasic({
|
|
|
4099
4123
|
] }) }),
|
|
4100
4124
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxRuntime.jsxs(Table, { children: [
|
|
4101
4125
|
/* @__PURE__ */ jsxRuntime.jsx(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsxRuntime.jsx(TableRow, { children: headerGroup.headers.map((header) => {
|
|
4102
|
-
|
|
4103
|
-
|
|
4126
|
+
const canSort = enableSorting && header.column.getCanSort();
|
|
4127
|
+
const sorted = header.column.getIsSorted();
|
|
4128
|
+
const headerDef = header.column.columnDef.header;
|
|
4129
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4130
|
+
TableHead,
|
|
4104
4131
|
{
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
header.
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4132
|
+
"aria-sort": canSort ? sorted === "asc" ? "ascending" : sorted === "desc" ? "descending" : "none" : void 0,
|
|
4133
|
+
children: header.isPlaceholder ? null : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4134
|
+
"div",
|
|
4135
|
+
{
|
|
4136
|
+
className: cn(
|
|
4137
|
+
"flex items-center gap-2",
|
|
4138
|
+
canSort && "cursor-pointer select-none"
|
|
4139
|
+
),
|
|
4140
|
+
onClick: canSort ? header.column.getToggleSortingHandler() : void 0,
|
|
4141
|
+
children: [
|
|
4142
|
+
reactTable.flexRender(
|
|
4143
|
+
header.column.columnDef.header,
|
|
4144
|
+
header.getContext()
|
|
4145
|
+
),
|
|
4146
|
+
canSort && /* #366: sıralama kontrolü yalnız fareyle çalışıyordu
|
|
4147
|
+
(dosyada `tabIndex`/`onKeyDown` grep'i 0 idi).
|
|
4148
|
+
Gerçek <button> ile Tab + Enter/Space native
|
|
4149
|
+
gelir; görünür odak focus-visible ring ile. */
|
|
4150
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4151
|
+
"button",
|
|
4152
|
+
{
|
|
4153
|
+
type: "button",
|
|
4154
|
+
onClick: (event) => {
|
|
4155
|
+
event.stopPropagation();
|
|
4156
|
+
header.column.getToggleSortingHandler()?.(event);
|
|
4157
|
+
},
|
|
4158
|
+
"aria-label": `Sort by ${typeof headerDef === "string" ? headerDef : header.column.id}`,
|
|
4159
|
+
className: "ml-auto inline-flex items-center rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
4160
|
+
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" })
|
|
4161
|
+
}
|
|
4162
|
+
)
|
|
4163
|
+
]
|
|
4164
|
+
}
|
|
4165
|
+
)
|
|
4166
|
+
},
|
|
4167
|
+
header.id
|
|
4168
|
+
);
|
|
4119
4169
|
}) }, headerGroup.id)) }),
|
|
4120
4170
|
/* @__PURE__ */ jsxRuntime.jsx(TableBody, { children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4121
4171
|
TableRow,
|
|
@@ -4883,7 +4933,20 @@ var progressIndicatorVariants = classVarianceAuthority.cva(
|
|
|
4883
4933
|
variant: {
|
|
4884
4934
|
default: "bg-foreground",
|
|
4885
4935
|
primary: "bg-primary",
|
|
4886
|
-
|
|
4936
|
+
// #372: dolgu `bg-secondary` idi — track (`bg-secondary/20`) ile AYNI
|
|
4937
|
+
// yüzey token'ına basıyordu; %20 alfa track ile tam dolgu iki temada da
|
|
4938
|
+
// ~1.0 oranında kalıyor, bar görünmüyordu (light rgb(235,239,245) /
|
|
4939
|
+
// dark rgb(2,8,23)). `bg-secondary-foreground` BİLEREK seçilmedi:
|
|
4940
|
+
// light'ta --primary ile aynı hue/sat'ta yalnız ΔL=%2 (49 vs 51,
|
|
4941
|
+
// fill↔fill 1.07), dark'ta birebir --primary değeri (210 40% 98%) —
|
|
4942
|
+
// secondary varyantı primary'nin klonuna dönerdi. `--secondary-500`
|
|
4943
|
+
// (tokens.css slate skalası, RGB üçlüsü) iki temada da track'e ≥3:1
|
|
4944
|
+
// (WCAG 1.4.11) veren TEK kademe: light 4.63, dark 4.23 (gerçek kart
|
|
4945
|
+
// #111827 üstünde 3.83; 400 light'ta 2.50 ✗, 600 dark'ta 2.66 ✗).
|
|
4946
|
+
// Skala :root'ta tanımlı olduğundan tema değişiminde sabittir;
|
|
4947
|
+
// tüketici --secondary-500'ü ezerek özelleştirebilir.
|
|
4948
|
+
// Regresyon: __tests__/progress-secondary-contrast.test.ts
|
|
4949
|
+
secondary: "bg-[rgb(var(--secondary-500))]",
|
|
4887
4950
|
success: "bg-success",
|
|
4888
4951
|
warning: "bg-warning",
|
|
4889
4952
|
error: "bg-error"
|
|
@@ -4977,6 +5040,26 @@ var formatFileSize = (bytes) => {
|
|
|
4977
5040
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
4978
5041
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
|
|
4979
5042
|
};
|
|
5043
|
+
var matchesAcceptToken = (file, token) => {
|
|
5044
|
+
const normalized = token.trim().toLowerCase();
|
|
5045
|
+
if (!normalized)
|
|
5046
|
+
return false;
|
|
5047
|
+
if (normalized === "*" || normalized === "*/*")
|
|
5048
|
+
return true;
|
|
5049
|
+
if (normalized.startsWith(".")) {
|
|
5050
|
+
return file.name.toLowerCase().endsWith(normalized);
|
|
5051
|
+
}
|
|
5052
|
+
if (normalized.endsWith("/*")) {
|
|
5053
|
+
return file.type.toLowerCase().startsWith(normalized.slice(0, -1));
|
|
5054
|
+
}
|
|
5055
|
+
return file.type.toLowerCase() === normalized;
|
|
5056
|
+
};
|
|
5057
|
+
var isFileAccepted = (file, accept) => {
|
|
5058
|
+
const trimmed = accept.trim();
|
|
5059
|
+
if (trimmed === "" || trimmed === "*")
|
|
5060
|
+
return true;
|
|
5061
|
+
return trimmed.split(",").some((token) => matchesAcceptToken(file, token));
|
|
5062
|
+
};
|
|
4980
5063
|
var FileItem = ({
|
|
4981
5064
|
uploadedFile,
|
|
4982
5065
|
onRemove
|
|
@@ -5055,13 +5138,7 @@ var FileUpload = React12__namespace.default.forwardRef(
|
|
|
5055
5138
|
if (file.size > maxSize) {
|
|
5056
5139
|
return `File size exceeds ${formatFileSize(maxSize)}`;
|
|
5057
5140
|
}
|
|
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
|
-
})) {
|
|
5141
|
+
if (!isFileAccepted(file, accept)) {
|
|
5065
5142
|
return `File type not supported`;
|
|
5066
5143
|
}
|
|
5067
5144
|
return null;
|
|
@@ -5095,6 +5172,7 @@ var FileUpload = React12__namespace.default.forwardRef(
|
|
|
5095
5172
|
preview: file.type.startsWith("image/") ? URL.createObjectURL(file) : void 0
|
|
5096
5173
|
}));
|
|
5097
5174
|
setUploadedFiles((prev) => [...prev, ...newUploadedFiles]);
|
|
5175
|
+
const progressIntervals = /* @__PURE__ */ new Map();
|
|
5098
5176
|
for (const uploadedFile of newUploadedFiles) {
|
|
5099
5177
|
let progress = 0;
|
|
5100
5178
|
const interval = setInterval(() => {
|
|
@@ -5102,25 +5180,33 @@ var FileUpload = React12__namespace.default.forwardRef(
|
|
|
5102
5180
|
if (progress >= 100) {
|
|
5103
5181
|
progress = 100;
|
|
5104
5182
|
clearInterval(interval);
|
|
5183
|
+
progressIntervals.delete(uploadedFile.id);
|
|
5105
5184
|
setUploadedFiles(
|
|
5106
5185
|
(prev) => prev.map(
|
|
5107
|
-
(f) =>
|
|
5186
|
+
(f) => (
|
|
5187
|
+
// 'error'a düşmüş dosya simülasyonca geri 'success' yapılamaz —
|
|
5188
|
+
// error nihai durumdur (#378)
|
|
5189
|
+
f.id === uploadedFile.id && f.status === "uploading" ? { ...f, progress: 100, status: "success" } : f
|
|
5190
|
+
)
|
|
5108
5191
|
)
|
|
5109
5192
|
);
|
|
5110
5193
|
} else {
|
|
5111
5194
|
setUploadedFiles(
|
|
5112
5195
|
(prev) => prev.map(
|
|
5113
|
-
(f) => f.id === uploadedFile.id ? { ...f, progress } : f
|
|
5196
|
+
(f) => f.id === uploadedFile.id && f.status === "uploading" ? { ...f, progress } : f
|
|
5114
5197
|
)
|
|
5115
5198
|
);
|
|
5116
5199
|
}
|
|
5117
5200
|
}, 200);
|
|
5201
|
+
progressIntervals.set(uploadedFile.id, interval);
|
|
5118
5202
|
}
|
|
5119
5203
|
if (onUpload) {
|
|
5120
5204
|
try {
|
|
5121
5205
|
await onUpload(newUploadedFiles);
|
|
5122
5206
|
} catch (error2) {
|
|
5123
5207
|
console.error("Upload failed:", error2);
|
|
5208
|
+
progressIntervals.forEach((handle) => clearInterval(handle));
|
|
5209
|
+
progressIntervals.clear();
|
|
5124
5210
|
setUploadedFiles(
|
|
5125
5211
|
(prev) => prev.map(
|
|
5126
5212
|
(f) => newUploadedFiles.some((nf) => nf.id === f.id) ? { ...f, status: "error" } : f
|