@underverse-ui/underverse 0.2.104 → 0.2.106
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 +318 -153
- 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 +341 -176
- 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-muted/20 via-muted/5 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-muted/20 via-muted/5 to-transparent z-10", ui.fadeHeight) }),
|
|
7202
7289
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
7203
7290
|
"div",
|
|
7204
7291
|
{
|
|
@@ -7215,11 +7302,14 @@ 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 -
|
|
7220
|
-
const
|
|
7221
|
-
const
|
|
7222
|
-
const
|
|
7305
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { children: extendedItems.map((n, index) => {
|
|
7306
|
+
const dist = Math.abs(index - currentVirtual);
|
|
7307
|
+
const distForVisual = Math.min(dist, 2);
|
|
7308
|
+
const t = distForVisual / 2;
|
|
7309
|
+
const ease = t * t;
|
|
7310
|
+
const scale = 1 - ease * 0.18;
|
|
7311
|
+
const opacity = 1 - ease * 0.55;
|
|
7312
|
+
const isSelected = index === currentVirtual;
|
|
7223
7313
|
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
7224
7314
|
"button",
|
|
7225
7315
|
{
|
|
@@ -7228,7 +7318,7 @@ function WheelColumn({
|
|
|
7228
7318
|
"aria-selected": isSelected,
|
|
7229
7319
|
className: cn(
|
|
7230
7320
|
"w-full snap-center flex items-center justify-center rounded-lg transition-all duration-200 font-bold tabular-nums",
|
|
7231
|
-
isSelected ? "text-primary
|
|
7321
|
+
isSelected ? cn("text-primary", ui.selectedText) : cn("text-muted-foreground hover:text-foreground/70", ui.unselectedText)
|
|
7232
7322
|
),
|
|
7233
7323
|
style: {
|
|
7234
7324
|
height: itemHeight,
|
|
@@ -7237,13 +7327,16 @@ function WheelColumn({
|
|
|
7237
7327
|
},
|
|
7238
7328
|
onClick: () => {
|
|
7239
7329
|
const el = scrollRef.current;
|
|
7330
|
+
if (!el) return;
|
|
7240
7331
|
suppressScrollSelectUntilRef.current = Date.now() + 350;
|
|
7241
|
-
|
|
7242
|
-
|
|
7332
|
+
lastVirtualIndexRef.current = index;
|
|
7333
|
+
el.scrollTo({ top: index * itemHeight, behavior: animate ? "smooth" : "auto" });
|
|
7334
|
+
const realIndex = (index % items.length + items.length) % items.length;
|
|
7335
|
+
onSelect(items[realIndex]);
|
|
7243
7336
|
},
|
|
7244
7337
|
children: pad(n)
|
|
7245
7338
|
},
|
|
7246
|
-
|
|
7339
|
+
`${column}_${index}`
|
|
7247
7340
|
);
|
|
7248
7341
|
}) })
|
|
7249
7342
|
}
|
|
@@ -7303,6 +7396,7 @@ function TimePicker({
|
|
|
7303
7396
|
secondStep = 1,
|
|
7304
7397
|
clearable = true,
|
|
7305
7398
|
variant = "default",
|
|
7399
|
+
matchTriggerWidth = true,
|
|
7306
7400
|
showNow = false,
|
|
7307
7401
|
showPresets = false,
|
|
7308
7402
|
allowManualInput = false,
|
|
@@ -7473,12 +7567,60 @@ function TimePicker({
|
|
|
7473
7567
|
const hours = format === "24" ? Array.from({ length: 24 }, (_, i) => i) : Array.from({ length: 12 }, (_, i) => i + 1);
|
|
7474
7568
|
const minutes = Array.from({ length: Math.ceil(60 / minuteStep) }, (_, i) => Math.min(59, i * minuteStep));
|
|
7475
7569
|
const seconds = Array.from({ length: Math.ceil(60 / secondStep) }, (_, i) => Math.min(59, i * secondStep));
|
|
7570
|
+
const panelSizeClasses = {
|
|
7571
|
+
sm: {
|
|
7572
|
+
contentPadding: "p-4",
|
|
7573
|
+
stackGap: "space-y-3",
|
|
7574
|
+
timeText: "text-xl",
|
|
7575
|
+
inputSize: "sm",
|
|
7576
|
+
icon: "w-3 h-3",
|
|
7577
|
+
separatorPad: "pt-6",
|
|
7578
|
+
presetText: "text-[11px]",
|
|
7579
|
+
presetPadding: "px-3 py-2",
|
|
7580
|
+
actionText: "text-[11px]",
|
|
7581
|
+
actionPadding: "px-3 py-2",
|
|
7582
|
+
periodLabel: "text-[9px] mb-2",
|
|
7583
|
+
periodGap: "gap-1.5",
|
|
7584
|
+
periodButton: "px-3 py-2 text-xs"
|
|
7585
|
+
},
|
|
7586
|
+
md: {
|
|
7587
|
+
contentPadding: "p-5",
|
|
7588
|
+
stackGap: "space-y-4",
|
|
7589
|
+
timeText: "text-2xl",
|
|
7590
|
+
inputSize: "sm",
|
|
7591
|
+
icon: "w-3.5 h-3.5",
|
|
7592
|
+
separatorPad: "pt-8",
|
|
7593
|
+
presetText: "text-xs",
|
|
7594
|
+
presetPadding: "px-3 py-2.5",
|
|
7595
|
+
actionText: "text-xs",
|
|
7596
|
+
actionPadding: "px-4 py-2.5",
|
|
7597
|
+
periodLabel: "text-[10px] mb-3",
|
|
7598
|
+
periodGap: "gap-2",
|
|
7599
|
+
periodButton: "px-4 py-3 text-sm"
|
|
7600
|
+
},
|
|
7601
|
+
lg: {
|
|
7602
|
+
contentPadding: "p-6",
|
|
7603
|
+
stackGap: "space-y-5",
|
|
7604
|
+
timeText: "text-3xl",
|
|
7605
|
+
inputSize: "md",
|
|
7606
|
+
icon: "w-4 h-4",
|
|
7607
|
+
separatorPad: "pt-9",
|
|
7608
|
+
presetText: "text-sm",
|
|
7609
|
+
presetPadding: "px-4 py-3",
|
|
7610
|
+
actionText: "text-sm",
|
|
7611
|
+
actionPadding: "px-5 py-3",
|
|
7612
|
+
periodLabel: "text-[11px] mb-3",
|
|
7613
|
+
periodGap: "gap-2",
|
|
7614
|
+
periodButton: "px-5 py-3.5 text-base"
|
|
7615
|
+
}
|
|
7616
|
+
};
|
|
7476
7617
|
const sizeClasses2 = {
|
|
7477
7618
|
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
7619
|
md: { label: "text-sm", height: "h-10", padding: "px-3 py-2", text: "text-sm", icon: "w-4 h-4" },
|
|
7479
7620
|
lg: { label: "text-base", height: "h-12", padding: "px-4 py-3", text: "text-base", icon: "w-5 h-5" }
|
|
7480
7621
|
};
|
|
7481
7622
|
const sz = sizeClasses2[size];
|
|
7623
|
+
const panelSz = panelSizeClasses[size];
|
|
7482
7624
|
const display = formatTime(parts, format, includeSeconds);
|
|
7483
7625
|
const trigger = variant === "inline" ? null : /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
7484
7626
|
"button",
|
|
@@ -7509,8 +7651,8 @@ function TimePicker({
|
|
|
7509
7651
|
"div",
|
|
7510
7652
|
{
|
|
7511
7653
|
className: cn(
|
|
7512
|
-
"flex items-center justify-center
|
|
7513
|
-
error ? "
|
|
7654
|
+
"flex items-center justify-center transition-colors duration-300",
|
|
7655
|
+
error ? "text-destructive" : success ? "text-success" : open ? "text-primary" : "text-muted-foreground group-hover:text-primary"
|
|
7514
7656
|
),
|
|
7515
7657
|
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react16.Clock, { className: cn(sz.icon, "transition-transform duration-300", open && "rotate-12") })
|
|
7516
7658
|
}
|
|
@@ -7543,8 +7685,8 @@ function TimePicker({
|
|
|
7543
7685
|
setParts(next);
|
|
7544
7686
|
emit(next);
|
|
7545
7687
|
};
|
|
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: "
|
|
7688
|
+
const timePickerContent = /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: panelSz.stackGap, children: [
|
|
7689
|
+
/* @__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
7690
|
allowManualInput && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "relative", children: [
|
|
7549
7691
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
7550
7692
|
Input_default,
|
|
@@ -7552,12 +7694,12 @@ function TimePicker({
|
|
|
7552
7694
|
placeholder: format === "12" ? "02:30 PM" : "14:30",
|
|
7553
7695
|
value: manualInput || display,
|
|
7554
7696
|
onChange: (e) => handleManualInput(e.target.value),
|
|
7555
|
-
size:
|
|
7697
|
+
size: panelSz.inputSize,
|
|
7556
7698
|
variant: "outlined",
|
|
7557
7699
|
className: "pl-9"
|
|
7558
7700
|
}
|
|
7559
7701
|
),
|
|
7560
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react16.Clock, { className: "absolute left-3 top-1/2 -translate-y-1/2
|
|
7702
|
+
/* @__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
7703
|
] }),
|
|
7562
7704
|
showPresets && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "grid grid-cols-2 gap-2", children: Object.keys(PRESETS).map((preset) => {
|
|
7563
7705
|
const { icon: Icon, label: label2, color } = PRESETS[preset];
|
|
@@ -7566,7 +7708,9 @@ function TimePicker({
|
|
|
7566
7708
|
{
|
|
7567
7709
|
type: "button",
|
|
7568
7710
|
className: cn(
|
|
7569
|
-
"group relative
|
|
7711
|
+
"group relative font-medium rounded-xl border border-border/50 overflow-hidden",
|
|
7712
|
+
panelSz.presetPadding,
|
|
7713
|
+
panelSz.presetText,
|
|
7570
7714
|
"bg-linear-to-br from-background to-muted/30",
|
|
7571
7715
|
"hover:border-primary/40 hover:shadow-md transition-all duration-300",
|
|
7572
7716
|
animate && "hover:scale-[1.02] active:scale-[0.98]"
|
|
@@ -7582,7 +7726,7 @@ function TimePicker({
|
|
|
7582
7726
|
}
|
|
7583
7727
|
),
|
|
7584
7728
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "relative flex items-center gap-2", children: [
|
|
7585
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Icon, { className: "
|
|
7729
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Icon, { className: cn("text-muted-foreground group-hover:text-primary transition-colors", panelSz.icon) }),
|
|
7586
7730
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-foreground/80 group-hover:text-foreground transition-colors", children: label2 })
|
|
7587
7731
|
] })
|
|
7588
7732
|
]
|
|
@@ -7595,7 +7739,9 @@ function TimePicker({
|
|
|
7595
7739
|
{
|
|
7596
7740
|
type: "button",
|
|
7597
7741
|
className: cn(
|
|
7598
|
-
"
|
|
7742
|
+
"font-medium rounded-xl border border-border/50",
|
|
7743
|
+
panelSz.presetPadding,
|
|
7744
|
+
panelSz.presetText,
|
|
7599
7745
|
"bg-linear-to-br from-background to-muted/30",
|
|
7600
7746
|
"hover:border-primary/40 hover:bg-primary/5 hover:shadow-md transition-all duration-300",
|
|
7601
7747
|
animate && "hover:scale-[1.02] active:scale-[0.98]"
|
|
@@ -7620,6 +7766,7 @@ function TimePicker({
|
|
|
7620
7766
|
onSelect: setHourFromDisplay,
|
|
7621
7767
|
scrollRef: hourScrollRef,
|
|
7622
7768
|
itemHeight,
|
|
7769
|
+
size,
|
|
7623
7770
|
animate,
|
|
7624
7771
|
focused: focusedColumn === "hour",
|
|
7625
7772
|
setFocusedColumn: (col) => setFocusedColumn(col),
|
|
@@ -7627,7 +7774,7 @@ function TimePicker({
|
|
|
7627
7774
|
}
|
|
7628
7775
|
);
|
|
7629
7776
|
})(),
|
|
7630
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex flex-col items-center justify-center
|
|
7777
|
+
/* @__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
7778
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "w-1.5 h-1.5 rounded-full bg-primary/60" }),
|
|
7632
7779
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "w-1.5 h-1.5 rounded-full bg-primary/60" })
|
|
7633
7780
|
] }) }),
|
|
@@ -7647,6 +7794,7 @@ function TimePicker({
|
|
|
7647
7794
|
},
|
|
7648
7795
|
scrollRef: minuteScrollRef,
|
|
7649
7796
|
itemHeight,
|
|
7797
|
+
size,
|
|
7650
7798
|
animate,
|
|
7651
7799
|
focused: focusedColumn === "minute",
|
|
7652
7800
|
setFocusedColumn: (col) => setFocusedColumn(col),
|
|
@@ -7655,7 +7803,7 @@ function TimePicker({
|
|
|
7655
7803
|
);
|
|
7656
7804
|
})(),
|
|
7657
7805
|
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
|
|
7806
|
+
/* @__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
7807
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "w-1.5 h-1.5 rounded-full bg-primary/60" }),
|
|
7660
7808
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "w-1.5 h-1.5 rounded-full bg-primary/60" })
|
|
7661
7809
|
] }) }),
|
|
@@ -7675,6 +7823,7 @@ function TimePicker({
|
|
|
7675
7823
|
},
|
|
7676
7824
|
scrollRef: secondScrollRef,
|
|
7677
7825
|
itemHeight,
|
|
7826
|
+
size,
|
|
7678
7827
|
animate,
|
|
7679
7828
|
focused: focusedColumn === "second",
|
|
7680
7829
|
setFocusedColumn: (col) => setFocusedColumn(col),
|
|
@@ -7683,52 +7832,62 @@ function TimePicker({
|
|
|
7683
7832
|
);
|
|
7684
7833
|
})()
|
|
7685
7834
|
] }),
|
|
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
|
-
|
|
7835
|
+
format === "12" && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
7836
|
+
"div",
|
|
7837
|
+
{
|
|
7838
|
+
className: cn(
|
|
7839
|
+
"flex-1",
|
|
7840
|
+
size === "sm" ? "min-w-[64px] max-w-[84px]" : size === "lg" ? "min-w-[80px] max-w-[110px]" : "min-w-[70px] max-w-[90px]"
|
|
7841
|
+
),
|
|
7842
|
+
children: [
|
|
7843
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn(panelSz.periodLabel, "font-bold uppercase tracking-wider text-muted-foreground/70 text-center"), children: "Period" }),
|
|
7844
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
7845
|
+
"div",
|
|
7846
|
+
{
|
|
7847
|
+
className: cn("flex flex-col p-1 rounded-xl bg-muted/30", panelSz.periodGap),
|
|
7848
|
+
role: "radiogroup",
|
|
7849
|
+
"aria-label": "Select AM or PM",
|
|
7850
|
+
tabIndex: focusedColumn === "period" ? 0 : -1,
|
|
7851
|
+
onKeyDown: (e) => handleKeyDown(e, "period"),
|
|
7852
|
+
onFocus: () => setFocusedColumn("period"),
|
|
7853
|
+
children: ["AM", "PM"].map((p) => {
|
|
7854
|
+
const isSelected = parts.p === p;
|
|
7855
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
7856
|
+
"button",
|
|
7857
|
+
{
|
|
7858
|
+
type: "button",
|
|
7859
|
+
role: "radio",
|
|
7860
|
+
"aria-checked": isSelected,
|
|
7861
|
+
className: cn(
|
|
7862
|
+
"relative rounded-lg transition-all duration-300 font-bold overflow-hidden",
|
|
7863
|
+
panelSz.periodButton,
|
|
7864
|
+
"focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-1",
|
|
7865
|
+
isSelected && "bg-linear-to-r from-primary to-primary/80 text-primary-foreground shadow-lg shadow-primary/25",
|
|
7866
|
+
!isSelected && "text-muted-foreground hover:text-foreground hover:bg-muted/50",
|
|
7867
|
+
animate && "hover:scale-[1.02] active:scale-[0.98]"
|
|
7868
|
+
),
|
|
7869
|
+
onClick: () => {
|
|
7870
|
+
const pVal = p;
|
|
7871
|
+
let hour = parts.h;
|
|
7872
|
+
if (pVal === "AM" && hour >= 12) hour -= 12;
|
|
7873
|
+
if (pVal === "PM" && hour < 12) hour += 12;
|
|
7874
|
+
const next = { ...parts, p: pVal, h: hour };
|
|
7875
|
+
setParts(next);
|
|
7876
|
+
emit(next);
|
|
7877
|
+
},
|
|
7878
|
+
children: [
|
|
7879
|
+
isSelected && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "absolute inset-0 bg-linear-to-tr from-white/20 to-transparent" }),
|
|
7880
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "relative", children: p })
|
|
7881
|
+
]
|
|
7882
|
+
},
|
|
7883
|
+
p
|
|
7884
|
+
);
|
|
7885
|
+
})
|
|
7886
|
+
}
|
|
7887
|
+
)
|
|
7888
|
+
]
|
|
7889
|
+
}
|
|
7890
|
+
)
|
|
7732
7891
|
] }),
|
|
7733
7892
|
(showNow || clearable) && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center gap-2 pt-3 border-t border-border/50", children: [
|
|
7734
7893
|
showNow && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
@@ -7736,7 +7895,9 @@ function TimePicker({
|
|
|
7736
7895
|
{
|
|
7737
7896
|
type: "button",
|
|
7738
7897
|
className: cn(
|
|
7739
|
-
"flex-1
|
|
7898
|
+
"flex-1 font-semibold rounded-xl",
|
|
7899
|
+
panelSz.actionPadding,
|
|
7900
|
+
panelSz.actionText,
|
|
7740
7901
|
"bg-linear-to-r from-primary/10 to-primary/5 border border-primary/30",
|
|
7741
7902
|
"text-primary hover:from-primary/20 hover:to-primary/10 hover:border-primary/50",
|
|
7742
7903
|
"transition-all duration-300 flex items-center justify-center gap-2",
|
|
@@ -7748,7 +7909,7 @@ function TimePicker({
|
|
|
7748
7909
|
},
|
|
7749
7910
|
"aria-label": "Set current time",
|
|
7750
7911
|
children: [
|
|
7751
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react16.Clock, { className:
|
|
7912
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react16.Clock, { className: panelSz.icon }),
|
|
7752
7913
|
"Now"
|
|
7753
7914
|
]
|
|
7754
7915
|
}
|
|
@@ -7758,7 +7919,9 @@ function TimePicker({
|
|
|
7758
7919
|
{
|
|
7759
7920
|
type: "button",
|
|
7760
7921
|
className: cn(
|
|
7761
|
-
"flex-1
|
|
7922
|
+
"flex-1 font-semibold rounded-xl",
|
|
7923
|
+
panelSz.actionPadding,
|
|
7924
|
+
panelSz.actionText,
|
|
7762
7925
|
"bg-linear-to-r from-destructive/10 to-destructive/5 border border-destructive/30",
|
|
7763
7926
|
"text-destructive hover:from-destructive/20 hover:to-destructive/10 hover:border-destructive/50",
|
|
7764
7927
|
"transition-all duration-300 flex items-center justify-center gap-2",
|
|
@@ -7771,7 +7934,7 @@ function TimePicker({
|
|
|
7771
7934
|
},
|
|
7772
7935
|
"aria-label": "Clear selected time",
|
|
7773
7936
|
children: [
|
|
7774
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react16.X, { className:
|
|
7937
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react16.X, { className: panelSz.icon }),
|
|
7775
7938
|
"Clear"
|
|
7776
7939
|
]
|
|
7777
7940
|
}
|
|
@@ -7784,7 +7947,7 @@ function TimePicker({
|
|
|
7784
7947
|
label,
|
|
7785
7948
|
required && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-destructive ml-1", children: "*" })
|
|
7786
7949
|
] }) }),
|
|
7787
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn("
|
|
7950
|
+
/* @__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
7951
|
] });
|
|
7789
7952
|
}
|
|
7790
7953
|
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "w-full", ...rest, children: [
|
|
@@ -7811,9 +7974,11 @@ function TimePicker({
|
|
|
7811
7974
|
open,
|
|
7812
7975
|
onOpenChange: handleOpenChange,
|
|
7813
7976
|
placement: "bottom-start",
|
|
7814
|
-
|
|
7977
|
+
matchTriggerWidth,
|
|
7978
|
+
contentWidth: matchTriggerWidth ? void 0 : contentWidth,
|
|
7815
7979
|
contentClassName: cn(
|
|
7816
|
-
|
|
7980
|
+
panelSz.contentPadding,
|
|
7981
|
+
"rounded-2xl border bg-popover/98 backdrop-blur-md shadow-2xl",
|
|
7817
7982
|
error && "border-destructive/40",
|
|
7818
7983
|
success && "border-success/40",
|
|
7819
7984
|
!error && !success && "border-border/60",
|
|
@@ -8165,7 +8330,7 @@ function getZonedWeekday(date, timeZone) {
|
|
|
8165
8330
|
}
|
|
8166
8331
|
|
|
8167
8332
|
// ../../components/ui/CalendarTimeline/layout.ts
|
|
8168
|
-
function
|
|
8333
|
+
function clamp4(n, min, max) {
|
|
8169
8334
|
return Math.max(min, Math.min(max, n));
|
|
8170
8335
|
}
|
|
8171
8336
|
function binarySearchFirstGE(arr, target) {
|
|
@@ -8304,7 +8469,7 @@ function useVirtualVariableRows(args) {
|
|
|
8304
8469
|
const endPos = Math.max(0, Math.min(scrollTop + viewportHeight, total));
|
|
8305
8470
|
let startIndex = Math.max(0, lowerBound(prefix, startPos) - 1);
|
|
8306
8471
|
let endIndex = Math.min(itemCount, lowerBound(prefix, endPos) + overscan);
|
|
8307
|
-
startIndex =
|
|
8472
|
+
startIndex = clamp4(startIndex - overscan, 0, itemCount);
|
|
8308
8473
|
const topSpacer = prefix[startIndex] ?? 0;
|
|
8309
8474
|
const bottomSpacer = total - (prefix[endIndex] ?? total);
|
|
8310
8475
|
return { startIndex, endIndex, topSpacer, bottomSpacer, totalHeight: total };
|
|
@@ -8456,11 +8621,11 @@ function computeSlotStarts(args) {
|
|
|
8456
8621
|
const step = Math.max(5, Math.min(240, Math.trunc(dayTimeStepMinutes)));
|
|
8457
8622
|
const stepMs = step * 6e4;
|
|
8458
8623
|
const hours = workHours ?? { startHour: 8, endHour: 17 };
|
|
8459
|
-
const boundedStartHour =
|
|
8460
|
-
const boundedEndHour =
|
|
8624
|
+
const boundedStartHour = clamp4(Math.trunc(hours.startHour), 0, 23);
|
|
8625
|
+
const boundedEndHour = clamp4(Math.trunc(hours.endHour), 1, 24);
|
|
8461
8626
|
const isWork = dayRangeMode === "work";
|
|
8462
8627
|
const start2 = isWork ? zonedDateAtTime(baseDayStart, timeZone, { hour: boundedStartHour }) : start;
|
|
8463
|
-
const end2 = isWork ? boundedEndHour === 24 ? addZonedDays(baseDayStart, 1, timeZone) : zonedDateAtTime(baseDayStart, timeZone, { hour:
|
|
8628
|
+
const end2 = isWork ? boundedEndHour === 24 ? addZonedDays(baseDayStart, 1, timeZone) : zonedDateAtTime(baseDayStart, timeZone, { hour: clamp4(boundedEndHour, 0, 23) }) : addZonedDays(start, 1, timeZone);
|
|
8464
8629
|
const end3 = end2.getTime() > start2.getTime() ? end2 : addZonedDays(start2, 1, timeZone);
|
|
8465
8630
|
const slotStarts2 = [];
|
|
8466
8631
|
for (let cur2 = start2.getTime(), guard2 = 0; cur2 < end3.getTime() && guard2++ < 2e3; cur2 += stepMs) {
|
|
@@ -8489,8 +8654,8 @@ function normalizeEvents(args) {
|
|
|
8489
8654
|
const ns = view === "day" ? start : startOfZonedDay(start, timeZone);
|
|
8490
8655
|
let ne = view === "day" ? end : startOfZonedDay(end, timeZone);
|
|
8491
8656
|
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(
|
|
8657
|
+
const cs = new Date(clamp4(ns.getTime(), rangeStart, rangeEnd));
|
|
8658
|
+
const ce = new Date(clamp4(ne.getTime(), rangeStart, rangeEnd));
|
|
8494
8659
|
if (ce.getTime() <= rangeStart || cs.getTime() >= rangeEnd) return null;
|
|
8495
8660
|
return { ...e, _start: cs, _end: ce };
|
|
8496
8661
|
}).filter(Boolean);
|
|
@@ -8852,12 +9017,12 @@ function useDayHeaderMarks(args) {
|
|
|
8852
9017
|
for (const ev of normalizedEvents) {
|
|
8853
9018
|
const startIdx = binarySearchLastLE(slotStarts, ev._start);
|
|
8854
9019
|
const endIdxRaw = binarySearchFirstGE(slotStarts, ev._end);
|
|
8855
|
-
const endIdx =
|
|
9020
|
+
const endIdx = clamp4(endIdxRaw, 0, n - 1);
|
|
8856
9021
|
if (startIdx >= 0 && startIdx < n) showTime[startIdx] = true;
|
|
8857
9022
|
if (endIdx >= 0 && endIdx < n) showTime[endIdx] = true;
|
|
8858
9023
|
const span = endIdx - startIdx;
|
|
8859
9024
|
if (span >= 3) {
|
|
8860
|
-
const mid =
|
|
9025
|
+
const mid = clamp4(Math.floor((startIdx + endIdx) / 2), 0, n - 1);
|
|
8861
9026
|
if (!showTime[mid]) showEllipsis[mid] = true;
|
|
8862
9027
|
}
|
|
8863
9028
|
}
|
|
@@ -8896,7 +9061,7 @@ function useSlotMetrics(args) {
|
|
|
8896
9061
|
lefts2[0] = 0;
|
|
8897
9062
|
for (let i = 0; i < n; i++) lefts2[i + 1] = lefts2[i] + widths[i];
|
|
8898
9063
|
const gridWidth2 = lefts2[n] ?? 0;
|
|
8899
|
-
const xToSlotIdx2 = (x) =>
|
|
9064
|
+
const xToSlotIdx2 = (x) => clamp4(Math.floor(x / Math.max(1, fixedSlotWidth)), 0, Math.max(0, n - 1));
|
|
8900
9065
|
return { slotWidths: widths, slotLefts: lefts2, slotHasEvent: null, gridWidth: gridWidth2, xToSlotIdx: xToSlotIdx2 };
|
|
8901
9066
|
}
|
|
8902
9067
|
const cfg = typeof adaptiveCfg === "object" ? adaptiveCfg : {};
|
|
@@ -8922,7 +9087,7 @@ function useSlotMetrics(args) {
|
|
|
8922
9087
|
};
|
|
8923
9088
|
if (dayAnchorCompression) {
|
|
8924
9089
|
const hasEvent2 = dayHeaderMarks.anchor.slice(0, n);
|
|
8925
|
-
const compressedEmptySlotWidth =
|
|
9090
|
+
const compressedEmptySlotWidth = clamp4(emptySlotWidth, 12, 20);
|
|
8926
9091
|
for (let i = 0; i < n; i++) widths[i] = hasEvent2[i] ? fixedSlotWidth : compressedEmptySlotWidth;
|
|
8927
9092
|
maybeFillToContainer(hasEvent2);
|
|
8928
9093
|
const lefts2 = new Array(n + 1);
|
|
@@ -8930,7 +9095,7 @@ function useSlotMetrics(args) {
|
|
|
8930
9095
|
for (let i = 0; i < n; i++) lefts2[i + 1] = lefts2[i] + widths[i];
|
|
8931
9096
|
const gridWidth2 = lefts2[n] ?? 0;
|
|
8932
9097
|
const xToSlotIdx2 = (x) => {
|
|
8933
|
-
const xc =
|
|
9098
|
+
const xc = clamp4(x, 0, Math.max(0, gridWidth2 - 1e-3));
|
|
8934
9099
|
let lo = 0;
|
|
8935
9100
|
let hi = n - 1;
|
|
8936
9101
|
while (lo <= hi) {
|
|
@@ -8941,14 +9106,14 @@ function useSlotMetrics(args) {
|
|
|
8941
9106
|
else if (xc >= right) lo = mid + 1;
|
|
8942
9107
|
else return mid;
|
|
8943
9108
|
}
|
|
8944
|
-
return
|
|
9109
|
+
return clamp4(lo, 0, Math.max(0, n - 1));
|
|
8945
9110
|
};
|
|
8946
9111
|
return { slotWidths: widths, slotLefts: lefts2, slotHasEvent: hasEvent2, gridWidth: gridWidth2, xToSlotIdx: xToSlotIdx2 };
|
|
8947
9112
|
}
|
|
8948
9113
|
const diff = new Array(n + 1).fill(0);
|
|
8949
9114
|
for (const ev of normalizedEvents) {
|
|
8950
9115
|
const startIdx = binarySearchLastLE(slotStarts, ev._start);
|
|
8951
|
-
const endIdx =
|
|
9116
|
+
const endIdx = clamp4(binarySearchFirstGE(slotStarts, ev._end), startIdx + 1, n);
|
|
8952
9117
|
diff[startIdx] = (diff[startIdx] ?? 0) + 1;
|
|
8953
9118
|
diff[endIdx] = (diff[endIdx] ?? 0) - 1;
|
|
8954
9119
|
}
|
|
@@ -8966,7 +9131,7 @@ function useSlotMetrics(args) {
|
|
|
8966
9131
|
lefts2[0] = 0;
|
|
8967
9132
|
for (let i = 0; i < n; i++) lefts2[i + 1] = lefts2[i] + widths[i];
|
|
8968
9133
|
const gridWidth2 = lefts2[n] ?? 0;
|
|
8969
|
-
const xToSlotIdx2 = (x) =>
|
|
9134
|
+
const xToSlotIdx2 = (x) => clamp4(Math.floor(x / Math.max(1, fixedSlotWidth)), 0, Math.max(0, n - 1));
|
|
8970
9135
|
return { slotWidths: widths, slotLefts: lefts2, slotHasEvent: null, gridWidth: gridWidth2, xToSlotIdx: xToSlotIdx2 };
|
|
8971
9136
|
}
|
|
8972
9137
|
const emptyCount = n - eventCount;
|
|
@@ -8976,7 +9141,7 @@ function useSlotMetrics(args) {
|
|
|
8976
9141
|
const remaining = Math.max(0, targetTotal - emptyCount * emptySlotWidth);
|
|
8977
9142
|
const raw = remaining / Math.max(1, eventCount);
|
|
8978
9143
|
const maxEventSlotWidth = cfg.maxEventSlotWidth ?? fixedSlotWidth * 2.5;
|
|
8979
|
-
eventSlotWidth =
|
|
9144
|
+
eventSlotWidth = clamp4(raw, fixedSlotWidth, Math.max(fixedSlotWidth, maxEventSlotWidth));
|
|
8980
9145
|
}
|
|
8981
9146
|
for (let i = 0; i < n; i++) widths[i] = hasEvent[i] ? eventSlotWidth : emptySlotWidth;
|
|
8982
9147
|
maybeFillToContainer(hasEvent);
|
|
@@ -8985,7 +9150,7 @@ function useSlotMetrics(args) {
|
|
|
8985
9150
|
for (let i = 0; i < n; i++) lefts[i + 1] = lefts[i] + widths[i];
|
|
8986
9151
|
const gridWidth = lefts[n] ?? 0;
|
|
8987
9152
|
const xToSlotIdx = (x) => {
|
|
8988
|
-
const xc =
|
|
9153
|
+
const xc = clamp4(x, 0, Math.max(0, gridWidth - 1e-3));
|
|
8989
9154
|
let lo = 0;
|
|
8990
9155
|
let hi = n - 1;
|
|
8991
9156
|
while (lo <= hi) {
|
|
@@ -8996,7 +9161,7 @@ function useSlotMetrics(args) {
|
|
|
8996
9161
|
else if (xc >= right) lo = mid + 1;
|
|
8997
9162
|
else return mid;
|
|
8998
9163
|
}
|
|
8999
|
-
return
|
|
9164
|
+
return clamp4(lo, 0, Math.max(0, n - 1));
|
|
9000
9165
|
};
|
|
9001
9166
|
return { slotWidths: widths, slotLefts: lefts, slotHasEvent: hasEvent, gridWidth, xToSlotIdx };
|
|
9002
9167
|
}, [
|
|
@@ -9023,7 +9188,7 @@ function useLayoutsByResource(args) {
|
|
|
9023
9188
|
const s = isPreview ? preview.start : ev._start;
|
|
9024
9189
|
const e = isPreview ? preview.end : ev._end;
|
|
9025
9190
|
const startIdx = binarySearchLastLE(slotStarts, s);
|
|
9026
|
-
const endIdx =
|
|
9191
|
+
const endIdx = clamp4(binarySearchFirstGE(slotStarts, e), startIdx + 1, slotsLength);
|
|
9027
9192
|
return { ev: { ...ev, _start: s, _end: e }, startIdx, endIdx };
|
|
9028
9193
|
});
|
|
9029
9194
|
const { packed, laneCount } = intervalPack(mapped);
|
|
@@ -9087,8 +9252,8 @@ function useVisibleSlotRange(args) {
|
|
|
9087
9252
|
const endPos = Math.max(0, scrollLeft + viewportWidth);
|
|
9088
9253
|
let startIdx = Math.max(0, lowerBound2(slotLefts, startPos) - 1);
|
|
9089
9254
|
let endIdx = Math.min(slotCount, lowerBound2(slotLefts, endPos) + 1);
|
|
9090
|
-
startIdx =
|
|
9091
|
-
endIdx =
|
|
9255
|
+
startIdx = clamp4(startIdx - overscan, 0, slotCount);
|
|
9256
|
+
endIdx = clamp4(endIdx + overscan, 0, slotCount);
|
|
9092
9257
|
if (endIdx <= startIdx) endIdx = Math.min(slotCount, startIdx + 1);
|
|
9093
9258
|
return { startIdx, endIdx };
|
|
9094
9259
|
}, [enabled, overscan, scrollLeft, slotCount, slotLefts, viewportWidth]);
|
|
@@ -9411,7 +9576,7 @@ function CalendarTimeline({
|
|
|
9411
9576
|
for (const [resourceId, list] of eventsByResource.entries()) {
|
|
9412
9577
|
const mapped = list.map((ev) => {
|
|
9413
9578
|
const startIdx = binarySearchLastLE(slotStarts, ev._start);
|
|
9414
|
-
const endIdx =
|
|
9579
|
+
const endIdx = clamp4(binarySearchFirstGE(slotStarts, ev._end), startIdx + 1, slots.length);
|
|
9415
9580
|
return { startIdx, endIdx };
|
|
9416
9581
|
});
|
|
9417
9582
|
const { laneCount } = intervalPack(mapped);
|
|
@@ -9434,7 +9599,7 @@ function CalendarTimeline({
|
|
|
9434
9599
|
);
|
|
9435
9600
|
const setRowHeightForResource = React31.useCallback(
|
|
9436
9601
|
(resourceId, height) => {
|
|
9437
|
-
const clamped =
|
|
9602
|
+
const clamped = clamp4(Math.round(height), rowMin, rowMax);
|
|
9438
9603
|
onRowHeightChange?.(clamped);
|
|
9439
9604
|
if (isControlledRowHeights) {
|
|
9440
9605
|
const next = { ...activeRowHeights ?? {}, [resourceId]: clamped };
|
|
@@ -9473,7 +9638,7 @@ function CalendarTimeline({
|
|
|
9473
9638
|
const resizeRef = React31.useRef(null);
|
|
9474
9639
|
const setResourceColumnWidth = React31.useCallback(
|
|
9475
9640
|
(next) => {
|
|
9476
|
-
const clamped =
|
|
9641
|
+
const clamped = clamp4(Math.round(next), colMin, colMax);
|
|
9477
9642
|
if (!isControlledResourceColumnWidth) setInternalResourceColumnWidth(clamped);
|
|
9478
9643
|
onResourceColumnWidthChange?.(clamped);
|
|
9479
9644
|
},
|
|
@@ -9596,10 +9761,10 @@ function CalendarTimeline({
|
|
|
9596
9761
|
if (slots.length > 0) {
|
|
9597
9762
|
if (activeView === "day") {
|
|
9598
9763
|
const inRange = resolvedNow.getTime() >= range.start.getTime() && resolvedNow.getTime() < range.end.getTime();
|
|
9599
|
-
startIdx =
|
|
9764
|
+
startIdx = clamp4(inRange ? binarySearchFirstGE(slotStarts, resolvedNow) : 0, 0, slots.length - 1);
|
|
9600
9765
|
} else {
|
|
9601
9766
|
const dayStart = startOfZonedDay(activeDate, resolvedTimeZone);
|
|
9602
|
-
startIdx =
|
|
9767
|
+
startIdx = clamp4(binarySearchLastLE(slotStarts, dayStart), 0, slots.length - 1);
|
|
9603
9768
|
}
|
|
9604
9769
|
}
|
|
9605
9770
|
setCreateStartIdx(startIdx);
|
|
@@ -9636,7 +9801,7 @@ function CalendarTimeline({
|
|
|
9636
9801
|
const commitCreate = React31.useCallback(() => {
|
|
9637
9802
|
if (!onCreateEvent) return;
|
|
9638
9803
|
if (!createResourceId) return;
|
|
9639
|
-
const start = slotStarts[
|
|
9804
|
+
const start = slotStarts[clamp4(createStartIdx, 0, Math.max(0, slotStarts.length - 1))];
|
|
9640
9805
|
if (!start) return;
|
|
9641
9806
|
const endBoundary = createEndIdx >= slotStarts.length ? range.end : slotStarts[createEndIdx];
|
|
9642
9807
|
if (!endBoundary) return;
|
|
@@ -9666,8 +9831,8 @@ function CalendarTimeline({
|
|
|
9666
9831
|
const body = bodyRef.current;
|
|
9667
9832
|
if (!body) return null;
|
|
9668
9833
|
const bodyRect = body.getBoundingClientRect();
|
|
9669
|
-
const probeX =
|
|
9670
|
-
const probeY =
|
|
9834
|
+
const probeX = clamp4(clientX, bodyRect.left + 1, bodyRect.right - 1);
|
|
9835
|
+
const probeY = clamp4(clientY, bodyRect.top + 1, bodyRect.bottom - 1);
|
|
9671
9836
|
const el = document.elementFromPoint(probeX, probeY);
|
|
9672
9837
|
const x = probeX - bodyRect.left + body.scrollLeft;
|
|
9673
9838
|
const epsilon = opts?.biasLeft ? 0.01 : 0;
|
|
@@ -9681,7 +9846,7 @@ function CalendarTimeline({
|
|
|
9681
9846
|
);
|
|
9682
9847
|
const slotToDate = React31.useCallback(
|
|
9683
9848
|
(slotIdx) => {
|
|
9684
|
-
const start = slotStarts[
|
|
9849
|
+
const start = slotStarts[clamp4(slotIdx, 0, slotStarts.length - 1)];
|
|
9685
9850
|
if (activeView === "day") {
|
|
9686
9851
|
const stepMs = Math.trunc(Math.max(5, Math.min(240, Math.trunc(dayTimeStepMinutes))) * 6e4);
|
|
9687
9852
|
return { start, end: new Date(start.getTime() + stepMs) };
|
|
@@ -9722,12 +9887,12 @@ function CalendarTimeline({
|
|
|
9722
9887
|
return;
|
|
9723
9888
|
}
|
|
9724
9889
|
if (drag.mode === "resize-start") {
|
|
9725
|
-
const nextStart = new Date(
|
|
9890
|
+
const nextStart = new Date(clamp4(targetSlotStart.getTime(), range.start.getTime(), drag.originEnd.getTime() - 6e4));
|
|
9726
9891
|
setPreview({ eventId: drag.eventId, resourceId: drag.resourceId, start: nextStart, end: drag.originEnd });
|
|
9727
9892
|
return;
|
|
9728
9893
|
}
|
|
9729
9894
|
if (drag.mode === "resize-end") {
|
|
9730
|
-
const nextEnd = new Date(
|
|
9895
|
+
const nextEnd = new Date(clamp4(targetSlotStart.getTime(), drag.originStart.getTime() + 6e4, range.end.getTime()));
|
|
9731
9896
|
setPreview({ eventId: drag.eventId, resourceId: drag.resourceId, start: drag.originStart, end: nextEnd });
|
|
9732
9897
|
return;
|
|
9733
9898
|
}
|
|
@@ -9744,7 +9909,7 @@ function CalendarTimeline({
|
|
|
9744
9909
|
}
|
|
9745
9910
|
const maxScrollLeft = Math.max(0, body.scrollWidth - body.clientWidth);
|
|
9746
9911
|
const prevLeft = body.scrollLeft;
|
|
9747
|
-
const nextLeft =
|
|
9912
|
+
const nextLeft = clamp4(prevLeft + st.dir * st.speed, 0, maxScrollLeft);
|
|
9748
9913
|
if (nextLeft === prevLeft) {
|
|
9749
9914
|
stopAutoScroll();
|
|
9750
9915
|
return;
|
|
@@ -9764,12 +9929,12 @@ function CalendarTimeline({
|
|
|
9764
9929
|
if (clientX < rect.left + edge) {
|
|
9765
9930
|
dir = -1;
|
|
9766
9931
|
const dist = clientX - rect.left;
|
|
9767
|
-
const t2 =
|
|
9932
|
+
const t2 = clamp4(1 - dist / edge, 0, 1);
|
|
9768
9933
|
speed = 8 + t2 * 28;
|
|
9769
9934
|
} else if (clientX > rect.right - edge) {
|
|
9770
9935
|
dir = 1;
|
|
9771
9936
|
const dist = rect.right - clientX;
|
|
9772
|
-
const t2 =
|
|
9937
|
+
const t2 = clamp4(1 - dist / edge, 0, 1);
|
|
9773
9938
|
speed = 8 + t2 * 28;
|
|
9774
9939
|
}
|
|
9775
9940
|
autoScrollStateRef.current.lastClientX = clientX;
|
|
@@ -9880,7 +10045,7 @@ function CalendarTimeline({
|
|
|
9880
10045
|
return;
|
|
9881
10046
|
}
|
|
9882
10047
|
const rect = rowEl.getBoundingClientRect();
|
|
9883
|
-
const y =
|
|
10048
|
+
const y = clamp4(e.clientY - rect.top, 0, rect.height);
|
|
9884
10049
|
if (!hoverCell || hoverCell.resourceId !== ctx.resourceId || hoverCell.slotIdx !== ctx.slotIdx || Math.abs(hoverCell.y - y) > 0.5) {
|
|
9885
10050
|
setHoverCell({ resourceId: ctx.resourceId, slotIdx: ctx.slotIdx, y });
|
|
9886
10051
|
}
|
|
@@ -10173,8 +10338,8 @@ function CalendarTimeline({
|
|
|
10173
10338
|
const resource = resourceById.get(ev.resourceId);
|
|
10174
10339
|
const tooltipTitle = ev.title || ev.id;
|
|
10175
10340
|
const shouldCompact = activeView === "day" && dayEventStyle === "compact";
|
|
10176
|
-
const defaultMaxVisual =
|
|
10177
|
-
const maxVisual =
|
|
10341
|
+
const defaultMaxVisual = clamp4(Math.round(fixedSlotWidth * 1.2), 160, 360);
|
|
10342
|
+
const maxVisual = clamp4(Math.round(dayEventMaxWidth ?? defaultMaxVisual), 80, 1200);
|
|
10178
10343
|
const visualWidth = shouldCompact ? Math.min(width, maxVisual) : width;
|
|
10179
10344
|
const isClipped = shouldCompact && width > visualWidth + 1;
|
|
10180
10345
|
const block = /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
@@ -10264,7 +10429,7 @@ function CalendarTimeline({
|
|
|
10264
10429
|
}),
|
|
10265
10430
|
preview && preview.resourceId === r.id && !preview.eventId ? (() => {
|
|
10266
10431
|
const startIdx = binarySearchLastLE(slotStarts, preview.start);
|
|
10267
|
-
const endIdx =
|
|
10432
|
+
const endIdx = clamp4(binarySearchFirstGE(slotStarts, preview.end), startIdx + 1, slots.length);
|
|
10268
10433
|
const left = slotLefts[startIdx] ?? 0;
|
|
10269
10434
|
const width = Math.max(1, (slotLefts[endIdx] ?? 0) - (slotLefts[startIdx] ?? 0));
|
|
10270
10435
|
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
@@ -10287,7 +10452,7 @@ function CalendarTimeline({
|
|
|
10287
10452
|
),
|
|
10288
10453
|
style: {
|
|
10289
10454
|
left: (slotLefts[hoverCell.slotIdx] ?? 0) + (slotWidths[hoverCell.slotIdx] ?? fixedSlotWidth) / 2 - 10,
|
|
10290
|
-
top:
|
|
10455
|
+
top: clamp4(Math.round(hoverCell.y - 10), 6, Math.max(6, h - 26))
|
|
10291
10456
|
},
|
|
10292
10457
|
"aria-hidden": true,
|
|
10293
10458
|
children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_lucide_react21.Plus, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
@@ -13523,7 +13688,7 @@ var Timeline_default = Timeline;
|
|
|
13523
13688
|
var React42 = __toESM(require("react"), 1);
|
|
13524
13689
|
var import_lucide_react29 = require("lucide-react");
|
|
13525
13690
|
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
13526
|
-
var
|
|
13691
|
+
var clamp5 = (n, min, max) => Math.max(min, Math.min(max, n));
|
|
13527
13692
|
function hexToRgb(hex) {
|
|
13528
13693
|
const str = hex.replace(/^#/, "").trim();
|
|
13529
13694
|
if (str.length === 3) {
|
|
@@ -13541,7 +13706,7 @@ function hexToRgb(hex) {
|
|
|
13541
13706
|
return null;
|
|
13542
13707
|
}
|
|
13543
13708
|
function rgbToHex(r, g, b) {
|
|
13544
|
-
return `#${[r, g, b].map((v) =>
|
|
13709
|
+
return `#${[r, g, b].map((v) => clamp5(Math.round(v), 0, 255).toString(16).padStart(2, "0")).join("")}`;
|
|
13545
13710
|
}
|
|
13546
13711
|
function rgbToHsl(r, g, b) {
|
|
13547
13712
|
r /= 255;
|
|
@@ -13602,10 +13767,10 @@ function parseAnyColor(input) {
|
|
|
13602
13767
|
}
|
|
13603
13768
|
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
13769
|
if (rgbaMatch) {
|
|
13605
|
-
const r =
|
|
13606
|
-
const g =
|
|
13607
|
-
const b =
|
|
13608
|
-
const a = rgbaMatch[4] != null ?
|
|
13770
|
+
const r = clamp5(parseInt(rgbaMatch[1], 10), 0, 255);
|
|
13771
|
+
const g = clamp5(parseInt(rgbaMatch[2], 10), 0, 255);
|
|
13772
|
+
const b = clamp5(parseInt(rgbaMatch[3], 10), 0, 255);
|
|
13773
|
+
const a = rgbaMatch[4] != null ? clamp5(parseFloat(rgbaMatch[4]), 0, 1) : 1;
|
|
13609
13774
|
return { r, g, b, a };
|
|
13610
13775
|
}
|
|
13611
13776
|
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 +13778,7 @@ function parseAnyColor(input) {
|
|
|
13613
13778
|
const h = parseFloat(hslaMatch[1]);
|
|
13614
13779
|
const sl = parseFloat(hslaMatch[2]);
|
|
13615
13780
|
const l = parseFloat(hslaMatch[3]);
|
|
13616
|
-
const a = hslaMatch[4] != null ?
|
|
13781
|
+
const a = hslaMatch[4] != null ? clamp5(parseFloat(hslaMatch[4]), 0, 1) : 1;
|
|
13617
13782
|
const rgb = hslToRgb(h, sl, l);
|
|
13618
13783
|
return { ...rgb, a };
|
|
13619
13784
|
}
|
|
@@ -13626,12 +13791,12 @@ function formatOutput({ r, g, b, a }, withAlpha, format) {
|
|
|
13626
13791
|
if (format === "hsl" || format === "hsla") {
|
|
13627
13792
|
const hsl = rgbToHsl(r, g, b);
|
|
13628
13793
|
if (format === "hsla" || withAlpha) {
|
|
13629
|
-
return `hsla(${Math.round(hsl.h)}, ${Math.round(hsl.s)}%, ${Math.round(hsl.l)}%, ${
|
|
13794
|
+
return `hsla(${Math.round(hsl.h)}, ${Math.round(hsl.s)}%, ${Math.round(hsl.l)}%, ${clamp5(a, 0, 1)})`;
|
|
13630
13795
|
}
|
|
13631
13796
|
return `hsl(${Math.round(hsl.h)}, ${Math.round(hsl.s)}%, ${Math.round(hsl.l)}%)`;
|
|
13632
13797
|
}
|
|
13633
13798
|
if (withAlpha || a !== 1) {
|
|
13634
|
-
return `rgba(${
|
|
13799
|
+
return `rgba(${clamp5(r, 0, 255)}, ${clamp5(g, 0, 255)}, ${clamp5(b, 0, 255)}, ${clamp5(a, 0, 1)})`;
|
|
13635
13800
|
}
|
|
13636
13801
|
return rgbToHex(r, g, b);
|
|
13637
13802
|
}
|
|
@@ -13765,7 +13930,7 @@ function ColorPicker({
|
|
|
13765
13930
|
emit(next);
|
|
13766
13931
|
};
|
|
13767
13932
|
const setAlpha = (aPct) => {
|
|
13768
|
-
const a =
|
|
13933
|
+
const a = clamp5(aPct / 100, 0, 1);
|
|
13769
13934
|
const next = { ...rgba, a };
|
|
13770
13935
|
setRgba(next);
|
|
13771
13936
|
emit(next);
|
|
@@ -18426,7 +18591,7 @@ function toNullableNumber(value) {
|
|
|
18426
18591
|
}
|
|
18427
18592
|
return null;
|
|
18428
18593
|
}
|
|
18429
|
-
function
|
|
18594
|
+
function clamp6(value, min, max) {
|
|
18430
18595
|
return Math.min(max, Math.max(min, value));
|
|
18431
18596
|
}
|
|
18432
18597
|
function ResizableImageNodeView(props) {
|
|
@@ -18488,18 +18653,18 @@ function ResizableImageNodeView(props) {
|
|
|
18488
18653
|
let nextH = drag.startH;
|
|
18489
18654
|
if (event.ctrlKey) {
|
|
18490
18655
|
if (Math.abs(dx) >= Math.abs(dy)) {
|
|
18491
|
-
nextW =
|
|
18492
|
-
nextH =
|
|
18656
|
+
nextW = clamp6(drag.startW + dx, MIN_IMAGE_SIZE_PX, drag.maxW);
|
|
18657
|
+
nextH = clamp6(nextW / drag.aspect, MIN_IMAGE_SIZE_PX, Number.POSITIVE_INFINITY);
|
|
18493
18658
|
} else {
|
|
18494
|
-
nextH =
|
|
18495
|
-
nextW =
|
|
18659
|
+
nextH = clamp6(drag.startH + dy, MIN_IMAGE_SIZE_PX, Number.POSITIVE_INFINITY);
|
|
18660
|
+
nextW = clamp6(nextH * drag.aspect, MIN_IMAGE_SIZE_PX, drag.maxW);
|
|
18496
18661
|
}
|
|
18497
18662
|
} else {
|
|
18498
18663
|
if (!drag.axis && (Math.abs(dx) > AXIS_LOCK_THRESHOLD_PX || Math.abs(dy) > AXIS_LOCK_THRESHOLD_PX)) {
|
|
18499
18664
|
drag.axis = Math.abs(dx) >= Math.abs(dy) ? "x" : "y";
|
|
18500
18665
|
}
|
|
18501
|
-
if (drag.axis === "x") nextW =
|
|
18502
|
-
if (drag.axis === "y") nextH =
|
|
18666
|
+
if (drag.axis === "x") nextW = clamp6(drag.startW + dx, MIN_IMAGE_SIZE_PX, drag.maxW);
|
|
18667
|
+
if (drag.axis === "y") nextH = clamp6(drag.startH + dy, MIN_IMAGE_SIZE_PX, Number.POSITIVE_INFINITY);
|
|
18503
18668
|
}
|
|
18504
18669
|
drag.lastW = nextW;
|
|
18505
18670
|
drag.lastH = nextH;
|