@spacesync/client 0.1.10 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -13
- package/dist/analog-clock-picker.js +3 -11
- package/dist/analog-clock-picker.js.map +1 -1
- package/dist/booking-schedule-calendars.js +82 -19
- package/dist/booking-schedule-calendars.js.map +1 -1
- package/dist/booking-schedule.js +1 -1
- package/dist/booking-space-layout-picker.d.ts +1 -1
- package/dist/booking-space-layout-picker.js +8 -11
- package/dist/booking-space-layout-picker.js.map +1 -1
- package/dist/button-Iem7kbk0.d.ts +16 -0
- package/dist/chat-stick-to-bottom.js +0 -10
- package/dist/chat-stick-to-bottom.js.map +1 -1
- package/dist/chunk-2IZODKTR.js +116 -0
- package/dist/chunk-2IZODKTR.js.map +1 -0
- package/dist/chunk-2TT2ZGMT.js +21 -0
- package/dist/chunk-2TT2ZGMT.js.map +1 -0
- package/dist/chunk-3MAGTCCN.js +192 -0
- package/dist/chunk-3MAGTCCN.js.map +1 -0
- package/dist/chunk-56H7UFAW.js +237 -0
- package/dist/chunk-56H7UFAW.js.map +1 -0
- package/dist/{chunk-OTSA5ROL.js → chunk-5CUJZNUC.js} +16 -5
- package/dist/chunk-5CUJZNUC.js.map +1 -0
- package/dist/chunk-5HOK5JHR.js +60 -0
- package/dist/chunk-5HOK5JHR.js.map +1 -0
- package/dist/chunk-6VJQIBC3.js +715 -0
- package/dist/chunk-6VJQIBC3.js.map +1 -0
- package/dist/{chunk-H7EX6B6N.js → chunk-AHFRK6KP.js} +25 -7
- package/dist/chunk-AHFRK6KP.js.map +1 -0
- package/dist/chunk-BQVMO33N.js +133 -0
- package/dist/chunk-BQVMO33N.js.map +1 -0
- package/dist/chunk-CXXOKCLJ.js +37 -0
- package/dist/chunk-CXXOKCLJ.js.map +1 -0
- package/dist/chunk-EQLKSX4E.js +241 -0
- package/dist/chunk-EQLKSX4E.js.map +1 -0
- package/dist/chunk-FN4BWFDX.js +43 -0
- package/dist/chunk-FN4BWFDX.js.map +1 -0
- package/dist/chunk-HRHDOLWU.js +62 -0
- package/dist/chunk-HRHDOLWU.js.map +1 -0
- package/dist/chunk-HZB2EHEH.js +216 -0
- package/dist/chunk-HZB2EHEH.js.map +1 -0
- package/dist/chunk-IBGGQXTH.js +21 -0
- package/dist/chunk-IBGGQXTH.js.map +1 -0
- package/dist/chunk-JCEOU7BU.js +128 -0
- package/dist/chunk-JCEOU7BU.js.map +1 -0
- package/dist/{chunk-CKCXQBHQ.js → chunk-KXTYPZDK.js} +91 -19
- package/dist/chunk-KXTYPZDK.js.map +1 -0
- package/dist/{chunk-RV5PMZYZ.js → chunk-MBZAYH5D.js} +4 -18
- package/dist/chunk-MBZAYH5D.js.map +1 -0
- package/dist/chunk-NWVNYKND.js +153 -0
- package/dist/chunk-NWVNYKND.js.map +1 -0
- package/dist/chunk-PPMJZVR4.js +37 -0
- package/dist/chunk-PPMJZVR4.js.map +1 -0
- package/dist/chunk-SHMKDGFF.js +75 -0
- package/dist/chunk-SHMKDGFF.js.map +1 -0
- package/dist/chunk-T3SOBIYA.js +61 -0
- package/dist/chunk-T3SOBIYA.js.map +1 -0
- package/dist/chunk-TH5RASJS.js +97 -0
- package/dist/chunk-TH5RASJS.js.map +1 -0
- package/dist/{chunk-LUB7QWGU.js → chunk-VIJ2HWPZ.js} +5 -159
- package/dist/chunk-VIJ2HWPZ.js.map +1 -0
- package/dist/chunk-VQ63T7CJ.js +22 -0
- package/dist/chunk-VQ63T7CJ.js.map +1 -0
- package/dist/chunk-XDVGFHK4.js +50 -0
- package/dist/chunk-XDVGFHK4.js.map +1 -0
- package/dist/chunk-XI4BQY5T.js +188 -0
- package/dist/chunk-XI4BQY5T.js.map +1 -0
- package/dist/chunk-ZVWUPYSV.js +170 -0
- package/dist/chunk-ZVWUPYSV.js.map +1 -0
- package/dist/detail-page-header.js +1 -1
- package/dist/file-viewer-dialog.js +3 -9
- package/dist/file-viewer-dialog.js.map +1 -1
- package/dist/floor-switcher.js +5 -9
- package/dist/floor-switcher.js.map +1 -1
- package/dist/{layout-canvas-view-DOjyUNJH.d.ts → layout-canvas-view-C3u96xu4.d.ts} +5 -1
- package/dist/layout-canvas-view.d.ts +1 -1
- package/dist/layout-canvas-view.js +8 -11
- package/dist/lib/dateDisplay.d.ts +16 -1
- package/dist/lib/dateDisplay.js +1 -1
- package/dist/notification-sidebar-preview.js +1 -1
- package/dist/page-list-chrome.d.ts +3 -1
- package/dist/page-list-chrome.js +5 -3
- package/dist/page-list-loading.js +5 -3
- package/dist/page-list-loading.js.map +1 -1
- package/dist/platform-support-message-composer.js +2 -10
- package/dist/platform-support-message-composer.js.map +1 -1
- package/dist/sidebar-Dzvrjr69.d.ts +85 -0
- package/dist/styles/theme.css +52 -2
- package/dist/styles/theme.css.map +1 -1
- package/dist/support-presence-status.js +1 -1
- package/dist/theme-appearance-control.js +2 -1
- package/dist/theme-appearance-control.js.map +1 -1
- package/dist/ui/accordion.d.ts +9 -0
- package/dist/ui/accordion.js +4 -0
- package/dist/ui/accordion.js.map +1 -0
- package/dist/ui/calendar.d.ts +6 -0
- package/dist/ui/calendar.js +4 -0
- package/dist/ui/calendar.js.map +1 -0
- package/dist/ui/carousel.d.ts +22 -0
- package/dist/ui/carousel.js +5 -0
- package/dist/ui/carousel.js.map +1 -0
- package/dist/ui/chart.d.ts +42 -0
- package/dist/ui/chart.js +229 -0
- package/dist/ui/chart.js.map +1 -0
- package/dist/ui/command.d.ts +19 -0
- package/dist/ui/command.js +5 -0
- package/dist/ui/command.js.map +1 -0
- package/dist/ui/context-menu.d.ts +27 -0
- package/dist/ui/context-menu.js +4 -0
- package/dist/ui/context-menu.js.map +1 -0
- package/dist/ui/form.d.ts +27 -0
- package/dist/ui/form.js +5 -0
- package/dist/ui/form.js.map +1 -0
- package/dist/ui/input-otp.d.ts +13 -0
- package/dist/ui/input-otp.js +4 -0
- package/dist/ui/input-otp.js.map +1 -0
- package/dist/ui/menubar.d.ts +28 -0
- package/dist/ui/menubar.js +4 -0
- package/dist/ui/menubar.js.map +1 -0
- package/dist/ui/navigation-menu.d.ts +17 -0
- package/dist/ui/navigation-menu.js +4 -0
- package/dist/ui/navigation-menu.js.map +1 -0
- package/dist/ui/resizable.d.ts +10 -0
- package/dist/ui/resizable.js +4 -0
- package/dist/ui/resizable.js.map +1 -0
- package/dist/ui/sidebar.d.ts +7 -0
- package/dist/ui/sidebar.js +9 -0
- package/dist/ui/sidebar.js.map +1 -0
- package/dist/ui.d.ts +36 -270
- package/dist/ui.js +2471 -6
- package/dist/ui.js.map +1 -1
- package/package.json +15 -5
- package/dist/chunk-CKCXQBHQ.js.map +0 -1
- package/dist/chunk-F7MU5T46.js +0 -5146
- package/dist/chunk-F7MU5T46.js.map +0 -1
- package/dist/chunk-H7EX6B6N.js.map +0 -1
- package/dist/chunk-LUB7QWGU.js.map +0 -1
- package/dist/chunk-OTSA5ROL.js.map +0 -1
- package/dist/chunk-PBNBLCC2.js +0 -84
- package/dist/chunk-PBNBLCC2.js.map +0 -1
- package/dist/chunk-RV5PMZYZ.js.map +0 -1
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// src/lib/dateDisplay.ts
|
|
2
|
+
function parseWallClockHm(value) {
|
|
3
|
+
const m = /^([01]\d|2[0-3]):([0-5]\d)$/.exec(value.trim());
|
|
4
|
+
if (!m) return void 0;
|
|
5
|
+
const h = Number(m[1]);
|
|
6
|
+
const min = Number(m[2]);
|
|
7
|
+
if (h > 23 || min > 59) return void 0;
|
|
8
|
+
return { h, m: min };
|
|
9
|
+
}
|
|
10
|
+
function toWallClockHmStr(h, m) {
|
|
11
|
+
return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`;
|
|
12
|
+
}
|
|
13
|
+
function formatWallClockTime(value, timeFormat) {
|
|
14
|
+
const p = parseWallClockHm(value);
|
|
15
|
+
if (!p) return value.trim() || "\u2014";
|
|
16
|
+
if (timeFormat === "24h") return toWallClockHmStr(p.h, p.m);
|
|
17
|
+
const ap = p.h >= 12 ? "PM" : "AM";
|
|
18
|
+
const h12 = p.h % 12 || 12;
|
|
19
|
+
return `${h12}:${String(p.m).padStart(2, "0")} ${ap}`;
|
|
20
|
+
}
|
|
21
|
+
function addWallClockMinutes(value, minutes) {
|
|
22
|
+
const p = parseWallClockHm(value);
|
|
23
|
+
if (!p) return value;
|
|
24
|
+
const total = p.h * 60 + p.m + minutes;
|
|
25
|
+
const wrapped = (total % (24 * 60) + 24 * 60) % (24 * 60);
|
|
26
|
+
return toWallClockHmStr(Math.floor(wrapped / 60), wrapped % 60);
|
|
27
|
+
}
|
|
28
|
+
function formatCalendarDate(ymd) {
|
|
29
|
+
if (!ymd || !/^\d{4}-\d{2}-\d{2}$/.test(ymd)) return ymd || "\u2014";
|
|
30
|
+
const [y, m, d] = ymd.split("-").map(Number);
|
|
31
|
+
return new Date(y, m - 1, d).toLocaleDateString("en-US", {
|
|
32
|
+
month: "short",
|
|
33
|
+
day: "numeric",
|
|
34
|
+
year: "numeric"
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function toDateStr(date) {
|
|
38
|
+
const y = date.getFullYear();
|
|
39
|
+
const m = String(date.getMonth() + 1).padStart(2, "0");
|
|
40
|
+
const d = String(date.getDate()).padStart(2, "0");
|
|
41
|
+
return `${y}-${m}-${d}`;
|
|
42
|
+
}
|
|
43
|
+
function isSameDay(a, b) {
|
|
44
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
45
|
+
}
|
|
46
|
+
function formatDate(date) {
|
|
47
|
+
if (isSameDay(date, /* @__PURE__ */ new Date())) return "Today";
|
|
48
|
+
return date.toLocaleDateString("en-US", {
|
|
49
|
+
weekday: "short",
|
|
50
|
+
month: "short",
|
|
51
|
+
day: "numeric"
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
var MS_MIN = 6e4;
|
|
55
|
+
var MS_HOUR = 60 * MS_MIN;
|
|
56
|
+
var MS_DAY = 24 * MS_HOUR;
|
|
57
|
+
function formatRelativeTimeAgo(iso, now = /* @__PURE__ */ new Date()) {
|
|
58
|
+
try {
|
|
59
|
+
const d = new Date(iso.trim());
|
|
60
|
+
if (!Number.isFinite(d.getTime())) return "";
|
|
61
|
+
let diffMs = now.getTime() - d.getTime();
|
|
62
|
+
if (diffMs < 0) diffMs = 0;
|
|
63
|
+
const sec = Math.floor(diffMs / 1e3);
|
|
64
|
+
if (sec < 60) return "just now";
|
|
65
|
+
const min = Math.floor(diffMs / MS_MIN);
|
|
66
|
+
if (min < 60) return `${min}m ago`;
|
|
67
|
+
const hr = Math.floor(diffMs / MS_HOUR);
|
|
68
|
+
if (hr < 24) return `${hr}h ago`;
|
|
69
|
+
const day = Math.floor(diffMs / MS_DAY);
|
|
70
|
+
if (day < 7) return `${day}d ago`;
|
|
71
|
+
const week = Math.floor(day / 7);
|
|
72
|
+
if (week < 5) return `${week}w ago`;
|
|
73
|
+
const mo = Math.floor(day / 30);
|
|
74
|
+
if (mo < 12) return `${mo}mo ago`;
|
|
75
|
+
const yr = Math.floor(day / 365);
|
|
76
|
+
return `${Math.max(1, yr)}y ago`;
|
|
77
|
+
} catch {
|
|
78
|
+
return "";
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
var YMD_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
82
|
+
function startOfLocalDay(d) {
|
|
83
|
+
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
84
|
+
}
|
|
85
|
+
function compactDaySpan(absDays) {
|
|
86
|
+
if (absDays < 7) return `${absDays}d`;
|
|
87
|
+
const week = Math.floor(absDays / 7);
|
|
88
|
+
if (week < 5) return `${week}w`;
|
|
89
|
+
const mo = Math.floor(absDays / 30);
|
|
90
|
+
if (mo < 12) return `${mo}mo`;
|
|
91
|
+
return `${Math.max(1, Math.floor(absDays / 365))}y`;
|
|
92
|
+
}
|
|
93
|
+
function formatCompactAbsolute(date, includeTime) {
|
|
94
|
+
const day = date.getDate();
|
|
95
|
+
const month = date.toLocaleDateString("en-US", { month: "short" });
|
|
96
|
+
if (includeTime) {
|
|
97
|
+
const time = date.toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" });
|
|
98
|
+
return `${day} ${month}, ${time}`;
|
|
99
|
+
}
|
|
100
|
+
const year = String(date.getFullYear()).slice(-2);
|
|
101
|
+
return `${day} ${month}, ${year}`;
|
|
102
|
+
}
|
|
103
|
+
function sameDayClockLabel(diffMs) {
|
|
104
|
+
const abs = Math.abs(diffMs);
|
|
105
|
+
if (abs < 6e4) return "Just now";
|
|
106
|
+
const min = Math.floor(abs / MS_MIN);
|
|
107
|
+
if (min < 60) {
|
|
108
|
+
const span2 = `${min}m`;
|
|
109
|
+
return diffMs > 0 ? `In ${span2}` : `${span2} ago`;
|
|
110
|
+
}
|
|
111
|
+
const hr = Math.max(1, Math.floor(abs / MS_HOUR));
|
|
112
|
+
const span = `${hr}h`;
|
|
113
|
+
return diffMs > 0 ? `In ${span}` : `${span} ago`;
|
|
114
|
+
}
|
|
115
|
+
function calendarRelativeLabel(diffDays) {
|
|
116
|
+
if (diffDays === 0) return "Today";
|
|
117
|
+
if (diffDays === 1) return "Tomorrow";
|
|
118
|
+
if (diffDays === -1) return "Yesterday";
|
|
119
|
+
const span = compactDaySpan(Math.abs(diffDays));
|
|
120
|
+
return diffDays > 0 ? `In ${span}` : `${span} ago`;
|
|
121
|
+
}
|
|
122
|
+
function formatRelativeWhen(value, now = /* @__PURE__ */ new Date()) {
|
|
123
|
+
const trimmed = value.trim();
|
|
124
|
+
if (!trimmed) return null;
|
|
125
|
+
let date;
|
|
126
|
+
let includeTime = false;
|
|
127
|
+
if (YMD_RE.test(trimmed)) {
|
|
128
|
+
const [y, m, d] = trimmed.split("-").map(Number);
|
|
129
|
+
date = new Date(y, m - 1, d);
|
|
130
|
+
} else {
|
|
131
|
+
date = new Date(trimmed);
|
|
132
|
+
includeTime = true;
|
|
133
|
+
}
|
|
134
|
+
if (!Number.isFinite(date.getTime())) return null;
|
|
135
|
+
const today = startOfLocalDay(now);
|
|
136
|
+
const targetDay = startOfLocalDay(date);
|
|
137
|
+
const diffDays = Math.round((targetDay.getTime() - today.getTime()) / MS_DAY);
|
|
138
|
+
const isCurrent = diffDays === 0;
|
|
139
|
+
const label = includeTime && isCurrent ? sameDayClockLabel(date.getTime() - now.getTime()) : calendarRelativeLabel(diffDays);
|
|
140
|
+
return {
|
|
141
|
+
label,
|
|
142
|
+
absolute: formatCompactAbsolute(date, includeTime),
|
|
143
|
+
diffDays,
|
|
144
|
+
isCurrent
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function relativeWhenTone(kind, diffDays) {
|
|
148
|
+
if (kind === "created") {
|
|
149
|
+
const elapsed = diffDays > 0 ? 0 : -diffDays;
|
|
150
|
+
if (elapsed < 2) return "success";
|
|
151
|
+
if (elapsed <= 7) return "warning";
|
|
152
|
+
return "danger";
|
|
153
|
+
}
|
|
154
|
+
if (kind === "deadline") {
|
|
155
|
+
if (diffDays < 0) return "danger";
|
|
156
|
+
if (diffDays === 0) return "current";
|
|
157
|
+
if (diffDays <= 2) return "danger";
|
|
158
|
+
if (diffDays <= 6) return "warning";
|
|
159
|
+
return "success";
|
|
160
|
+
}
|
|
161
|
+
if (diffDays < 0) return "muted";
|
|
162
|
+
if (diffDays === 0) return "current";
|
|
163
|
+
if (diffDays <= 2) return "danger";
|
|
164
|
+
if (diffDays <= 6) return "warning";
|
|
165
|
+
return "success";
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export { addWallClockMinutes, formatCalendarDate, formatDate, formatRelativeTimeAgo, formatRelativeWhen, formatWallClockTime, isSameDay, parseWallClockHm, relativeWhenTone, toDateStr, toWallClockHmStr };
|
|
169
|
+
//# sourceMappingURL=chunk-ZVWUPYSV.js.map
|
|
170
|
+
//# sourceMappingURL=chunk-ZVWUPYSV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/dateDisplay.ts"],"names":["span"],"mappings":";AACO,SAAS,iBAAiB,KAAA,EAAqD;AACpF,EAAA,MAAM,CAAA,GAAI,6BAAA,CAA8B,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AACzD,EAAA,IAAI,CAAC,GAAG,OAAO,MAAA;AACf,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,CAAA,CAAE,CAAC,CAAC,CAAA;AACrB,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,CAAA,CAAE,CAAC,CAAC,CAAA;AACvB,EAAA,IAAI,CAAA,GAAI,EAAA,IAAM,GAAA,GAAM,EAAA,EAAI,OAAO,MAAA;AAC/B,EAAA,OAAO,EAAE,CAAA,EAAG,CAAA,EAAG,GAAA,EAAI;AACrB;AAEO,SAAS,gBAAA,CAAiB,GAAW,CAAA,EAAmB;AAC7D,EAAA,OAAO,CAAA,EAAG,MAAA,CAAO,CAAC,CAAA,CAAE,SAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA,EAAI,OAAO,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA;AACpE;AAGO,SAAS,mBAAA,CAAoB,OAAe,UAAA,EAAmC;AACpF,EAAA,MAAM,CAAA,GAAI,iBAAiB,KAAK,CAAA;AAChC,EAAA,IAAI,CAAC,CAAA,EAAG,OAAO,KAAA,CAAM,MAAK,IAAK,QAAA;AAC/B,EAAA,IAAI,eAAe,KAAA,EAAO,OAAO,iBAAiB,CAAA,CAAE,CAAA,EAAG,EAAE,CAAC,CAAA;AAC1D,EAAA,MAAM,EAAA,GAAK,CAAA,CAAE,CAAA,IAAK,EAAA,GAAK,IAAA,GAAO,IAAA;AAC9B,EAAA,MAAM,GAAA,GAAM,CAAA,CAAE,CAAA,GAAI,EAAA,IAAM,EAAA;AACxB,EAAA,OAAO,CAAA,EAAG,GAAG,CAAA,CAAA,EAAI,MAAA,CAAO,CAAA,CAAE,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA;AACrD;AAGO,SAAS,mBAAA,CAAoB,OAAe,OAAA,EAAyB;AAC1E,EAAA,MAAM,CAAA,GAAI,iBAAiB,KAAK,CAAA;AAChC,EAAA,IAAI,CAAC,GAAG,OAAO,KAAA;AACf,EAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,CAAA,GAAI,EAAA,GAAK,EAAE,CAAA,GAAI,OAAA;AAC/B,EAAA,MAAM,WAAY,KAAA,IAAS,EAAA,GAAK,EAAA,CAAA,GAAO,EAAA,GAAK,OAAO,EAAA,GAAK,EAAA,CAAA;AACxD,EAAA,OAAO,iBAAiB,IAAA,CAAK,KAAA,CAAM,UAAU,EAAE,CAAA,EAAG,UAAU,EAAE,CAAA;AAChE;AAGO,SAAS,mBAAmB,GAAA,EAAqB;AACtD,EAAA,IAAI,CAAC,OAAO,CAAC,qBAAA,CAAsB,KAAK,GAAG,CAAA,SAAU,GAAA,IAAO,QAAA;AAC5D,EAAA,MAAM,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,GAAI,IAAI,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,MAAM,CAAA;AAC3C,EAAA,OAAO,IAAI,KAAK,CAAA,EAAG,CAAA,GAAI,GAAG,CAAC,CAAA,CAAE,mBAAmB,OAAA,EAAS;AAAA,IACvD,KAAA,EAAO,OAAA;AAAA,IACP,GAAA,EAAK,SAAA;AAAA,IACL,IAAA,EAAM;AAAA,GACP,CAAA;AACH;AAGO,SAAS,UAAU,IAAA,EAAoB;AAC5C,EAAA,MAAM,CAAA,GAAI,KAAK,WAAA,EAAY;AAC3B,EAAA,MAAM,CAAA,GAAI,OAAO,IAAA,CAAK,QAAA,KAAa,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAA;AACrD,EAAA,MAAM,CAAA,GAAI,OAAO,IAAA,CAAK,OAAA,EAAS,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAA;AAChD,EAAA,OAAO,CAAA,EAAG,CAAC,CAAA,CAAA,EAAI,CAAC,IAAI,CAAC,CAAA,CAAA;AACvB;AAEO,SAAS,SAAA,CAAU,GAAS,CAAA,EAAkB;AACnD,EAAA,OACE,EAAE,WAAA,EAAY,KAAM,CAAA,CAAE,WAAA,MACtB,CAAA,CAAE,QAAA,EAAS,KAAM,CAAA,CAAE,UAAS,IAC5B,CAAA,CAAE,OAAA,EAAQ,KAAM,EAAE,OAAA,EAAQ;AAE9B;AAGO,SAAS,WAAW,IAAA,EAAoB;AAC7C,EAAA,IAAI,UAAU,IAAA,kBAAM,IAAI,IAAA,EAAM,GAAG,OAAO,OAAA;AACxC,EAAA,OAAO,IAAA,CAAK,mBAAmB,OAAA,EAAS;AAAA,IACtC,OAAA,EAAS,OAAA;AAAA,IACT,KAAA,EAAO,OAAA;AAAA,IACP,GAAA,EAAK;AAAA,GACN,CAAA;AACH;AAEA,IAAM,MAAA,GAAS,GAAA;AACf,IAAM,UAAU,EAAA,GAAK,MAAA;AACrB,IAAM,SAAS,EAAA,GAAK,OAAA;AAMb,SAAS,qBAAA,CAAsB,GAAA,EAAa,GAAA,mBAAY,IAAI,MAAK,EAAW;AACjF,EAAA,IAAI;AACF,IAAA,MAAM,CAAA,GAAI,IAAI,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA;AAC7B,IAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,EAAE,OAAA,EAAS,GAAG,OAAO,EAAA;AAC1C,IAAA,IAAI,MAAA,GAAS,GAAA,CAAI,OAAA,EAAQ,GAAI,EAAE,OAAA,EAAQ;AACvC,IAAA,IAAI,MAAA,GAAS,GAAG,MAAA,GAAS,CAAA;AACzB,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,GAAI,CAAA;AACpC,IAAA,IAAI,GAAA,GAAM,IAAI,OAAO,UAAA;AACrB,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,MAAM,CAAA;AACtC,IAAA,IAAI,GAAA,GAAM,EAAA,EAAI,OAAO,CAAA,EAAG,GAAG,CAAA,KAAA,CAAA;AAC3B,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,OAAO,CAAA;AACtC,IAAA,IAAI,EAAA,GAAK,EAAA,EAAI,OAAO,CAAA,EAAG,EAAE,CAAA,KAAA,CAAA;AACzB,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,MAAM,CAAA;AACtC,IAAA,IAAI,GAAA,GAAM,CAAA,EAAG,OAAO,CAAA,EAAG,GAAG,CAAA,KAAA,CAAA;AAC1B,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,GAAA,GAAM,CAAC,CAAA;AAC/B,IAAA,IAAI,IAAA,GAAO,CAAA,EAAG,OAAO,CAAA,EAAG,IAAI,CAAA,KAAA,CAAA;AAC5B,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,KAAA,CAAM,GAAA,GAAM,EAAE,CAAA;AAC9B,IAAA,IAAI,EAAA,GAAK,EAAA,EAAI,OAAO,CAAA,EAAG,EAAE,CAAA,MAAA,CAAA;AACzB,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,KAAA,CAAM,GAAA,GAAM,GAAG,CAAA;AAC/B,IAAA,OAAO,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,EAAE,CAAC,CAAA,KAAA,CAAA;AAAA,EAC3B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAA;AAAA,EACT;AACF;AAEA,IAAM,MAAA,GAAS,qBAAA;AAYf,SAAS,gBAAgB,CAAA,EAAe;AACtC,EAAA,OAAO,IAAI,IAAA,CAAK,CAAA,CAAE,WAAA,EAAY,EAAG,EAAE,QAAA,EAAS,EAAG,CAAA,CAAE,OAAA,EAAS,CAAA;AAC5D;AAEA,SAAS,eAAe,OAAA,EAAyB;AAC/C,EAAA,IAAI,OAAA,GAAU,CAAA,EAAG,OAAO,CAAA,EAAG,OAAO,CAAA,CAAA,CAAA;AAClC,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,CAAC,CAAA;AACnC,EAAA,IAAI,IAAA,GAAO,CAAA,EAAG,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,CAAA;AAC5B,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,EAAE,CAAA;AAClC,EAAA,IAAI,EAAA,GAAK,EAAA,EAAI,OAAO,CAAA,EAAG,EAAE,CAAA,EAAA,CAAA;AACzB,EAAA,OAAO,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,OAAA,GAAU,GAAG,CAAC,CAAC,CAAA,CAAA,CAAA;AAClD;AAEA,SAAS,qBAAA,CAAsB,MAAY,WAAA,EAA8B;AACvE,EAAA,MAAM,GAAA,GAAM,KAAK,OAAA,EAAQ;AACzB,EAAA,MAAM,QAAQ,IAAA,CAAK,kBAAA,CAAmB,SAAS,EAAE,KAAA,EAAO,SAAS,CAAA;AACjE,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,MAAM,IAAA,GAAO,KAAK,kBAAA,CAAmB,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAW,MAAA,EAAQ,SAAA,EAAW,CAAA;AACpF,IAAA,OAAO,CAAA,EAAG,GAAG,CAAA,CAAA,EAAI,KAAK,KAAK,IAAI,CAAA,CAAA;AAAA,EACjC;AACA,EAAA,MAAM,OAAO,MAAA,CAAO,IAAA,CAAK,aAAa,CAAA,CAAE,MAAM,EAAE,CAAA;AAChD,EAAA,OAAO,CAAA,EAAG,GAAG,CAAA,CAAA,EAAI,KAAK,KAAK,IAAI,CAAA,CAAA;AACjC;AAEA,SAAS,kBAAkB,MAAA,EAAwB;AACjD,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA;AAC3B,EAAA,IAAI,GAAA,GAAM,KAAQ,OAAO,UAAA;AACzB,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,GAAA,GAAM,MAAM,CAAA;AACnC,EAAA,IAAI,MAAM,EAAA,EAAI;AACZ,IAAA,MAAMA,KAAAA,GAAO,GAAG,GAAG,CAAA,CAAA,CAAA;AACnB,IAAA,OAAO,SAAS,CAAA,GAAI,CAAA,GAAA,EAAMA,KAAI,CAAA,CAAA,GAAK,GAAGA,KAAI,CAAA,IAAA,CAAA;AAAA,EAC5C;AACA,EAAA,MAAM,EAAA,GAAK,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,GAAA,GAAM,OAAO,CAAC,CAAA;AAChD,EAAA,MAAM,IAAA,GAAO,GAAG,EAAE,CAAA,CAAA,CAAA;AAClB,EAAA,OAAO,SAAS,CAAA,GAAI,CAAA,GAAA,EAAM,IAAI,CAAA,CAAA,GAAK,GAAG,IAAI,CAAA,IAAA,CAAA;AAC5C;AAEA,SAAS,sBAAsB,QAAA,EAA0B;AACvD,EAAA,IAAI,QAAA,KAAa,GAAG,OAAO,OAAA;AAC3B,EAAA,IAAI,QAAA,KAAa,GAAG,OAAO,UAAA;AAC3B,EAAA,IAAI,QAAA,KAAa,IAAI,OAAO,WAAA;AAC5B,EAAA,MAAM,IAAA,GAAO,cAAA,CAAe,IAAA,CAAK,GAAA,CAAI,QAAQ,CAAC,CAAA;AAC9C,EAAA,OAAO,WAAW,CAAA,GAAI,CAAA,GAAA,EAAM,IAAI,CAAA,CAAA,GAAK,GAAG,IAAI,CAAA,IAAA,CAAA;AAC9C;AAMO,SAAS,kBAAA,CAAmB,KAAA,EAAe,GAAA,mBAAY,IAAI,MAAK,EAA8B;AACnG,EAAA,MAAM,OAAA,GAAU,MAAM,IAAA,EAAK;AAC3B,EAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AAErB,EAAA,IAAI,IAAA;AACJ,EAAA,IAAI,WAAA,GAAc,KAAA;AAClB,EAAA,IAAI,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,EAAG;AACxB,IAAA,MAAM,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,GAAI,QAAQ,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,MAAM,CAAA;AAC/C,IAAA,IAAA,GAAO,IAAI,IAAA,CAAK,CAAA,EAAG,CAAA,GAAI,GAAG,CAAC,CAAA;AAAA,EAC7B,CAAA,MAAO;AACL,IAAA,IAAA,GAAO,IAAI,KAAK,OAAO,CAAA;AACvB,IAAA,WAAA,GAAc,IAAA;AAAA,EAChB;AACA,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,OAAA,EAAS,GAAG,OAAO,IAAA;AAE7C,EAAA,MAAM,KAAA,GAAQ,gBAAgB,GAAG,CAAA;AACjC,EAAA,MAAM,SAAA,GAAY,gBAAgB,IAAI,CAAA;AACtC,EAAA,MAAM,QAAA,GAAW,KAAK,KAAA,CAAA,CAAO,SAAA,CAAU,SAAQ,GAAI,KAAA,CAAM,OAAA,EAAQ,IAAK,MAAM,CAAA;AAC5E,EAAA,MAAM,YAAY,QAAA,KAAa,CAAA;AAC/B,EAAA,MAAM,KAAA,GACJ,WAAA,IAAe,SAAA,GACX,iBAAA,CAAkB,IAAA,CAAK,OAAA,EAAQ,GAAI,GAAA,CAAI,OAAA,EAAS,CAAA,GAChD,qBAAA,CAAsB,QAAQ,CAAA;AAEpC,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,QAAA,EAAU,qBAAA,CAAsB,IAAA,EAAM,WAAW,CAAA;AAAA,IACjD,QAAA;AAAA,IACA;AAAA,GACF;AACF;AAGO,SAAS,gBAAA,CAAiB,MAAwB,QAAA,EAAoC;AAC3F,EAAA,IAAI,SAAS,SAAA,EAAW;AACtB,IAAA,MAAM,OAAA,GAAU,QAAA,GAAW,CAAA,GAAI,CAAA,GAAI,CAAC,QAAA;AACpC,IAAA,IAAI,OAAA,GAAU,GAAG,OAAO,SAAA;AACxB,IAAA,IAAI,OAAA,IAAW,GAAG,OAAO,SAAA;AACzB,IAAA,OAAO,QAAA;AAAA,EACT;AACA,EAAA,IAAI,SAAS,UAAA,EAAY;AACvB,IAAA,IAAI,QAAA,GAAW,GAAG,OAAO,QAAA;AACzB,IAAA,IAAI,QAAA,KAAa,GAAG,OAAO,SAAA;AAC3B,IAAA,IAAI,QAAA,IAAY,GAAG,OAAO,QAAA;AAC1B,IAAA,IAAI,QAAA,IAAY,GAAG,OAAO,SAAA;AAC1B,IAAA,OAAO,SAAA;AAAA,EACT;AACA,EAAA,IAAI,QAAA,GAAW,GAAG,OAAO,OAAA;AACzB,EAAA,IAAI,QAAA,KAAa,GAAG,OAAO,SAAA;AAC3B,EAAA,IAAI,QAAA,IAAY,GAAG,OAAO,QAAA;AAC1B,EAAA,IAAI,QAAA,IAAY,GAAG,OAAO,SAAA;AAC1B,EAAA,OAAO,SAAA;AACT","file":"chunk-ZVWUPYSV.js","sourcesContent":["/** Parse `HH:mm` wall-clock time. */\nexport function parseWallClockHm(value: string): { h: number; m: number } | undefined {\n const m = /^([01]\\d|2[0-3]):([0-5]\\d)$/.exec(value.trim());\n if (!m) return undefined;\n const h = Number(m[1]);\n const min = Number(m[2]);\n if (h > 23 || min > 59) return undefined;\n return { h, m: min };\n}\n\nexport function toWallClockHmStr(h: number, m: number): string {\n return `${String(h).padStart(2, \"0\")}:${String(m).padStart(2, \"0\")}`;\n}\n\n/** Format stored `HH:mm` without timezone conversion. */\nexport function formatWallClockTime(value: string, timeFormat: \"12h\" | \"24h\"): string {\n const p = parseWallClockHm(value);\n if (!p) return value.trim() || \"—\";\n if (timeFormat === \"24h\") return toWallClockHmStr(p.h, p.m);\n const ap = p.h >= 12 ? \"PM\" : \"AM\";\n const h12 = p.h % 12 || 12;\n return `${h12}:${String(p.m).padStart(2, \"0\")} ${ap}`;\n}\n\n/** Add minutes to a wall-clock `HH:mm`, wrapping at 24h. */\nexport function addWallClockMinutes(value: string, minutes: number): string {\n const p = parseWallClockHm(value);\n if (!p) return value;\n const total = p.h * 60 + p.m + minutes;\n const wrapped = ((total % (24 * 60)) + 24 * 60) % (24 * 60);\n return toWallClockHmStr(Math.floor(wrapped / 60), wrapped % 60);\n}\n\n/** Format `YYYY-MM-DD` as a calendar date (no timezone shift). */\nexport function formatCalendarDate(ymd: string): string {\n if (!ymd || !/^\\d{4}-\\d{2}-\\d{2}$/.test(ymd)) return ymd || \"—\";\n const [y, m, d] = ymd.split(\"-\").map(Number);\n return new Date(y, m - 1, d).toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n });\n}\n\n/** ISO `yyyy-mm-dd` for a local calendar date. */\nexport function toDateStr(date: Date): string {\n const y = date.getFullYear();\n const m = String(date.getMonth() + 1).padStart(2, \"0\");\n const d = String(date.getDate()).padStart(2, \"0\");\n return `${y}-${m}-${d}`;\n}\n\nexport function isSameDay(a: Date, b: Date): boolean {\n return (\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate()\n );\n}\n\n/** Short label for a date; shows \"Today\" when it matches the current local day. */\nexport function formatDate(date: Date): string {\n if (isSameDay(date, new Date())) return \"Today\";\n return date.toLocaleDateString(\"en-US\", {\n weekday: \"short\",\n month: \"short\",\n day: \"numeric\",\n });\n}\n\nconst MS_MIN = 60_000;\nconst MS_HOUR = 60 * MS_MIN;\nconst MS_DAY = 24 * MS_HOUR;\n\n/**\n * Compact relative time for feeds (e.g. announcements, notifications): `2m ago`, `2d ago`.\n * Uses elapsed wall time from `now` (defaults to current time). Returns \"\" if `iso` is unparseable.\n */\nexport function formatRelativeTimeAgo(iso: string, now: Date = new Date()): string {\n try {\n const d = new Date(iso.trim());\n if (!Number.isFinite(d.getTime())) return \"\";\n let diffMs = now.getTime() - d.getTime();\n if (diffMs < 0) diffMs = 0;\n const sec = Math.floor(diffMs / 1000);\n if (sec < 60) return \"just now\";\n const min = Math.floor(diffMs / MS_MIN);\n if (min < 60) return `${min}m ago`;\n const hr = Math.floor(diffMs / MS_HOUR);\n if (hr < 24) return `${hr}h ago`;\n const day = Math.floor(diffMs / MS_DAY);\n if (day < 7) return `${day}d ago`;\n const week = Math.floor(day / 7);\n if (week < 5) return `${week}w ago`;\n const mo = Math.floor(day / 30);\n if (mo < 12) return `${mo}mo ago`;\n const yr = Math.floor(day / 365);\n return `${Math.max(1, yr)}y ago`;\n } catch {\n return \"\";\n }\n}\n\nconst YMD_RE = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nexport type RelativeWhenKind = \"created\" | \"event\" | \"deadline\";\nexport type RelativeWhenTone = \"muted\" | \"current\" | \"danger\" | \"warning\" | \"success\";\n\nexport type RelativeWhenResult = {\n label: string;\n absolute: string;\n diffDays: number;\n isCurrent: boolean;\n};\n\nfunction startOfLocalDay(d: Date): Date {\n return new Date(d.getFullYear(), d.getMonth(), d.getDate());\n}\n\nfunction compactDaySpan(absDays: number): string {\n if (absDays < 7) return `${absDays}d`;\n const week = Math.floor(absDays / 7);\n if (week < 5) return `${week}w`;\n const mo = Math.floor(absDays / 30);\n if (mo < 12) return `${mo}mo`;\n return `${Math.max(1, Math.floor(absDays / 365))}y`;\n}\n\nfunction formatCompactAbsolute(date: Date, includeTime: boolean): string {\n const day = date.getDate();\n const month = date.toLocaleDateString(\"en-US\", { month: \"short\" });\n if (includeTime) {\n const time = date.toLocaleTimeString(\"en-US\", { hour: \"numeric\", minute: \"2-digit\" });\n return `${day} ${month}, ${time}`;\n }\n const year = String(date.getFullYear()).slice(-2);\n return `${day} ${month}, ${year}`;\n}\n\nfunction sameDayClockLabel(diffMs: number): string {\n const abs = Math.abs(diffMs);\n if (abs < 60_000) return \"Just now\";\n const min = Math.floor(abs / MS_MIN);\n if (min < 60) {\n const span = `${min}m`;\n return diffMs > 0 ? `In ${span}` : `${span} ago`;\n }\n const hr = Math.max(1, Math.floor(abs / MS_HOUR));\n const span = `${hr}h`;\n return diffMs > 0 ? `In ${span}` : `${span} ago`;\n}\n\nfunction calendarRelativeLabel(diffDays: number): string {\n if (diffDays === 0) return \"Today\";\n if (diffDays === 1) return \"Tomorrow\";\n if (diffDays === -1) return \"Yesterday\";\n const span = compactDaySpan(Math.abs(diffDays));\n return diffDays > 0 ? `In ${span}` : `${span} ago`;\n}\n\n/**\n * Stacked relative + absolute date for list cells.\n * Accepts `YYYY-MM-DD` (calendar day) or an ISO timestamp.\n */\nexport function formatRelativeWhen(value: string, now: Date = new Date()): RelativeWhenResult | null {\n const trimmed = value.trim();\n if (!trimmed) return null;\n\n let date: Date;\n let includeTime = false;\n if (YMD_RE.test(trimmed)) {\n const [y, m, d] = trimmed.split(\"-\").map(Number);\n date = new Date(y, m - 1, d);\n } else {\n date = new Date(trimmed);\n includeTime = true;\n }\n if (!Number.isFinite(date.getTime())) return null;\n\n const today = startOfLocalDay(now);\n const targetDay = startOfLocalDay(date);\n const diffDays = Math.round((targetDay.getTime() - today.getTime()) / MS_DAY);\n const isCurrent = diffDays === 0;\n const label =\n includeTime && isCurrent\n ? sameDayClockLabel(date.getTime() - now.getTime())\n : calendarRelativeLabel(diffDays);\n\n return {\n label,\n absolute: formatCompactAbsolute(date, includeTime),\n diffDays,\n isCurrent,\n };\n}\n\n/** Text tone for a relative-when cell. `diffDays` is calendar days (value − today). */\nexport function relativeWhenTone(kind: RelativeWhenKind, diffDays: number): RelativeWhenTone {\n if (kind === \"created\") {\n const elapsed = diffDays > 0 ? 0 : -diffDays;\n if (elapsed < 2) return \"success\";\n if (elapsed <= 7) return \"warning\";\n return \"danger\";\n }\n if (kind === \"deadline\") {\n if (diffDays < 0) return \"danger\";\n if (diffDays === 0) return \"current\";\n if (diffDays <= 2) return \"danger\";\n if (diffDays <= 6) return \"warning\";\n return \"success\";\n }\n if (diffDays < 0) return \"muted\";\n if (diffDays === 0) return \"current\";\n if (diffDays <= 2) return \"danger\";\n if (diffDays <= 6) return \"warning\";\n return \"success\";\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ShellTopBar } from './chunk-4NNK5IXY.js';
|
|
2
|
-
import { Button } from './chunk-VHINHHZQ.js';
|
|
3
2
|
import { shellTopBarBackButtonClass, shellTopBarMutedIconClass, shellTopBarTitleTextClass } from './chunk-FCY5FYJB.js';
|
|
3
|
+
import { Button } from './chunk-VHINHHZQ.js';
|
|
4
4
|
import './chunk-OWNUMPUC.js';
|
|
5
5
|
import './chunk-DMPSQ22Q.js';
|
|
6
6
|
import { ChevronLeft } from 'lucide-react';
|
|
@@ -1,14 +1,8 @@
|
|
|
1
|
-
import { ResponsiveDialog, ResponsiveDialogContent, ResponsiveDialogTitle } from './chunk-
|
|
2
|
-
import './chunk-RV5PMZYZ.js';
|
|
3
|
-
import './chunk-L65F4EMK.js';
|
|
4
|
-
import './chunk-PBNBLCC2.js';
|
|
1
|
+
import { ResponsiveDialog, ResponsiveDialogContent, ResponsiveDialogTitle } from './chunk-SHMKDGFF.js';
|
|
5
2
|
import './chunk-VVXGQKN7.js';
|
|
6
|
-
import './chunk-
|
|
7
|
-
import './chunk-DC4QH6W2.js';
|
|
8
|
-
import './chunk-LUB7QWGU.js';
|
|
3
|
+
import './chunk-2TT2ZGMT.js';
|
|
9
4
|
import { Button } from './chunk-VHINHHZQ.js';
|
|
10
|
-
import './chunk-
|
|
11
|
-
import './chunk-OWNUMPUC.js';
|
|
5
|
+
import './chunk-7YCAAP43.js';
|
|
12
6
|
import { cn } from './chunk-DMPSQ22Q.js';
|
|
13
7
|
import { useState, useRef, useEffect, useMemo } from 'react';
|
|
14
8
|
import { Minus, Plus, RotateCcw, Download, ExternalLink, Loader2, FileText } from 'lucide-react';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/files/file-viewer-dialog.tsx"],"names":[],"mappings":"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","file":"file-viewer-dialog.js","sourcesContent":["import { useEffect, useMemo, useRef, useState } from \"react\";\nimport { Download, ExternalLink, FileText, Loader2, Minus, Plus, RotateCcw } from \"lucide-react\";\nimport {\n Button,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogTitle,\n cn,\n} from \"../ui\";\n\nexport interface FileViewerFile {\n name: string;\n mimeType: string;\n sizeLabel?: string;\n url: string;\n}\n\nexport function FileViewerDialog({\n file,\n open,\n onOpenChange,\n}: {\n file: FileViewerFile | null;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n const [zoom, setZoom] = useState(1);\n const [dragging, setDragging] = useState(false);\n const [imageStatus, setImageStatus] = useState<\"loading\" | \"ready\" | \"error\">(\"loading\");\n const scrollRef = useRef<HTMLDivElement | null>(null);\n const dragStateRef = useRef<{\n pointerId: number;\n startX: number;\n startY: number;\n scrollLeft: number;\n scrollTop: number;\n } | null>(null);\n\n useEffect(() => {\n if (open) setZoom(1);\n setImageStatus(\"loading\");\n }, [open, file?.url]);\n\n const kind = useMemo(() => {\n if (!file) return \"other\";\n if (file.mimeType.startsWith(\"image/\")) return \"image\";\n if (file.mimeType === \"application/pdf\" || file.name.toLowerCase().endsWith(\".pdf\")) return \"pdf\";\n return \"other\";\n }, [file]);\n\n const zoomPercent = Math.round(zoom * 100);\n const isDraggable = kind === \"image\" && zoom > 1;\n\n const handleImagePointerDown = (event: React.PointerEvent<HTMLDivElement>) => {\n if (!isDraggable || !scrollRef.current) return;\n event.preventDefault();\n dragStateRef.current = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n scrollLeft: scrollRef.current.scrollLeft,\n scrollTop: scrollRef.current.scrollTop,\n };\n setDragging(true);\n event.currentTarget.setPointerCapture(event.pointerId);\n };\n\n const handleImagePointerMove = (event: React.PointerEvent<HTMLDivElement>) => {\n const state = dragStateRef.current;\n if (!state || state.pointerId !== event.pointerId || !scrollRef.current) return;\n scrollRef.current.scrollLeft = state.scrollLeft - (event.clientX - state.startX);\n scrollRef.current.scrollTop = state.scrollTop - (event.clientY - state.startY);\n };\n\n const handleImagePointerEnd = (event: React.PointerEvent<HTMLDivElement>) => {\n const state = dragStateRef.current;\n if (!state || state.pointerId !== event.pointerId) return;\n dragStateRef.current = null;\n setDragging(false);\n if (event.currentTarget.hasPointerCapture(event.pointerId)) {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"flex h-[min(88vh,900px)] w-[min(96vw,1100px)] max-w-none flex-col gap-0 overflow-hidden rounded-xl border-border bg-card p-0\">\n <div className=\"flex shrink-0 flex-col gap-3 border-b border-border py-3 pl-4 pr-14 lg:flex-row lg:items-center lg:justify-between\">\n <div className=\"min-w-0 flex-1\">\n <ResponsiveDialogTitle className=\"truncate text-base font-semibold text-foreground\">\n {file?.name ?? \"File preview\"}\n </ResponsiveDialogTitle>\n {file?.sizeLabel ? (\n <p className=\"mt-1 text-xs text-muted-foreground\">{file.sizeLabel}</p>\n ) : null}\n </div>\n {file ? (\n <div className=\"flex shrink-0 flex-wrap items-center gap-1.5 lg:justify-end\">\n {kind === \"image\" ? (\n <div className=\"flex items-center gap-0.5 rounded-lg border border-border bg-background p-0.5\">\n <button\n type=\"button\"\n className=\"inline-flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-40\"\n onClick={() => setZoom((value) => Math.max(0.25, Number((value - 0.25).toFixed(2))))}\n disabled={zoom <= 0.25}\n aria-label=\"Zoom out\"\n >\n <Minus size={14} />\n </button>\n <span className=\"min-w-11 text-center text-xs font-medium tabular-nums text-muted-foreground\">\n {zoomPercent}%\n </span>\n <button\n type=\"button\"\n className=\"inline-flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-40\"\n onClick={() => setZoom((value) => Math.min(4, Number((value + 0.25).toFixed(2))))}\n disabled={zoom >= 4}\n aria-label=\"Zoom in\"\n >\n <Plus size={14} />\n </button>\n <button\n type=\"button\"\n className=\"inline-flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground\"\n onClick={() => setZoom(1)}\n aria-label=\"Reset zoom\"\n >\n <RotateCcw size={14} />\n </button>\n </div>\n ) : null}\n <Button\n asChild\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-9\"\n title=\"Download\"\n >\n <a href={file.url} download={file.name}>\n <Download size={14} />\n <span className=\"sr-only\">Download</span>\n </a>\n </Button>\n <Button\n asChild\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-9\"\n title=\"Open in new tab\"\n >\n <a href={file.url} target=\"_blank\" rel=\"noreferrer\">\n <ExternalLink size={14} />\n <span className=\"sr-only\">Open in new tab</span>\n </a>\n </Button>\n </div>\n ) : null}\n </div>\n <div className=\"min-h-0 flex-1 overflow-hidden bg-muted/60\">\n {!file ? (\n <div className=\"flex h-full items-center justify-center text-sm text-muted-foreground\">\n No file selected.\n </div>\n ) : kind === \"image\" ? (\n <div ref={scrollRef} className=\"h-full overflow-auto p-4\">\n <div\n className=\"flex min-h-full items-center justify-center\"\n style={{ minWidth: `${zoom * 100}%` }}\n onPointerDown={handleImagePointerDown}\n onPointerMove={handleImagePointerMove}\n onPointerUp={handleImagePointerEnd}\n onPointerCancel={handleImagePointerEnd}\n >\n <div className=\"relative flex min-h-[240px] w-full items-center justify-center\">\n {imageStatus !== \"ready\" ? (\n <div\n className=\"absolute inset-0 z-10 flex items-center justify-center\"\n role=\"status\"\n aria-live=\"polite\"\n aria-label={imageStatus === \"error\" ? \"Couldn't load image\" : \"Loading image\"}\n >\n {imageStatus === \"error\" ? (\n <p className=\"text-sm text-muted-foreground\">Couldn't load image</p>\n ) : (\n <Loader2 size={28} className=\"animate-spin text-muted-foreground\" />\n )}\n </div>\n ) : null}\n <img\n src={file.url}\n alt={file.name}\n className={cn(\n \"block shrink-0 select-none rounded-lg border border-border bg-card shadow-sm\",\n imageStatus !== \"ready\" && \"opacity-0\",\n )}\n draggable={false}\n onLoad={() => setImageStatus(\"ready\")}\n onError={() => setImageStatus(\"error\")}\n style={{\n width: `${zoom * 100}%`,\n maxWidth: \"none\",\n cursor: isDraggable ? (dragging ? \"grabbing\" : \"grab\") : \"default\",\n touchAction: isDraggable ? \"none\" : \"auto\",\n }}\n />\n </div>\n </div>\n </div>\n ) : kind === \"pdf\" ? (\n <object data={file.url} type=\"application/pdf\" className=\"h-full w-full\">\n <div className=\"flex h-full flex-col items-center justify-center gap-3 p-6 text-center\">\n <FileText size={34} className=\"text-muted-foreground\" />\n <p className=\"max-w-md text-sm text-muted-foreground\">\n This browser cannot preview the PDF inline. You can still download or open it in a new tab.\n </p>\n </div>\n </object>\n ) : (\n <div className=\"flex h-full flex-col items-center justify-center gap-3 p-6 text-center\">\n <FileText size={34} className=\"text-muted-foreground\" />\n <p className=\"max-w-md text-sm text-muted-foreground\">\n Preview is not available for this file type. Download or open it in a new tab.\n </p>\n </div>\n )}\n </div>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/files/file-viewer-dialog.tsx"],"names":[],"mappings":"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","file":"file-viewer-dialog.js","sourcesContent":["import { useEffect, useMemo, useRef, useState } from \"react\";\nimport { Download, ExternalLink, FileText, Loader2, Minus, Plus, RotateCcw } from \"lucide-react\";\nimport { Button } from \"../ui/button\";\nimport {\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogTitle,\n} from \"../ui/responsive-dialog\";\nimport { cn } from \"../ui/utils\";\n\nexport interface FileViewerFile {\n name: string;\n mimeType: string;\n sizeLabel?: string;\n url: string;\n}\n\nexport function FileViewerDialog({\n file,\n open,\n onOpenChange,\n}: {\n file: FileViewerFile | null;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n const [zoom, setZoom] = useState(1);\n const [dragging, setDragging] = useState(false);\n const [imageStatus, setImageStatus] = useState<\"loading\" | \"ready\" | \"error\">(\"loading\");\n const scrollRef = useRef<HTMLDivElement | null>(null);\n const dragStateRef = useRef<{\n pointerId: number;\n startX: number;\n startY: number;\n scrollLeft: number;\n scrollTop: number;\n } | null>(null);\n\n useEffect(() => {\n if (open) setZoom(1);\n setImageStatus(\"loading\");\n }, [open, file?.url]);\n\n const kind = useMemo(() => {\n if (!file) return \"other\";\n if (file.mimeType.startsWith(\"image/\")) return \"image\";\n if (file.mimeType === \"application/pdf\" || file.name.toLowerCase().endsWith(\".pdf\")) return \"pdf\";\n return \"other\";\n }, [file]);\n\n const zoomPercent = Math.round(zoom * 100);\n const isDraggable = kind === \"image\" && zoom > 1;\n\n const handleImagePointerDown = (event: React.PointerEvent<HTMLDivElement>) => {\n if (!isDraggable || !scrollRef.current) return;\n event.preventDefault();\n dragStateRef.current = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n scrollLeft: scrollRef.current.scrollLeft,\n scrollTop: scrollRef.current.scrollTop,\n };\n setDragging(true);\n event.currentTarget.setPointerCapture(event.pointerId);\n };\n\n const handleImagePointerMove = (event: React.PointerEvent<HTMLDivElement>) => {\n const state = dragStateRef.current;\n if (!state || state.pointerId !== event.pointerId || !scrollRef.current) return;\n scrollRef.current.scrollLeft = state.scrollLeft - (event.clientX - state.startX);\n scrollRef.current.scrollTop = state.scrollTop - (event.clientY - state.startY);\n };\n\n const handleImagePointerEnd = (event: React.PointerEvent<HTMLDivElement>) => {\n const state = dragStateRef.current;\n if (!state || state.pointerId !== event.pointerId) return;\n dragStateRef.current = null;\n setDragging(false);\n if (event.currentTarget.hasPointerCapture(event.pointerId)) {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"flex h-[min(88vh,900px)] w-[min(96vw,1100px)] max-w-none flex-col gap-0 overflow-hidden rounded-xl border-border bg-card p-0\">\n <div className=\"flex shrink-0 flex-col gap-3 border-b border-border py-3 pl-4 pr-14 lg:flex-row lg:items-center lg:justify-between\">\n <div className=\"min-w-0 flex-1\">\n <ResponsiveDialogTitle className=\"truncate text-base font-semibold text-foreground\">\n {file?.name ?? \"File preview\"}\n </ResponsiveDialogTitle>\n {file?.sizeLabel ? (\n <p className=\"mt-1 text-xs text-muted-foreground\">{file.sizeLabel}</p>\n ) : null}\n </div>\n {file ? (\n <div className=\"flex shrink-0 flex-wrap items-center gap-1.5 lg:justify-end\">\n {kind === \"image\" ? (\n <div className=\"flex items-center gap-0.5 rounded-lg border border-border bg-background p-0.5\">\n <button\n type=\"button\"\n className=\"inline-flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-40\"\n onClick={() => setZoom((value) => Math.max(0.25, Number((value - 0.25).toFixed(2))))}\n disabled={zoom <= 0.25}\n aria-label=\"Zoom out\"\n >\n <Minus size={14} />\n </button>\n <span className=\"min-w-11 text-center text-xs font-medium tabular-nums text-muted-foreground\">\n {zoomPercent}%\n </span>\n <button\n type=\"button\"\n className=\"inline-flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-40\"\n onClick={() => setZoom((value) => Math.min(4, Number((value + 0.25).toFixed(2))))}\n disabled={zoom >= 4}\n aria-label=\"Zoom in\"\n >\n <Plus size={14} />\n </button>\n <button\n type=\"button\"\n className=\"inline-flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground\"\n onClick={() => setZoom(1)}\n aria-label=\"Reset zoom\"\n >\n <RotateCcw size={14} />\n </button>\n </div>\n ) : null}\n <Button\n asChild\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-9\"\n title=\"Download\"\n >\n <a href={file.url} download={file.name}>\n <Download size={14} />\n <span className=\"sr-only\">Download</span>\n </a>\n </Button>\n <Button\n asChild\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-9\"\n title=\"Open in new tab\"\n >\n <a href={file.url} target=\"_blank\" rel=\"noreferrer\">\n <ExternalLink size={14} />\n <span className=\"sr-only\">Open in new tab</span>\n </a>\n </Button>\n </div>\n ) : null}\n </div>\n <div className=\"min-h-0 flex-1 overflow-hidden bg-muted/60\">\n {!file ? (\n <div className=\"flex h-full items-center justify-center text-sm text-muted-foreground\">\n No file selected.\n </div>\n ) : kind === \"image\" ? (\n <div ref={scrollRef} className=\"h-full overflow-auto p-4\">\n <div\n className=\"flex min-h-full items-center justify-center\"\n style={{ minWidth: `${zoom * 100}%` }}\n onPointerDown={handleImagePointerDown}\n onPointerMove={handleImagePointerMove}\n onPointerUp={handleImagePointerEnd}\n onPointerCancel={handleImagePointerEnd}\n >\n <div className=\"relative flex min-h-[240px] w-full items-center justify-center\">\n {imageStatus !== \"ready\" ? (\n <div\n className=\"absolute inset-0 z-10 flex items-center justify-center\"\n role=\"status\"\n aria-live=\"polite\"\n aria-label={imageStatus === \"error\" ? \"Couldn't load image\" : \"Loading image\"}\n >\n {imageStatus === \"error\" ? (\n <p className=\"text-sm text-muted-foreground\">Couldn't load image</p>\n ) : (\n <Loader2 size={28} className=\"animate-spin text-muted-foreground\" />\n )}\n </div>\n ) : null}\n <img\n src={file.url}\n alt={file.name}\n className={cn(\n \"block shrink-0 select-none rounded-lg border border-border bg-card shadow-sm\",\n imageStatus !== \"ready\" && \"opacity-0\",\n )}\n draggable={false}\n onLoad={() => setImageStatus(\"ready\")}\n onError={() => setImageStatus(\"error\")}\n style={{\n width: `${zoom * 100}%`,\n maxWidth: \"none\",\n cursor: isDraggable ? (dragging ? \"grabbing\" : \"grab\") : \"default\",\n touchAction: isDraggable ? \"none\" : \"auto\",\n }}\n />\n </div>\n </div>\n </div>\n ) : kind === \"pdf\" ? (\n <object data={file.url} type=\"application/pdf\" className=\"h-full w-full\">\n <div className=\"flex h-full flex-col items-center justify-center gap-3 p-6 text-center\">\n <FileText size={34} className=\"text-muted-foreground\" />\n <p className=\"max-w-md text-sm text-muted-foreground\">\n This browser cannot preview the PDF inline. You can still download or open it in a new tab.\n </p>\n </div>\n </object>\n ) : (\n <div className=\"flex h-full flex-col items-center justify-center gap-3 p-6 text-center\">\n <FileText size={34} className=\"text-muted-foreground\" />\n <p className=\"max-w-md text-sm text-muted-foreground\">\n Preview is not available for this file type. Download or open it in a new tab.\n </p>\n </div>\n )}\n </div>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"]}
|
package/dist/floor-switcher.js
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator } from './chunk-
|
|
2
|
-
import { Label } from './chunk-RV5PMZYZ.js';
|
|
3
|
-
import './chunk-L65F4EMK.js';
|
|
4
|
-
import './chunk-PBNBLCC2.js';
|
|
5
|
-
import './chunk-VVXGQKN7.js';
|
|
6
|
-
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from './chunk-7YCAAP43.js';
|
|
7
|
-
import './chunk-DC4QH6W2.js';
|
|
8
|
-
import { Input } from './chunk-LUB7QWGU.js';
|
|
9
|
-
import { Button } from './chunk-VHINHHZQ.js';
|
|
1
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator } from './chunk-3MAGTCCN.js';
|
|
10
2
|
import { shellTopBarMutedIconClass, shellTopBarSecondaryButtonClass } from './chunk-FCY5FYJB.js';
|
|
3
|
+
import { Input } from './chunk-PPMJZVR4.js';
|
|
4
|
+
import { Button } from './chunk-VHINHHZQ.js';
|
|
11
5
|
import './chunk-OWNUMPUC.js';
|
|
6
|
+
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from './chunk-7YCAAP43.js';
|
|
7
|
+
import { Label } from './chunk-IBGGQXTH.js';
|
|
12
8
|
import { cn } from './chunk-DMPSQ22Q.js';
|
|
13
9
|
import { Layers, ChevronDown, Check, Plus, Trash2 } from 'lucide-react';
|
|
14
10
|
import { useState, useEffect } from 'react';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/live-space/floor-switcher.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/live-space/floor-switcher.tsx"],"names":[],"mappings":"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","file":"floor-switcher.js","sourcesContent":["import { Check, ChevronDown, Layers, Plus, Trash2 } from \"lucide-react\";\nimport { shellTopBarMutedIconClass, shellTopBarSecondaryButtonClass } from \"../shell/shell-top-bar-chrome\";\nimport { Button } from \"../ui/button\";\nimport { cn } from \"../ui/utils\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"../ui/dialog\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"../ui/dropdown-menu\";\nimport { Input } from \"../ui/input\";\nimport { Label } from \"../ui/label\";\nimport { useEffect, useState } from \"react\";\n\nexport interface FloorSwitcherFloor {\n id: string;\n name: string;\n}\n\nexport function FloorSwitcher({\n floors,\n activeFloorId,\n onFloorChange,\n onAddFloor,\n onDeleteFloor,\n}: {\n floors: FloorSwitcherFloor[];\n activeFloorId: string;\n onFloorChange: (floorId: string) => void;\n onAddFloor?: (name: string) => void;\n onDeleteFloor?: (floorId: string) => void;\n}) {\n const activeFloor = floors.find((f) => f.id === activeFloorId) ?? floors[0];\n const [addOpen, setAddOpen] = useState(false);\n const [name, setName] = useState(\"\");\n const canDeleteFloor = Boolean(onDeleteFloor) && floors.length > 1;\n\n useEffect(() => {\n if (addOpen) {\n setName(`Floor ${floors.length + 1}`);\n }\n }, [addOpen, floors.length]);\n\n const handleAdd = () => {\n onAddFloor?.(name.trim() || `Floor ${floors.length + 1}`);\n setAddOpen(false);\n };\n\n return (\n <>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n className={cn(\n shellTopBarSecondaryButtonClass,\n \"min-w-0 max-w-[10rem] outline-none focus-visible:ring-2 focus-visible:ring-blue-500/30\",\n )}\n aria-label=\"Switch floor\"\n >\n <Layers size={12} className={cn(\"shrink-0\", shellTopBarMutedIconClass)} aria-hidden />\n <span className=\"truncate\">{activeFloor?.name ?? \"Floor\"}</span>\n <ChevronDown size={12} className={cn(\"shrink-0\", shellTopBarMutedIconClass)} aria-hidden />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-48\">\n {floors.map((floor) => (\n <DropdownMenuItem\n key={floor.id}\n onClick={() => onFloorChange(floor.id)}\n className=\"flex items-center justify-between gap-2\"\n >\n <span className=\"truncate\">{floor.name}</span>\n {floor.id === activeFloorId ? (\n <Check size={14} className=\"shrink-0 text-blue-600\" aria-hidden />\n ) : (\n <span className=\"size-3.5 shrink-0\" aria-hidden />\n )}\n </DropdownMenuItem>\n ))}\n {onAddFloor || canDeleteFloor ? (\n <>\n <DropdownMenuSeparator />\n {onAddFloor ? (\n <DropdownMenuItem onClick={() => setAddOpen(true)}>\n <Plus size={14} className=\"mr-1.5\" />\n Add floor…\n </DropdownMenuItem>\n ) : null}\n {canDeleteFloor ? (\n <DropdownMenuItem\n variant=\"destructive\"\n onClick={() => onDeleteFloor?.(activeFloorId)}\n >\n <Trash2 size={14} className=\"mr-1.5\" />\n Delete floor…\n </DropdownMenuItem>\n ) : null}\n </>\n ) : null}\n </DropdownMenuContent>\n </DropdownMenu>\n\n {onAddFloor ? (\n <Dialog open={addOpen} onOpenChange={setAddOpen}>\n <DialogContent className=\"sm:max-w-md border-border\">\n <DialogHeader>\n <DialogTitle>Add floor</DialogTitle>\n <DialogDescription>\n Create a new floor with its own resources and 2D layout.\n </DialogDescription>\n </DialogHeader>\n <div className=\"py-1\">\n <Label htmlFor=\"new-floor-name\">Name</Label>\n <Input\n id=\"new-floor-name\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"e.g. Floor 2\"\n className=\"mt-2 h-9\"\n autoFocus\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleAdd();\n }}\n />\n </div>\n <DialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setAddOpen(false)}>\n Cancel\n </Button>\n <Button type=\"button\" onClick={handleAdd}>\n Add floor\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n ) : null}\n </>\n );\n}\n"]}
|
|
@@ -54,12 +54,16 @@ interface LayoutCanvasViewProps {
|
|
|
54
54
|
/** Occupancy green/red dots. Off for booking pickers. */
|
|
55
55
|
showStatusDot?: boolean;
|
|
56
56
|
selectedIds?: string[];
|
|
57
|
+
/** Label for the highlighted resource (shown in the clear-highlight banner). */
|
|
58
|
+
highlightLabel?: string;
|
|
59
|
+
/** Clears URL / selection highlight (member live space). */
|
|
60
|
+
onClearHighlight?: () => void;
|
|
57
61
|
/** Rendered on the left of the zoom toolbar (e.g. floor select). */
|
|
58
62
|
toolbarStart?: ReactNode;
|
|
59
63
|
className?: string;
|
|
60
64
|
viewportClassName?: string;
|
|
61
65
|
}
|
|
62
66
|
declare function matchesCanvasResourceSearch(resourceName: string, planName: string | undefined, query: string): boolean;
|
|
63
|
-
declare function LayoutCanvasView({ layout, rows, onResourceSelect, resourceQuickBook, searchQuery, onSearchQueryChange, searchPlaceholder, showStatusDot, selectedIds, toolbarStart, className, viewportClassName, }: LayoutCanvasViewProps): React.JSX.Element;
|
|
67
|
+
declare function LayoutCanvasView({ layout, rows, onResourceSelect, resourceQuickBook, searchQuery, onSearchQueryChange, searchPlaceholder, showStatusDot, selectedIds, highlightLabel, onClearHighlight, toolbarStart, className, viewportClassName, }: LayoutCanvasViewProps): React.JSX.Element;
|
|
64
68
|
|
|
65
69
|
export { type LayoutCanvasFloorLayout as L, type LayoutCanvasViewRow as a, type LayoutCanvasResourceQuickBook as b, LayoutCanvasView as c, type LayoutCanvasViewProps as d, matchesCanvasResourceSearch as m };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import 'react';
|
|
2
|
-
export { b as LayoutCanvasResourceQuickBook, c as LayoutCanvasView, d as LayoutCanvasViewProps, a as LayoutCanvasViewRow, m as matchesCanvasResourceSearch } from './layout-canvas-view-
|
|
2
|
+
export { b as LayoutCanvasResourceQuickBook, c as LayoutCanvasView, d as LayoutCanvasViewProps, a as LayoutCanvasViewRow, m as matchesCanvasResourceSearch } from './layout-canvas-view-C3u96xu4.js';
|
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
export { LayoutCanvasView, matchesCanvasResourceSearch } from './chunk-
|
|
1
|
+
export { LayoutCanvasView, matchesCanvasResourceSearch } from './chunk-KXTYPZDK.js';
|
|
2
2
|
import './chunk-XU3EFSQX.js';
|
|
3
3
|
import './chunk-4Y5DBM6Z.js';
|
|
4
4
|
import './chunk-ZIJQ7BXU.js';
|
|
5
|
-
import './chunk-
|
|
6
|
-
import './chunk-
|
|
7
|
-
import './chunk-
|
|
8
|
-
import './chunk-
|
|
9
|
-
import './chunk-VVXGQKN7.js';
|
|
10
|
-
import './chunk-7YCAAP43.js';
|
|
11
|
-
import './chunk-DC4QH6W2.js';
|
|
12
|
-
import './chunk-H7EX6B6N.js';
|
|
13
|
-
import './chunk-LUB7QWGU.js';
|
|
14
|
-
import './chunk-VHINHHZQ.js';
|
|
5
|
+
import './chunk-AHFRK6KP.js';
|
|
6
|
+
import './chunk-CXXOKCLJ.js';
|
|
7
|
+
import './chunk-BQVMO33N.js';
|
|
8
|
+
import './chunk-VIJ2HWPZ.js';
|
|
15
9
|
import './chunk-FCY5FYJB.js';
|
|
10
|
+
import './chunk-XDVGFHK4.js';
|
|
11
|
+
import './chunk-PPMJZVR4.js';
|
|
12
|
+
import './chunk-VHINHHZQ.js';
|
|
16
13
|
import './chunk-OWNUMPUC.js';
|
|
17
14
|
import './chunk-DMPSQ22Q.js';
|
|
18
15
|
//# sourceMappingURL=layout-canvas-view.js.map
|
|
@@ -20,5 +20,20 @@ declare function formatDate(date: Date): string;
|
|
|
20
20
|
* Uses elapsed wall time from `now` (defaults to current time). Returns "" if `iso` is unparseable.
|
|
21
21
|
*/
|
|
22
22
|
declare function formatRelativeTimeAgo(iso: string, now?: Date): string;
|
|
23
|
+
type RelativeWhenKind = "created" | "event" | "deadline";
|
|
24
|
+
type RelativeWhenTone = "muted" | "current" | "danger" | "warning" | "success";
|
|
25
|
+
type RelativeWhenResult = {
|
|
26
|
+
label: string;
|
|
27
|
+
absolute: string;
|
|
28
|
+
diffDays: number;
|
|
29
|
+
isCurrent: boolean;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Stacked relative + absolute date for list cells.
|
|
33
|
+
* Accepts `YYYY-MM-DD` (calendar day) or an ISO timestamp.
|
|
34
|
+
*/
|
|
35
|
+
declare function formatRelativeWhen(value: string, now?: Date): RelativeWhenResult | null;
|
|
36
|
+
/** Text tone for a relative-when cell. `diffDays` is calendar days (value − today). */
|
|
37
|
+
declare function relativeWhenTone(kind: RelativeWhenKind, diffDays: number): RelativeWhenTone;
|
|
23
38
|
|
|
24
|
-
export { addWallClockMinutes, formatCalendarDate, formatDate, formatRelativeTimeAgo, formatWallClockTime, isSameDay, parseWallClockHm, toDateStr, toWallClockHmStr };
|
|
39
|
+
export { type RelativeWhenKind, type RelativeWhenResult, type RelativeWhenTone, addWallClockMinutes, formatCalendarDate, formatDate, formatRelativeTimeAgo, formatRelativeWhen, formatWallClockTime, isSameDay, parseWallClockHm, relativeWhenTone, toDateStr, toWallClockHmStr };
|
package/dist/lib/dateDisplay.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { addWallClockMinutes, formatCalendarDate, formatDate, formatRelativeTimeAgo, formatWallClockTime, isSameDay, parseWallClockHm, toDateStr, toWallClockHmStr } from '../chunk-
|
|
1
|
+
export { addWallClockMinutes, formatCalendarDate, formatDate, formatRelativeTimeAgo, formatRelativeWhen, formatWallClockTime, isSameDay, parseWallClockHm, relativeWhenTone, toDateStr, toWallClockHmStr } from '../chunk-ZVWUPYSV.js';
|
|
2
2
|
//# sourceMappingURL=dateDisplay.js.map
|
|
3
3
|
//# sourceMappingURL=dateDisplay.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HoverCard, HoverCardTrigger, HoverCardContent } from './chunk-L65F4EMK.js';
|
|
2
|
-
import { formatRelativeTimeAgo } from './chunk-
|
|
2
|
+
import { formatRelativeTimeAgo } from './chunk-ZVWUPYSV.js';
|
|
3
3
|
import { cn } from './chunk-DMPSQ22Q.js';
|
|
4
4
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
@@ -40,10 +40,12 @@ declare function PageListToolbar({ className, ...props }: React.ComponentProps<"
|
|
|
40
40
|
/** Compact KPI tiles (Live space stat row). */
|
|
41
41
|
declare function PageListStatGrid({ className, ...props }: React.ComponentProps<"div">): React$1.JSX.Element;
|
|
42
42
|
type PageListStatTone = "default" | "danger" | "success";
|
|
43
|
-
declare function PageListStatCard({ label, value, tone, }: {
|
|
43
|
+
declare function PageListStatCard({ label, value, tone, onClick, action, }: {
|
|
44
44
|
label: string;
|
|
45
45
|
value: ReactNode;
|
|
46
46
|
tone?: PageListStatTone;
|
|
47
|
+
onClick?: () => void;
|
|
48
|
+
action?: ReactNode;
|
|
47
49
|
}): React$1.JSX.Element;
|
|
48
50
|
/** Scrollable white region for tables / lists. Stay flush horizontally; table cells provide inset (same as Live space). */
|
|
49
51
|
declare function PageListTableArea({ className, ...props }: React.ComponentProps<"div">): React$1.JSX.Element;
|
package/dist/page-list-chrome.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
export { DetailSection, DetailTableFrame, PageListEmptyState, PageListHeader, PageListHeaderRow, PageListPagination, PageListPrimaryActionButton, PageListRoot, PageListSearchField, PageListSecondaryActionButton, PageListSortableTh, PageListStatCard, PageListStatGrid, PageListStickyThead, PageListTable, PageListTableArea, PageListTd, PageListTh, PageListThead, PageListTitleRow, PageListToolbar, PageListTr, ShellTopBarPrimaryActionButton, ShellTopBarSecondaryActionButton, pageListStickyColumnClass, pageListTableWithFixedColumnsClass, pageListTdClass, pageListThClass } from './chunk-
|
|
2
|
-
import './chunk-
|
|
3
|
-
import './chunk-
|
|
1
|
+
export { DetailSection, DetailTableFrame, PageListEmptyState, PageListHeader, PageListHeaderRow, PageListPagination, PageListPrimaryActionButton, PageListRoot, PageListSearchField, PageListSecondaryActionButton, PageListSortableTh, PageListStatCard, PageListStatGrid, PageListStickyThead, PageListTable, PageListTableArea, PageListTd, PageListTh, PageListThead, PageListTitleRow, PageListToolbar, PageListTr, ShellTopBarPrimaryActionButton, ShellTopBarSecondaryActionButton, pageListStickyColumnClass, pageListTableWithFixedColumnsClass, pageListTdClass, pageListThClass } from './chunk-AHFRK6KP.js';
|
|
2
|
+
import './chunk-BQVMO33N.js';
|
|
3
|
+
import './chunk-VIJ2HWPZ.js';
|
|
4
4
|
export { shellTopBarNeutralActionDataAttr } from './chunk-FCY5FYJB.js';
|
|
5
|
+
import './chunk-PPMJZVR4.js';
|
|
6
|
+
import './chunk-VHINHHZQ.js';
|
|
5
7
|
import './chunk-OWNUMPUC.js';
|
|
6
8
|
import './chunk-DMPSQ22Q.js';
|
|
7
9
|
//# sourceMappingURL=page-list-chrome.js.map
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { PageListTable, PageListStickyThead, PageListHeaderRow, PageListTh, PageListTr, PageListTd } from './chunk-AHFRK6KP.js';
|
|
2
|
+
import './chunk-BQVMO33N.js';
|
|
3
|
+
import './chunk-VIJ2HWPZ.js';
|
|
4
|
+
import './chunk-FCY5FYJB.js';
|
|
1
5
|
import { Skeleton } from './chunk-DC4QH6W2.js';
|
|
2
|
-
import
|
|
3
|
-
import './chunk-LUB7QWGU.js';
|
|
6
|
+
import './chunk-PPMJZVR4.js';
|
|
4
7
|
import './chunk-VHINHHZQ.js';
|
|
5
|
-
import './chunk-FCY5FYJB.js';
|
|
6
8
|
import './chunk-OWNUMPUC.js';
|
|
7
9
|
import './chunk-DMPSQ22Q.js';
|
|
8
10
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shell/page-list-loading.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/shell/page-list-loading.tsx"],"names":[],"mappings":"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","file":"page-list-loading.js","sourcesContent":["import type { ReactNode } from \"react\";\nimport { Skeleton } from \"../ui/skeleton\";\nimport {\n PageListHeaderRow,\n PageListStickyThead,\n PageListTable,\n PageListTd,\n PageListTh,\n PageListTr,\n} from \"./page-list-chrome\";\n\nexport type PageListSkeletonCell =\n | \"text\"\n | \"pill\"\n | \"avatar\"\n | \"actions\"\n | \"empty\"\n | \"checkbox\"\n | \"titleBody\";\n\nexport type PageListSkeletonColumn = {\n label?: ReactNode;\n align?: \"left\" | \"right\";\n cell: PageListSkeletonCell;\n className?: string;\n hidden?: boolean;\n};\n\nconst TEXT_WIDTHS = [\"w-28\", \"w-20\", \"w-24\", \"w-32\", \"w-16\"] as const;\n\nexport function StatValueSkeleton() {\n return (\n <span className=\"inline-flex h-5 items-center\" role=\"status\" aria-busy=\"true\" aria-label=\"Loading\">\n <Skeleton className=\"h-4 w-10\" />\n <span className=\"sr-only\">Loading</span>\n </span>\n );\n}\n\nfunction SkeletonCell({ cell, row, align }: { cell: PageListSkeletonCell; row: number; align?: \"left\" | \"right\" }) {\n switch (cell) {\n case \"checkbox\":\n return <Skeleton className=\"size-4 rounded\" />;\n case \"avatar\":\n return (\n <span className=\"inline-flex items-center gap-2.5\">\n <Skeleton className=\"size-7 shrink-0 rounded-full\" />\n <Skeleton className={`h-3.5 ${TEXT_WIDTHS[row % TEXT_WIDTHS.length]}`} />\n </span>\n );\n case \"pill\":\n return <Skeleton className=\"h-5 w-16 rounded-full\" />;\n case \"actions\":\n return (\n <div className={`inline-flex gap-2 ${align === \"right\" ? \"justify-end\" : \"\"}`}>\n <Skeleton className=\"h-7 w-16 rounded-lg\" />\n {row % 3 !== 0 ? <Skeleton className=\"h-7 w-14 rounded-lg\" /> : null}\n </div>\n );\n case \"titleBody\":\n return (\n <div className=\"flex items-start gap-3 min-w-0\">\n <Skeleton className=\"mt-1.5 h-2 w-2 shrink-0 rounded-full\" />\n <div className=\"min-w-0 space-y-1.5\">\n <Skeleton className={`h-3.5 ${row % 2 === 0 ? \"w-40\" : \"w-32\"}`} />\n <Skeleton className={`h-3 ${row % 3 === 0 ? \"w-56\" : \"w-44\"}`} />\n </div>\n </div>\n );\n case \"empty\":\n return null;\n default:\n return (\n <Skeleton\n className={`h-3.5 ${TEXT_WIDTHS[row % TEXT_WIDTHS.length]} ${align === \"right\" ? \"ml-auto\" : \"\"}`}\n />\n );\n }\n}\n\nexport function PageListTableSkeleton({\n columns,\n rows = 8,\n label = \"Loading\",\n minWidth,\n}: {\n columns: PageListSkeletonColumn[];\n rows?: number;\n label?: string;\n minWidth?: number;\n}) {\n const visible = columns.filter((column) => !column.hidden);\n\n return (\n <div role=\"status\" aria-busy=\"true\" aria-label={label}>\n <PageListTable minWidth={minWidth}>\n <PageListStickyThead>\n <PageListHeaderRow>\n {visible.map((column, i) => (\n <PageListTh\n key={i}\n align={column.align}\n className={column.className}\n aria-hidden={column.label == null ? true : undefined}\n >\n {column.label}\n </PageListTh>\n ))}\n </PageListHeaderRow>\n </PageListStickyThead>\n <tbody>\n {Array.from({ length: rows }, (_, row) => (\n <PageListTr key={row}>\n {visible.map((column, i) => (\n <PageListTd key={i} align={column.align} className={column.className}>\n <SkeletonCell cell={column.cell} row={row} align={column.align} />\n </PageListTd>\n ))}\n </PageListTr>\n ))}\n </tbody>\n </PageListTable>\n <span className=\"sr-only\">{label}</span>\n </div>\n );\n}\n"]}
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import { FilePickerField } from './chunk-OMSJWTSZ.js';
|
|
2
|
-
import {
|
|
3
|
-
import './chunk-
|
|
4
|
-
import './chunk-L65F4EMK.js';
|
|
5
|
-
import './chunk-PBNBLCC2.js';
|
|
6
|
-
import './chunk-VVXGQKN7.js';
|
|
7
|
-
import './chunk-7YCAAP43.js';
|
|
8
|
-
import './chunk-DC4QH6W2.js';
|
|
9
|
-
import './chunk-LUB7QWGU.js';
|
|
2
|
+
import { Textarea } from './chunk-VQ63T7CJ.js';
|
|
3
|
+
import { Tooltip, TooltipTrigger, TooltipContent } from './chunk-XDVGFHK4.js';
|
|
10
4
|
import { Button } from './chunk-VHINHHZQ.js';
|
|
11
|
-
import './chunk-FCY5FYJB.js';
|
|
12
|
-
import './chunk-OWNUMPUC.js';
|
|
13
5
|
import { cn } from './chunk-DMPSQ22Q.js';
|
|
14
6
|
import { useState, useCallback } from 'react';
|
|
15
7
|
import { Paperclip, X, Image, FileText, Plus, Send } from 'lucide-react';
|