efficient-shell 4.134.0 → 4.137.1
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/LICENSE +6 -17
- package/README.md +84 -8
- package/dist/Browser-ZX5OTOKK.js +43 -0
- package/dist/Calculator-4SQGOQFQ.js +29 -0
- package/dist/ConfirmDialog-NPKW2XHM.js +1 -0
- package/dist/CurrencyConverter-2KOM7L6V.js +21 -0
- package/dist/Documents-IZTIQYPG.js +52 -0
- package/dist/Files-B63KKXGZ.js +89 -0
- package/dist/Notepad-WA77V45J.js +25 -0
- package/dist/PdfViewer-RBRGEKWF.js +1 -0
- package/dist/PomodoroTimer-SDUBKXUS.js +99 -0
- package/dist/Preview-D4KOA4OI.js +187 -0
- package/dist/Sidebar-Y57LYXXI.js +23 -0
- package/dist/Spreadsheet-JX5E6WH6.js +37 -0
- package/dist/Stock-XAQ5WMUZ.js +16 -0
- package/dist/Weather-HLAGJ5LV.js +60 -0
- package/dist/WorldClock-IRI4VCTA.js +32 -0
- package/dist/apps/index.js +1 -151
- package/dist/brand.css +1 -1
- package/dist/chunk-3A46NCXK.js +29 -0
- package/dist/chunk-44UO7FYU.js +11 -0
- package/dist/chunk-466CM2TJ.js +1 -0
- package/dist/chunk-57MIENLJ.js +1 -0
- package/dist/chunk-5CRAF2AD.js +2 -0
- package/dist/chunk-A2OQLLYK.js +6 -0
- package/dist/chunk-B43AGQET.js +4 -0
- package/dist/chunk-BR22X7E5.js +1 -0
- package/dist/chunk-BUTSU7FO.js +1 -0
- package/dist/chunk-D65T4H6J.js +1 -0
- package/dist/chunk-ESL5TDNA.js +1 -0
- package/dist/chunk-FBDZGO3V.js +1 -0
- package/dist/chunk-FHTLC7HH.js +1 -0
- package/dist/chunk-FQLMX3IE.js +948 -0
- package/dist/chunk-H562R4GX.js +34 -0
- package/dist/chunk-JN4WXTWJ.js +106 -0
- package/dist/chunk-LVDRBRYU.js +1 -0
- package/dist/chunk-LWLCNQY7.js +1 -0
- package/dist/chunk-MAIHBBWT.js +1 -0
- package/dist/chunk-NPJH5MD7.js +13 -0
- package/dist/chunk-OCSOMMY2.js +1 -0
- package/dist/chunk-OQDWLHZI.js +1 -0
- package/dist/chunk-OWSAMA3I.js +23 -0
- package/dist/chunk-PH3PRIFP.js +5 -0
- package/dist/chunk-TAWKWSPN.js +9 -0
- package/dist/chunk-U4GTZPXP.js +1 -0
- package/dist/chunk-UB4JIOLD.js +2 -0
- package/dist/chunk-UZAJ5BF6.js +9 -0
- package/dist/chunk-VEGMDXT4.js +1 -0
- package/dist/chunk-VTVSMRFX.js +1 -0
- package/dist/chunk-VVAGSKW7.js +1 -0
- package/dist/chunk-XO43FJRM.js +19 -0
- package/dist/chunk-Y7BOLDRM.js +69 -0
- package/dist/file-intake/index.js +1 -4
- package/dist/{index-DZ7E7bCl.d.ts → index-DVI9DMSu.d.ts} +189 -18
- package/dist/index.d.ts +2 -2
- package/dist/index.js +639 -7473
- package/dist/map/index.js +20 -540
- package/dist/markdown/index.js +6 -184
- package/dist/markup/index.js +1 -135
- package/dist/page-tabs/index.js +21 -709
- package/dist/sounds-OMHXVVQ4.js +1 -0
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +1 -19
- package/dist/ui.css +78 -10
- package/package.json +4 -3
- package/dist/Browser-O3QZGUF2.js +0 -482
- package/dist/Browser-O3QZGUF2.js.map +0 -1
- package/dist/Calculator-L6N5X3KU.js +0 -192
- package/dist/Calculator-L6N5X3KU.js.map +0 -1
- package/dist/ConfirmDialog-LYSSZSUD.js +0 -4
- package/dist/ConfirmDialog-LYSSZSUD.js.map +0 -1
- package/dist/CurrencyConverter-64MKXB3D.js +0 -236
- package/dist/CurrencyConverter-64MKXB3D.js.map +0 -1
- package/dist/Documents-5WXXYCLI.js +0 -441
- package/dist/Documents-5WXXYCLI.js.map +0 -1
- package/dist/Files-AUURUUDN.js +0 -805
- package/dist/Files-AUURUUDN.js.map +0 -1
- package/dist/Notepad-GPXJVPB7.js +0 -410
- package/dist/Notepad-GPXJVPB7.js.map +0 -1
- package/dist/PdfViewer-HKO6P4SR.js +0 -5
- package/dist/PdfViewer-HKO6P4SR.js.map +0 -1
- package/dist/PomodoroTimer-4TQBWLP2.js +0 -633
- package/dist/PomodoroTimer-4TQBWLP2.js.map +0 -1
- package/dist/Preview-FOZYPKM2.js +0 -2959
- package/dist/Preview-FOZYPKM2.js.map +0 -1
- package/dist/Sidebar-BPU7RCZP.js +0 -291
- package/dist/Sidebar-BPU7RCZP.js.map +0 -1
- package/dist/Spreadsheet-3C66BBBF.js +0 -519
- package/dist/Spreadsheet-3C66BBBF.js.map +0 -1
- package/dist/Stock-IF4IHYLU.js +0 -158
- package/dist/Stock-IF4IHYLU.js.map +0 -1
- package/dist/Weather-725PFR7T.js +0 -431
- package/dist/Weather-725PFR7T.js.map +0 -1
- package/dist/WorldClock-UU4NZIQ7.js +0 -202
- package/dist/WorldClock-UU4NZIQ7.js.map +0 -1
- package/dist/apps/index.js.map +0 -1
- package/dist/chunk-2TPTHAKI.js +0 -316
- package/dist/chunk-2TPTHAKI.js.map +0 -1
- package/dist/chunk-4P44JXDS.js +0 -195
- package/dist/chunk-4P44JXDS.js.map +0 -1
- package/dist/chunk-5O42JXQE.js +0 -26
- package/dist/chunk-5O42JXQE.js.map +0 -1
- package/dist/chunk-72CQWN7O.js +0 -547
- package/dist/chunk-72CQWN7O.js.map +0 -1
- package/dist/chunk-7CCHEEYC.js +0 -94
- package/dist/chunk-7CCHEEYC.js.map +0 -1
- package/dist/chunk-BE7FZOFU.js +0 -17
- package/dist/chunk-BE7FZOFU.js.map +0 -1
- package/dist/chunk-D276EMXS.js +0 -57
- package/dist/chunk-D276EMXS.js.map +0 -1
- package/dist/chunk-D7PYW2QS.js +0 -265
- package/dist/chunk-D7PYW2QS.js.map +0 -1
- package/dist/chunk-DVZWYWSD.js +0 -26
- package/dist/chunk-DVZWYWSD.js.map +0 -1
- package/dist/chunk-ET6ID4LP.js +0 -102
- package/dist/chunk-ET6ID4LP.js.map +0 -1
- package/dist/chunk-GA35NEND.js +0 -56
- package/dist/chunk-GA35NEND.js.map +0 -1
- package/dist/chunk-GIGV2ZRW.js +0 -70
- package/dist/chunk-GIGV2ZRW.js.map +0 -1
- package/dist/chunk-IPXN646P.js +0 -14
- package/dist/chunk-IPXN646P.js.map +0 -1
- package/dist/chunk-IRWSRJ4K.js +0 -48
- package/dist/chunk-IRWSRJ4K.js.map +0 -1
- package/dist/chunk-IULP5BCD.js +0 -79
- package/dist/chunk-IULP5BCD.js.map +0 -1
- package/dist/chunk-MGGY74RY.js +0 -14
- package/dist/chunk-MGGY74RY.js.map +0 -1
- package/dist/chunk-OLJDJYSU.js +0 -13678
- package/dist/chunk-OLJDJYSU.js.map +0 -1
- package/dist/chunk-PIGDNN5F.js +0 -46
- package/dist/chunk-PIGDNN5F.js.map +0 -1
- package/dist/chunk-Q2MJVSJT.js +0 -7
- package/dist/chunk-Q2MJVSJT.js.map +0 -1
- package/dist/chunk-Q3LT745N.js +0 -3710
- package/dist/chunk-Q3LT745N.js.map +0 -1
- package/dist/chunk-QAGQRNKI.js +0 -145
- package/dist/chunk-QAGQRNKI.js.map +0 -1
- package/dist/chunk-QRL64J5F.js +0 -503
- package/dist/chunk-QRL64J5F.js.map +0 -1
- package/dist/chunk-QSKCQUZE.js +0 -1103
- package/dist/chunk-QSKCQUZE.js.map +0 -1
- package/dist/chunk-R4OQIQYX.js +0 -153
- package/dist/chunk-R4OQIQYX.js.map +0 -1
- package/dist/chunk-RT6DSB5Y.js +0 -143
- package/dist/chunk-RT6DSB5Y.js.map +0 -1
- package/dist/chunk-SHQM5CK3.js +0 -549
- package/dist/chunk-SHQM5CK3.js.map +0 -1
- package/dist/chunk-T4VQHMG4.js +0 -822
- package/dist/chunk-T4VQHMG4.js.map +0 -1
- package/dist/chunk-TRCWINHF.js +0 -105
- package/dist/chunk-TRCWINHF.js.map +0 -1
- package/dist/chunk-TW7LPMVR.js +0 -16
- package/dist/chunk-TW7LPMVR.js.map +0 -1
- package/dist/chunk-W622KQTD.js +0 -465
- package/dist/chunk-W622KQTD.js.map +0 -1
- package/dist/chunk-X4Q6G253.js +0 -416
- package/dist/chunk-X4Q6G253.js.map +0 -1
- package/dist/chunk-YNKK7NE3.js +0 -171
- package/dist/chunk-YNKK7NE3.js.map +0 -1
- package/dist/chunk-YPO6RDMX.js +0 -20
- package/dist/chunk-YPO6RDMX.js.map +0 -1
- package/dist/file-intake/index.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/map/index.js.map +0 -1
- package/dist/markdown/index.js.map +0 -1
- package/dist/markup/index.js.map +0 -1
- package/dist/page-tabs/index.js.map +0 -1
- package/dist/sounds-NT4DEZGD.js +0 -3
- package/dist/sounds-NT4DEZGD.js.map +0 -1
- package/dist/ui/index.js.map +0 -1
package/dist/page-tabs/index.js
CHANGED
|
@@ -1,710 +1,22 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
var
|
|
23
|
-
function orderPinned(tabs, pinnedKeys) {
|
|
24
|
-
const pinned = pinnedKeys.map((key) => tabs.find((t) => t.key === key)).filter((t) => Boolean(t));
|
|
25
|
-
return [...pinned, ...tabs.filter((t) => !pinnedKeys.includes(t.key))];
|
|
26
|
-
}
|
|
27
|
-
function visit(state, entry, maxTabs = DEFAULT_MAX_TABS) {
|
|
28
|
-
const clock = state.clock + 1;
|
|
29
|
-
const existing = state.tabs.find((t) => t.key === entry.key);
|
|
30
|
-
let tabs;
|
|
31
|
-
if (existing) {
|
|
32
|
-
tabs = state.tabs.map(
|
|
33
|
-
(t) => t.key === entry.key ? {
|
|
34
|
-
...t,
|
|
35
|
-
path: entry.path,
|
|
36
|
-
title: t.titleFrom === "page" ? t.title : entry.title || t.title,
|
|
37
|
-
lastActive: clock
|
|
38
|
-
} : t
|
|
39
|
-
);
|
|
40
|
-
} else {
|
|
41
|
-
tabs = [
|
|
42
|
-
...state.tabs,
|
|
43
|
-
{ key: entry.key, path: entry.path, title: entry.title, titleFrom: "route", pinned: false, lastActive: clock }
|
|
44
|
-
];
|
|
45
|
-
}
|
|
46
|
-
let next = {
|
|
47
|
-
...state,
|
|
48
|
-
tabs,
|
|
49
|
-
activeKey: entry.key,
|
|
50
|
-
mounted: withKey(state.mounted, entry.key),
|
|
51
|
-
clock
|
|
52
|
-
};
|
|
53
|
-
if (next.closing && next.closing !== entry.key) next = removeTab(next, next.closing);
|
|
54
|
-
else if (next.closing === entry.key) next = { ...next, closing: null };
|
|
55
|
-
return evictOverflow(next, maxTabs);
|
|
56
|
-
}
|
|
57
|
-
function visitTransient(state) {
|
|
58
|
-
let next = { ...state, activeKey: null };
|
|
59
|
-
if (next.closing) next = removeTab(next, next.closing);
|
|
60
|
-
return next;
|
|
61
|
-
}
|
|
62
|
-
function evictOverflow(state, maxTabs) {
|
|
63
|
-
let next = state;
|
|
64
|
-
while (next.tabs.length > maxTabs) {
|
|
65
|
-
const candidates = next.tabs.filter((t) => !t.pinned && t.key !== next.activeKey && !next.dirty.includes(t.key) && t.key !== next.closing).sort((a, b) => a.lastActive - b.lastActive);
|
|
66
|
-
if (candidates.length === 0) break;
|
|
67
|
-
next = removeTab(next, candidates[0].key);
|
|
68
|
-
}
|
|
69
|
-
return next;
|
|
70
|
-
}
|
|
71
|
-
function removeTab(state, key) {
|
|
72
|
-
return {
|
|
73
|
-
...state,
|
|
74
|
-
tabs: state.tabs.filter((t) => t.key !== key),
|
|
75
|
-
mounted: without(state.mounted, key),
|
|
76
|
-
dirty: without(state.dirty, key),
|
|
77
|
-
activeKey: state.activeKey === key ? null : state.activeKey,
|
|
78
|
-
closing: state.closing === key ? null : state.closing
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
function neighbourOf(state, key) {
|
|
82
|
-
const visible = state.tabs.filter((t) => t.key !== state.closing || t.key === key);
|
|
83
|
-
const i = visible.findIndex((t) => t.key === key);
|
|
84
|
-
if (i < 0) return null;
|
|
85
|
-
return visible[i + 1] ?? visible[i - 1] ?? null;
|
|
86
|
-
}
|
|
87
|
-
function beginClose(state, key) {
|
|
88
|
-
return { ...state, closing: key };
|
|
89
|
-
}
|
|
90
|
-
function keysToClose(state, scope, key) {
|
|
91
|
-
const closable = state.tabs.filter((t) => !t.pinned);
|
|
92
|
-
if (scope === "all") return closable.map((t) => t.key);
|
|
93
|
-
if (scope === "others") return closable.filter((t) => t.key !== key).map((t) => t.key);
|
|
94
|
-
const i = state.tabs.findIndex((t) => t.key === key);
|
|
95
|
-
if (i < 0) return [];
|
|
96
|
-
return state.tabs.slice(i + 1).filter((t) => !t.pinned).map((t) => t.key);
|
|
97
|
-
}
|
|
98
|
-
function setTitle(state, key, title) {
|
|
99
|
-
const tab = state.tabs.find((t) => t.key === key);
|
|
100
|
-
if (!tab || !title || tab.title === title && tab.titleFrom === "page") return state;
|
|
101
|
-
return {
|
|
102
|
-
...state,
|
|
103
|
-
tabs: state.tabs.map((t) => t.key === key ? { ...t, title, titleFrom: "page" } : t)
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
function setDirty(state, key, dirty) {
|
|
107
|
-
const has = state.dirty.includes(key);
|
|
108
|
-
if (dirty === has) return state;
|
|
109
|
-
return { ...state, dirty: dirty ? [...state.dirty, key] : without(state.dirty, key) };
|
|
110
|
-
}
|
|
111
|
-
function ensurePinned(state, pinned) {
|
|
112
|
-
const pinnedKeys = pinned.map((p) => p.key);
|
|
113
|
-
let tabs = state.tabs.map((t) => ({ ...t, pinned: pinnedKeys.includes(t.key) }));
|
|
114
|
-
for (const p of pinned) {
|
|
115
|
-
if (!tabs.some((t) => t.key === p.key)) {
|
|
116
|
-
tabs = [...tabs, { key: p.key, path: p.path, title: p.title, titleFrom: "route", pinned: true, lastActive: 0 }];
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return { ...state, tabs: orderPinned(tabs, pinnedKeys) };
|
|
120
|
-
}
|
|
121
|
-
function serialize(state) {
|
|
122
|
-
const stored = {
|
|
123
|
-
v: 1,
|
|
124
|
-
tabs: state.tabs.filter((t) => t.key !== state.closing).map(({ key, path, title, titleFrom }) => ({ key, path, title, titleFrom }))
|
|
125
|
-
};
|
|
126
|
-
return JSON.stringify(stored);
|
|
127
|
-
}
|
|
128
|
-
function restore(raw, resolve) {
|
|
129
|
-
if (!raw) return [];
|
|
130
|
-
let parsed;
|
|
131
|
-
try {
|
|
132
|
-
parsed = JSON.parse(raw);
|
|
133
|
-
} catch {
|
|
134
|
-
return [];
|
|
135
|
-
}
|
|
136
|
-
const stored = parsed;
|
|
137
|
-
if (!stored || stored.v !== 1 || !Array.isArray(stored.tabs)) return [];
|
|
138
|
-
const out = [];
|
|
139
|
-
for (const item of stored.tabs) {
|
|
140
|
-
if (!item || typeof item.path !== "string" || !item.path.startsWith("/") || item.path.startsWith("//")) continue;
|
|
141
|
-
const hashAt = item.path.indexOf("#");
|
|
142
|
-
const path = hashAt >= 0 ? item.path.slice(0, hashAt) : item.path;
|
|
143
|
-
const entry = resolve(path);
|
|
144
|
-
if (!entry || out.some((t) => t.key === entry.key)) continue;
|
|
145
|
-
const pageTitle = item.titleFrom === "page" && typeof item.title === "string" && item.title;
|
|
146
|
-
out.push({
|
|
147
|
-
key: entry.key,
|
|
148
|
-
path,
|
|
149
|
-
title: pageTitle || entry.title,
|
|
150
|
-
titleFrom: pageTitle ? "page" : "route",
|
|
151
|
-
pinned: false,
|
|
152
|
-
lastActive: 0
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
return out;
|
|
156
|
-
}
|
|
157
|
-
function reducer(state, action) {
|
|
158
|
-
switch (action.type) {
|
|
159
|
-
case "visit":
|
|
160
|
-
return visit(state, action.entry, action.maxTabs);
|
|
161
|
-
case "transient":
|
|
162
|
-
return visitTransient(state);
|
|
163
|
-
case "close": {
|
|
164
|
-
let next = state;
|
|
165
|
-
for (const key of action.keys) next = removeTab(next, key);
|
|
166
|
-
return action.closing ? beginClose(next, action.closing) : next;
|
|
167
|
-
}
|
|
168
|
-
case "title":
|
|
169
|
-
return setTitle(state, action.key, action.title);
|
|
170
|
-
case "dirty":
|
|
171
|
-
return setDirty(state, action.key, action.dirty);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
var pathOf = (location) => `${location.pathname}${location.search}`;
|
|
175
|
-
function parseTabPath(path) {
|
|
176
|
-
const hashAt = path.indexOf("#");
|
|
177
|
-
const hash = hashAt >= 0 ? path.slice(hashAt) : "";
|
|
178
|
-
const rest = hashAt >= 0 ? path.slice(0, hashAt) : path;
|
|
179
|
-
const searchAt = rest.indexOf("?");
|
|
180
|
-
return {
|
|
181
|
-
pathname: searchAt >= 0 ? rest.slice(0, searchAt) : rest,
|
|
182
|
-
search: searchAt >= 0 ? rest.slice(searchAt) : "",
|
|
183
|
-
hash
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
function readStorage(key) {
|
|
187
|
-
if (!key) return null;
|
|
188
|
-
try {
|
|
189
|
-
return localStorage.getItem(key);
|
|
190
|
-
} catch {
|
|
191
|
-
return null;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
function PageTabsProvider({
|
|
195
|
-
children,
|
|
196
|
-
resolve,
|
|
197
|
-
pinned = [],
|
|
198
|
-
storageKey,
|
|
199
|
-
maxTabs = DEFAULT_MAX_TABS,
|
|
200
|
-
enabled = true,
|
|
201
|
-
confirmDiscard
|
|
202
|
-
}) {
|
|
203
|
-
const location = useLocation();
|
|
204
|
-
const navigate = useNavigate();
|
|
205
|
-
const strings = useShellStrings().pageTabs;
|
|
206
|
-
const idPrefix = useId();
|
|
207
|
-
const resolveRef = useRef(resolve);
|
|
208
|
-
resolveRef.current = resolve;
|
|
209
|
-
const entryFor = useCallback((loc) => {
|
|
210
|
-
const route = resolveRef.current(loc);
|
|
211
|
-
if (!route) return null;
|
|
212
|
-
return { key: route.key ?? loc.pathname, path: pathOf(loc), title: route.title };
|
|
213
|
-
}, []);
|
|
214
|
-
const [state, dispatch] = useReducer(reducer, void 0, () => {
|
|
215
|
-
const restored = restore(readStorage(storageKey), (path) => entryFor(parseTabPath(path)));
|
|
216
|
-
const pinnedEntries = pinned.map((path) => entryFor(parseTabPath(path))).filter((e) => Boolean(e));
|
|
217
|
-
let initial = ensurePinned({ ...emptyState(), tabs: restored }, pinnedEntries);
|
|
218
|
-
const entry = enabled ? entryFor(location) : null;
|
|
219
|
-
initial = entry ? visit(initial, entry, maxTabs) : visitTransient(initial);
|
|
220
|
-
return initial;
|
|
221
|
-
});
|
|
222
|
-
const stateRef = useRef(state);
|
|
223
|
-
stateRef.current = state;
|
|
224
|
-
const locations = useRef(/* @__PURE__ */ new Map());
|
|
225
|
-
const current = enabled ? entryFor(location) : null;
|
|
226
|
-
const currentKey = current?.key ?? null;
|
|
227
|
-
useBrowserLayoutEffect(() => {
|
|
228
|
-
if (!enabled) return;
|
|
229
|
-
const entry = entryFor(location);
|
|
230
|
-
if (entry) {
|
|
231
|
-
locations.current.set(entry.key, location);
|
|
232
|
-
dispatch({ type: "visit", entry, maxTabs });
|
|
233
|
-
} else {
|
|
234
|
-
dispatch({ type: "transient" });
|
|
235
|
-
}
|
|
236
|
-
}, [location, enabled, maxTabs, entryFor]);
|
|
237
|
-
useEffect(() => {
|
|
238
|
-
const open = new Set(state.tabs.map((t) => t.key));
|
|
239
|
-
for (const key of locations.current.keys()) if (!open.has(key)) locations.current.delete(key);
|
|
240
|
-
}, [state.tabs]);
|
|
241
|
-
const serialized = useMemo(() => serialize(state), [state]);
|
|
242
|
-
useEffect(() => {
|
|
243
|
-
if (!storageKey) return;
|
|
244
|
-
try {
|
|
245
|
-
localStorage.setItem(storageKey, serialized);
|
|
246
|
-
} catch {
|
|
247
|
-
}
|
|
248
|
-
}, [serialized, storageKey]);
|
|
249
|
-
const anyDirty = state.dirty.length > 0;
|
|
250
|
-
useEffect(() => {
|
|
251
|
-
if (!anyDirty) return;
|
|
252
|
-
const hold = (e) => {
|
|
253
|
-
e.preventDefault();
|
|
254
|
-
e.returnValue = "";
|
|
255
|
-
};
|
|
256
|
-
window.addEventListener("beforeunload", hold);
|
|
257
|
-
return () => window.removeEventListener("beforeunload", hold);
|
|
258
|
-
}, [anyDirty]);
|
|
259
|
-
const ids = useRef(/* @__PURE__ */ new Map());
|
|
260
|
-
const idFor = useCallback(
|
|
261
|
-
(key, part) => {
|
|
262
|
-
let n = ids.current.get(key);
|
|
263
|
-
if (n === void 0) {
|
|
264
|
-
n = ids.current.size;
|
|
265
|
-
ids.current.set(key, n);
|
|
266
|
-
}
|
|
267
|
-
return `${idPrefix}-page-${part}-${n}`;
|
|
268
|
-
},
|
|
269
|
-
[idPrefix]
|
|
270
|
-
);
|
|
271
|
-
const askDiscard = useCallback(
|
|
272
|
-
(tabs) => {
|
|
273
|
-
if (confirmDiscard) return confirmDiscard(tabs);
|
|
274
|
-
return confirm({
|
|
275
|
-
title: strings.discardTitle,
|
|
276
|
-
message: tabs.length === 1 ? strings.discardOne : strings.discardCount?.(tabs.length) ?? `${tabs.length} ${strings.discardMany}`,
|
|
277
|
-
confirmLabel: strings.discardConfirm,
|
|
278
|
-
cancelLabel: strings.keepEditing,
|
|
279
|
-
variant: "warning"
|
|
280
|
-
});
|
|
281
|
-
},
|
|
282
|
-
[confirmDiscard, strings]
|
|
283
|
-
);
|
|
284
|
-
const fallbackPath = useCallback(() => {
|
|
285
|
-
const s = stateRef.current;
|
|
286
|
-
return s.tabs.find((t) => t.pinned)?.path ?? "/";
|
|
287
|
-
}, []);
|
|
288
|
-
const closeNow = useCallback(
|
|
289
|
-
(keys, to, prefer) => {
|
|
290
|
-
const s = stateRef.current;
|
|
291
|
-
const active = s.activeKey;
|
|
292
|
-
if (!active || !keys.includes(active)) {
|
|
293
|
-
dispatch({ type: "close", keys, closing: null });
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
let target = to;
|
|
297
|
-
if (!target) {
|
|
298
|
-
const survivors = { ...s, tabs: s.tabs.filter((t) => t.key === active || !keys.includes(t.key)) };
|
|
299
|
-
const preferred = prefer ? s.tabs.find((t) => t.key === prefer && !keys.includes(t.key)) : void 0;
|
|
300
|
-
target = (preferred ?? neighbourOf(survivors, active))?.path ?? fallbackPath();
|
|
301
|
-
}
|
|
302
|
-
dispatch({ type: "close", keys: keys.filter((k) => k !== active), closing: active });
|
|
303
|
-
navigate(target);
|
|
304
|
-
},
|
|
305
|
-
[navigate, fallbackPath]
|
|
306
|
-
);
|
|
307
|
-
const close = useCallback(
|
|
308
|
-
async (key, options = {}) => {
|
|
309
|
-
const tab = stateRef.current.tabs.find((t) => t.key === key);
|
|
310
|
-
if (!tab || tab.pinned) {
|
|
311
|
-
if (options.to) navigate(options.to);
|
|
312
|
-
return false;
|
|
313
|
-
}
|
|
314
|
-
if (!options.force && stateRef.current.dirty.includes(key) && !await askDiscard([tab])) return false;
|
|
315
|
-
if (!stateRef.current.tabs.some((t) => t.key === key)) return false;
|
|
316
|
-
closeNow([key], options.to);
|
|
317
|
-
return true;
|
|
318
|
-
},
|
|
319
|
-
[askDiscard, closeNow, navigate]
|
|
320
|
-
);
|
|
321
|
-
const closeMany = useCallback(
|
|
322
|
-
async (scope, key) => {
|
|
323
|
-
let keys = keysToClose(stateRef.current, scope, key);
|
|
324
|
-
const dirty = stateRef.current.tabs.filter(
|
|
325
|
-
(t) => keys.includes(t.key) && stateRef.current.dirty.includes(t.key)
|
|
326
|
-
);
|
|
327
|
-
if (dirty.length && !await askDiscard(dirty)) {
|
|
328
|
-
keys = keys.filter((k) => !dirty.some((t) => t.key === k));
|
|
329
|
-
}
|
|
330
|
-
const open = new Set(stateRef.current.tabs.map((t) => t.key));
|
|
331
|
-
keys = keys.filter((k) => open.has(k));
|
|
332
|
-
if (keys.length) closeNow(keys, void 0, scope === "all" ? null : key);
|
|
333
|
-
},
|
|
334
|
-
[askDiscard, closeNow]
|
|
335
|
-
);
|
|
336
|
-
const activate = useCallback(
|
|
337
|
-
(key) => {
|
|
338
|
-
const tab = stateRef.current.tabs.find((t) => t.key === key);
|
|
339
|
-
if (!tab || key === stateRef.current.activeKey) return;
|
|
340
|
-
navigate(tab.path);
|
|
341
|
-
},
|
|
342
|
-
[navigate]
|
|
343
|
-
);
|
|
344
|
-
const setTitle2 = useCallback((key, title) => dispatch({ type: "title", key, title }), []);
|
|
345
|
-
const setDirty2 = useCallback((key, dirty) => dispatch({ type: "dirty", key, dirty }), []);
|
|
346
|
-
const keyFor = useCallback((loc) => entryFor(loc)?.key ?? null, [entryFor]);
|
|
347
|
-
const locationFor = useCallback((key) => locations.current.get(key), []);
|
|
348
|
-
const visibleTabs = useMemo(
|
|
349
|
-
() => enabled ? state.tabs.filter((t) => t.key !== state.closing) : [],
|
|
350
|
-
[enabled, state.tabs, state.closing]
|
|
351
|
-
);
|
|
352
|
-
const value = useMemo(
|
|
353
|
-
() => ({
|
|
354
|
-
enabled,
|
|
355
|
-
state,
|
|
356
|
-
currentKey,
|
|
357
|
-
resolve,
|
|
358
|
-
keyFor,
|
|
359
|
-
locationFor,
|
|
360
|
-
idFor,
|
|
361
|
-
activate,
|
|
362
|
-
close,
|
|
363
|
-
closeMany,
|
|
364
|
-
setTitle: setTitle2,
|
|
365
|
-
setDirty: setDirty2,
|
|
366
|
-
visibleTabs
|
|
367
|
-
}),
|
|
368
|
-
[enabled, state, currentKey, resolve, keyFor, locationFor, idFor, activate, close, closeMany, setTitle2, setDirty2, visibleTabs]
|
|
369
|
-
);
|
|
370
|
-
return /* @__PURE__ */ jsx(PageTabsContext.Provider, { value, children });
|
|
371
|
-
}
|
|
372
|
-
var Activity2 = ReactModule.Activity;
|
|
373
|
-
var PAGE_TABS_PAUSE_HIDDEN = Boolean(Activity2);
|
|
374
|
-
function KeepAlive({ active, children }) {
|
|
375
|
-
if (Activity2) return /* @__PURE__ */ jsx(Activity2, { mode: active ? "visible" : "hidden", children });
|
|
376
|
-
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
377
|
-
}
|
|
378
|
-
var sameFrame = (a, b) => a.active === b.active && a.location === b.location && a.className === b.className && a.panelId === b.panelId && a.tabId === b.tabId && (!b.active || a.render === b.render);
|
|
379
|
-
var TabFrame = memo(function TabFrame2({ tabKey, active, location, render, className, panelId, tabId }) {
|
|
380
|
-
const ref = useRef(null);
|
|
381
|
-
const activeRef = useRef(active);
|
|
382
|
-
const scrolls = useRef(/* @__PURE__ */ new Map());
|
|
383
|
-
useBrowserLayoutEffect(() => {
|
|
384
|
-
const wasActive = activeRef.current;
|
|
385
|
-
activeRef.current = active;
|
|
386
|
-
if (!active || wasActive) return;
|
|
387
|
-
for (const [el, [top, left]] of scrolls.current) {
|
|
388
|
-
if (!el.isConnected) {
|
|
389
|
-
scrolls.current.delete(el);
|
|
390
|
-
continue;
|
|
391
|
-
}
|
|
392
|
-
el.scrollTop = top;
|
|
393
|
-
el.scrollLeft = left;
|
|
394
|
-
}
|
|
395
|
-
}, [active]);
|
|
396
|
-
useEffect(() => {
|
|
397
|
-
const el = ref.current;
|
|
398
|
-
if (!el) return;
|
|
399
|
-
const onScroll = (e) => {
|
|
400
|
-
if (!activeRef.current) return;
|
|
401
|
-
const target = e.target;
|
|
402
|
-
if (!target || typeof target.scrollTop !== "number") return;
|
|
403
|
-
scrolls.current.set(target, [target.scrollTop, target.scrollLeft]);
|
|
404
|
-
};
|
|
405
|
-
el.addEventListener("scroll", onScroll, true);
|
|
406
|
-
return () => el.removeEventListener("scroll", onScroll, true);
|
|
407
|
-
}, []);
|
|
408
|
-
const frame = useMemo(() => ({ key: tabKey, activeRef }), [tabKey]);
|
|
409
|
-
return /* @__PURE__ */ jsx(
|
|
410
|
-
"div",
|
|
411
|
-
{
|
|
412
|
-
ref,
|
|
413
|
-
role: panelId ? "tabpanel" : void 0,
|
|
414
|
-
id: panelId,
|
|
415
|
-
"aria-labelledby": tabId,
|
|
416
|
-
hidden: !active,
|
|
417
|
-
style: active ? void 0 : { display: "none" },
|
|
418
|
-
className,
|
|
419
|
-
"data-page-tab": tabKey,
|
|
420
|
-
children: /* @__PURE__ */ jsx(PageTabFrameContext.Provider, { value: frame, children: /* @__PURE__ */ jsx(KeepAlive, { active, children: render(location) }) })
|
|
421
|
-
}
|
|
422
|
-
);
|
|
423
|
-
}, sameFrame);
|
|
424
|
-
var TRANSIENT = "\0transient";
|
|
425
|
-
function PageTabsOutlet({ children, frameClassName }) {
|
|
426
|
-
const ctx = useContext(PageTabsContext);
|
|
427
|
-
const location = useLocation();
|
|
428
|
-
if (!ctx || !ctx.enabled) {
|
|
429
|
-
return /* @__PURE__ */ jsx("div", { className: frameClassName, children: children(location) }, TRANSIENT);
|
|
430
|
-
}
|
|
431
|
-
const { state, currentKey, locationFor, idFor } = ctx;
|
|
432
|
-
const keys = state.tabs.filter((t) => state.mounted.includes(t.key)).map((t) => t.key);
|
|
433
|
-
if (currentKey && !keys.includes(currentKey)) keys.push(currentKey);
|
|
434
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
435
|
-
keys.map((key) => {
|
|
436
|
-
const active = key === currentKey;
|
|
437
|
-
const loc = active ? location : locationFor(key);
|
|
438
|
-
if (!loc) return null;
|
|
439
|
-
return /* @__PURE__ */ jsx(
|
|
440
|
-
TabFrame,
|
|
441
|
-
{
|
|
442
|
-
tabKey: key,
|
|
443
|
-
active,
|
|
444
|
-
location: loc,
|
|
445
|
-
render: children,
|
|
446
|
-
className: frameClassName,
|
|
447
|
-
panelId: idFor(key, "panel"),
|
|
448
|
-
tabId: idFor(key, "tab")
|
|
449
|
-
},
|
|
450
|
-
key
|
|
451
|
-
);
|
|
452
|
-
}),
|
|
453
|
-
!currentKey && /* @__PURE__ */ jsx(TabFrame, { tabKey: TRANSIENT, active: true, location, render: children, className: frameClassName }, TRANSIENT)
|
|
454
|
-
] });
|
|
455
|
-
}
|
|
456
|
-
var STRIP = "relative flex h-10 shrink-0 items-end gap-3 bg-gray-100 px-3";
|
|
457
|
-
var TABLIST = "flex min-w-0 flex-1 items-end overflow-x-auto overflow-y-hidden [scrollbar-width:none] [&::-webkit-scrollbar]:hidden";
|
|
458
|
-
var TAB_BASE = "group @container relative flex h-9 flex-[0_1_15rem] items-center rounded-t-md border border-b-0 text-[13px] transition-colors";
|
|
459
|
-
var TAB_FLOOR_IDLE = "min-w-[2.75rem]";
|
|
460
|
-
var TAB_FLOOR_ACTIVE = "min-w-[4.25rem]";
|
|
461
|
-
var TAB_PINNED = "group relative flex h-9 flex-none items-center justify-center rounded-t-md border border-b-0 transition-colors";
|
|
462
|
-
var TAB_ACTIVE = "z-[1] border-gray-200 bg-gray-50 text-gray-900";
|
|
463
|
-
var TAB_IDLE = "border-transparent text-gray-600 hover:bg-gray-200/70 hover:text-gray-900";
|
|
464
|
-
var TITLE = "min-w-0 flex-1 overflow-hidden whitespace-nowrap [mask-image:linear-gradient(to_right,#000_calc(100%-1rem),transparent)]";
|
|
465
|
-
var ICON_WRAP = "relative flex size-4 shrink-0 items-center justify-center text-gray-500 [&>svg]:size-4";
|
|
466
|
-
var FOCUS_RING = "outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-500";
|
|
467
|
-
function CloseIcon() {
|
|
468
|
-
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 20 20", fill: "currentColor", "aria-hidden": "true", className: "size-3.5", children: /* @__PURE__ */ jsx("path", { d: "M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" }) });
|
|
469
|
-
}
|
|
470
|
-
function PageTabBar({ className, activeClassName, end }) {
|
|
471
|
-
const ctx = useContext(PageTabsContext);
|
|
472
|
-
const strings = useShellStrings().pageTabs;
|
|
473
|
-
const stripRef = useRef(null);
|
|
474
|
-
const [menu, setMenu] = useState(null);
|
|
475
|
-
const activeKey = ctx?.currentKey ?? null;
|
|
476
|
-
useEffect(() => {
|
|
477
|
-
if (!ctx || !activeKey) return;
|
|
478
|
-
const el = document.getElementById(ctx.idFor(activeKey, "tab"));
|
|
479
|
-
el?.scrollIntoView?.({ block: "nearest", inline: "nearest" });
|
|
480
|
-
}, [ctx, activeKey]);
|
|
481
|
-
if (!ctx || !ctx.enabled) return null;
|
|
482
|
-
const { visibleTabs: tabs, state, idFor, activate, close, closeMany, resolve } = ctx;
|
|
483
|
-
const focusKey = tabs.some((t) => t.key === activeKey) ? activeKey : tabs[0]?.key;
|
|
484
|
-
const focusTab = (index) => {
|
|
485
|
-
const tab = tabs[(index + tabs.length) % tabs.length];
|
|
486
|
-
if (tab) document.getElementById(idFor(tab.key, "tab"))?.focus();
|
|
487
|
-
};
|
|
488
|
-
const onKeyDown = (e) => {
|
|
489
|
-
const i = tabs.findIndex((t) => document.getElementById(idFor(t.key, "tab")) === e.target);
|
|
490
|
-
if (i < 0) return;
|
|
491
|
-
if (e.key === "ArrowRight") focusTab(i + 1);
|
|
492
|
-
else if (e.key === "ArrowLeft") focusTab(i - 1);
|
|
493
|
-
else if (e.key === "Home") focusTab(0);
|
|
494
|
-
else if (e.key === "End") focusTab(tabs.length - 1);
|
|
495
|
-
else if (e.key === "Delete" && !tabs[i].pinned) void close(tabs[i].key);
|
|
496
|
-
else return;
|
|
497
|
-
e.preventDefault();
|
|
498
|
-
};
|
|
499
|
-
const onContextMenu = (e, tab) => {
|
|
500
|
-
e.preventDefault();
|
|
501
|
-
setMenu({ x: e.clientX, y: e.clientY, key: tab.key });
|
|
502
|
-
};
|
|
503
|
-
const onAuxClick = (e, tab) => {
|
|
504
|
-
if (e.button !== 1 || tab.pinned) return;
|
|
505
|
-
e.preventDefault();
|
|
506
|
-
void close(tab.key);
|
|
507
|
-
};
|
|
508
|
-
const menuTab = menu ? tabs.find((t) => t.key === menu.key) : void 0;
|
|
509
|
-
const menuIndex = menuTab ? tabs.indexOf(menuTab) : -1;
|
|
510
|
-
const closable = (list) => list.some((t) => !t.pinned);
|
|
511
|
-
const run = (fn) => () => {
|
|
512
|
-
setMenu(null);
|
|
513
|
-
void fn();
|
|
514
|
-
};
|
|
515
|
-
return /* @__PURE__ */ jsxs("div", { className: className ?? STRIP, children: [
|
|
516
|
-
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-x-0 bottom-0 h-px bg-gray-200" }),
|
|
517
|
-
/* @__PURE__ */ jsx(
|
|
518
|
-
"div",
|
|
519
|
-
{
|
|
520
|
-
ref: stripRef,
|
|
521
|
-
role: "tablist",
|
|
522
|
-
"aria-label": strings.label,
|
|
523
|
-
onKeyDown,
|
|
524
|
-
className: TABLIST,
|
|
525
|
-
children: tabs.map((tab, i) => {
|
|
526
|
-
const active = tab.key === activeKey;
|
|
527
|
-
const dirty = state.dirty.includes(tab.key);
|
|
528
|
-
const icon = resolve(parseTabPath(tab.path))?.icon;
|
|
529
|
-
const colours = active ? activeClassName ?? TAB_ACTIVE : TAB_IDLE;
|
|
530
|
-
const divider = i > 0 && !active && tabs[i - 1].key !== activeKey;
|
|
531
|
-
const tabButton = {
|
|
532
|
-
type: "button",
|
|
533
|
-
role: "tab",
|
|
534
|
-
id: idFor(tab.key, "tab"),
|
|
535
|
-
"aria-selected": active,
|
|
536
|
-
"aria-controls": state.mounted.includes(tab.key) ? idFor(tab.key, "panel") : void 0,
|
|
537
|
-
tabIndex: tab.key === focusKey ? 0 : -1,
|
|
538
|
-
title: tab.title,
|
|
539
|
-
onClick: () => activate(tab.key)
|
|
540
|
-
};
|
|
541
|
-
const handlers = {
|
|
542
|
-
onContextMenu: (e) => onContextMenu(e, tab),
|
|
543
|
-
onAuxClick: (e) => onAuxClick(e, tab),
|
|
544
|
-
// A middle-press would otherwise start the browser's autoscroll.
|
|
545
|
-
onMouseDown: (e) => {
|
|
546
|
-
if (e.button === 1) e.preventDefault();
|
|
547
|
-
}
|
|
548
|
-
};
|
|
549
|
-
const iconEl = icon && // The consumer's nav icons, whatever size they were drawn at for
|
|
550
|
-
// the sidebar, sit at the strip's size here.
|
|
551
|
-
/* @__PURE__ */ jsxs("span", { className: ICON_WRAP, "aria-hidden": "true", children: [
|
|
552
|
-
icon,
|
|
553
|
-
dirty && !active && !tab.pinned && // Unsaved work on a tab too narrow for its × slot: the dot
|
|
554
|
-
// moves onto the icon.
|
|
555
|
-
/* @__PURE__ */ jsx("span", { className: "absolute -right-1 -top-1 hidden size-2 rounded-full bg-gray-500 ring-2 ring-gray-100 @max-[6.5rem]:block @max-[6.5rem]:group-hover:hidden" })
|
|
556
|
-
] });
|
|
557
|
-
if (tab.pinned) {
|
|
558
|
-
return /* @__PURE__ */ jsx("div", { role: "presentation", className: `${TAB_PINNED} ${icon ? "w-10" : ""} ${colours}`, ...handlers, children: /* @__PURE__ */ jsxs("button", { ...tabButton, className: `flex h-full items-center justify-center rounded-t-md ${icon ? "w-full" : "px-3"} ${FOCUS_RING}`, children: [
|
|
559
|
-
iconEl,
|
|
560
|
-
/* @__PURE__ */ jsx("span", { className: icon ? "sr-only" : "whitespace-nowrap text-[13px]", children: tab.title })
|
|
561
|
-
] }) }, tab.key);
|
|
562
|
-
}
|
|
563
|
-
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
564
|
-
divider && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "mb-2.5 h-4 w-px shrink-0 self-end border-l border-gray-300" }),
|
|
565
|
-
/* @__PURE__ */ jsxs(
|
|
566
|
-
"div",
|
|
567
|
-
{
|
|
568
|
-
role: "presentation",
|
|
569
|
-
className: `${TAB_BASE} ${active ? TAB_FLOOR_ACTIVE : TAB_FLOOR_IDLE} ${colours}`,
|
|
570
|
-
...handlers,
|
|
571
|
-
children: [
|
|
572
|
-
/* @__PURE__ */ jsxs(
|
|
573
|
-
"button",
|
|
574
|
-
{
|
|
575
|
-
...tabButton,
|
|
576
|
-
className: `flex h-full min-w-0 flex-1 items-center gap-2 rounded-t-md pl-3 pr-1 text-left ${FOCUS_RING} ${active ? "@max-[5rem]:pl-2.5" : "@max-[6.5rem]:pr-3 @max-[6.5rem]:group-hover:pr-1 @max-[4.5rem]:justify-center @max-[4.5rem]:px-0 @max-[4.5rem]:group-hover:pl-1.5"}`,
|
|
577
|
-
children: [
|
|
578
|
-
iconEl,
|
|
579
|
-
/* @__PURE__ */ jsx("span", { className: `${TITLE} ${icon ? active ? "@max-[5rem]:sr-only" : "@max-[4.5rem]:sr-only" : ""}`, children: tab.title })
|
|
580
|
-
]
|
|
581
|
-
}
|
|
582
|
-
),
|
|
583
|
-
/* @__PURE__ */ jsxs(
|
|
584
|
-
"span",
|
|
585
|
-
{
|
|
586
|
-
className: `mr-1.5 flex size-5 shrink-0 items-center justify-center ${active ? "" : "@max-[6.5rem]:hidden @max-[6.5rem]:group-hover:flex"}`,
|
|
587
|
-
children: [
|
|
588
|
-
dirty && /* @__PURE__ */ jsx(
|
|
589
|
-
"span",
|
|
590
|
-
{
|
|
591
|
-
role: "img",
|
|
592
|
-
"aria-label": strings.unsaved,
|
|
593
|
-
className: "size-2 rounded-full bg-gray-500 group-hover:hidden"
|
|
594
|
-
}
|
|
595
|
-
),
|
|
596
|
-
/* @__PURE__ */ jsx(
|
|
597
|
-
"button",
|
|
598
|
-
{
|
|
599
|
-
type: "button",
|
|
600
|
-
tabIndex: -1,
|
|
601
|
-
"aria-label": strings.closeTab?.(tab.title) ?? `${strings.close} ${tab.title}`,
|
|
602
|
-
onClick: () => void close(tab.key),
|
|
603
|
-
className: `size-5 items-center justify-center rounded text-gray-400 hover:bg-gray-200 hover:text-gray-700 ${dirty ? "hidden group-hover:flex" : active ? "flex" : "flex opacity-0 group-hover:opacity-100 focus-visible:opacity-100"}`,
|
|
604
|
-
children: /* @__PURE__ */ jsx(CloseIcon, {})
|
|
605
|
-
}
|
|
606
|
-
)
|
|
607
|
-
]
|
|
608
|
-
}
|
|
609
|
-
)
|
|
610
|
-
]
|
|
611
|
-
}
|
|
612
|
-
)
|
|
613
|
-
] }, tab.key);
|
|
614
|
-
})
|
|
615
|
-
}
|
|
616
|
-
),
|
|
617
|
-
end && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-2 self-center", children: end }),
|
|
618
|
-
menu && menuTab && /* @__PURE__ */ jsxs(PopupMenu, { portal: true, style: { left: menu.x, top: menu.y }, onClose: () => setMenu(null), children: [
|
|
619
|
-
/* @__PURE__ */ jsx(PopupMenuItem, { disabled: menuTab.pinned, onClick: run(() => close(menuTab.key)), children: strings.close }),
|
|
620
|
-
/* @__PURE__ */ jsx(PopupMenuDivider, {}),
|
|
621
|
-
/* @__PURE__ */ jsx(
|
|
622
|
-
PopupMenuItem,
|
|
623
|
-
{
|
|
624
|
-
disabled: !closable(tabs.filter((t) => t.key !== menuTab.key)),
|
|
625
|
-
onClick: run(() => closeMany("others", menuTab.key)),
|
|
626
|
-
children: strings.closeOthers
|
|
627
|
-
}
|
|
628
|
-
),
|
|
629
|
-
/* @__PURE__ */ jsx(
|
|
630
|
-
PopupMenuItem,
|
|
631
|
-
{
|
|
632
|
-
disabled: !closable(tabs.slice(menuIndex + 1)),
|
|
633
|
-
onClick: run(() => closeMany("right", menuTab.key)),
|
|
634
|
-
children: strings.closeRight
|
|
635
|
-
}
|
|
636
|
-
),
|
|
637
|
-
/* @__PURE__ */ jsx(PopupMenuItem, { disabled: !closable(tabs), onClick: run(() => closeMany("all", null)), children: strings.closeAll })
|
|
638
|
-
] })
|
|
639
|
-
] });
|
|
640
|
-
}
|
|
641
|
-
var NO_TABS = {
|
|
642
|
-
enabled: false,
|
|
643
|
-
tabs: [],
|
|
644
|
-
activeKey: null,
|
|
645
|
-
activate: () => {
|
|
646
|
-
},
|
|
647
|
-
close: async () => false,
|
|
648
|
-
closeOthers: async () => {
|
|
649
|
-
},
|
|
650
|
-
closeRight: async () => {
|
|
651
|
-
},
|
|
652
|
-
closeAll: async () => {
|
|
653
|
-
}
|
|
654
|
-
};
|
|
655
|
-
function usePageTabs() {
|
|
656
|
-
const ctx = useContext(PageTabsContext);
|
|
657
|
-
if (!ctx || !ctx.enabled) return NO_TABS;
|
|
658
|
-
return {
|
|
659
|
-
enabled: true,
|
|
660
|
-
tabs: ctx.visibleTabs,
|
|
661
|
-
activeKey: ctx.currentKey,
|
|
662
|
-
activate: ctx.activate,
|
|
663
|
-
close: ctx.close,
|
|
664
|
-
closeOthers: (key) => ctx.closeMany("others", key),
|
|
665
|
-
closeRight: (key) => ctx.closeMany("right", key),
|
|
666
|
-
closeAll: () => ctx.closeMany("all", null)
|
|
667
|
-
};
|
|
668
|
-
}
|
|
669
|
-
function usePageTab() {
|
|
670
|
-
const ctx = useContext(PageTabsContext);
|
|
671
|
-
const frame = useContext(PageTabFrameContext);
|
|
672
|
-
const navigate = useNavigate();
|
|
673
|
-
const key = ctx?.enabled && frame ? frame.key : null;
|
|
674
|
-
const close = useCallback(
|
|
675
|
-
async (options = {}) => {
|
|
676
|
-
if (ctx?.enabled && frame && ctx.state.tabs.some((t) => t.key === frame.key)) {
|
|
677
|
-
return ctx.close(frame.key, options);
|
|
678
|
-
}
|
|
679
|
-
if (options.to) navigate(options.to);
|
|
680
|
-
return false;
|
|
681
|
-
},
|
|
682
|
-
[ctx, frame, navigate]
|
|
683
|
-
);
|
|
684
|
-
return { key, close };
|
|
685
|
-
}
|
|
686
|
-
function usePageTabTitle(title) {
|
|
687
|
-
const ctx = useContext(PageTabsContext);
|
|
688
|
-
const frame = useContext(PageTabFrameContext);
|
|
689
|
-
const setTitle2 = ctx?.enabled ? ctx.setTitle : void 0;
|
|
690
|
-
const key = frame?.key;
|
|
691
|
-
useEffect(() => {
|
|
692
|
-
if (setTitle2 && key && title) setTitle2(key, title);
|
|
693
|
-
}, [setTitle2, key, title]);
|
|
694
|
-
}
|
|
695
|
-
function usePageTabDirty(dirty) {
|
|
696
|
-
const ctx = useContext(PageTabsContext);
|
|
697
|
-
const frame = useContext(PageTabFrameContext);
|
|
698
|
-
const setDirty2 = ctx?.enabled ? ctx.setDirty : void 0;
|
|
699
|
-
useEffect(() => {
|
|
700
|
-
if (!setDirty2 || !frame) return;
|
|
701
|
-
setDirty2(frame.key, dirty);
|
|
702
|
-
return () => {
|
|
703
|
-
if (frame.activeRef.current) setDirty2(frame.key, false);
|
|
704
|
-
};
|
|
705
|
-
}, [setDirty2, frame, dirty]);
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
export { DEFAULT_MAX_TABS, PAGE_TABS_PAUSE_HIDDEN, PageTabBar, PageTabsOutlet, PageTabsProvider, parseTabPath, usePageTab, usePageTabDirty, usePageTabTitle, usePageTabs };
|
|
709
|
-
//# sourceMappingURL=index.js.map
|
|
710
|
-
//# sourceMappingURL=index.js.map
|
|
2
|
+
import{PopupMenu as e,PopupMenuItem as t,PopupMenuDivider as n}from"../chunk-UZAJ5BF6.js";import{confirm as r}from"../chunk-3A46NCXK.js";import"../chunk-57MIENLJ.js";import{useShellStrings as i}from"../chunk-OQDWLHZI.js";import"../chunk-MAIHBBWT.js";import{useBrowserLayoutEffect as l}from"../chunk-D65T4H6J.js";import*as a from"react";import{createContext as s,memo as o,useRef as c,useEffect as d,useMemo as u,useId as y,useCallback as f,useReducer as m,useContext as p,useState as h,Fragment as b}from"react";import{useLocation as k,useNavigate as v}from"react-router-dom";import{jsx as g,Fragment as x,jsxs as w}from"react/jsx-runtime";var N=s(null),I=s(null),K=12;var A=(e,t)=>e.filter(e=>e!==t);function F(e,t){return[...t.map(t=>e.find(e=>e.key===t)).filter(e=>Boolean(e)),...e.filter(e=>!t.includes(e.key))]}function T(e,t,n=12){const r=e.clock+1;let i;i=e.tabs.find(e=>e.key===t.key)?e.tabs.map(e=>e.key===t.key?{...e,path:t.path,title:"page"===e.titleFrom?e.title:t.title||e.title,lastActive:r}:e):[...e.tabs,{key:t.key,path:t.path,title:t.title,titleFrom:"route",pinned:!1,lastActive:r}];let l={...e,tabs:i,activeKey:t.key,mounted:(a=e.mounted,s=t.key,a.includes(s)?a:[...a,s]),clock:r};var a,s;return l.closing&&l.closing!==t.key?l=C(l,l.closing):l.closing===t.key&&(l={...l,closing:null}),function(e,t){let n=e;for(;n.tabs.length>t;){const e=n.tabs.filter(e=>!e.pinned&&e.key!==n.activeKey&&!n.dirty.includes(e.key)&&e.key!==n.closing).sort((e,t)=>e.lastActive-t.lastActive);if(0===e.length)break;n=C(n,e[0].key)}return n}(l,n)}function $(e){let t={...e,activeKey:null};return t.closing&&(t=C(t,t.closing)),t}function C(e,t){return{...e,tabs:e.tabs.filter(e=>e.key!==t),mounted:A(e.mounted,t),dirty:A(e.dirty,t),activeKey:e.activeKey===t?null:e.activeKey,closing:e.closing===t?null:e.closing}}function L(e,t){switch(t.type){case"visit":return T(e,t.entry,t.maxTabs);case"transient":return $(e);case"close":{let n=e;for(const e of t.keys)n=C(n,e);return t.closing?function(e,t){return{...e,closing:t}}(n,t.closing):n}case"title":return function(e,t,n){const r=e.tabs.find(e=>e.key===t);return!r||!n||r.title===n&&"page"===r.titleFrom?e:{...e,tabs:e.tabs.map(e=>e.key===t?{...e,title:n,titleFrom:"page"}:e)}}(e,t.key,t.title);case"dirty":return function(e,t,n){return n===e.dirty.includes(t)?e:{...e,dirty:n?[...e.dirty,t]:A(e.dirty,t)}}(e,t.key,t.dirty)}}var M=e=>`${e.pathname}${e.search}`;function j(e){const t=e.indexOf("#"),n=t>=0?e.slice(t):"",r=t>=0?e.slice(0,t):e,i=r.indexOf("?");return{pathname:i>=0?r.slice(0,i):r,search:i>=0?r.slice(i):"",hash:n}}function D({children:e,resolve:t,pinned:n=[],storageKey:a,maxTabs:s=12,enabled:o=!0,confirmDiscard:p}){const h=k(),b=v(),x=i().pageTabs,w=y(),I=c(t);I.current=t;const K=f(e=>{const t=I.current(e);return t?{key:t.key??e.pathname,path:M(e),title:t.title}:null},[]),[A,C]=m(L,void 0,()=>{const e=function(e,t){if(!e)return[];let n;try{n=JSON.parse(e)}catch{return[]}const r=n;if(!r||1!==r.v||!Array.isArray(r.tabs))return[];const i=[];for(const e of r.tabs){if(!e||"string"!=typeof e.path||!e.path.startsWith("/")||e.path.startsWith("//"))continue;const n=e.path.indexOf("#"),r=n>=0?e.path.slice(0,n):e.path,l=t(r);if(!l||i.some(e=>e.key===l.key))continue;const a="page"===e.titleFrom&&"string"==typeof e.title&&e.title;i.push({key:l.key,path:r,title:a||l.title,titleFrom:a?"page":"route",pinned:!1,lastActive:0})}return i}(function(e){if(!e)return null;try{return localStorage.getItem(e)}catch{return null}}(a),e=>K(j(e)));let t=function(e,t){const n=t.map(e=>e.key);let r=e.tabs.map(e=>({...e,pinned:n.includes(e.key)}));for(const e of t)r.some(t=>t.key===e.key)||(r=[...r,{key:e.key,path:e.path,title:e.title,titleFrom:"route",pinned:!0,lastActive:0}]);return{...e,tabs:F(r,n)}}({tabs:[],activeKey:null,mounted:[],dirty:[],closing:null,clock:0,tabs:e},n.map(e=>K(j(e))).filter(e=>Boolean(e)));const r=o?K(h):null;return t=r?T(t,r,s):$(t),t}),D=c(A);D.current=A;const O=c(/* @__PURE__ */new Map),z=o?K(h):null,B=z?.key??null;l(()=>{if(!o)return;const e=K(h);e?(O.current.set(e.key,h),C({type:"visit",entry:e,maxTabs:s})):C({type:"transient"})},[h,o,s,K]),d(()=>{const e=new Set(A.tabs.map(e=>e.key));for(const t of O.current.keys())e.has(t)||O.current.delete(t)},[A.tabs]);const E=u(()=>function(e){const t={v:1,tabs:e.tabs.filter(t=>t.key!==e.closing).map(({key:e,path:t,title:n,titleFrom:r})=>({key:e,path:t,title:n,titleFrom:r}))};return JSON.stringify(t)}(A),[A]);d(()=>{if(a)try{localStorage.setItem(a,E)}catch{}},[E,a]);const R=A.dirty.length>0;d(()=>{if(!R)return;const e=e=>{e.preventDefault(),e.returnValue=""};return window.addEventListener("beforeunload",e),()=>window.removeEventListener("beforeunload",e)},[R]);const S=c(/* @__PURE__ */new Map),J=f((e,t)=>{let n=S.current.get(e);return void 0===n&&(n=S.current.size,S.current.set(e,n)),`${w}-page-${t}-${n}`},[w]),H=f(e=>p?p(e):r({title:x.discardTitle,message:1===e.length?x.discardOne:x.discardCount?.(e.length)??`${e.length} ${x.discardMany}`,confirmLabel:x.discardConfirm,cancelLabel:x.keepEditing,variant:"warning"}),[p,x]),W=f(()=>{const e=D.current;return e.tabs.find(e=>e.pinned)?.path??"/"},[]),_=f((e,t,n)=>{const r=D.current,i=r.activeKey;if(!i||!e.includes(i))return void C({type:"close",keys:e,closing:null});let l=t;if(!l){const t={...r,tabs:r.tabs.filter(t=>t.key===i||!e.includes(t.key))},a=n?r.tabs.find(t=>t.key===n&&!e.includes(t.key)):void 0;l=(a??function(e,t){const n=e.tabs.filter(n=>n.key!==e.closing||n.key===t),r=n.findIndex(e=>e.key===t);return r<0?null:n[r+1]??n[r-1]??null}(t,i))?.path??W()}C({type:"close",keys:e.filter(e=>e!==i),closing:i}),b(l)},[b,W]),P=f(async(e,t={})=>{const n=D.current.tabs.find(t=>t.key===e);return!n||n.pinned?(t.to&&b(t.to),!1):!(!t.force&&D.current.dirty.includes(e)&&!await H([n]))&&(!!D.current.tabs.some(t=>t.key===e)&&(_([e],t.to),!0))},[H,_,b]),V=f(async(e,t)=>{let n=function(e,t,n){const r=e.tabs.filter(e=>!e.pinned);if("all"===t)return r.map(e=>e.key);if("others"===t)return r.filter(e=>e.key!==n).map(e=>e.key);const i=e.tabs.findIndex(e=>e.key===n);return i<0?[]:e.tabs.slice(i+1).filter(e=>!e.pinned).map(e=>e.key)}(D.current,e,t);const r=D.current.tabs.filter(e=>n.includes(e.key)&&D.current.dirty.includes(e.key));r.length&&!await H(r)&&(n=n.filter(e=>!r.some(t=>t.key===e)));const i=new Set(D.current.tabs.map(e=>e.key));n=n.filter(e=>i.has(e)),n.length&&_(n,void 0,"all"===e?null:t)},[H,_]),X=f(e=>{const t=D.current.tabs.find(t=>t.key===e);t&&e!==D.current.activeKey&&b(t.path)},[b]),Z=f((e,t)=>C({type:"title",key:e,title:t}),[]),Q=f((e,t)=>C({type:"dirty",key:e,dirty:t}),[]),U=f(e=>K(e)?.key??null,[K]),Y=f(e=>O.current.get(e),[]),q=u(()=>o?A.tabs.filter(e=>e.key!==A.closing):[],[o,A.tabs,A.closing]),G=u(()=>({enabled:o,state:A,currentKey:B,resolve:t,keyFor:U,locationFor:Y,idFor:J,activate:X,close:P,closeMany:V,setTitle:Z,setDirty:Q,visibleTabs:q}),[o,A,B,t,U,Y,J,X,P,V,Z,Q,q]);/* @__PURE__ */
|
|
3
|
+
return g(N.Provider,{value:G,children:e})}var O=a.Activity,z=Boolean(O);function B({active:e,children:t}){return O?/* @__PURE__ */g(O,{mode:e?"visible":"hidden",children:t}):/* @__PURE__ */g(x,{children:t})}var E=o(function({tabKey:e,active:t,location:n,render:r,className:i,panelId:a,tabId:s}){const o=c(null),y=c(t),f=c(/* @__PURE__ */new Map);l(()=>{const e=y.current;if(y.current=t,t&&!e)for(const[e,[t,n]]of f.current)e.isConnected?(e.scrollTop=t,e.scrollLeft=n):f.current.delete(e)},[t]),d(()=>{const e=o.current;if(!e)return;const t=e=>{if(!y.current)return;const t=e.target;t&&"number"==typeof t.scrollTop&&f.current.set(t,[t.scrollTop,t.scrollLeft])};return e.addEventListener("scroll",t,!0),()=>e.removeEventListener("scroll",t,!0)},[]);const m=u(()=>({key:e,activeRef:y}),[e]);/* @__PURE__ */
|
|
4
|
+
return g("div",{ref:o,role:a?"tabpanel":void 0,id:a,"aria-labelledby":s,hidden:!t,style:t?void 0:{display:"none"},className:i,"data-page-tab":e,children:/* @__PURE__ */g(I.Provider,{value:m,children:/* @__PURE__ */g(B,{active:t,children:r(n)})})})},(e,t)=>e.active===t.active&&e.location===t.location&&e.className===t.className&&e.panelId===t.panelId&&e.tabId===t.tabId&&(!t.active||e.render===t.render)),R="\0transient";function S({children:e,frameClassName:t}){const n=p(N),r=k();if(!n||!n.enabled)/* @__PURE__ */
|
|
5
|
+
return g("div",{className:t,children:e(r)},R);const{state:i,currentKey:l,locationFor:a,idFor:s}=n,o=i.tabs.filter(e=>i.mounted.includes(e.key)).map(e=>e.key);return l&&!o.includes(l)&&o.push(l),/* @__PURE__ */w(x,{children:[o.map(n=>{const i=n===l,o=i?r:a(n);return o?/* @__PURE__ */g(E,{tabKey:n,active:i,location:o,render:e,className:t,panelId:s(n,"panel"),tabId:s(n,"tab")},n):null}),!l&&/* @__PURE__ */g(E,{tabKey:R,active:!0,location:r,render:e,className:t},R)]})}var J="outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-500";function H(){/* @__PURE__ */
|
|
6
|
+
return g("svg",{viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true",className:"size-3.5",children:/* @__PURE__ */g("path",{d:"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"})})}function W({className:r,activeClassName:l,end:a}){const s=p(N),o=i().pageTabs,u=c(null),[y,f]=h(null),m=s?.currentKey??null;if(d(()=>{if(!s||!m)return;const e=document.getElementById(s.idFor(m,"tab"));e?.scrollIntoView?.({block:"nearest",inline:"nearest"})},[s,m]),!s||!s.enabled)return null;const{visibleTabs:k,state:v,idFor:x,activate:I,close:K,closeMany:A,resolve:F}=s,T=k.some(e=>e.key===m)?m:k[0]?.key,$=e=>{const t=k[(e+k.length)%k.length];t&&document.getElementById(x(t.key,"tab"))?.focus()},C=y?k.find(e=>e.key===y.key):void 0,L=C?k.indexOf(C):-1,M=e=>e.some(e=>!e.pinned),D=e=>()=>{f(null),e()};/* @__PURE__ */
|
|
7
|
+
return w("div",{className:r??"relative flex h-10 shrink-0 items-end gap-3 bg-gray-100 px-3",children:[
|
|
8
|
+
/* @__PURE__ */g("div",{"aria-hidden":"true",className:"pointer-events-none absolute inset-x-0 bottom-0 h-px bg-gray-200"}),
|
|
9
|
+
/* @__PURE__ */g("div",{ref:u,role:"tablist","aria-label":o.label,onKeyDown:e=>{const t=k.findIndex(t=>document.getElementById(x(t.key,"tab"))===e.target);if(!(t<0)){if("ArrowRight"===e.key)$(t+1);else if("ArrowLeft"===e.key)$(t-1);else if("Home"===e.key)$(0);else if("End"===e.key)$(k.length-1);else{if("Delete"!==e.key||k[t].pinned)return;K(k[t].key)}e.preventDefault()}},className:"flex min-w-0 flex-1 items-end overflow-x-auto overflow-y-hidden [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",children:k.map((e,t)=>{const n=e.key===m,r=v.dirty.includes(e.key),i=F(j(e.path))?.icon,a=n?l??"z-[1] border-gray-200 bg-gray-50 text-gray-900":"border-transparent text-gray-600 hover:bg-gray-200/70 hover:text-gray-900",s=t>0&&!n&&k[t-1].key!==m,c={type:"button",role:"tab",id:x(e.key,"tab"),"aria-selected":n,"aria-controls":v.mounted.includes(e.key)?x(e.key,"panel"):void 0,tabIndex:e.key===T?0:-1,title:e.title,onClick:()=>I(e.key)},d={onContextMenu:t=>((e,t)=>{e.preventDefault(),f({x:e.clientX,y:e.clientY,key:t.key})})(t,e),onAuxClick:t=>((e,t)=>{1!==e.button||t.pinned||(e.preventDefault(),K(t.key))})(t,e),onMouseDown:e=>{1===e.button&&e.preventDefault()}},u=i&&
|
|
10
|
+
/* @__PURE__ */w("span",{className:"relative flex size-4 shrink-0 items-center justify-center text-gray-500 [&>svg]:size-4","aria-hidden":"true",children:[i,r&&!n&&!e.pinned&&
|
|
11
|
+
/* @__PURE__ */g("span",{className:"absolute -right-1 -top-1 hidden size-2 rounded-full bg-gray-500 ring-2 ring-gray-100 @max-[6.5rem]:block @max-[6.5rem]:group-hover:hidden"})]});return e.pinned?/* @__PURE__ */g("div",{role:"presentation",className:`group relative flex h-9 flex-none items-center justify-center rounded-t-md border border-b-0 transition-colors ${i?"w-10":""} ${a}`,...d,children:/* @__PURE__ */w("button",{...c,className:`flex h-full items-center justify-center rounded-t-md ${i?"w-full":"px-3"} ${J}`,children:[u,
|
|
12
|
+
/* @__PURE__ */g("span",{className:i?"sr-only":"whitespace-nowrap text-[13px]",children:e.title})]})},e.key):/* @__PURE__ */w(b,{children:[s&&/* @__PURE__ */g("span",{"aria-hidden":"true",className:"mb-2.5 h-4 w-px shrink-0 self-end border-l border-gray-300"}),
|
|
13
|
+
/* @__PURE__ */w("div",{role:"presentation",className:`group @container relative flex h-9 flex-[0_1_15rem] items-center rounded-t-md border border-b-0 text-[13px] transition-colors ${n?"min-w-[4.25rem]":"min-w-[2.75rem]"} ${a}`,...d,children:[
|
|
14
|
+
/* @__PURE__ */w("button",{...c,className:`flex h-full min-w-0 flex-1 items-center gap-2 rounded-t-md pl-3 pr-1 text-left ${J} ${n?"@max-[5rem]:pl-2.5":"@max-[6.5rem]:pr-3 @max-[6.5rem]:group-hover:pr-1 @max-[4.5rem]:justify-center @max-[4.5rem]:px-0 @max-[4.5rem]:group-hover:pl-1.5"}`,children:[u,
|
|
15
|
+
/* @__PURE__ */g("span",{className:"min-w-0 flex-1 overflow-hidden whitespace-nowrap [mask-image:linear-gradient(to_right,#000_calc(100%-1rem),transparent)] "+(i?n?"@max-[5rem]:sr-only":"@max-[4.5rem]:sr-only":""),children:e.title})]}),
|
|
16
|
+
/* @__PURE__ */w("span",{className:"mr-1.5 flex size-5 shrink-0 items-center justify-center "+(n?"":"@max-[6.5rem]:hidden @max-[6.5rem]:group-hover:flex"),children:[r&&/* @__PURE__ */g("span",{role:"img","aria-label":o.unsaved,className:"size-2 rounded-full bg-gray-500 group-hover:hidden"}),
|
|
17
|
+
/* @__PURE__ */g("button",{type:"button",tabIndex:-1,"aria-label":o.closeTab?.(e.title)??`${o.close} ${e.title}`,onClick:()=>{K(e.key)},className:"size-5 items-center justify-center rounded text-gray-400 hover:bg-gray-200 hover:text-gray-700 "+(r?"hidden group-hover:flex":n?"flex":"flex opacity-0 group-hover:opacity-100 focus-visible:opacity-100"),children:/* @__PURE__ */g(H,{})})]})]})]},e.key)})}),a&&/* @__PURE__ */g("div",{className:"flex shrink-0 items-center gap-2 self-center",children:a}),y&&C&&/* @__PURE__ */w(e,{portal:!0,style:{left:y.x,top:y.y},onClose:()=>f(null),children:[
|
|
18
|
+
/* @__PURE__ */g(t,{disabled:C.pinned,onClick:D(()=>K(C.key)),children:o.close}),
|
|
19
|
+
/* @__PURE__ */g(n,{}),
|
|
20
|
+
/* @__PURE__ */g(t,{disabled:!M(k.filter(e=>e.key!==C.key)),onClick:D(()=>A("others",C.key)),children:o.closeOthers}),
|
|
21
|
+
/* @__PURE__ */g(t,{disabled:!M(k.slice(L+1)),onClick:D(()=>A("right",C.key)),children:o.closeRight}),
|
|
22
|
+
/* @__PURE__ */g(t,{disabled:!M(k),onClick:D(()=>A("all",null)),children:o.closeAll})]})]})}var _={enabled:!1,tabs:[],activeKey:null,activate:()=>{},close:async()=>!1,closeOthers:async()=>{},closeRight:async()=>{},closeAll:async()=>{}};function P(){const e=p(N);return e&&e.enabled?{enabled:!0,tabs:e.visibleTabs,activeKey:e.currentKey,activate:e.activate,close:e.close,closeOthers:t=>e.closeMany("others",t),closeRight:t=>e.closeMany("right",t),closeAll:()=>e.closeMany("all",null)}:_}function V(){const e=p(N),t=p(I),n=v();return{key:e?.enabled&&t?t.key:null,close:f(async(r={})=>e?.enabled&&t&&e.state.tabs.some(e=>e.key===t.key)?e.close(t.key,r):(r.to&&n(r.to),!1),[e,t,n])}}function X(e){const t=p(N),n=p(I),r=t?.enabled?t.setTitle:void 0,i=n?.key;d(()=>{r&&i&&e&&r(i,e)},[r,i,e])}function Z(e){const t=p(N),n=p(I),r=t?.enabled?t.setDirty:void 0;d(()=>{if(r&&n)return r(n.key,e),()=>{n.activeRef.current&&r(n.key,!1)}},[r,n,e])}export{K as DEFAULT_MAX_TABS,z as PAGE_TABS_PAUSE_HIDDEN,W as PageTabBar,S as PageTabsOutlet,D as PageTabsProvider,j as parseTabPath,V as usePageTab,Z as usePageTabDirty,X as usePageTabTitle,P as usePageTabs};
|