@underverse-ui/underverse 0.2.104 → 0.2.105
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.cjs +313 -151
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +336 -174
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -7082,6 +7082,7 @@ var React25 = __toESM(require("react"), 1);
|
|
|
7082
7082
|
var import_lucide_react16 = require("lucide-react");
|
|
7083
7083
|
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
7084
7084
|
var pad = (n) => n.toString().padStart(2, "0");
|
|
7085
|
+
var clamp3 = (n, min, max) => Math.min(max, Math.max(min, n));
|
|
7085
7086
|
var WHEEL_ITEM_HEIGHT = {
|
|
7086
7087
|
sm: 30,
|
|
7087
7088
|
md: 34,
|
|
@@ -7096,6 +7097,7 @@ function WheelColumn({
|
|
|
7096
7097
|
onSelect,
|
|
7097
7098
|
scrollRef,
|
|
7098
7099
|
itemHeight,
|
|
7100
|
+
size,
|
|
7099
7101
|
animate,
|
|
7100
7102
|
focused,
|
|
7101
7103
|
setFocusedColumn,
|
|
@@ -7104,18 +7106,72 @@ function WheelColumn({
|
|
|
7104
7106
|
const height = itemHeight * WHEEL_VISIBLE_ITEMS;
|
|
7105
7107
|
const paddingY = (height - itemHeight) / 2;
|
|
7106
7108
|
const rafRef = React25.useRef(0);
|
|
7107
|
-
const
|
|
7109
|
+
const lastVirtualIndexRef = React25.useRef(null);
|
|
7108
7110
|
const wheelDeltaRef = React25.useRef(0);
|
|
7109
7111
|
const scrollEndTimeoutRef = React25.useRef(null);
|
|
7110
7112
|
const suppressScrollSelectUntilRef = React25.useRef(0);
|
|
7113
|
+
const loop = true;
|
|
7114
|
+
const ui = React25.useMemo(() => {
|
|
7115
|
+
if (size === "sm") {
|
|
7116
|
+
return {
|
|
7117
|
+
columnWidth: "min-w-[64px] max-w-[84px]",
|
|
7118
|
+
label: "text-[9px] mb-2",
|
|
7119
|
+
selectedText: "text-base",
|
|
7120
|
+
unselectedText: "text-sm",
|
|
7121
|
+
fadeHeight: "h-10"
|
|
7122
|
+
};
|
|
7123
|
+
}
|
|
7124
|
+
if (size === "lg") {
|
|
7125
|
+
return {
|
|
7126
|
+
columnWidth: "min-w-[80px] max-w-[110px]",
|
|
7127
|
+
label: "text-[11px] mb-3",
|
|
7128
|
+
selectedText: "text-xl",
|
|
7129
|
+
unselectedText: "text-lg",
|
|
7130
|
+
fadeHeight: "h-14"
|
|
7131
|
+
};
|
|
7132
|
+
}
|
|
7133
|
+
return {
|
|
7134
|
+
columnWidth: "min-w-[70px] max-w-[90px]",
|
|
7135
|
+
label: "text-[10px] mb-3",
|
|
7136
|
+
selectedText: "text-lg",
|
|
7137
|
+
unselectedText: "text-base",
|
|
7138
|
+
fadeHeight: "h-12"
|
|
7139
|
+
};
|
|
7140
|
+
}, [size]);
|
|
7141
|
+
const baseOffset = React25.useMemo(() => loop ? items.length : 0, [items.length, loop]);
|
|
7142
|
+
const extendedItems = React25.useMemo(() => loop ? [...items, ...items, ...items] : items, [items, loop]);
|
|
7143
|
+
const getNearestVirtualIndex = React25.useCallback(
|
|
7144
|
+
(realIndex, fromVirtual) => {
|
|
7145
|
+
const len = items.length;
|
|
7146
|
+
if (len <= 0) return 0;
|
|
7147
|
+
if (!loop) return clamp3(realIndex, 0, Math.max(0, len - 1));
|
|
7148
|
+
const candidates = [realIndex, realIndex + len, realIndex + 2 * len];
|
|
7149
|
+
let best = candidates[0];
|
|
7150
|
+
let bestDist = Math.abs(best - fromVirtual);
|
|
7151
|
+
for (const c of candidates) {
|
|
7152
|
+
const dist = Math.abs(c - fromVirtual);
|
|
7153
|
+
if (dist < bestDist) {
|
|
7154
|
+
best = c;
|
|
7155
|
+
bestDist = dist;
|
|
7156
|
+
}
|
|
7157
|
+
}
|
|
7158
|
+
return best;
|
|
7159
|
+
},
|
|
7160
|
+
[items.length, loop]
|
|
7161
|
+
);
|
|
7111
7162
|
React25.useEffect(() => {
|
|
7112
7163
|
const el = scrollRef.current;
|
|
7113
7164
|
if (!el) return;
|
|
7114
|
-
const
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7165
|
+
const maxVirtual = Math.max(0, extendedItems.length - 1);
|
|
7166
|
+
const currentVirtual2 = clamp3(Math.round(el.scrollTop / itemHeight), 0, maxVirtual);
|
|
7167
|
+
const desiredVirtual = loop ? getNearestVirtualIndex(valueIndex, currentVirtual2) : valueIndex;
|
|
7168
|
+
const nextTop = desiredVirtual * itemHeight;
|
|
7169
|
+
const delta = Math.abs(el.scrollTop - nextTop);
|
|
7170
|
+
if (delta > 1) {
|
|
7171
|
+
const behavior = animate && delta <= itemHeight * 1.5 ? "smooth" : "auto";
|
|
7172
|
+
el.scrollTo({ top: nextTop, behavior });
|
|
7173
|
+
}
|
|
7174
|
+
lastVirtualIndexRef.current = desiredVirtual;
|
|
7119
7175
|
return () => {
|
|
7120
7176
|
if (scrollEndTimeoutRef.current != null) {
|
|
7121
7177
|
window.clearTimeout(scrollEndTimeoutRef.current);
|
|
@@ -7123,7 +7179,7 @@ function WheelColumn({
|
|
|
7123
7179
|
}
|
|
7124
7180
|
cancelAnimationFrame(rafRef.current);
|
|
7125
7181
|
};
|
|
7126
|
-
}, [animate, itemHeight, scrollRef, valueIndex]);
|
|
7182
|
+
}, [animate, extendedItems.length, getNearestVirtualIndex, itemHeight, loop, scrollRef, valueIndex]);
|
|
7127
7183
|
React25.useEffect(() => {
|
|
7128
7184
|
const el = scrollRef.current;
|
|
7129
7185
|
if (!el) return;
|
|
@@ -7155,19 +7211,29 @@ function WheelColumn({
|
|
|
7155
7211
|
step = Math.sign(wheelDeltaRef.current);
|
|
7156
7212
|
wheelDeltaRef.current = 0;
|
|
7157
7213
|
}
|
|
7158
|
-
|
|
7159
|
-
const
|
|
7160
|
-
|
|
7214
|
+
if (items.length <= 0) return;
|
|
7215
|
+
const fromVirtual = lastVirtualIndexRef.current ?? (loop ? baseOffset + valueIndex : valueIndex);
|
|
7216
|
+
let nextVirtual = fromVirtual + step;
|
|
7217
|
+
if (!loop) {
|
|
7218
|
+
nextVirtual = clamp3(nextVirtual, 0, Math.max(0, items.length - 1));
|
|
7219
|
+
} else {
|
|
7220
|
+
const len = items.length;
|
|
7221
|
+
const maxVirtual = Math.max(0, len * 3 - 1);
|
|
7222
|
+
if (nextVirtual < 0) nextVirtual += len;
|
|
7223
|
+
if (nextVirtual > maxVirtual) nextVirtual -= len;
|
|
7224
|
+
}
|
|
7225
|
+
if (nextVirtual === fromVirtual) return;
|
|
7161
7226
|
lastStepAtRef.current = Date.now();
|
|
7162
7227
|
lastStepSignRef.current = step;
|
|
7163
|
-
|
|
7228
|
+
lastVirtualIndexRef.current = nextVirtual;
|
|
7164
7229
|
suppressScrollSelectUntilRef.current = Date.now() + 350;
|
|
7165
|
-
el.scrollTo({ top:
|
|
7166
|
-
|
|
7230
|
+
el.scrollTo({ top: nextVirtual * itemHeight, behavior: animate ? "smooth" : "auto" });
|
|
7231
|
+
const realIndex = (nextVirtual % items.length + items.length) % items.length;
|
|
7232
|
+
onSelect(items[realIndex]);
|
|
7167
7233
|
};
|
|
7168
7234
|
el.addEventListener("wheel", onWheel, { passive: false });
|
|
7169
7235
|
return () => el.removeEventListener("wheel", onWheel);
|
|
7170
|
-
}, [animate, column, itemHeight, items, onSelect, scrollRef, setFocusedColumn, valueIndex]);
|
|
7236
|
+
}, [animate, baseOffset, column, itemHeight, items, loop, onSelect, scrollRef, setFocusedColumn, valueIndex]);
|
|
7171
7237
|
const handleScroll = () => {
|
|
7172
7238
|
const el = scrollRef.current;
|
|
7173
7239
|
if (!el) return;
|
|
@@ -7178,17 +7244,38 @@ function WheelColumn({
|
|
|
7178
7244
|
window.clearTimeout(scrollEndTimeoutRef.current);
|
|
7179
7245
|
}
|
|
7180
7246
|
scrollEndTimeoutRef.current = window.setTimeout(() => {
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
|
|
7247
|
+
if (items.length <= 0) return;
|
|
7248
|
+
const len = items.length;
|
|
7249
|
+
const maxVirtual = Math.max(0, extendedItems.length - 1);
|
|
7250
|
+
const idxVirtual = clamp3(Math.round(el.scrollTop / itemHeight), 0, maxVirtual);
|
|
7251
|
+
const realIndex = (idxVirtual % len + len) % len;
|
|
7252
|
+
const snappedVirtual = loop ? getNearestVirtualIndex(realIndex, idxVirtual) : realIndex;
|
|
7253
|
+
if (lastVirtualIndexRef.current !== snappedVirtual) lastVirtualIndexRef.current = snappedVirtual;
|
|
7184
7254
|
suppressScrollSelectUntilRef.current = Date.now() + 350;
|
|
7185
|
-
el.scrollTo({ top:
|
|
7186
|
-
onSelect(items[
|
|
7255
|
+
el.scrollTo({ top: snappedVirtual * itemHeight, behavior: animate ? "smooth" : "auto" });
|
|
7256
|
+
onSelect(items[realIndex]);
|
|
7257
|
+
if (loop) {
|
|
7258
|
+
const min = len;
|
|
7259
|
+
const max = len * 2 - 1;
|
|
7260
|
+
let centered = snappedVirtual;
|
|
7261
|
+
if (centered < min) centered += len;
|
|
7262
|
+
if (centered > max) centered -= len;
|
|
7263
|
+
if (centered !== snappedVirtual) {
|
|
7264
|
+
lastVirtualIndexRef.current = centered;
|
|
7265
|
+
el.scrollTo({ top: centered * itemHeight, behavior: "auto" });
|
|
7266
|
+
}
|
|
7267
|
+
}
|
|
7187
7268
|
}, 120);
|
|
7188
7269
|
});
|
|
7189
7270
|
};
|
|
7190
|
-
|
|
7191
|
-
|
|
7271
|
+
const currentVirtual = React25.useMemo(() => {
|
|
7272
|
+
if (!loop || items.length <= 0) return valueIndex;
|
|
7273
|
+
const fallback = baseOffset + valueIndex;
|
|
7274
|
+
const from = lastVirtualIndexRef.current ?? fallback;
|
|
7275
|
+
return getNearestVirtualIndex(valueIndex, from);
|
|
7276
|
+
}, [baseOffset, getNearestVirtualIndex, items.length, loop, valueIndex]);
|
|
7277
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: cn("flex-1", ui.columnWidth), children: [
|
|
7278
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn(ui.label, "font-bold uppercase tracking-wider text-muted-foreground/70 text-center"), children: labelText }),
|
|
7192
7279
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "relative rounded-xl bg-muted/30 overflow-hidden", style: { height }, children: [
|
|
7193
7280
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
7194
7281
|
"div",
|
|
@@ -7197,8 +7284,8 @@ function WheelColumn({
|
|
|
7197
7284
|
style: { height: itemHeight }
|
|
7198
7285
|
}
|
|
7199
7286
|
),
|
|
7200
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "pointer-events-none absolute inset-x-0 top-0
|
|
7201
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "pointer-events-none absolute inset-x-0 bottom-0
|
|
7287
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn("pointer-events-none absolute inset-x-0 top-0 bg-linear-to-b from-background/95 via-background/60 to-transparent z-10", ui.fadeHeight) }),
|
|
7288
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn("pointer-events-none absolute inset-x-0 bottom-0 bg-linear-to-t from-background/95 via-background/60 to-transparent z-10", ui.fadeHeight) }),
|
|
7202
7289
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
7203
7290
|
"div",
|
|
7204
7291
|
{
|
|
@@ -7215,11 +7302,11 @@ function WheelColumn({
|
|
|
7215
7302
|
onKeyDown: (e) => onKeyDown(e, column),
|
|
7216
7303
|
onFocus: () => setFocusedColumn(column),
|
|
7217
7304
|
onScroll: handleScroll,
|
|
7218
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { children:
|
|
7219
|
-
const dist = Math.abs(index -
|
|
7305
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { children: extendedItems.map((n, index) => {
|
|
7306
|
+
const dist = Math.abs(index - currentVirtual);
|
|
7220
7307
|
const scale = 1 - Math.min(dist * 0.12, 0.36);
|
|
7221
7308
|
const opacity = 1 - Math.min(dist * 0.22, 0.75);
|
|
7222
|
-
const isSelected = index ===
|
|
7309
|
+
const isSelected = index === currentVirtual;
|
|
7223
7310
|
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
7224
7311
|
"button",
|
|
7225
7312
|
{
|
|
@@ -7228,7 +7315,7 @@ function WheelColumn({
|
|
|
7228
7315
|
"aria-selected": isSelected,
|
|
7229
7316
|
className: cn(
|
|
7230
7317
|
"w-full snap-center flex items-center justify-center rounded-lg transition-all duration-200 font-bold tabular-nums",
|
|
7231
|
-
isSelected ? "text-primary
|
|
7318
|
+
isSelected ? cn("text-primary", ui.selectedText) : cn("text-muted-foreground hover:text-foreground/70", ui.unselectedText)
|
|
7232
7319
|
),
|
|
7233
7320
|
style: {
|
|
7234
7321
|
height: itemHeight,
|
|
@@ -7237,13 +7324,16 @@ function WheelColumn({
|
|
|
7237
7324
|
},
|
|
7238
7325
|
onClick: () => {
|
|
7239
7326
|
const el = scrollRef.current;
|
|
7327
|
+
if (!el) return;
|
|
7240
7328
|
suppressScrollSelectUntilRef.current = Date.now() + 350;
|
|
7241
|
-
|
|
7242
|
-
|
|
7329
|
+
lastVirtualIndexRef.current = index;
|
|
7330
|
+
el.scrollTo({ top: index * itemHeight, behavior: animate ? "smooth" : "auto" });
|
|
7331
|
+
const realIndex = (index % items.length + items.length) % items.length;
|
|
7332
|
+
onSelect(items[realIndex]);
|
|
7243
7333
|
},
|
|
7244
7334
|
children: pad(n)
|
|
7245
7335
|
},
|
|
7246
|
-
|
|
7336
|
+
`${column}_${index}`
|
|
7247
7337
|
);
|
|
7248
7338
|
}) })
|
|
7249
7339
|
}
|
|
@@ -7303,6 +7393,7 @@ function TimePicker({
|
|
|
7303
7393
|
secondStep = 1,
|
|
7304
7394
|
clearable = true,
|
|
7305
7395
|
variant = "default",
|
|
7396
|
+
matchTriggerWidth = true,
|
|
7306
7397
|
showNow = false,
|
|
7307
7398
|
showPresets = false,
|
|
7308
7399
|
allowManualInput = false,
|
|
@@ -7473,12 +7564,60 @@ function TimePicker({
|
|
|
7473
7564
|
const hours = format === "24" ? Array.from({ length: 24 }, (_, i) => i) : Array.from({ length: 12 }, (_, i) => i + 1);
|
|
7474
7565
|
const minutes = Array.from({ length: Math.ceil(60 / minuteStep) }, (_, i) => Math.min(59, i * minuteStep));
|
|
7475
7566
|
const seconds = Array.from({ length: Math.ceil(60 / secondStep) }, (_, i) => Math.min(59, i * secondStep));
|
|
7567
|
+
const panelSizeClasses = {
|
|
7568
|
+
sm: {
|
|
7569
|
+
contentPadding: "p-4",
|
|
7570
|
+
stackGap: "space-y-3",
|
|
7571
|
+
timeText: "text-xl",
|
|
7572
|
+
inputSize: "sm",
|
|
7573
|
+
icon: "w-3 h-3",
|
|
7574
|
+
separatorPad: "pt-6",
|
|
7575
|
+
presetText: "text-[11px]",
|
|
7576
|
+
presetPadding: "px-3 py-2",
|
|
7577
|
+
actionText: "text-[11px]",
|
|
7578
|
+
actionPadding: "px-3 py-2",
|
|
7579
|
+
periodLabel: "text-[9px] mb-2",
|
|
7580
|
+
periodGap: "gap-1.5",
|
|
7581
|
+
periodButton: "px-3 py-2 text-xs"
|
|
7582
|
+
},
|
|
7583
|
+
md: {
|
|
7584
|
+
contentPadding: "p-5",
|
|
7585
|
+
stackGap: "space-y-4",
|
|
7586
|
+
timeText: "text-2xl",
|
|
7587
|
+
inputSize: "sm",
|
|
7588
|
+
icon: "w-3.5 h-3.5",
|
|
7589
|
+
separatorPad: "pt-8",
|
|
7590
|
+
presetText: "text-xs",
|
|
7591
|
+
presetPadding: "px-3 py-2.5",
|
|
7592
|
+
actionText: "text-xs",
|
|
7593
|
+
actionPadding: "px-4 py-2.5",
|
|
7594
|
+
periodLabel: "text-[10px] mb-3",
|
|
7595
|
+
periodGap: "gap-2",
|
|
7596
|
+
periodButton: "px-4 py-3 text-sm"
|
|
7597
|
+
},
|
|
7598
|
+
lg: {
|
|
7599
|
+
contentPadding: "p-6",
|
|
7600
|
+
stackGap: "space-y-5",
|
|
7601
|
+
timeText: "text-3xl",
|
|
7602
|
+
inputSize: "md",
|
|
7603
|
+
icon: "w-4 h-4",
|
|
7604
|
+
separatorPad: "pt-9",
|
|
7605
|
+
presetText: "text-sm",
|
|
7606
|
+
presetPadding: "px-4 py-3",
|
|
7607
|
+
actionText: "text-sm",
|
|
7608
|
+
actionPadding: "px-5 py-3",
|
|
7609
|
+
periodLabel: "text-[11px] mb-3",
|
|
7610
|
+
periodGap: "gap-2",
|
|
7611
|
+
periodButton: "px-5 py-3.5 text-base"
|
|
7612
|
+
}
|
|
7613
|
+
};
|
|
7476
7614
|
const sizeClasses2 = {
|
|
7477
7615
|
sm: { label: "text-xs", height: "h-8", padding: "px-2.5 py-1.5", text: "text-xs", icon: "w-3.5 h-3.5" },
|
|
7478
7616
|
md: { label: "text-sm", height: "h-10", padding: "px-3 py-2", text: "text-sm", icon: "w-4 h-4" },
|
|
7479
7617
|
lg: { label: "text-base", height: "h-12", padding: "px-4 py-3", text: "text-base", icon: "w-5 h-5" }
|
|
7480
7618
|
};
|
|
7481
7619
|
const sz = sizeClasses2[size];
|
|
7620
|
+
const panelSz = panelSizeClasses[size];
|
|
7482
7621
|
const display = formatTime(parts, format, includeSeconds);
|
|
7483
7622
|
const trigger = variant === "inline" ? null : /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
7484
7623
|
"button",
|
|
@@ -7509,8 +7648,8 @@ function TimePicker({
|
|
|
7509
7648
|
"div",
|
|
7510
7649
|
{
|
|
7511
7650
|
className: cn(
|
|
7512
|
-
"flex items-center justify-center
|
|
7513
|
-
error ? "
|
|
7651
|
+
"flex items-center justify-center transition-colors duration-300",
|
|
7652
|
+
error ? "text-destructive" : success ? "text-success" : open ? "text-primary" : "text-muted-foreground group-hover:text-primary"
|
|
7514
7653
|
),
|
|
7515
7654
|
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react16.Clock, { className: cn(sz.icon, "transition-transform duration-300", open && "rotate-12") })
|
|
7516
7655
|
}
|
|
@@ -7543,8 +7682,8 @@ function TimePicker({
|
|
|
7543
7682
|
setParts(next);
|
|
7544
7683
|
emit(next);
|
|
7545
7684
|
};
|
|
7546
|
-
const timePickerContent = /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className:
|
|
7547
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex items-center justify-center py-2 px-3 rounded-xl bg-linear-to-r from-primary/10 via-primary/5 to-primary/10 border border-primary/20", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "
|
|
7685
|
+
const timePickerContent = /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: panelSz.stackGap, children: [
|
|
7686
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex items-center justify-center py-2 px-3 rounded-xl bg-linear-to-r from-primary/10 via-primary/5 to-primary/10 border border-primary/20", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: cn(panelSz.timeText, "font-bold tabular-nums tracking-wide text-foreground"), children: display }) }),
|
|
7548
7687
|
allowManualInput && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "relative", children: [
|
|
7549
7688
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
7550
7689
|
Input_default,
|
|
@@ -7552,12 +7691,12 @@ function TimePicker({
|
|
|
7552
7691
|
placeholder: format === "12" ? "02:30 PM" : "14:30",
|
|
7553
7692
|
value: manualInput || display,
|
|
7554
7693
|
onChange: (e) => handleManualInput(e.target.value),
|
|
7555
|
-
size:
|
|
7694
|
+
size: panelSz.inputSize,
|
|
7556
7695
|
variant: "outlined",
|
|
7557
7696
|
className: "pl-9"
|
|
7558
7697
|
}
|
|
7559
7698
|
),
|
|
7560
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react16.Clock, { className: "absolute left-3 top-1/2 -translate-y-1/2
|
|
7699
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react16.Clock, { className: cn("absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground", panelSz.icon) })
|
|
7561
7700
|
] }),
|
|
7562
7701
|
showPresets && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "grid grid-cols-2 gap-2", children: Object.keys(PRESETS).map((preset) => {
|
|
7563
7702
|
const { icon: Icon, label: label2, color } = PRESETS[preset];
|
|
@@ -7566,7 +7705,9 @@ function TimePicker({
|
|
|
7566
7705
|
{
|
|
7567
7706
|
type: "button",
|
|
7568
7707
|
className: cn(
|
|
7569
|
-
"group relative
|
|
7708
|
+
"group relative font-medium rounded-xl border border-border/50 overflow-hidden",
|
|
7709
|
+
panelSz.presetPadding,
|
|
7710
|
+
panelSz.presetText,
|
|
7570
7711
|
"bg-linear-to-br from-background to-muted/30",
|
|
7571
7712
|
"hover:border-primary/40 hover:shadow-md transition-all duration-300",
|
|
7572
7713
|
animate && "hover:scale-[1.02] active:scale-[0.98]"
|
|
@@ -7582,7 +7723,7 @@ function TimePicker({
|
|
|
7582
7723
|
}
|
|
7583
7724
|
),
|
|
7584
7725
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "relative flex items-center gap-2", children: [
|
|
7585
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Icon, { className: "
|
|
7726
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Icon, { className: cn("text-muted-foreground group-hover:text-primary transition-colors", panelSz.icon) }),
|
|
7586
7727
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-foreground/80 group-hover:text-foreground transition-colors", children: label2 })
|
|
7587
7728
|
] })
|
|
7588
7729
|
]
|
|
@@ -7595,7 +7736,9 @@ function TimePicker({
|
|
|
7595
7736
|
{
|
|
7596
7737
|
type: "button",
|
|
7597
7738
|
className: cn(
|
|
7598
|
-
"
|
|
7739
|
+
"font-medium rounded-xl border border-border/50",
|
|
7740
|
+
panelSz.presetPadding,
|
|
7741
|
+
panelSz.presetText,
|
|
7599
7742
|
"bg-linear-to-br from-background to-muted/30",
|
|
7600
7743
|
"hover:border-primary/40 hover:bg-primary/5 hover:shadow-md transition-all duration-300",
|
|
7601
7744
|
animate && "hover:scale-[1.02] active:scale-[0.98]"
|
|
@@ -7620,6 +7763,7 @@ function TimePicker({
|
|
|
7620
7763
|
onSelect: setHourFromDisplay,
|
|
7621
7764
|
scrollRef: hourScrollRef,
|
|
7622
7765
|
itemHeight,
|
|
7766
|
+
size,
|
|
7623
7767
|
animate,
|
|
7624
7768
|
focused: focusedColumn === "hour",
|
|
7625
7769
|
setFocusedColumn: (col) => setFocusedColumn(col),
|
|
@@ -7627,7 +7771,7 @@ function TimePicker({
|
|
|
7627
7771
|
}
|
|
7628
7772
|
);
|
|
7629
7773
|
})(),
|
|
7630
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex flex-col items-center justify-center
|
|
7774
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn("flex flex-col items-center justify-center", panelSz.separatorPad), children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
7631
7775
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "w-1.5 h-1.5 rounded-full bg-primary/60" }),
|
|
7632
7776
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "w-1.5 h-1.5 rounded-full bg-primary/60" })
|
|
7633
7777
|
] }) }),
|
|
@@ -7647,6 +7791,7 @@ function TimePicker({
|
|
|
7647
7791
|
},
|
|
7648
7792
|
scrollRef: minuteScrollRef,
|
|
7649
7793
|
itemHeight,
|
|
7794
|
+
size,
|
|
7650
7795
|
animate,
|
|
7651
7796
|
focused: focusedColumn === "minute",
|
|
7652
7797
|
setFocusedColumn: (col) => setFocusedColumn(col),
|
|
@@ -7655,7 +7800,7 @@ function TimePicker({
|
|
|
7655
7800
|
);
|
|
7656
7801
|
})(),
|
|
7657
7802
|
includeSeconds && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_jsx_runtime31.Fragment, { children: [
|
|
7658
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex flex-col items-center justify-center
|
|
7803
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn("flex flex-col items-center justify-center", panelSz.separatorPad), children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
7659
7804
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "w-1.5 h-1.5 rounded-full bg-primary/60" }),
|
|
7660
7805
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "w-1.5 h-1.5 rounded-full bg-primary/60" })
|
|
7661
7806
|
] }) }),
|
|
@@ -7675,6 +7820,7 @@ function TimePicker({
|
|
|
7675
7820
|
},
|
|
7676
7821
|
scrollRef: secondScrollRef,
|
|
7677
7822
|
itemHeight,
|
|
7823
|
+
size,
|
|
7678
7824
|
animate,
|
|
7679
7825
|
focused: focusedColumn === "second",
|
|
7680
7826
|
setFocusedColumn: (col) => setFocusedColumn(col),
|
|
@@ -7683,52 +7829,62 @@ function TimePicker({
|
|
|
7683
7829
|
);
|
|
7684
7830
|
})()
|
|
7685
7831
|
] }),
|
|
7686
|
-
format === "12" && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
7687
|
-
|
|
7688
|
-
|
|
7689
|
-
|
|
7690
|
-
|
|
7691
|
-
|
|
7692
|
-
|
|
7693
|
-
|
|
7694
|
-
|
|
7695
|
-
|
|
7696
|
-
|
|
7697
|
-
|
|
7698
|
-
|
|
7699
|
-
|
|
7700
|
-
"
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
|
|
7704
|
-
|
|
7705
|
-
|
|
7706
|
-
|
|
7707
|
-
"
|
|
7708
|
-
|
|
7709
|
-
|
|
7710
|
-
|
|
7711
|
-
|
|
7712
|
-
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
|
|
7832
|
+
format === "12" && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
7833
|
+
"div",
|
|
7834
|
+
{
|
|
7835
|
+
className: cn(
|
|
7836
|
+
"flex-1",
|
|
7837
|
+
size === "sm" ? "min-w-[64px] max-w-[84px]" : size === "lg" ? "min-w-[80px] max-w-[110px]" : "min-w-[70px] max-w-[90px]"
|
|
7838
|
+
),
|
|
7839
|
+
children: [
|
|
7840
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn(panelSz.periodLabel, "font-bold uppercase tracking-wider text-muted-foreground/70 text-center"), children: "Period" }),
|
|
7841
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
7842
|
+
"div",
|
|
7843
|
+
{
|
|
7844
|
+
className: cn("flex flex-col p-1 rounded-xl bg-muted/30", panelSz.periodGap),
|
|
7845
|
+
role: "radiogroup",
|
|
7846
|
+
"aria-label": "Select AM or PM",
|
|
7847
|
+
tabIndex: focusedColumn === "period" ? 0 : -1,
|
|
7848
|
+
onKeyDown: (e) => handleKeyDown(e, "period"),
|
|
7849
|
+
onFocus: () => setFocusedColumn("period"),
|
|
7850
|
+
children: ["AM", "PM"].map((p) => {
|
|
7851
|
+
const isSelected = parts.p === p;
|
|
7852
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
7853
|
+
"button",
|
|
7854
|
+
{
|
|
7855
|
+
type: "button",
|
|
7856
|
+
role: "radio",
|
|
7857
|
+
"aria-checked": isSelected,
|
|
7858
|
+
className: cn(
|
|
7859
|
+
"relative rounded-lg transition-all duration-300 font-bold overflow-hidden",
|
|
7860
|
+
panelSz.periodButton,
|
|
7861
|
+
"focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-1",
|
|
7862
|
+
isSelected && "bg-linear-to-r from-primary to-primary/80 text-primary-foreground shadow-lg shadow-primary/25",
|
|
7863
|
+
!isSelected && "text-muted-foreground hover:text-foreground hover:bg-muted/50",
|
|
7864
|
+
animate && "hover:scale-[1.02] active:scale-[0.98]"
|
|
7865
|
+
),
|
|
7866
|
+
onClick: () => {
|
|
7867
|
+
const pVal = p;
|
|
7868
|
+
let hour = parts.h;
|
|
7869
|
+
if (pVal === "AM" && hour >= 12) hour -= 12;
|
|
7870
|
+
if (pVal === "PM" && hour < 12) hour += 12;
|
|
7871
|
+
const next = { ...parts, p: pVal, h: hour };
|
|
7872
|
+
setParts(next);
|
|
7873
|
+
emit(next);
|
|
7874
|
+
},
|
|
7875
|
+
children: [
|
|
7876
|
+
isSelected && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "absolute inset-0 bg-linear-to-tr from-white/20 to-transparent" }),
|
|
7877
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "relative", children: p })
|
|
7878
|
+
]
|
|
7879
|
+
},
|
|
7880
|
+
p
|
|
7881
|
+
);
|
|
7882
|
+
})
|
|
7883
|
+
}
|
|
7884
|
+
)
|
|
7885
|
+
]
|
|
7886
|
+
}
|
|
7887
|
+
)
|
|
7732
7888
|
] }),
|
|
7733
7889
|
(showNow || clearable) && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center gap-2 pt-3 border-t border-border/50", children: [
|
|
7734
7890
|
showNow && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
@@ -7736,7 +7892,9 @@ function TimePicker({
|
|
|
7736
7892
|
{
|
|
7737
7893
|
type: "button",
|
|
7738
7894
|
className: cn(
|
|
7739
|
-
"flex-1
|
|
7895
|
+
"flex-1 font-semibold rounded-xl",
|
|
7896
|
+
panelSz.actionPadding,
|
|
7897
|
+
panelSz.actionText,
|
|
7740
7898
|
"bg-linear-to-r from-primary/10 to-primary/5 border border-primary/30",
|
|
7741
7899
|
"text-primary hover:from-primary/20 hover:to-primary/10 hover:border-primary/50",
|
|
7742
7900
|
"transition-all duration-300 flex items-center justify-center gap-2",
|
|
@@ -7748,7 +7906,7 @@ function TimePicker({
|
|
|
7748
7906
|
},
|
|
7749
7907
|
"aria-label": "Set current time",
|
|
7750
7908
|
children: [
|
|
7751
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react16.Clock, { className:
|
|
7909
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react16.Clock, { className: panelSz.icon }),
|
|
7752
7910
|
"Now"
|
|
7753
7911
|
]
|
|
7754
7912
|
}
|
|
@@ -7758,7 +7916,9 @@ function TimePicker({
|
|
|
7758
7916
|
{
|
|
7759
7917
|
type: "button",
|
|
7760
7918
|
className: cn(
|
|
7761
|
-
"flex-1
|
|
7919
|
+
"flex-1 font-semibold rounded-xl",
|
|
7920
|
+
panelSz.actionPadding,
|
|
7921
|
+
panelSz.actionText,
|
|
7762
7922
|
"bg-linear-to-r from-destructive/10 to-destructive/5 border border-destructive/30",
|
|
7763
7923
|
"text-destructive hover:from-destructive/20 hover:to-destructive/10 hover:border-destructive/50",
|
|
7764
7924
|
"transition-all duration-300 flex items-center justify-center gap-2",
|
|
@@ -7771,7 +7931,7 @@ function TimePicker({
|
|
|
7771
7931
|
},
|
|
7772
7932
|
"aria-label": "Clear selected time",
|
|
7773
7933
|
children: [
|
|
7774
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react16.X, { className:
|
|
7934
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react16.X, { className: panelSz.icon }),
|
|
7775
7935
|
"Clear"
|
|
7776
7936
|
]
|
|
7777
7937
|
}
|
|
@@ -7784,7 +7944,7 @@ function TimePicker({
|
|
|
7784
7944
|
label,
|
|
7785
7945
|
required && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-destructive ml-1", children: "*" })
|
|
7786
7946
|
] }) }),
|
|
7787
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn("
|
|
7947
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn(panelSz.contentPadding, "rounded-2xl border border-border/60 bg-card/95 backdrop-blur-sm shadow-xl", className), children: timePickerContent })
|
|
7788
7948
|
] });
|
|
7789
7949
|
}
|
|
7790
7950
|
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "w-full", ...rest, children: [
|
|
@@ -7811,9 +7971,11 @@ function TimePicker({
|
|
|
7811
7971
|
open,
|
|
7812
7972
|
onOpenChange: handleOpenChange,
|
|
7813
7973
|
placement: "bottom-start",
|
|
7814
|
-
|
|
7974
|
+
matchTriggerWidth,
|
|
7975
|
+
contentWidth: matchTriggerWidth ? void 0 : contentWidth,
|
|
7815
7976
|
contentClassName: cn(
|
|
7816
|
-
|
|
7977
|
+
panelSz.contentPadding,
|
|
7978
|
+
"rounded-2xl border bg-popover/95 backdrop-blur-xl shadow-2xl",
|
|
7817
7979
|
error && "border-destructive/40",
|
|
7818
7980
|
success && "border-success/40",
|
|
7819
7981
|
!error && !success && "border-border/60",
|
|
@@ -8165,7 +8327,7 @@ function getZonedWeekday(date, timeZone) {
|
|
|
8165
8327
|
}
|
|
8166
8328
|
|
|
8167
8329
|
// ../../components/ui/CalendarTimeline/layout.ts
|
|
8168
|
-
function
|
|
8330
|
+
function clamp4(n, min, max) {
|
|
8169
8331
|
return Math.max(min, Math.min(max, n));
|
|
8170
8332
|
}
|
|
8171
8333
|
function binarySearchFirstGE(arr, target) {
|
|
@@ -8304,7 +8466,7 @@ function useVirtualVariableRows(args) {
|
|
|
8304
8466
|
const endPos = Math.max(0, Math.min(scrollTop + viewportHeight, total));
|
|
8305
8467
|
let startIndex = Math.max(0, lowerBound(prefix, startPos) - 1);
|
|
8306
8468
|
let endIndex = Math.min(itemCount, lowerBound(prefix, endPos) + overscan);
|
|
8307
|
-
startIndex =
|
|
8469
|
+
startIndex = clamp4(startIndex - overscan, 0, itemCount);
|
|
8308
8470
|
const topSpacer = prefix[startIndex] ?? 0;
|
|
8309
8471
|
const bottomSpacer = total - (prefix[endIndex] ?? total);
|
|
8310
8472
|
return { startIndex, endIndex, topSpacer, bottomSpacer, totalHeight: total };
|
|
@@ -8456,11 +8618,11 @@ function computeSlotStarts(args) {
|
|
|
8456
8618
|
const step = Math.max(5, Math.min(240, Math.trunc(dayTimeStepMinutes)));
|
|
8457
8619
|
const stepMs = step * 6e4;
|
|
8458
8620
|
const hours = workHours ?? { startHour: 8, endHour: 17 };
|
|
8459
|
-
const boundedStartHour =
|
|
8460
|
-
const boundedEndHour =
|
|
8621
|
+
const boundedStartHour = clamp4(Math.trunc(hours.startHour), 0, 23);
|
|
8622
|
+
const boundedEndHour = clamp4(Math.trunc(hours.endHour), 1, 24);
|
|
8461
8623
|
const isWork = dayRangeMode === "work";
|
|
8462
8624
|
const start2 = isWork ? zonedDateAtTime(baseDayStart, timeZone, { hour: boundedStartHour }) : start;
|
|
8463
|
-
const end2 = isWork ? boundedEndHour === 24 ? addZonedDays(baseDayStart, 1, timeZone) : zonedDateAtTime(baseDayStart, timeZone, { hour:
|
|
8625
|
+
const end2 = isWork ? boundedEndHour === 24 ? addZonedDays(baseDayStart, 1, timeZone) : zonedDateAtTime(baseDayStart, timeZone, { hour: clamp4(boundedEndHour, 0, 23) }) : addZonedDays(start, 1, timeZone);
|
|
8464
8626
|
const end3 = end2.getTime() > start2.getTime() ? end2 : addZonedDays(start2, 1, timeZone);
|
|
8465
8627
|
const slotStarts2 = [];
|
|
8466
8628
|
for (let cur2 = start2.getTime(), guard2 = 0; cur2 < end3.getTime() && guard2++ < 2e3; cur2 += stepMs) {
|
|
@@ -8489,8 +8651,8 @@ function normalizeEvents(args) {
|
|
|
8489
8651
|
const ns = view === "day" ? start : startOfZonedDay(start, timeZone);
|
|
8490
8652
|
let ne = view === "day" ? end : startOfZonedDay(end, timeZone);
|
|
8491
8653
|
if (ne.getTime() <= ns.getTime()) ne = view === "day" ? new Date(ns.getTime() + 6e4) : addZonedDays(ns, 1, timeZone);
|
|
8492
|
-
const cs = new Date(
|
|
8493
|
-
const ce = new Date(
|
|
8654
|
+
const cs = new Date(clamp4(ns.getTime(), rangeStart, rangeEnd));
|
|
8655
|
+
const ce = new Date(clamp4(ne.getTime(), rangeStart, rangeEnd));
|
|
8494
8656
|
if (ce.getTime() <= rangeStart || cs.getTime() >= rangeEnd) return null;
|
|
8495
8657
|
return { ...e, _start: cs, _end: ce };
|
|
8496
8658
|
}).filter(Boolean);
|
|
@@ -8852,12 +9014,12 @@ function useDayHeaderMarks(args) {
|
|
|
8852
9014
|
for (const ev of normalizedEvents) {
|
|
8853
9015
|
const startIdx = binarySearchLastLE(slotStarts, ev._start);
|
|
8854
9016
|
const endIdxRaw = binarySearchFirstGE(slotStarts, ev._end);
|
|
8855
|
-
const endIdx =
|
|
9017
|
+
const endIdx = clamp4(endIdxRaw, 0, n - 1);
|
|
8856
9018
|
if (startIdx >= 0 && startIdx < n) showTime[startIdx] = true;
|
|
8857
9019
|
if (endIdx >= 0 && endIdx < n) showTime[endIdx] = true;
|
|
8858
9020
|
const span = endIdx - startIdx;
|
|
8859
9021
|
if (span >= 3) {
|
|
8860
|
-
const mid =
|
|
9022
|
+
const mid = clamp4(Math.floor((startIdx + endIdx) / 2), 0, n - 1);
|
|
8861
9023
|
if (!showTime[mid]) showEllipsis[mid] = true;
|
|
8862
9024
|
}
|
|
8863
9025
|
}
|
|
@@ -8896,7 +9058,7 @@ function useSlotMetrics(args) {
|
|
|
8896
9058
|
lefts2[0] = 0;
|
|
8897
9059
|
for (let i = 0; i < n; i++) lefts2[i + 1] = lefts2[i] + widths[i];
|
|
8898
9060
|
const gridWidth2 = lefts2[n] ?? 0;
|
|
8899
|
-
const xToSlotIdx2 = (x) =>
|
|
9061
|
+
const xToSlotIdx2 = (x) => clamp4(Math.floor(x / Math.max(1, fixedSlotWidth)), 0, Math.max(0, n - 1));
|
|
8900
9062
|
return { slotWidths: widths, slotLefts: lefts2, slotHasEvent: null, gridWidth: gridWidth2, xToSlotIdx: xToSlotIdx2 };
|
|
8901
9063
|
}
|
|
8902
9064
|
const cfg = typeof adaptiveCfg === "object" ? adaptiveCfg : {};
|
|
@@ -8922,7 +9084,7 @@ function useSlotMetrics(args) {
|
|
|
8922
9084
|
};
|
|
8923
9085
|
if (dayAnchorCompression) {
|
|
8924
9086
|
const hasEvent2 = dayHeaderMarks.anchor.slice(0, n);
|
|
8925
|
-
const compressedEmptySlotWidth =
|
|
9087
|
+
const compressedEmptySlotWidth = clamp4(emptySlotWidth, 12, 20);
|
|
8926
9088
|
for (let i = 0; i < n; i++) widths[i] = hasEvent2[i] ? fixedSlotWidth : compressedEmptySlotWidth;
|
|
8927
9089
|
maybeFillToContainer(hasEvent2);
|
|
8928
9090
|
const lefts2 = new Array(n + 1);
|
|
@@ -8930,7 +9092,7 @@ function useSlotMetrics(args) {
|
|
|
8930
9092
|
for (let i = 0; i < n; i++) lefts2[i + 1] = lefts2[i] + widths[i];
|
|
8931
9093
|
const gridWidth2 = lefts2[n] ?? 0;
|
|
8932
9094
|
const xToSlotIdx2 = (x) => {
|
|
8933
|
-
const xc =
|
|
9095
|
+
const xc = clamp4(x, 0, Math.max(0, gridWidth2 - 1e-3));
|
|
8934
9096
|
let lo = 0;
|
|
8935
9097
|
let hi = n - 1;
|
|
8936
9098
|
while (lo <= hi) {
|
|
@@ -8941,14 +9103,14 @@ function useSlotMetrics(args) {
|
|
|
8941
9103
|
else if (xc >= right) lo = mid + 1;
|
|
8942
9104
|
else return mid;
|
|
8943
9105
|
}
|
|
8944
|
-
return
|
|
9106
|
+
return clamp4(lo, 0, Math.max(0, n - 1));
|
|
8945
9107
|
};
|
|
8946
9108
|
return { slotWidths: widths, slotLefts: lefts2, slotHasEvent: hasEvent2, gridWidth: gridWidth2, xToSlotIdx: xToSlotIdx2 };
|
|
8947
9109
|
}
|
|
8948
9110
|
const diff = new Array(n + 1).fill(0);
|
|
8949
9111
|
for (const ev of normalizedEvents) {
|
|
8950
9112
|
const startIdx = binarySearchLastLE(slotStarts, ev._start);
|
|
8951
|
-
const endIdx =
|
|
9113
|
+
const endIdx = clamp4(binarySearchFirstGE(slotStarts, ev._end), startIdx + 1, n);
|
|
8952
9114
|
diff[startIdx] = (diff[startIdx] ?? 0) + 1;
|
|
8953
9115
|
diff[endIdx] = (diff[endIdx] ?? 0) - 1;
|
|
8954
9116
|
}
|
|
@@ -8966,7 +9128,7 @@ function useSlotMetrics(args) {
|
|
|
8966
9128
|
lefts2[0] = 0;
|
|
8967
9129
|
for (let i = 0; i < n; i++) lefts2[i + 1] = lefts2[i] + widths[i];
|
|
8968
9130
|
const gridWidth2 = lefts2[n] ?? 0;
|
|
8969
|
-
const xToSlotIdx2 = (x) =>
|
|
9131
|
+
const xToSlotIdx2 = (x) => clamp4(Math.floor(x / Math.max(1, fixedSlotWidth)), 0, Math.max(0, n - 1));
|
|
8970
9132
|
return { slotWidths: widths, slotLefts: lefts2, slotHasEvent: null, gridWidth: gridWidth2, xToSlotIdx: xToSlotIdx2 };
|
|
8971
9133
|
}
|
|
8972
9134
|
const emptyCount = n - eventCount;
|
|
@@ -8976,7 +9138,7 @@ function useSlotMetrics(args) {
|
|
|
8976
9138
|
const remaining = Math.max(0, targetTotal - emptyCount * emptySlotWidth);
|
|
8977
9139
|
const raw = remaining / Math.max(1, eventCount);
|
|
8978
9140
|
const maxEventSlotWidth = cfg.maxEventSlotWidth ?? fixedSlotWidth * 2.5;
|
|
8979
|
-
eventSlotWidth =
|
|
9141
|
+
eventSlotWidth = clamp4(raw, fixedSlotWidth, Math.max(fixedSlotWidth, maxEventSlotWidth));
|
|
8980
9142
|
}
|
|
8981
9143
|
for (let i = 0; i < n; i++) widths[i] = hasEvent[i] ? eventSlotWidth : emptySlotWidth;
|
|
8982
9144
|
maybeFillToContainer(hasEvent);
|
|
@@ -8985,7 +9147,7 @@ function useSlotMetrics(args) {
|
|
|
8985
9147
|
for (let i = 0; i < n; i++) lefts[i + 1] = lefts[i] + widths[i];
|
|
8986
9148
|
const gridWidth = lefts[n] ?? 0;
|
|
8987
9149
|
const xToSlotIdx = (x) => {
|
|
8988
|
-
const xc =
|
|
9150
|
+
const xc = clamp4(x, 0, Math.max(0, gridWidth - 1e-3));
|
|
8989
9151
|
let lo = 0;
|
|
8990
9152
|
let hi = n - 1;
|
|
8991
9153
|
while (lo <= hi) {
|
|
@@ -8996,7 +9158,7 @@ function useSlotMetrics(args) {
|
|
|
8996
9158
|
else if (xc >= right) lo = mid + 1;
|
|
8997
9159
|
else return mid;
|
|
8998
9160
|
}
|
|
8999
|
-
return
|
|
9161
|
+
return clamp4(lo, 0, Math.max(0, n - 1));
|
|
9000
9162
|
};
|
|
9001
9163
|
return { slotWidths: widths, slotLefts: lefts, slotHasEvent: hasEvent, gridWidth, xToSlotIdx };
|
|
9002
9164
|
}, [
|
|
@@ -9023,7 +9185,7 @@ function useLayoutsByResource(args) {
|
|
|
9023
9185
|
const s = isPreview ? preview.start : ev._start;
|
|
9024
9186
|
const e = isPreview ? preview.end : ev._end;
|
|
9025
9187
|
const startIdx = binarySearchLastLE(slotStarts, s);
|
|
9026
|
-
const endIdx =
|
|
9188
|
+
const endIdx = clamp4(binarySearchFirstGE(slotStarts, e), startIdx + 1, slotsLength);
|
|
9027
9189
|
return { ev: { ...ev, _start: s, _end: e }, startIdx, endIdx };
|
|
9028
9190
|
});
|
|
9029
9191
|
const { packed, laneCount } = intervalPack(mapped);
|
|
@@ -9087,8 +9249,8 @@ function useVisibleSlotRange(args) {
|
|
|
9087
9249
|
const endPos = Math.max(0, scrollLeft + viewportWidth);
|
|
9088
9250
|
let startIdx = Math.max(0, lowerBound2(slotLefts, startPos) - 1);
|
|
9089
9251
|
let endIdx = Math.min(slotCount, lowerBound2(slotLefts, endPos) + 1);
|
|
9090
|
-
startIdx =
|
|
9091
|
-
endIdx =
|
|
9252
|
+
startIdx = clamp4(startIdx - overscan, 0, slotCount);
|
|
9253
|
+
endIdx = clamp4(endIdx + overscan, 0, slotCount);
|
|
9092
9254
|
if (endIdx <= startIdx) endIdx = Math.min(slotCount, startIdx + 1);
|
|
9093
9255
|
return { startIdx, endIdx };
|
|
9094
9256
|
}, [enabled, overscan, scrollLeft, slotCount, slotLefts, viewportWidth]);
|
|
@@ -9411,7 +9573,7 @@ function CalendarTimeline({
|
|
|
9411
9573
|
for (const [resourceId, list] of eventsByResource.entries()) {
|
|
9412
9574
|
const mapped = list.map((ev) => {
|
|
9413
9575
|
const startIdx = binarySearchLastLE(slotStarts, ev._start);
|
|
9414
|
-
const endIdx =
|
|
9576
|
+
const endIdx = clamp4(binarySearchFirstGE(slotStarts, ev._end), startIdx + 1, slots.length);
|
|
9415
9577
|
return { startIdx, endIdx };
|
|
9416
9578
|
});
|
|
9417
9579
|
const { laneCount } = intervalPack(mapped);
|
|
@@ -9434,7 +9596,7 @@ function CalendarTimeline({
|
|
|
9434
9596
|
);
|
|
9435
9597
|
const setRowHeightForResource = React31.useCallback(
|
|
9436
9598
|
(resourceId, height) => {
|
|
9437
|
-
const clamped =
|
|
9599
|
+
const clamped = clamp4(Math.round(height), rowMin, rowMax);
|
|
9438
9600
|
onRowHeightChange?.(clamped);
|
|
9439
9601
|
if (isControlledRowHeights) {
|
|
9440
9602
|
const next = { ...activeRowHeights ?? {}, [resourceId]: clamped };
|
|
@@ -9473,7 +9635,7 @@ function CalendarTimeline({
|
|
|
9473
9635
|
const resizeRef = React31.useRef(null);
|
|
9474
9636
|
const setResourceColumnWidth = React31.useCallback(
|
|
9475
9637
|
(next) => {
|
|
9476
|
-
const clamped =
|
|
9638
|
+
const clamped = clamp4(Math.round(next), colMin, colMax);
|
|
9477
9639
|
if (!isControlledResourceColumnWidth) setInternalResourceColumnWidth(clamped);
|
|
9478
9640
|
onResourceColumnWidthChange?.(clamped);
|
|
9479
9641
|
},
|
|
@@ -9596,10 +9758,10 @@ function CalendarTimeline({
|
|
|
9596
9758
|
if (slots.length > 0) {
|
|
9597
9759
|
if (activeView === "day") {
|
|
9598
9760
|
const inRange = resolvedNow.getTime() >= range.start.getTime() && resolvedNow.getTime() < range.end.getTime();
|
|
9599
|
-
startIdx =
|
|
9761
|
+
startIdx = clamp4(inRange ? binarySearchFirstGE(slotStarts, resolvedNow) : 0, 0, slots.length - 1);
|
|
9600
9762
|
} else {
|
|
9601
9763
|
const dayStart = startOfZonedDay(activeDate, resolvedTimeZone);
|
|
9602
|
-
startIdx =
|
|
9764
|
+
startIdx = clamp4(binarySearchLastLE(slotStarts, dayStart), 0, slots.length - 1);
|
|
9603
9765
|
}
|
|
9604
9766
|
}
|
|
9605
9767
|
setCreateStartIdx(startIdx);
|
|
@@ -9636,7 +9798,7 @@ function CalendarTimeline({
|
|
|
9636
9798
|
const commitCreate = React31.useCallback(() => {
|
|
9637
9799
|
if (!onCreateEvent) return;
|
|
9638
9800
|
if (!createResourceId) return;
|
|
9639
|
-
const start = slotStarts[
|
|
9801
|
+
const start = slotStarts[clamp4(createStartIdx, 0, Math.max(0, slotStarts.length - 1))];
|
|
9640
9802
|
if (!start) return;
|
|
9641
9803
|
const endBoundary = createEndIdx >= slotStarts.length ? range.end : slotStarts[createEndIdx];
|
|
9642
9804
|
if (!endBoundary) return;
|
|
@@ -9666,8 +9828,8 @@ function CalendarTimeline({
|
|
|
9666
9828
|
const body = bodyRef.current;
|
|
9667
9829
|
if (!body) return null;
|
|
9668
9830
|
const bodyRect = body.getBoundingClientRect();
|
|
9669
|
-
const probeX =
|
|
9670
|
-
const probeY =
|
|
9831
|
+
const probeX = clamp4(clientX, bodyRect.left + 1, bodyRect.right - 1);
|
|
9832
|
+
const probeY = clamp4(clientY, bodyRect.top + 1, bodyRect.bottom - 1);
|
|
9671
9833
|
const el = document.elementFromPoint(probeX, probeY);
|
|
9672
9834
|
const x = probeX - bodyRect.left + body.scrollLeft;
|
|
9673
9835
|
const epsilon = opts?.biasLeft ? 0.01 : 0;
|
|
@@ -9681,7 +9843,7 @@ function CalendarTimeline({
|
|
|
9681
9843
|
);
|
|
9682
9844
|
const slotToDate = React31.useCallback(
|
|
9683
9845
|
(slotIdx) => {
|
|
9684
|
-
const start = slotStarts[
|
|
9846
|
+
const start = slotStarts[clamp4(slotIdx, 0, slotStarts.length - 1)];
|
|
9685
9847
|
if (activeView === "day") {
|
|
9686
9848
|
const stepMs = Math.trunc(Math.max(5, Math.min(240, Math.trunc(dayTimeStepMinutes))) * 6e4);
|
|
9687
9849
|
return { start, end: new Date(start.getTime() + stepMs) };
|
|
@@ -9722,12 +9884,12 @@ function CalendarTimeline({
|
|
|
9722
9884
|
return;
|
|
9723
9885
|
}
|
|
9724
9886
|
if (drag.mode === "resize-start") {
|
|
9725
|
-
const nextStart = new Date(
|
|
9887
|
+
const nextStart = new Date(clamp4(targetSlotStart.getTime(), range.start.getTime(), drag.originEnd.getTime() - 6e4));
|
|
9726
9888
|
setPreview({ eventId: drag.eventId, resourceId: drag.resourceId, start: nextStart, end: drag.originEnd });
|
|
9727
9889
|
return;
|
|
9728
9890
|
}
|
|
9729
9891
|
if (drag.mode === "resize-end") {
|
|
9730
|
-
const nextEnd = new Date(
|
|
9892
|
+
const nextEnd = new Date(clamp4(targetSlotStart.getTime(), drag.originStart.getTime() + 6e4, range.end.getTime()));
|
|
9731
9893
|
setPreview({ eventId: drag.eventId, resourceId: drag.resourceId, start: drag.originStart, end: nextEnd });
|
|
9732
9894
|
return;
|
|
9733
9895
|
}
|
|
@@ -9744,7 +9906,7 @@ function CalendarTimeline({
|
|
|
9744
9906
|
}
|
|
9745
9907
|
const maxScrollLeft = Math.max(0, body.scrollWidth - body.clientWidth);
|
|
9746
9908
|
const prevLeft = body.scrollLeft;
|
|
9747
|
-
const nextLeft =
|
|
9909
|
+
const nextLeft = clamp4(prevLeft + st.dir * st.speed, 0, maxScrollLeft);
|
|
9748
9910
|
if (nextLeft === prevLeft) {
|
|
9749
9911
|
stopAutoScroll();
|
|
9750
9912
|
return;
|
|
@@ -9764,12 +9926,12 @@ function CalendarTimeline({
|
|
|
9764
9926
|
if (clientX < rect.left + edge) {
|
|
9765
9927
|
dir = -1;
|
|
9766
9928
|
const dist = clientX - rect.left;
|
|
9767
|
-
const t2 =
|
|
9929
|
+
const t2 = clamp4(1 - dist / edge, 0, 1);
|
|
9768
9930
|
speed = 8 + t2 * 28;
|
|
9769
9931
|
} else if (clientX > rect.right - edge) {
|
|
9770
9932
|
dir = 1;
|
|
9771
9933
|
const dist = rect.right - clientX;
|
|
9772
|
-
const t2 =
|
|
9934
|
+
const t2 = clamp4(1 - dist / edge, 0, 1);
|
|
9773
9935
|
speed = 8 + t2 * 28;
|
|
9774
9936
|
}
|
|
9775
9937
|
autoScrollStateRef.current.lastClientX = clientX;
|
|
@@ -9880,7 +10042,7 @@ function CalendarTimeline({
|
|
|
9880
10042
|
return;
|
|
9881
10043
|
}
|
|
9882
10044
|
const rect = rowEl.getBoundingClientRect();
|
|
9883
|
-
const y =
|
|
10045
|
+
const y = clamp4(e.clientY - rect.top, 0, rect.height);
|
|
9884
10046
|
if (!hoverCell || hoverCell.resourceId !== ctx.resourceId || hoverCell.slotIdx !== ctx.slotIdx || Math.abs(hoverCell.y - y) > 0.5) {
|
|
9885
10047
|
setHoverCell({ resourceId: ctx.resourceId, slotIdx: ctx.slotIdx, y });
|
|
9886
10048
|
}
|
|
@@ -10173,8 +10335,8 @@ function CalendarTimeline({
|
|
|
10173
10335
|
const resource = resourceById.get(ev.resourceId);
|
|
10174
10336
|
const tooltipTitle = ev.title || ev.id;
|
|
10175
10337
|
const shouldCompact = activeView === "day" && dayEventStyle === "compact";
|
|
10176
|
-
const defaultMaxVisual =
|
|
10177
|
-
const maxVisual =
|
|
10338
|
+
const defaultMaxVisual = clamp4(Math.round(fixedSlotWidth * 1.2), 160, 360);
|
|
10339
|
+
const maxVisual = clamp4(Math.round(dayEventMaxWidth ?? defaultMaxVisual), 80, 1200);
|
|
10178
10340
|
const visualWidth = shouldCompact ? Math.min(width, maxVisual) : width;
|
|
10179
10341
|
const isClipped = shouldCompact && width > visualWidth + 1;
|
|
10180
10342
|
const block = /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
@@ -10264,7 +10426,7 @@ function CalendarTimeline({
|
|
|
10264
10426
|
}),
|
|
10265
10427
|
preview && preview.resourceId === r.id && !preview.eventId ? (() => {
|
|
10266
10428
|
const startIdx = binarySearchLastLE(slotStarts, preview.start);
|
|
10267
|
-
const endIdx =
|
|
10429
|
+
const endIdx = clamp4(binarySearchFirstGE(slotStarts, preview.end), startIdx + 1, slots.length);
|
|
10268
10430
|
const left = slotLefts[startIdx] ?? 0;
|
|
10269
10431
|
const width = Math.max(1, (slotLefts[endIdx] ?? 0) - (slotLefts[startIdx] ?? 0));
|
|
10270
10432
|
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
@@ -10287,7 +10449,7 @@ function CalendarTimeline({
|
|
|
10287
10449
|
),
|
|
10288
10450
|
style: {
|
|
10289
10451
|
left: (slotLefts[hoverCell.slotIdx] ?? 0) + (slotWidths[hoverCell.slotIdx] ?? fixedSlotWidth) / 2 - 10,
|
|
10290
|
-
top:
|
|
10452
|
+
top: clamp4(Math.round(hoverCell.y - 10), 6, Math.max(6, h - 26))
|
|
10291
10453
|
},
|
|
10292
10454
|
"aria-hidden": true,
|
|
10293
10455
|
children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_lucide_react21.Plus, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
@@ -13523,7 +13685,7 @@ var Timeline_default = Timeline;
|
|
|
13523
13685
|
var React42 = __toESM(require("react"), 1);
|
|
13524
13686
|
var import_lucide_react29 = require("lucide-react");
|
|
13525
13687
|
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
13526
|
-
var
|
|
13688
|
+
var clamp5 = (n, min, max) => Math.max(min, Math.min(max, n));
|
|
13527
13689
|
function hexToRgb(hex) {
|
|
13528
13690
|
const str = hex.replace(/^#/, "").trim();
|
|
13529
13691
|
if (str.length === 3) {
|
|
@@ -13541,7 +13703,7 @@ function hexToRgb(hex) {
|
|
|
13541
13703
|
return null;
|
|
13542
13704
|
}
|
|
13543
13705
|
function rgbToHex(r, g, b) {
|
|
13544
|
-
return `#${[r, g, b].map((v) =>
|
|
13706
|
+
return `#${[r, g, b].map((v) => clamp5(Math.round(v), 0, 255).toString(16).padStart(2, "0")).join("")}`;
|
|
13545
13707
|
}
|
|
13546
13708
|
function rgbToHsl(r, g, b) {
|
|
13547
13709
|
r /= 255;
|
|
@@ -13602,10 +13764,10 @@ function parseAnyColor(input) {
|
|
|
13602
13764
|
}
|
|
13603
13765
|
const rgbaMatch = s.match(/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*,\s*(\d*\.?\d+))?\s*\)/i);
|
|
13604
13766
|
if (rgbaMatch) {
|
|
13605
|
-
const r =
|
|
13606
|
-
const g =
|
|
13607
|
-
const b =
|
|
13608
|
-
const a = rgbaMatch[4] != null ?
|
|
13767
|
+
const r = clamp5(parseInt(rgbaMatch[1], 10), 0, 255);
|
|
13768
|
+
const g = clamp5(parseInt(rgbaMatch[2], 10), 0, 255);
|
|
13769
|
+
const b = clamp5(parseInt(rgbaMatch[3], 10), 0, 255);
|
|
13770
|
+
const a = rgbaMatch[4] != null ? clamp5(parseFloat(rgbaMatch[4]), 0, 1) : 1;
|
|
13609
13771
|
return { r, g, b, a };
|
|
13610
13772
|
}
|
|
13611
13773
|
const hslaMatch = s.match(/hsla?\(\s*(\d{1,3}(?:\.\d+)?)\s*,?\s*(\d{1,3}(?:\.\d+)?)%?\s*,?\s*(\d{1,3}(?:\.\d+)?)%?(?:\s*,?\s*(\d*\.?\d+))?\s*\)/i);
|
|
@@ -13613,7 +13775,7 @@ function parseAnyColor(input) {
|
|
|
13613
13775
|
const h = parseFloat(hslaMatch[1]);
|
|
13614
13776
|
const sl = parseFloat(hslaMatch[2]);
|
|
13615
13777
|
const l = parseFloat(hslaMatch[3]);
|
|
13616
|
-
const a = hslaMatch[4] != null ?
|
|
13778
|
+
const a = hslaMatch[4] != null ? clamp5(parseFloat(hslaMatch[4]), 0, 1) : 1;
|
|
13617
13779
|
const rgb = hslToRgb(h, sl, l);
|
|
13618
13780
|
return { ...rgb, a };
|
|
13619
13781
|
}
|
|
@@ -13626,12 +13788,12 @@ function formatOutput({ r, g, b, a }, withAlpha, format) {
|
|
|
13626
13788
|
if (format === "hsl" || format === "hsla") {
|
|
13627
13789
|
const hsl = rgbToHsl(r, g, b);
|
|
13628
13790
|
if (format === "hsla" || withAlpha) {
|
|
13629
|
-
return `hsla(${Math.round(hsl.h)}, ${Math.round(hsl.s)}%, ${Math.round(hsl.l)}%, ${
|
|
13791
|
+
return `hsla(${Math.round(hsl.h)}, ${Math.round(hsl.s)}%, ${Math.round(hsl.l)}%, ${clamp5(a, 0, 1)})`;
|
|
13630
13792
|
}
|
|
13631
13793
|
return `hsl(${Math.round(hsl.h)}, ${Math.round(hsl.s)}%, ${Math.round(hsl.l)}%)`;
|
|
13632
13794
|
}
|
|
13633
13795
|
if (withAlpha || a !== 1) {
|
|
13634
|
-
return `rgba(${
|
|
13796
|
+
return `rgba(${clamp5(r, 0, 255)}, ${clamp5(g, 0, 255)}, ${clamp5(b, 0, 255)}, ${clamp5(a, 0, 1)})`;
|
|
13635
13797
|
}
|
|
13636
13798
|
return rgbToHex(r, g, b);
|
|
13637
13799
|
}
|
|
@@ -13765,7 +13927,7 @@ function ColorPicker({
|
|
|
13765
13927
|
emit(next);
|
|
13766
13928
|
};
|
|
13767
13929
|
const setAlpha = (aPct) => {
|
|
13768
|
-
const a =
|
|
13930
|
+
const a = clamp5(aPct / 100, 0, 1);
|
|
13769
13931
|
const next = { ...rgba, a };
|
|
13770
13932
|
setRgba(next);
|
|
13771
13933
|
emit(next);
|
|
@@ -18426,7 +18588,7 @@ function toNullableNumber(value) {
|
|
|
18426
18588
|
}
|
|
18427
18589
|
return null;
|
|
18428
18590
|
}
|
|
18429
|
-
function
|
|
18591
|
+
function clamp6(value, min, max) {
|
|
18430
18592
|
return Math.min(max, Math.max(min, value));
|
|
18431
18593
|
}
|
|
18432
18594
|
function ResizableImageNodeView(props) {
|
|
@@ -18488,18 +18650,18 @@ function ResizableImageNodeView(props) {
|
|
|
18488
18650
|
let nextH = drag.startH;
|
|
18489
18651
|
if (event.ctrlKey) {
|
|
18490
18652
|
if (Math.abs(dx) >= Math.abs(dy)) {
|
|
18491
|
-
nextW =
|
|
18492
|
-
nextH =
|
|
18653
|
+
nextW = clamp6(drag.startW + dx, MIN_IMAGE_SIZE_PX, drag.maxW);
|
|
18654
|
+
nextH = clamp6(nextW / drag.aspect, MIN_IMAGE_SIZE_PX, Number.POSITIVE_INFINITY);
|
|
18493
18655
|
} else {
|
|
18494
|
-
nextH =
|
|
18495
|
-
nextW =
|
|
18656
|
+
nextH = clamp6(drag.startH + dy, MIN_IMAGE_SIZE_PX, Number.POSITIVE_INFINITY);
|
|
18657
|
+
nextW = clamp6(nextH * drag.aspect, MIN_IMAGE_SIZE_PX, drag.maxW);
|
|
18496
18658
|
}
|
|
18497
18659
|
} else {
|
|
18498
18660
|
if (!drag.axis && (Math.abs(dx) > AXIS_LOCK_THRESHOLD_PX || Math.abs(dy) > AXIS_LOCK_THRESHOLD_PX)) {
|
|
18499
18661
|
drag.axis = Math.abs(dx) >= Math.abs(dy) ? "x" : "y";
|
|
18500
18662
|
}
|
|
18501
|
-
if (drag.axis === "x") nextW =
|
|
18502
|
-
if (drag.axis === "y") nextH =
|
|
18663
|
+
if (drag.axis === "x") nextW = clamp6(drag.startW + dx, MIN_IMAGE_SIZE_PX, drag.maxW);
|
|
18664
|
+
if (drag.axis === "y") nextH = clamp6(drag.startH + dy, MIN_IMAGE_SIZE_PX, Number.POSITIVE_INFINITY);
|
|
18503
18665
|
}
|
|
18504
18666
|
drag.lastW = nextW;
|
|
18505
18667
|
drag.lastH = nextH;
|