@brainfish-ai/components 0.22.5 → 0.22.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/chunks/{layout.BNZjeF7G.js → layout.ClofLZcT.js} +2 -2
- package/dist/esm/chunks/{layout.BNZjeF7G.js.map → layout.ClofLZcT.js.map} +1 -1
- package/dist/esm/chunks/{review-list.DybOsf_S.js → review-list.COTpWPmq.js} +15 -6
- package/dist/esm/chunks/review-list.COTpWPmq.js.map +1 -0
- package/dist/esm/chunks/{sidebar.DCi9MWl5.js → sidebar.kcc3uFga.js} +165 -47
- package/dist/esm/chunks/sidebar.kcc3uFga.js.map +1 -0
- package/dist/esm/components/ui/input.js +22 -3
- package/dist/esm/components/ui/input.js.map +1 -1
- package/dist/esm/components/ui/scroll-area.js +9 -1
- package/dist/esm/components/ui/scroll-area.js.map +1 -1
- package/dist/esm/global.css +1 -1
- package/dist/esm/index.js +3 -3
- package/dist/esm/knowledge-review.css +1 -1
- package/dist/esm/layouts/full-layout.js +1 -1
- package/dist/esm/layouts/sidebar.js +1 -1
- package/dist/esm/scenes/knowledge-review.js +38 -8
- package/dist/esm/scenes/knowledge-review.js.map +1 -1
- package/dist/index.d.ts +12 -1
- package/dist/input.d.ts +2 -0
- package/dist/knowledge-review.d.ts +7 -1
- package/dist/sidebar.d.ts +5 -0
- package/dist/stats.html +1 -1
- package/package.json +1 -1
- package/dist/esm/chunks/review-list.DybOsf_S.js.map +0 -1
- package/dist/esm/chunks/sidebar.DCi9MWl5.js.map +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { ScrollArea } from '../components/ui/scroll-area.js';
|
|
3
3
|
import { c as cn } from './utils.Cwtlq8dh.js';
|
|
4
|
-
import { ArrowBendUpLeft, MagnifyingGlass,
|
|
4
|
+
import { ArrowBendUpLeft, X, MagnifyingGlass, Folder, FolderOpen, FolderDashed, DotsThree, Plus, FileDashed, File, Lightning, Article } from '@phosphor-icons/react';
|
|
5
5
|
import { Button } from '../components/ui/button.js';
|
|
6
6
|
import { u as useDebounce } from './hooks.CKojclfe.js';
|
|
7
7
|
import { Input } from '../components/ui/input.js';
|
|
8
|
-
import { Button as Button$1, useTreeData, useDragAndDrop, DropIndicator, Tree, TreeItem, TreeItemContent, Collection } from 'react-aria-components';
|
|
8
|
+
import { TreeStateContext, Button as Button$1, useTreeData, useDragAndDrop, DropIndicator, Tree, TreeItem, TreeItemContent, Collection } from 'react-aria-components';
|
|
9
9
|
import { ButtonGroup } from '../components/ui/button-group.js';
|
|
10
10
|
|
|
11
11
|
const SidebarContext = React.createContext(null);
|
|
@@ -22,9 +22,12 @@ function SidebarProvider({
|
|
|
22
22
|
children
|
|
23
23
|
}) {
|
|
24
24
|
const [isSearching, setIsSearching] = React.useState(false);
|
|
25
|
+
const [searchValue, setSearchValue] = React.useState("");
|
|
26
|
+
const [lastSelectedArticleId, setLastSelectedArticleId] = React.useState(null);
|
|
25
27
|
const handleSearchArticles = React.useCallback(
|
|
26
28
|
(value) => {
|
|
27
|
-
|
|
29
|
+
const trimmedValue = value.trim();
|
|
30
|
+
setIsSearching(trimmedValue !== "");
|
|
28
31
|
onSearchArticles?.(value);
|
|
29
32
|
},
|
|
30
33
|
[onSearchArticles]
|
|
@@ -41,10 +44,16 @@ function SidebarProvider({
|
|
|
41
44
|
canMoveArticle,
|
|
42
45
|
onMoveArticle,
|
|
43
46
|
isSearching,
|
|
47
|
+
searchValue,
|
|
48
|
+
setSearchValue,
|
|
49
|
+
lastSelectedArticleId,
|
|
50
|
+
setLastSelectedArticleId,
|
|
44
51
|
handleSearchArticles
|
|
45
52
|
}),
|
|
46
53
|
[
|
|
47
54
|
isSearching,
|
|
55
|
+
searchValue,
|
|
56
|
+
lastSelectedArticleId,
|
|
48
57
|
collapsed,
|
|
49
58
|
ItemLinkComponent2,
|
|
50
59
|
activeArticleId,
|
|
@@ -97,29 +106,41 @@ function AppNav({ className, items, activeId, showBack, onBack }) {
|
|
|
97
106
|
}
|
|
98
107
|
|
|
99
108
|
function ArticleSearch() {
|
|
100
|
-
const { handleSearchArticles } = useSidebar();
|
|
109
|
+
const { handleSearchArticles, searchValue, setSearchValue } = useSidebar();
|
|
101
110
|
const [searchInteracted, setSearchInteracted] = React.useState(false);
|
|
102
|
-
const
|
|
103
|
-
const
|
|
111
|
+
const debouncedSearchValue = useDebounce(searchValue, 300);
|
|
112
|
+
const searchInputRef = React.useRef(null);
|
|
104
113
|
React.useEffect(() => {
|
|
105
114
|
if (searchInteracted) handleSearchArticles?.(debouncedSearchValue);
|
|
106
115
|
}, [debouncedSearchValue, handleSearchArticles, searchInteracted]);
|
|
107
116
|
return /* @__PURE__ */ React.createElement("div", { className: "mb-2" }, /* @__PURE__ */ React.createElement(
|
|
108
117
|
Input,
|
|
109
118
|
{
|
|
119
|
+
ref: searchInputRef,
|
|
110
120
|
className: "h-auto text-subtlest border-border-subtle",
|
|
111
|
-
|
|
121
|
+
startIcon: MagnifyingGlass,
|
|
122
|
+
endIcon: searchValue ? X : void 0,
|
|
123
|
+
onEndIconClick: () => {
|
|
124
|
+
setSearchValue("");
|
|
125
|
+
handleSearchArticles?.("");
|
|
126
|
+
},
|
|
112
127
|
value: searchValue,
|
|
113
128
|
onChange: (e) => {
|
|
129
|
+
const value = e.target.value;
|
|
114
130
|
if (!searchInteracted) setSearchInteracted(true);
|
|
115
|
-
setSearchValue(
|
|
131
|
+
setSearchValue(value);
|
|
132
|
+
if (value.trim() === "") handleSearchArticles("");
|
|
116
133
|
},
|
|
117
134
|
placeholder: "Find an article",
|
|
118
|
-
"aria-label": "Find an article"
|
|
135
|
+
"aria-label": "Find an article",
|
|
136
|
+
type: "search"
|
|
119
137
|
}
|
|
120
138
|
));
|
|
121
139
|
}
|
|
122
140
|
|
|
141
|
+
function FolderSlotButton({ children }) {
|
|
142
|
+
return /* @__PURE__ */ React.createElement(Button$1, { slot: "chevron", className: "relative z-30 flex p-0" }, /* @__PURE__ */ React.createElement("span", { className: "relative inline-flex size-4 items-center justify-center" }, children));
|
|
143
|
+
}
|
|
123
144
|
function ArticleItem({
|
|
124
145
|
item,
|
|
125
146
|
hasChildItems,
|
|
@@ -128,8 +149,10 @@ function ArticleItem({
|
|
|
128
149
|
ItemLinkComponent: ItemLinkComponent2,
|
|
129
150
|
onAddArticle,
|
|
130
151
|
isAddingArticle,
|
|
131
|
-
onMoreActions
|
|
152
|
+
onMoreActions,
|
|
153
|
+
isSearching
|
|
132
154
|
}) {
|
|
155
|
+
const treeState = React.useContext(TreeStateContext);
|
|
133
156
|
const handleAddClick = (e) => {
|
|
134
157
|
e.stopPropagation();
|
|
135
158
|
onAddArticle?.(item.value.id);
|
|
@@ -151,20 +174,62 @@ function ArticleItem({
|
|
|
151
174
|
default:
|
|
152
175
|
statusLabel = "";
|
|
153
176
|
}
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
177
|
+
const folderIcon = /* @__PURE__ */ React.createElement(FolderSlotButton, null, /* @__PURE__ */ React.createElement(
|
|
178
|
+
Folder,
|
|
179
|
+
{
|
|
180
|
+
"aria-hidden": "true",
|
|
181
|
+
weight: "fill",
|
|
182
|
+
className: cn(
|
|
183
|
+
"absolute size-4 transition-opacity duration-200 ease-out",
|
|
184
|
+
isExpanded ? "opacity-0" : "opacity-100"
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
), /* @__PURE__ */ React.createElement(
|
|
188
|
+
FolderOpen,
|
|
189
|
+
{
|
|
190
|
+
"aria-hidden": "true",
|
|
191
|
+
weight: "fill",
|
|
192
|
+
className: cn(
|
|
193
|
+
"absolute size-4 transition-opacity duration-200 ease-out",
|
|
194
|
+
isExpanded ? "opacity-100" : "opacity-0"
|
|
195
|
+
)
|
|
196
|
+
}
|
|
197
|
+
));
|
|
198
|
+
const folderWithChangesIcon = /* @__PURE__ */ React.createElement(FolderSlotButton, null, /* @__PURE__ */ React.createElement(
|
|
199
|
+
FolderDashed,
|
|
200
|
+
{
|
|
201
|
+
"aria-hidden": "true",
|
|
202
|
+
weight: "fill",
|
|
203
|
+
className: cn(
|
|
204
|
+
"absolute size-4 transition-opacity duration-200 ease-out",
|
|
205
|
+
isExpanded ? "opacity-0" : "opacity-100"
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
), /* @__PURE__ */ React.createElement(
|
|
209
|
+
FolderOpen,
|
|
210
|
+
{
|
|
211
|
+
"aria-hidden": "true",
|
|
212
|
+
weight: "fill",
|
|
213
|
+
className: cn(
|
|
214
|
+
"absolute size-4 transition-opacity duration-200 ease-out",
|
|
215
|
+
isExpanded ? "opacity-100" : "opacity-0"
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
));
|
|
219
|
+
const discoveryIconContent = /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", { className: "sr-only" }, "Knowledge Discovery"), /* @__PURE__ */ React.createElement(Lightning, { "aria-hidden": "true", weight: "fill", className: "size-4 shrink-0 text-blue-600" }));
|
|
220
|
+
const discoveryIcon = hasChildItems ? /* @__PURE__ */ React.createElement(FolderSlotButton, null, /* @__PURE__ */ React.createElement("span", { className: "text-blue-600" }, discoveryIconContent)) : /* @__PURE__ */ React.createElement("span", { className: "flex size-4 shrink-0 items-center justify-center text-blue-600" }, discoveryIconContent);
|
|
221
|
+
const fileIcon = /* @__PURE__ */ React.createElement("span", { className: "flex size-4 shrink-0 items-center justify-center" }, /* @__PURE__ */ React.createElement(File, { "aria-hidden": "true", className: "size-4" }));
|
|
222
|
+
const fileWithChangesIcon = /* @__PURE__ */ React.createElement("span", { className: "flex size-4 shrink-0 items-center justify-center" }, /* @__PURE__ */ React.createElement("span", { className: "sr-only" }, "Unpublished Changes"), /* @__PURE__ */ React.createElement(FileDashed, { "aria-hidden": "true", className: "size-4" }));
|
|
223
|
+
const renderStatusIcon = (status, hasChildItems2) => {
|
|
159
224
|
if (status === "discovery") {
|
|
160
225
|
return discoveryIcon;
|
|
161
|
-
} else if (status === "unpublished" || status === "draft") {
|
|
162
|
-
return unpublishedIcon;
|
|
163
226
|
}
|
|
164
|
-
|
|
165
|
-
|
|
227
|
+
const hasChanges = status === "unpublished" || status === "draft";
|
|
228
|
+
if (hasChildItems2) {
|
|
229
|
+
return hasChanges ? folderWithChangesIcon : folderIcon;
|
|
230
|
+
} else {
|
|
231
|
+
return hasChanges ? fileWithChangesIcon : fileIcon;
|
|
166
232
|
}
|
|
167
|
-
return null;
|
|
168
233
|
};
|
|
169
234
|
return /* @__PURE__ */ React.createElement(
|
|
170
235
|
"div",
|
|
@@ -176,8 +241,7 @@ function ArticleItem({
|
|
|
176
241
|
)
|
|
177
242
|
},
|
|
178
243
|
/* @__PURE__ */ React.createElement(Button$1, { slot: "drag", className: "sr-only" }, "Drag ", item.value.label),
|
|
179
|
-
|
|
180
|
-
renderStatusIcon(item.value.status, !hasChildItems),
|
|
244
|
+
isSearching ? null : renderStatusIcon(item.value.status, hasChildItems),
|
|
181
245
|
/* @__PURE__ */ React.createElement(
|
|
182
246
|
ItemLinkComponent2,
|
|
183
247
|
{
|
|
@@ -188,7 +252,15 @@ function ArticleItem({
|
|
|
188
252
|
className: cn(
|
|
189
253
|
"min-w-0 text-inherit text-sm truncate flex-1 after:absolute after:inset-0 after:z-10 pr-1",
|
|
190
254
|
isSelected && "text-primary-foreground"
|
|
191
|
-
)
|
|
255
|
+
),
|
|
256
|
+
onClick: hasChildItems && treeState ? () => {
|
|
257
|
+
treeState.toggleKey(item.key);
|
|
258
|
+
} : void 0,
|
|
259
|
+
onKeyDown: hasChildItems && treeState ? (e) => {
|
|
260
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
261
|
+
treeState?.toggleKey(item.key);
|
|
262
|
+
}
|
|
263
|
+
} : void 0
|
|
192
264
|
},
|
|
193
265
|
item.value.label
|
|
194
266
|
),
|
|
@@ -241,16 +313,21 @@ function getParentKeys(items, targetId, parents = []) {
|
|
|
241
313
|
}
|
|
242
314
|
return null;
|
|
243
315
|
}
|
|
244
|
-
function ArticleTree({ articles }) {
|
|
316
|
+
function ArticleTree({ articles, isSearching }) {
|
|
245
317
|
const {
|
|
246
318
|
ItemLinkComponent,
|
|
247
319
|
activeArticleId,
|
|
320
|
+
lastSelectedArticleId,
|
|
321
|
+
setLastSelectedArticleId,
|
|
248
322
|
onSelectArticle,
|
|
323
|
+
handleSearchArticles,
|
|
324
|
+
setSearchValue,
|
|
249
325
|
canMoveArticle,
|
|
250
326
|
onMoveArticle,
|
|
251
327
|
onAddArticle,
|
|
252
328
|
onMoreActions
|
|
253
329
|
} = useSidebar();
|
|
330
|
+
const effectiveActiveId = activeArticleId ?? lastSelectedArticleId ?? void 0;
|
|
254
331
|
const articlesTree = useTreeData({
|
|
255
332
|
initialItems: articles,
|
|
256
333
|
getKey: (articleItem) => articleItem.id,
|
|
@@ -261,6 +338,7 @@ function ArticleTree({ articles }) {
|
|
|
261
338
|
"text/plain": item.value.label
|
|
262
339
|
})),
|
|
263
340
|
onMove: (e) => {
|
|
341
|
+
if (isSearching) return;
|
|
264
342
|
const movedArticleId = Array.from(e.keys)[0];
|
|
265
343
|
if (!movedArticleId) return;
|
|
266
344
|
const targetItem = articlesTree.getItem(e.target.key);
|
|
@@ -310,31 +388,40 @@ function ArticleTree({ articles }) {
|
|
|
310
388
|
}
|
|
311
389
|
)
|
|
312
390
|
});
|
|
313
|
-
const [
|
|
314
|
-
const
|
|
315
|
-
|
|
391
|
+
const [localSelectedKeys, setLocalSelectedKeys] = React.useState(/* @__PURE__ */ new Set());
|
|
392
|
+
const selectedKeys = effectiveActiveId != null ? /* @__PURE__ */ new Set([effectiveActiveId]) : localSelectedKeys;
|
|
393
|
+
const pathToActive = React.useMemo(() => {
|
|
394
|
+
if (!effectiveActiveId || isSearching || !articlesTree?.items?.length) return [];
|
|
316
395
|
const path = getParentKeys(
|
|
317
396
|
articlesTree.items.map((node) => node.value),
|
|
318
|
-
|
|
397
|
+
effectiveActiveId
|
|
319
398
|
);
|
|
320
|
-
return path
|
|
321
|
-
});
|
|
399
|
+
return path ?? [];
|
|
400
|
+
}, [effectiveActiveId, isSearching, articlesTree.items]);
|
|
401
|
+
const [expandedKeysState, setExpandedKeysState] = React.useState(/* @__PURE__ */ new Set());
|
|
402
|
+
const expandedKeys = React.useMemo(
|
|
403
|
+
() => /* @__PURE__ */ new Set([...pathToActive, ...expandedKeysState]),
|
|
404
|
+
[pathToActive, expandedKeysState]
|
|
405
|
+
);
|
|
406
|
+
React.useEffect(() => {
|
|
407
|
+
if (activeArticleId) setLastSelectedArticleId(null);
|
|
408
|
+
}, [activeArticleId, setLastSelectedArticleId]);
|
|
322
409
|
const pendingAddIdsRef = React.useRef(/* @__PURE__ */ new Set());
|
|
323
410
|
const [pendingAddIds, setPendingAddIds] = React.useState(/* @__PURE__ */ new Set());
|
|
324
411
|
const handleAddArticle = React.useCallback(
|
|
325
412
|
(parentId) => {
|
|
326
|
-
if (!onAddArticle || pendingAddIdsRef.current.has(parentId)) return;
|
|
413
|
+
if (isSearching || !onAddArticle || pendingAddIdsRef.current.has(parentId)) return;
|
|
327
414
|
pendingAddIdsRef.current.add(parentId);
|
|
328
415
|
setPendingAddIds(new Set(pendingAddIdsRef.current));
|
|
329
416
|
const tempId = `__placeholder_${++placeholderCounter}`;
|
|
330
417
|
const placeholder = { id: tempId, label: "Untitled", href: "", status: "draft" };
|
|
331
418
|
articlesTree.append(parentId, placeholder);
|
|
332
|
-
|
|
419
|
+
setExpandedKeysState((prev) => /* @__PURE__ */ new Set([...prev, parentId]));
|
|
333
420
|
onAddArticle(parentId).then(
|
|
334
421
|
(created) => {
|
|
335
422
|
articlesTree.remove(tempId);
|
|
336
423
|
articlesTree.append(parentId, created);
|
|
337
|
-
|
|
424
|
+
setLocalSelectedKeys(/* @__PURE__ */ new Set([created.id]));
|
|
338
425
|
onSelectArticle?.(created.id);
|
|
339
426
|
pendingAddIdsRef.current.delete(parentId);
|
|
340
427
|
setPendingAddIds(new Set(pendingAddIdsRef.current));
|
|
@@ -346,26 +433,34 @@ function ArticleTree({ articles }) {
|
|
|
346
433
|
}
|
|
347
434
|
);
|
|
348
435
|
},
|
|
349
|
-
[onAddArticle, articlesTree, onSelectArticle]
|
|
436
|
+
[isSearching, onAddArticle, articlesTree, onSelectArticle]
|
|
350
437
|
);
|
|
351
438
|
return /* @__PURE__ */ React.createElement(
|
|
352
439
|
Tree,
|
|
353
440
|
{
|
|
354
|
-
"aria-label": "Articles tree",
|
|
441
|
+
"aria-label": isSearching ? "Search results" : "Articles tree",
|
|
355
442
|
items: articlesTree.items,
|
|
356
|
-
dragAndDropHooks,
|
|
443
|
+
dragAndDropHooks: isSearching ? void 0 : dragAndDropHooks,
|
|
357
444
|
className: "flex flex-col gap-0.5",
|
|
358
445
|
selectionBehavior: "toggle",
|
|
359
446
|
selectionMode: "single",
|
|
360
447
|
expandedKeys,
|
|
361
|
-
onExpandedChange:
|
|
448
|
+
onExpandedChange: setExpandedKeysState,
|
|
362
449
|
selectedKeys,
|
|
363
450
|
disallowEmptySelection: true,
|
|
364
451
|
onSelectionChange: (selection) => {
|
|
365
452
|
if (selection !== "all") {
|
|
366
|
-
|
|
453
|
+
if (effectiveActiveId == null) setLocalSelectedKeys(selection);
|
|
367
454
|
const selected = Array.from(selection)?.[0];
|
|
368
|
-
|
|
455
|
+
if (selected) {
|
|
456
|
+
const selectedId = selected.toString();
|
|
457
|
+
onSelectArticle?.(selectedId);
|
|
458
|
+
if (isSearching) {
|
|
459
|
+
setLastSelectedArticleId(selectedId);
|
|
460
|
+
setSearchValue("");
|
|
461
|
+
handleSearchArticles?.("");
|
|
462
|
+
}
|
|
463
|
+
}
|
|
369
464
|
}
|
|
370
465
|
}
|
|
371
466
|
},
|
|
@@ -375,20 +470,43 @@ function ArticleTree({ articles }) {
|
|
|
375
470
|
{
|
|
376
471
|
ItemLinkComponent,
|
|
377
472
|
item,
|
|
378
|
-
onAddArticle: onAddArticle ? handleAddArticle : void 0,
|
|
379
|
-
isAddingArticle: pendingAddIds.has(item.value.id),
|
|
473
|
+
onAddArticle: !isSearching && onAddArticle ? handleAddArticle : void 0,
|
|
474
|
+
isAddingArticle: !isSearching && pendingAddIds.has(item.value.id),
|
|
380
475
|
onMoreActions: onMoreActions ? (articleId) => onMoreActions(articleId) : void 0,
|
|
476
|
+
isSearching,
|
|
381
477
|
...props
|
|
382
478
|
}
|
|
383
|
-
)), item.children && /* @__PURE__ */ React.createElement(Collection, { items: item.children }, renderItem));
|
|
479
|
+
)), !isSearching && item.children && /* @__PURE__ */ React.createElement(Collection, { items: item.children }, renderItem));
|
|
384
480
|
}
|
|
385
481
|
);
|
|
386
482
|
}
|
|
387
483
|
|
|
484
|
+
function flattenAndFilterArticles(articles, query) {
|
|
485
|
+
const result = [];
|
|
486
|
+
const queryWords = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
487
|
+
const traverse = (items) => {
|
|
488
|
+
items.forEach((item) => {
|
|
489
|
+
const label = item.label.toLowerCase();
|
|
490
|
+
const isMatch = queryWords.every((word) => label.includes(word));
|
|
491
|
+
if (isMatch) {
|
|
492
|
+
result.push({ ...item, items: [] });
|
|
493
|
+
}
|
|
494
|
+
if (item.items) {
|
|
495
|
+
traverse(item.items);
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
};
|
|
499
|
+
traverse(articles);
|
|
500
|
+
return result;
|
|
501
|
+
}
|
|
388
502
|
function ArticleNav({ articles, className }) {
|
|
389
|
-
const { isSearching, onAddArticle } = useSidebar();
|
|
503
|
+
const { isSearching, searchValue, onAddArticle } = useSidebar();
|
|
504
|
+
const filteredArticles = React.useMemo(() => {
|
|
505
|
+
if (!isSearching || !articles) return [];
|
|
506
|
+
return flattenAndFilterArticles(articles, searchValue);
|
|
507
|
+
}, [articles, isSearching, searchValue]);
|
|
390
508
|
return /* @__PURE__ */ React.createElement("div", { className: cn("flex flex-col gap-0.5 px-4", className) }, !isSearching && (!articles || articles.length === 0) ? /* @__PURE__ */ React.createElement(Button, { variant: "ghost", className: "text-subtlest", onClick: () => onAddArticle?.(null).catch(() => {
|
|
391
|
-
}) }, /* @__PURE__ */ React.createElement(Article, { "aria-hidden": "true" }), "Create first article or folder") : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ArticleSearch, null),
|
|
509
|
+
}) }, /* @__PURE__ */ React.createElement(Article, { "aria-hidden": "true" }), "Create first article or folder") : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ArticleSearch, null), isSearching ? filteredArticles.length > 0 ? /* @__PURE__ */ React.createElement(ArticleTree, { key: searchValue, articles: filteredArticles, isSearching: true }) : /* @__PURE__ */ React.createElement("span", { className: "text-subtlest text-sm px-2" }, "No articles found") : articles?.length ? /* @__PURE__ */ React.createElement("nav", { "aria-label": "Articles navigation" }, /* @__PURE__ */ React.createElement(ArticleTree, { articles })) : null));
|
|
392
510
|
}
|
|
393
511
|
|
|
394
512
|
function SectionNav({ className, items, activeId }) {
|
|
@@ -457,7 +575,7 @@ const Sidebar = React.forwardRef(function Sidebar2({
|
|
|
457
575
|
ref,
|
|
458
576
|
...props,
|
|
459
577
|
className: cn(
|
|
460
|
-
"py-4 transition-width duration-200 ease-in-out flex flex-col h-dvh
|
|
578
|
+
"py-4 transition-width duration-200 ease-in-out flex flex-col h-dvh",
|
|
461
579
|
collapsed ? "w-[64px]" : "w-[260px]",
|
|
462
580
|
className
|
|
463
581
|
),
|
|
@@ -477,7 +595,7 @@ const Sidebar = React.forwardRef(function Sidebar2({
|
|
|
477
595
|
onBack: onAppBack
|
|
478
596
|
}
|
|
479
597
|
),
|
|
480
|
-
!collapsed && /* @__PURE__ */ React.createElement(React.Fragment, null, showArticles && /* @__PURE__ */ React.createElement(ScrollArea, {
|
|
598
|
+
!collapsed && /* @__PURE__ */ React.createElement(React.Fragment, null, showArticles && /* @__PURE__ */ React.createElement(ScrollArea, { onScroll: handleScroll }, /* @__PURE__ */ React.createElement(ArticleNav, { className: "py-4 max-w-[var(--left-nav-width,inherit)]", articles })), sectionNavItems && sectionNavItems.length > 0 && /* @__PURE__ */ React.createElement(
|
|
481
599
|
SectionNav,
|
|
482
600
|
{
|
|
483
601
|
className: cn("pt-4 flex-shrink-0", !collapsed && !atScrollBottom && "border-t border-subtle"),
|
|
@@ -490,4 +608,4 @@ const Sidebar = React.forwardRef(function Sidebar2({
|
|
|
490
608
|
});
|
|
491
609
|
|
|
492
610
|
export { Sidebar as S, useSidebar as u };
|
|
493
|
-
//# sourceMappingURL=sidebar.
|
|
611
|
+
//# sourceMappingURL=sidebar.kcc3uFga.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidebar.kcc3uFga.js","sources":["../../../src/layouts/sidebar/context.tsx","../../../src/layouts/sidebar/app-nav/app-nav.tsx","../../../src/layouts/sidebar/article-nav/article-search.tsx","../../../src/layouts/sidebar/article-nav/article-item.tsx","../../../src/layouts/sidebar/article-nav/article-tree.tsx","../../../src/layouts/sidebar/article-nav/article-nav.tsx","../../../src/layouts/sidebar/section-nav/section-nav.tsx","../../../src/layouts/sidebar/sidebar.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { ArticleNavItem, ItemLinkComponent } from './types';\n\nexport interface SidebarContextProps {\n collapsed: boolean;\n ItemLinkComponent: ItemLinkComponent;\n activeArticleId?: string;\n onSelectArticle?: (id: string) => void;\n onSearchArticles?: (value: string) => void;\n onAddArticle?: (parentId: string | null) => Promise<ArticleNavItem>;\n onMoreActions?: (articleId: string) => void;\n canMoveArticle?: (move: { id: string; parentId: string | null; index: number }) => boolean;\n onMoveArticle?: (moved: { id: string; parentId: string | null; index: number }) => void | Promise<void>;\n}\n\nexport interface SidebarContextValue extends SidebarContextProps {\n handleSearchArticles: (value: string) => void;\n isSearching: boolean;\n searchValue: string;\n setSearchValue: React.Dispatch<React.SetStateAction<string>>;\n /** Set when user selects from search results; tree uses this until activeArticleId catches up */\n lastSelectedArticleId: string | null;\n setLastSelectedArticleId: React.Dispatch<React.SetStateAction<string | null>>;\n}\n\nconst SidebarContext = React.createContext<SidebarContextValue | null>(null);\n\nexport function SidebarProvider({\n collapsed,\n ItemLinkComponent,\n activeArticleId,\n onSelectArticle,\n onSearchArticles,\n onAddArticle,\n onMoreActions,\n canMoveArticle,\n onMoveArticle,\n children,\n}: React.PropsWithChildren<SidebarContextProps>) {\n const [isSearching, setIsSearching] = React.useState<boolean>(false);\n const [searchValue, setSearchValue] = React.useState<string>('');\n const [lastSelectedArticleId, setLastSelectedArticleId] = React.useState<string | null>(null);\n\n const handleSearchArticles = React.useCallback(\n (value: string) => {\n const trimmedValue = value.trim();\n setIsSearching(trimmedValue !== '');\n onSearchArticles?.(value);\n },\n [onSearchArticles],\n );\n\n const contextValue = React.useMemo<SidebarContextValue>(\n () => ({\n collapsed,\n ItemLinkComponent,\n activeArticleId,\n onSearchArticles,\n onSelectArticle,\n onAddArticle,\n onMoreActions,\n canMoveArticle,\n onMoveArticle,\n isSearching,\n searchValue,\n setSearchValue,\n lastSelectedArticleId,\n setLastSelectedArticleId,\n handleSearchArticles,\n }),\n [\n isSearching,\n searchValue,\n lastSelectedArticleId,\n collapsed,\n ItemLinkComponent,\n activeArticleId,\n onSelectArticle,\n onSearchArticles,\n onAddArticle,\n onMoreActions,\n canMoveArticle,\n onMoveArticle,\n handleSearchArticles,\n ],\n );\n\n return <SidebarContext.Provider value={contextValue}>{children}</SidebarContext.Provider>;\n}\n\nexport function useSidebar() {\n const sidebarContext = React.useContext(SidebarContext);\n\n if (!sidebarContext) throw new Error('useSidebar must be used within SidebarProvider');\n\n return sidebarContext;\n}\n","import * as React from 'react';\nimport { ArrowBendUpLeft } from '@phosphor-icons/react';\n\nimport type { SidebarNavItem } from '../types';\nimport { useSidebar } from '../context';\n\nimport { Button } from '@/components/ui/button';\nimport { cn } from '@/lib/utils';\n\nexport interface AppNavProps {\n className?: string;\n items?: SidebarNavItem[];\n activeId?: string;\n showBack?: boolean;\n onBack?: () => void;\n}\n\nexport function AppNav({ className, items, activeId, showBack, onBack }: AppNavProps) {\n const { collapsed, ItemLinkComponent } = useSidebar();\n\n const hasBack = !!showBack && !!onBack;\n\n return (\n <nav className={cn('flex flex-col gap-2', className)} aria-label=\"App navigation\">\n {hasBack && (\n <Button\n variant=\"link\"\n className={cn('py-2 text-base text-default w-full', collapsed ? 'justify-center' : 'justify-start')}\n size=\"icon\"\n onClick={onBack}\n >\n <ArrowBendUpLeft aria-hidden=\"true\" />\n <span className={cn(collapsed && 'sr-only')}>back to Brainfish</span>\n </Button>\n )}\n {items?.map((item) => (\n <ItemLinkComponent\n key={item.id}\n className={cn(\n 'flex p-2 rounded-lg gap-1 text-base text-default items-center hover:text-primary-foreground focus:text-primary-foreground',\n item.id === activeId\n ? 'bg-primary text-primary-foreground font-bold'\n : 'hover:bg-lime-100 focus:bg-lime-100',\n )}\n href={item.href}\n data-sidebar-item-id={item.id}\n data-sidebar-item-type=\"app\"\n data-sidebar-app-nav-item-selected={item.id === activeId}\n >\n {item.Icon ? <item.Icon weight={item.id === activeId ? 'fill' : 'regular'} size={16} /> : null}\n <span className={cn('transition-opacity duration-200', collapsed && 'opacity-0 sr-only')}>{item.label}</span>\n </ItemLinkComponent>\n ))}\n </nav>\n );\n}\n","import * as React from 'react';\nimport { MagnifyingGlass, X } from '@phosphor-icons/react';\n\nimport { useSidebar } from '../context';\n\nimport { useDebounce } from '@/lib/hooks';\nimport { Input } from '@/components/ui/input';\n\nexport function ArticleSearch() {\n const { handleSearchArticles, searchValue, setSearchValue } = useSidebar();\n const [searchInteracted, setSearchInteracted] = React.useState(false);\n const debouncedSearchValue = useDebounce(searchValue, 300);\n const searchInputRef = React.useRef<HTMLInputElement>(null);\n\n React.useEffect(() => {\n if (searchInteracted) handleSearchArticles?.(debouncedSearchValue);\n }, [debouncedSearchValue, handleSearchArticles, searchInteracted]);\n\n return (\n <div className=\"mb-2\">\n <Input\n ref={searchInputRef}\n className=\"h-auto text-subtlest border-border-subtle\"\n startIcon={MagnifyingGlass}\n endIcon={searchValue ? X : undefined}\n onEndIconClick={() => {\n setSearchValue('');\n handleSearchArticles?.('');\n }}\n value={searchValue}\n onChange={(e) => {\n const value = e.target.value;\n if (!searchInteracted) setSearchInteracted(true);\n setSearchValue(value);\n if (value.trim() === '') handleSearchArticles('');\n }}\n placeholder=\"Find an article\"\n aria-label=\"Find an article\"\n type=\"search\"\n />\n </div>\n );\n}\n","import * as React from 'react';\nimport { Folder, FolderDashed, FolderOpen, File, FileDashed, DotsThree, Lightning, Plus } from '@phosphor-icons/react';\nimport { Key, TreeItemContentRenderProps, TreeStateContext, Button as AriaButton } from 'react-aria-components';\n\nimport { ArticleNavItem, ItemLinkComponent } from '../types';\n\nimport { cn } from '@/lib/utils';\nimport { Button } from '@/components/ui/button';\nimport { ButtonGroup } from '@/components/ui/button-group';\n\ntype ArticleItemTreeNode = {\n key: Key;\n value: ArticleNavItem;\n children: ArticleItemTreeNode[] | null;\n};\n\nfunction FolderSlotButton({ children }: { children: React.ReactNode }) {\n return (\n <AriaButton slot=\"chevron\" className=\"relative z-30 flex p-0\">\n <span className=\"relative inline-flex size-4 items-center justify-center\">{children}</span>\n </AriaButton>\n );\n}\n\nexport interface ArticleItemProps extends TreeItemContentRenderProps {\n ItemLinkComponent: ItemLinkComponent;\n item: ArticleItemTreeNode;\n onAddArticle?: (parentId: string) => void;\n isAddingArticle?: boolean;\n onMoreActions?: (articleId: string) => void;\n isSearching?: boolean;\n}\n\nexport function ArticleItem({\n item,\n hasChildItems,\n isSelected,\n isExpanded,\n ItemLinkComponent,\n onAddArticle,\n isAddingArticle,\n onMoreActions,\n isSearching,\n}: ArticleItemProps) {\n const treeState = React.useContext(TreeStateContext);\n\n const handleAddClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n onAddArticle?.(item.value.id);\n };\n\n const handleMoreClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n onMoreActions?.(item.value.id);\n };\n\n const showActions = !!((onAddArticle && !isAddingArticle) || onMoreActions);\n\n const isDraft = item.value.status === 'draft';\n\n let statusLabel: string;\n switch (item.value.status) {\n case 'draft':\n statusLabel = '(draft)';\n break;\n case 'unpublished':\n statusLabel = '(unpublished changes)';\n break;\n default:\n statusLabel = '';\n }\n\n const folderIcon = (\n <FolderSlotButton>\n <Folder\n aria-hidden=\"true\"\n weight=\"fill\"\n className={cn(\n 'absolute size-4 transition-opacity duration-200 ease-out',\n isExpanded ? 'opacity-0' : 'opacity-100',\n )}\n />\n <FolderOpen\n aria-hidden=\"true\"\n weight=\"fill\"\n className={cn(\n 'absolute size-4 transition-opacity duration-200 ease-out',\n isExpanded ? 'opacity-100' : 'opacity-0',\n )}\n />\n </FolderSlotButton>\n );\n\n const folderWithChangesIcon = (\n <FolderSlotButton>\n <FolderDashed\n aria-hidden=\"true\"\n weight=\"fill\"\n className={cn(\n 'absolute size-4 transition-opacity duration-200 ease-out',\n isExpanded ? 'opacity-0' : 'opacity-100',\n )}\n />\n <FolderOpen\n aria-hidden=\"true\"\n weight=\"fill\"\n className={cn(\n 'absolute size-4 transition-opacity duration-200 ease-out',\n isExpanded ? 'opacity-100' : 'opacity-0',\n )}\n />\n </FolderSlotButton>\n );\n\n const discoveryIconContent = (\n <>\n <span className=\"sr-only\">Knowledge Discovery</span>\n <Lightning aria-hidden=\"true\" weight=\"fill\" className=\"size-4 shrink-0 text-blue-600\" />\n </>\n );\n\n const discoveryIcon = hasChildItems ? (\n <FolderSlotButton>\n <span className=\"text-blue-600\">{discoveryIconContent}</span>\n </FolderSlotButton>\n ) : (\n <span className=\"flex size-4 shrink-0 items-center justify-center text-blue-600\">{discoveryIconContent}</span>\n );\n\n const fileIcon = (\n <span className=\"flex size-4 shrink-0 items-center justify-center\">\n <File aria-hidden=\"true\" className=\"size-4\" />\n </span>\n );\n\n const fileWithChangesIcon = (\n <span className=\"flex size-4 shrink-0 items-center justify-center\">\n <span className=\"sr-only\">Unpublished Changes</span>\n <FileDashed aria-hidden=\"true\" className=\"size-4\" />\n </span>\n );\n\n const renderStatusIcon = (status: ArticleNavItem['status'], hasChildItems: boolean) => {\n if (status === 'discovery') {\n return discoveryIcon;\n }\n\n const hasChanges = status === 'unpublished' || status === 'draft';\n\n if (hasChildItems) {\n return hasChanges ? folderWithChangesIcon : folderIcon;\n } else {\n return hasChanges ? fileWithChangesIcon : fileIcon;\n }\n };\n\n return (\n <div\n className={cn(\n 'group relative flex items-center gap-1 rounded-md py-1 pl-[calc(var(--tree-item-level)*0.5rem)] pr-4 h-9',\n isDraft && 'text-subtlest italic',\n isSelected\n ? 'bg-lime-100 text-primary-foreground font-bold after:absolute after:-right-0.5 after:top-1/2 after:h-1/2 after:w-1 after:-translate-y-1/2 after:bg-lime-400'\n : 'hover:bg-dark-200 hover:text-accent-foreground',\n )}\n >\n <AriaButton slot=\"drag\" className=\"sr-only\">\n Drag {item.value.label}\n </AriaButton>\n\n {isSearching ? null : renderStatusIcon(item.value.status, hasChildItems)}\n\n <ItemLinkComponent\n href={item.value.href}\n title={`${item.value.label} ${statusLabel}`}\n data-sidebar-item-id={item.value.id}\n data-sidebar-item-type=\"article\"\n className={cn(\n 'min-w-0 text-inherit text-sm truncate flex-1 after:absolute after:inset-0 after:z-10 pr-1',\n isSelected && 'text-primary-foreground',\n )}\n onClick={\n hasChildItems && treeState\n ? () => {\n treeState.toggleKey(item.key);\n }\n : undefined\n }\n onKeyDown={\n hasChildItems && treeState\n ? (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n treeState?.toggleKey(item.key);\n }\n }\n : undefined\n }\n >\n {item.value.label}\n </ItemLinkComponent>\n\n {showActions && (\n <ButtonGroup\n orientation=\"horizontal\"\n className={cn(\n 'absolute h-4 my-auto right-0.5 top-0 bottom-0 z-20 hidden items-center rounded-xl',\n 'group-hover:flex group-focus-within:flex',\n isSelected ? 'bg-lime-100 text-primary-foreground' : 'bg-dark-200',\n )}\n >\n {onMoreActions && (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`More actions for ${item.value.label}`}\n className=\"size-4 [&_svg]:size-3.5\"\n onClick={handleMoreClick}\n >\n <DotsThree aria-hidden=\"true\" weight=\"bold\" />\n </Button>\n )}\n\n {onAddArticle && !isAddingArticle && (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`Add article to ${item.value.label}`}\n className=\"size-4 [&_svg]:size-3.5\"\n onClick={handleAddClick}\n >\n <Plus aria-hidden=\"true\" />\n </Button>\n )}\n </ButtonGroup>\n )}\n </div>\n );\n}\n","import * as React from 'react';\nimport {\n useDragAndDrop,\n useTreeData,\n Tree,\n TreeItem,\n TreeItemContent,\n Collection,\n DropIndicator,\n type Key,\n} from 'react-aria-components';\n\nimport { ArticleNavItem } from '../types';\nimport { ArticleItem } from './article-item';\nimport { useSidebar } from '../context';\n\nlet placeholderCounter = 0;\n\ninterface ArticleTreeProps {\n articles: ArticleNavItem[];\n isSearching?: boolean;\n}\n\nfunction getParentKeys(items: ArticleNavItem[], targetId: string, parents: string[] = []): string[] | null {\n for (const item of items) {\n if (item.id === targetId) {\n return parents;\n }\n if (item.items && item.items.length > 0) {\n const result = getParentKeys(item.items, targetId, [...parents, item.id]);\n if (result) return result;\n }\n }\n\n return null;\n}\n\nexport function ArticleTree({ articles, isSearching }: ArticleTreeProps) {\n const {\n ItemLinkComponent,\n activeArticleId,\n lastSelectedArticleId,\n setLastSelectedArticleId,\n onSelectArticle,\n handleSearchArticles,\n setSearchValue,\n canMoveArticle,\n onMoveArticle,\n onAddArticle,\n onMoreActions,\n } = useSidebar();\n\n const effectiveActiveId = activeArticleId ?? lastSelectedArticleId ?? undefined;\n\n const articlesTree = useTreeData({\n initialItems: articles,\n getKey: (articleItem) => articleItem.id,\n getChildren: (articleItem) => articleItem.items ?? [],\n });\n\n const { dragAndDropHooks } = useDragAndDrop({\n getItems: (_keys, items: typeof articlesTree.items) =>\n items.map((item) => ({\n 'text/plain': item.value.label,\n })),\n onMove: (e) => {\n if (isSearching) return;\n const movedArticleId = Array.from(e.keys)[0];\n if (!movedArticleId) return;\n\n const targetItem = articlesTree.getItem(e.target.key);\n if (!targetItem) return;\n\n let movedToParentId: string | null;\n let movedToIndex: number;\n\n if (e.target.dropPosition === 'on') {\n movedToParentId = e.target.key.toString();\n movedToIndex = targetItem.children?.length ?? 0;\n } else {\n movedToParentId = targetItem.parentKey?.toString() ?? null;\n const siblings = movedToParentId ? (articlesTree.getItem(movedToParentId)?.children ?? []) : articlesTree.items;\n const targetIndex = siblings.findIndex((i) => i.key === e.target.key);\n movedToIndex = e.target.dropPosition === 'before' ? targetIndex : targetIndex + 1;\n }\n\n const moveDetails = {\n id: movedArticleId.toString(),\n parentId: movedToParentId,\n index: movedToIndex,\n };\n\n if (canMoveArticle && !canMoveArticle(moveDetails)) {\n return;\n }\n\n const movedItem = articlesTree.getItem(movedArticleId);\n const originalParentId = movedItem?.parentKey?.toString() ?? null;\n const originalSiblings = originalParentId\n ? (articlesTree.getItem(originalParentId)?.children ?? [])\n : articlesTree.items;\n const originalIndex = originalSiblings.findIndex((i) => i.key === movedArticleId);\n\n if (e.target.dropPosition === 'on') {\n articlesTree.move(movedArticleId, movedToParentId, movedToIndex);\n } else if (e.target.dropPosition === 'before') {\n articlesTree.moveBefore(e.target.key, e.keys);\n } else {\n articlesTree.moveAfter(e.target.key, e.keys);\n }\n\n const result = onMoveArticle?.(moveDetails);\n\n if (result && typeof result.then === 'function') {\n result.catch(() => {\n articlesTree.move(movedArticleId, originalParentId, originalIndex);\n });\n }\n },\n renderDropIndicator: (target) => (\n <DropIndicator\n target={target}\n className=\"outline outline-1 outline-lime-200 ml-[calc(var(--tree-item-level)*0.5rem)]\"\n />\n ),\n });\n\n // Selection when there's no active article from URL/context; used so the tree can show a selection before navigation.\n const [localSelectedKeys, setLocalSelectedKeys] = React.useState<Set<Key>>(new Set());\n const selectedKeys = effectiveActiveId != null ? new Set<Key>([effectiveActiveId]) : localSelectedKeys;\n\n const pathToActive = React.useMemo(() => {\n if (!effectiveActiveId || isSearching || !articlesTree?.items?.length) return [];\n const path = getParentKeys(\n articlesTree.items.map((node) => node.value),\n effectiveActiveId,\n );\n\n return path ?? [];\n }, [effectiveActiveId, isSearching, articlesTree.items]);\n\n const [expandedKeysState, setExpandedKeysState] = React.useState<Set<Key>>(new Set());\n const expandedKeys = React.useMemo(\n () => new Set<Key>([...pathToActive, ...expandedKeysState]),\n [pathToActive, expandedKeysState],\n );\n\n React.useEffect(() => {\n if (activeArticleId) setLastSelectedArticleId(null);\n }, [activeArticleId, setLastSelectedArticleId]);\n\n const pendingAddIdsRef = React.useRef<Set<string>>(new Set());\n const [pendingAddIds, setPendingAddIds] = React.useState<Set<string>>(new Set());\n\n const handleAddArticle = React.useCallback(\n (parentId: string) => {\n if (isSearching || !onAddArticle || pendingAddIdsRef.current.has(parentId)) return;\n\n pendingAddIdsRef.current.add(parentId);\n setPendingAddIds(new Set(pendingAddIdsRef.current));\n\n const tempId = `__placeholder_${++placeholderCounter}`;\n const placeholder: ArticleNavItem = { id: tempId, label: 'Untitled', href: '', status: 'draft' };\n\n articlesTree.append(parentId, placeholder);\n setExpandedKeysState((prev) => new Set([...prev, parentId]));\n\n onAddArticle(parentId).then(\n (created) => {\n articlesTree.remove(tempId);\n articlesTree.append(parentId, created);\n // Highlight the newly created article in the tree.\n setLocalSelectedKeys(new Set([created.id]));\n onSelectArticle?.(created.id);\n pendingAddIdsRef.current.delete(parentId);\n setPendingAddIds(new Set(pendingAddIdsRef.current));\n },\n () => {\n articlesTree.remove(tempId);\n pendingAddIdsRef.current.delete(parentId);\n setPendingAddIds(new Set(pendingAddIdsRef.current));\n },\n );\n },\n [isSearching, onAddArticle, articlesTree, onSelectArticle],\n );\n\n return (\n <Tree\n aria-label={isSearching ? 'Search results' : 'Articles tree'}\n items={articlesTree.items}\n dragAndDropHooks={isSearching ? undefined : dragAndDropHooks}\n className=\"flex flex-col gap-0.5\"\n selectionBehavior=\"toggle\"\n selectionMode=\"single\"\n expandedKeys={expandedKeys}\n onExpandedChange={setExpandedKeysState}\n selectedKeys={selectedKeys}\n disallowEmptySelection\n onSelectionChange={(selection) => {\n if (selection !== 'all') {\n // Keep local selection in sync when we're not driven by URL/active article.\n if (effectiveActiveId == null) setLocalSelectedKeys(selection);\n const selected = Array.from(selection)?.[0];\n\n if (selected) {\n const selectedId = selected.toString();\n onSelectArticle?.(selectedId);\n\n if (isSearching) {\n setLastSelectedArticleId(selectedId);\n setSearchValue('');\n handleSearchArticles?.('');\n }\n }\n }\n }}\n >\n {function renderItem(item) {\n return (\n <TreeItem className=\"list-none\" textValue={item.value.label} id={item.value.id}>\n <TreeItemContent>\n {(props) => (\n <ArticleItem\n ItemLinkComponent={ItemLinkComponent}\n item={item}\n onAddArticle={!isSearching && onAddArticle ? handleAddArticle : undefined}\n isAddingArticle={!isSearching && pendingAddIds.has(item.value.id)}\n onMoreActions={onMoreActions ? (articleId) => onMoreActions(articleId) : undefined}\n isSearching={isSearching}\n {...props}\n />\n )}\n </TreeItemContent>\n\n {!isSearching && item.children && <Collection items={item.children}>{renderItem}</Collection>}\n </TreeItem>\n );\n }}\n </Tree>\n );\n}\n","import * as React from 'react';\nimport { Article } from '@phosphor-icons/react';\n\nimport { useSidebar } from '../context';\nimport { ArticleNavItem } from '../types';\nimport { ArticleSearch } from './article-search';\nimport { ArticleTree } from './article-tree';\n\nimport { cn } from '@/lib/utils';\nimport { Button } from '@/components/ui/button';\n\nexport interface ArticleNavProps {\n className?: string;\n articles?: ArticleNavItem[];\n}\n\nfunction flattenAndFilterArticles(articles: ArticleNavItem[], query: string): ArticleNavItem[] {\n const result: ArticleNavItem[] = [];\n const queryWords = query.toLowerCase().split(/\\s+/).filter(Boolean);\n\n const traverse = (items: ArticleNavItem[]) => {\n items.forEach((item) => {\n const label = item.label.toLowerCase();\n const isMatch = queryWords.every((word) => label.includes(word));\n\n if (isMatch) {\n // Keep the original item but without its children for the flat view\n result.push({ ...item, items: [] });\n }\n if (item.items) {\n traverse(item.items);\n }\n });\n };\n\n traverse(articles);\n\n return result;\n}\n\nexport function ArticleNav({ articles, className }: ArticleNavProps) {\n const { isSearching, searchValue, onAddArticle } = useSidebar();\n\n const filteredArticles = React.useMemo(() => {\n if (!isSearching || !articles) return [];\n\n return flattenAndFilterArticles(articles, searchValue);\n }, [articles, isSearching, searchValue]);\n\n return (\n <div className={cn('flex flex-col gap-0.5 px-4', className)}>\n {!isSearching && (!articles || articles.length === 0) ? (\n <Button variant=\"ghost\" className=\"text-subtlest\" onClick={() => onAddArticle?.(null).catch(() => {})}>\n <Article aria-hidden=\"true\" />\n Create first article or folder\n </Button>\n ) : (\n <>\n <ArticleSearch />\n {isSearching ? (\n filteredArticles.length > 0 ? (\n <ArticleTree key={searchValue} articles={filteredArticles} isSearching />\n ) : (\n <span className=\"text-subtlest text-sm px-2\">No articles found</span>\n )\n ) : articles?.length ? (\n <nav aria-label=\"Articles navigation\">\n <ArticleTree articles={articles} />\n </nav>\n ) : null}\n </>\n )}\n </div>\n );\n}\n","import * as React from 'react';\n\nimport { SidebarNavItem } from '../types';\nimport { useSidebar } from '../context';\n\nimport { cn } from '@/lib/utils';\n\nexport interface SectionNavProps {\n className?: string;\n items: SidebarNavItem[];\n activeId?: string;\n}\n\nexport function SectionNav({ className, items, activeId }: SectionNavProps) {\n const { ItemLinkComponent } = useSidebar();\n\n return (\n <nav className={cn('flex flex-col', className)} aria-label=\"App section navigation\">\n {items.map((item) => (\n <ItemLinkComponent\n key={item.id}\n href={item.href}\n data-sidebar-item-id={item.id}\n data-sidebar-item-type=\"section\"\n data-sidebar-section-nav-item-selected={item.id === activeId}\n className={cn(\n 'flex p-2 mx-4 text-base text-default relative rounded-lg',\n 'after:transition-opacity after:absolute after:top-0 after:bottom-0 after:-right-4 after:w-2 after:bg-primary after:rounded-l-md after:opacity-0',\n 'hover:bg-lime-100 focus:bg-lime-100 hover:text-primary-foreground focus:text-primary-foreground',\n item.id === activeId && 'font-bold after:opacity-100',\n )}\n >\n {item.label}\n </ItemLinkComponent>\n ))}\n </nav>\n );\n}\n","import * as React from 'react';\n\nimport { SidebarNavItem, ArticleNavItem } from './types';\nimport { SidebarContextProps, SidebarProvider } from './context';\nimport { AppNav } from './app-nav';\nimport { ArticleNav } from './article-nav';\nimport { SectionNav } from './section-nav';\n\nimport { ScrollArea } from '@/components/ui/scroll-area';\nimport { cn } from '@/lib/utils';\n\nexport interface SidebarProps extends React.ComponentPropsWithoutRef<'aside'>, SidebarContextProps {\n showAppBack?: boolean;\n onAppBack?: () => void;\n appNavItems?: SidebarNavItem[];\n appNavActiveId?: string;\n showArticles?: boolean;\n articles?: ArticleNavItem[];\n sectionNavItems?: SidebarNavItem[];\n sectionNavActiveId?: string;\n}\n\nexport const Sidebar = React.forwardRef<HTMLElement, SidebarProps>(function Sidebar(\n {\n className,\n ItemLinkComponent,\n collapsed,\n showAppBack,\n onAppBack,\n appNavItems,\n appNavActiveId,\n sectionNavItems,\n sectionNavActiveId,\n activeArticleId,\n showArticles,\n articles,\n onSelectArticle,\n onSearchArticles,\n onAddArticle,\n onMoreActions,\n canMoveArticle,\n onMoveArticle,\n ...props\n },\n ref,\n) {\n // indicates if the scroll area is at the bottom\n const [atScrollBottom, setAtScrollBottom] = React.useState(false);\n\n // detect if the scroll area is at the bottom\n const handleScroll = (event: React.UIEvent<HTMLDivElement>) => {\n const { scrollHeight, scrollTop, clientHeight } = event.currentTarget;\n setAtScrollBottom(scrollTop + clientHeight >= scrollHeight);\n };\n\n return (\n <SidebarProvider\n collapsed={!!collapsed}\n ItemLinkComponent={ItemLinkComponent}\n activeArticleId={activeArticleId}\n onSelectArticle={onSelectArticle}\n onSearchArticles={onSearchArticles}\n onAddArticle={onAddArticle}\n onMoreActions={onMoreActions}\n canMoveArticle={canMoveArticle}\n onMoveArticle={onMoveArticle}\n >\n <aside\n ref={ref}\n {...props}\n className={cn(\n 'py-4 transition-width duration-200 ease-in-out flex flex-col h-dvh',\n collapsed ? 'w-[64px]' : 'w-[260px]',\n className,\n )}\n aria-label=\"Application navigation\"\n >\n <AppNav\n className={cn(\n 'px-4 flex-shrink-0',\n appNavItems && appNavItems.length > 0 && 'pb-4',\n !collapsed && 'border-b border-border-subtle',\n )}\n showBack={showAppBack}\n items={appNavItems}\n activeId={appNavActiveId}\n onBack={onAppBack}\n />\n\n {!collapsed && (\n <>\n {showArticles && (\n <ScrollArea onScroll={handleScroll}>\n <ArticleNav className=\"py-4 max-w-[var(--left-nav-width,inherit)]\" articles={articles} />\n </ScrollArea>\n )}\n {sectionNavItems && sectionNavItems.length > 0 && (\n <SectionNav\n className={cn('pt-4 flex-shrink-0', !collapsed && !atScrollBottom && 'border-t border-subtle')}\n items={sectionNavItems}\n activeId={sectionNavActiveId}\n />\n )}\n </>\n )}\n </aside>\n </SidebarProvider>\n );\n});\n"],"names":["ItemLinkComponent","AriaButton","hasChildItems","Sidebar"],"mappings":"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"}
|
|
@@ -2,15 +2,25 @@ import React__default from 'react';
|
|
|
2
2
|
import { c as cn } from '../../chunks/utils.Cwtlq8dh.js';
|
|
3
3
|
|
|
4
4
|
const Input = React__default.forwardRef(
|
|
5
|
-
({ className, type, startIcon, endIcon, ...props }, ref) => {
|
|
5
|
+
({ className, type, startIcon, endIcon, onStartIconClick, onEndIconClick, ...props }, ref) => {
|
|
6
6
|
const StartIcon = startIcon;
|
|
7
7
|
const EndIcon = endIcon;
|
|
8
|
-
return /* @__PURE__ */ React__default.createElement("div", { className: "w-full relative" }, StartIcon && /* @__PURE__ */ React__default.createElement("div", { className: "absolute left-
|
|
8
|
+
return /* @__PURE__ */ React__default.createElement("div", { className: "w-full relative" }, StartIcon && /* @__PURE__ */ React__default.createElement("div", { className: "absolute left-2 top-1/2 transform -translate-y-1/2" }, onStartIconClick ? /* @__PURE__ */ React__default.createElement(
|
|
9
|
+
"button",
|
|
10
|
+
{
|
|
11
|
+
type: "button",
|
|
12
|
+
onClick: onStartIconClick,
|
|
13
|
+
className: "flex items-center justify-center cursor-pointer hover:opacity-70 transition-opacity",
|
|
14
|
+
"aria-label": "Clear start icon"
|
|
15
|
+
},
|
|
16
|
+
/* @__PURE__ */ React__default.createElement(StartIcon, { size: 18, className: "text-muted-foreground" })
|
|
17
|
+
) : /* @__PURE__ */ React__default.createElement(StartIcon, { size: 18, className: "text-muted-foreground" })), /* @__PURE__ */ React__default.createElement(
|
|
9
18
|
"input",
|
|
10
19
|
{
|
|
11
20
|
type,
|
|
12
21
|
className: cn(
|
|
13
22
|
"flex h-12 w-full rounded-md border border-border bg-transparent py-3 text-base transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
23
|
+
type === "search" && !!endIcon && "appearance-none [&::-webkit-search-cancel-button]:hidden [&::-webkit-search-decoration]:hidden [&::-webkit-search-results-button]:hidden [&::-webkit-search-results-decoration]:hidden",
|
|
14
24
|
startIcon && "pl-8 pr-4",
|
|
15
25
|
endIcon && "pl-4 pr-8",
|
|
16
26
|
startIcon && endIcon && "px-8",
|
|
@@ -20,7 +30,16 @@ const Input = React__default.forwardRef(
|
|
|
20
30
|
ref,
|
|
21
31
|
...props
|
|
22
32
|
}
|
|
23
|
-
), EndIcon && /* @__PURE__ */ React__default.createElement("div", { className: "absolute right-3 top-1/2 transform -translate-y-1/2" }, /* @__PURE__ */ React__default.createElement(
|
|
33
|
+
), EndIcon && /* @__PURE__ */ React__default.createElement("div", { className: "absolute right-3 top-1/2 transform -translate-y-1/2" }, onEndIconClick ? /* @__PURE__ */ React__default.createElement(
|
|
34
|
+
"button",
|
|
35
|
+
{
|
|
36
|
+
type: "button",
|
|
37
|
+
onClick: onEndIconClick,
|
|
38
|
+
className: "flex items-center justify-center cursor-pointer hover:opacity-70 transition-opacity",
|
|
39
|
+
"aria-label": "Clear input"
|
|
40
|
+
},
|
|
41
|
+
/* @__PURE__ */ React__default.createElement(EndIcon, { className: "text-muted-foreground", size: 18 })
|
|
42
|
+
) : /* @__PURE__ */ React__default.createElement(EndIcon, { className: "text-muted-foreground", size: 18 })));
|
|
24
43
|
}
|
|
25
44
|
);
|
|
26
45
|
Input.displayName = "Input";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input.js","sources":["../../../../src/components/ui/input.tsx"],"sourcesContent":["import React from 'react';\nimport { type Icon } from '@phosphor-icons/react';\n\nimport { cn } from '@/lib/utils';\n\nexport interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {\n startIcon?: Icon;\n endIcon?: Icon;\n}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, startIcon, endIcon, ...props }, ref) => {\n const StartIcon = startIcon;\n const EndIcon = endIcon;\n\n return (\n <div className=\"w-full relative\">\n {StartIcon && (\n <div className=\"absolute left-
|
|
1
|
+
{"version":3,"file":"input.js","sources":["../../../../src/components/ui/input.tsx"],"sourcesContent":["import React from 'react';\nimport { type Icon } from '@phosphor-icons/react';\n\nimport { cn } from '@/lib/utils';\n\nexport interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {\n startIcon?: Icon;\n endIcon?: Icon;\n onStartIconClick?: () => void;\n onEndIconClick?: () => void;\n}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, startIcon, endIcon, onStartIconClick, onEndIconClick, ...props }, ref) => {\n const StartIcon = startIcon;\n const EndIcon = endIcon;\n\n return (\n <div className=\"w-full relative\">\n {StartIcon && (\n <div className=\"absolute left-2 top-1/2 transform -translate-y-1/2\">\n {onStartIconClick ? (\n <button\n type=\"button\"\n onClick={onStartIconClick}\n className=\"flex items-center justify-center cursor-pointer hover:opacity-70 transition-opacity\"\n aria-label=\"Clear start icon\"\n >\n <StartIcon size={18} className=\"text-muted-foreground\" />\n </button>\n ) : (\n <StartIcon size={18} className=\"text-muted-foreground\" />\n )}\n </div>\n )}\n <input\n type={type}\n className={cn(\n 'flex h-12 w-full rounded-md border border-border bg-transparent py-3 text-base transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',\n type === 'search' &&\n !!endIcon &&\n 'appearance-none [&::-webkit-search-cancel-button]:hidden [&::-webkit-search-decoration]:hidden [&::-webkit-search-results-button]:hidden [&::-webkit-search-results-decoration]:hidden',\n startIcon && 'pl-8 pr-4',\n endIcon && 'pl-4 pr-8',\n startIcon && endIcon && 'px-8',\n !startIcon && !endIcon && 'px-4',\n className,\n )}\n ref={ref}\n {...props}\n />\n {EndIcon && (\n <div className=\"absolute right-3 top-1/2 transform -translate-y-1/2\">\n {onEndIconClick ? (\n <button\n type=\"button\"\n onClick={onEndIconClick}\n className=\"flex items-center justify-center cursor-pointer hover:opacity-70 transition-opacity\"\n aria-label=\"Clear input\"\n >\n <EndIcon className=\"text-muted-foreground\" size={18} />\n </button>\n ) : (\n <EndIcon className=\"text-muted-foreground\" size={18} />\n )}\n </div>\n )}\n </div>\n );\n },\n);\nInput.displayName = 'Input';\n\nexport { Input };\n"],"names":["React"],"mappings":";;;AAYA,MAAM,QAAQA,cAAA,CAAM,UAAA;AAAA,EAClB,CAAC,EAAE,SAAA,EAAW,IAAA,EAAM,SAAA,EAAW,OAAA,EAAS,gBAAA,EAAkB,cAAA,EAAgB,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AAC5F,IAAA,MAAM,SAAA,GAAY,SAAA;AAClB,IAAA,MAAM,OAAA,GAAU,OAAA;AAEhB,IAAA,uBACEA,cAAA,CAAA,aAAA,CAAC,SAAI,SAAA,EAAU,iBAAA,EAAA,EACZ,6BACCA,cAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,oDAAA,EAAA,EACZ,gBAAA,mBACCA,cAAA,CAAA,aAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,OAAA,EAAS,gBAAA;AAAA,QACT,SAAA,EAAU,qFAAA;AAAA,QACV,YAAA,EAAW;AAAA,OAAA;AAAA,sBAEXA,cAAA,CAAA,aAAA,CAAC,SAAA,EAAA,EAAU,IAAA,EAAM,EAAA,EAAI,WAAU,uBAAA,EAAwB;AAAA,KACzD,gDAEC,SAAA,EAAA,EAAU,IAAA,EAAM,IAAI,SAAA,EAAU,uBAAA,EAAwB,CAE3D,CAAA,kBAEFA,cAAA,CAAA,aAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,IAAA;AAAA,QACA,SAAA,EAAW,EAAA;AAAA,UACT,4VAAA;AAAA,UACA,IAAA,KAAS,QAAA,IACP,CAAC,CAAC,OAAA,IACF,wLAAA;AAAA,UACF,SAAA,IAAa,WAAA;AAAA,UACb,OAAA,IAAW,WAAA;AAAA,UACX,aAAa,OAAA,IAAW,MAAA;AAAA,UACxB,CAAC,SAAA,IAAa,CAAC,OAAA,IAAW,MAAA;AAAA,UAC1B;AAAA,SACF;AAAA,QACA,GAAA;AAAA,QACC,GAAG;AAAA;AAAA,OAEL,OAAA,oBACCA,cAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yDACZ,cAAA,mBACCA,cAAA,CAAA,aAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,OAAA,EAAS,cAAA;AAAA,QACT,SAAA,EAAU,qFAAA;AAAA,QACV,YAAA,EAAW;AAAA,OAAA;AAAA,sBAEXA,cAAA,CAAA,aAAA,CAAC,OAAA,EAAA,EAAQ,SAAA,EAAU,uBAAA,EAAwB,MAAM,EAAA,EAAI;AAAA,KACvD,gDAEC,OAAA,EAAA,EAAQ,SAAA,EAAU,yBAAwB,IAAA,EAAM,EAAA,EAAI,CAEzD,CAEJ,CAAA;AAAA,EAEJ;AACF;AACA,KAAA,CAAM,WAAA,GAAc,OAAA;;;;"}
|
|
@@ -2,7 +2,15 @@ import * as React from 'react';
|
|
|
2
2
|
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
|
3
3
|
import { c as cn } from '../../chunks/utils.Cwtlq8dh.js';
|
|
4
4
|
|
|
5
|
-
const ScrollArea = React.forwardRef(({ className, children, onScroll, ...props }, ref) => /* @__PURE__ */ React.createElement(ScrollAreaPrimitive.Root, { className: cn("relative overflow-hidden", className), ...props }, /* @__PURE__ */ React.createElement(
|
|
5
|
+
const ScrollArea = React.forwardRef(({ className, children, onScroll, ...props }, ref) => /* @__PURE__ */ React.createElement(ScrollAreaPrimitive.Root, { className: cn("relative overflow-hidden", className), ...props }, /* @__PURE__ */ React.createElement(
|
|
6
|
+
ScrollAreaPrimitive.Viewport,
|
|
7
|
+
{
|
|
8
|
+
ref,
|
|
9
|
+
className: "h-full w-full rounded-[inherit] [&_>div]:w-full [&_>div]:table-fixed",
|
|
10
|
+
onScroll
|
|
11
|
+
},
|
|
12
|
+
children
|
|
13
|
+
), /* @__PURE__ */ React.createElement(ScrollBar, null), /* @__PURE__ */ React.createElement(ScrollAreaPrimitive.Corner, null)));
|
|
6
14
|
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
|
|
7
15
|
const ScrollBar = React.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ React.createElement(
|
|
8
16
|
ScrollAreaPrimitive.ScrollAreaScrollbar,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scroll-area.js","sources":["../../../../src/components/ui/scroll-area.tsx"],"sourcesContent":["import * as React from 'react';\nimport * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';\n\nimport { cn } from '@/lib/utils';\n\nconst ScrollArea = React.forwardRef<\n React.ElementRef<typeof ScrollAreaPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>\n>(({ className, children, onScroll, ...props }, ref) => (\n <ScrollAreaPrimitive.Root className={cn('relative overflow-hidden', className)} {...props}>\n <ScrollAreaPrimitive.Viewport
|
|
1
|
+
{"version":3,"file":"scroll-area.js","sources":["../../../../src/components/ui/scroll-area.tsx"],"sourcesContent":["import * as React from 'react';\nimport * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';\n\nimport { cn } from '@/lib/utils';\n\nconst ScrollArea = React.forwardRef<\n React.ElementRef<typeof ScrollAreaPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>\n>(({ className, children, onScroll, ...props }, ref) => (\n <ScrollAreaPrimitive.Root className={cn('relative overflow-hidden', className)} {...props}>\n <ScrollAreaPrimitive.Viewport\n ref={ref}\n className=\"h-full w-full rounded-[inherit] [&_>div]:w-full [&_>div]:table-fixed\"\n onScroll={onScroll}\n >\n {children}\n </ScrollAreaPrimitive.Viewport>\n <ScrollBar />\n <ScrollAreaPrimitive.Corner />\n </ScrollAreaPrimitive.Root>\n));\nScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;\n\nconst ScrollBar = React.forwardRef<\n React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,\n React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>\n>(({ className, orientation = 'vertical', ...props }, ref) => (\n <ScrollAreaPrimitive.ScrollAreaScrollbar\n ref={ref}\n orientation={orientation}\n className={cn(\n 'flex touch-none select-none transition-colors',\n orientation === 'vertical' && 'h-full w-2.5 border-l border-l-transparent p-[1px]',\n orientation === 'horizontal' && 'h-2.5 flex-col border-t border-t-transparent p-[1px]',\n className,\n )}\n {...props}\n >\n <ScrollAreaPrimitive.ScrollAreaThumb className=\"relative flex-1 rounded-full bg-dark-400\" />\n </ScrollAreaPrimitive.ScrollAreaScrollbar>\n));\nScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;\n\nexport { ScrollArea, ScrollBar };\n"],"names":[],"mappings":";;;;AAKA,MAAM,UAAA,GAAa,MAAM,UAAA,CAGvB,CAAC,EAAE,SAAA,EAAW,QAAA,EAAU,QAAA,EAAU,GAAG,KAAA,EAAM,EAAG,wBAC9C,KAAA,CAAA,aAAA,CAAC,mBAAA,CAAoB,MAApB,EAAyB,SAAA,EAAW,GAAG,0BAAA,EAA4B,SAAS,CAAA,EAAI,GAAG,KAAA,EAAA,kBAClF,KAAA,CAAA,aAAA;AAAA,EAAC,mBAAA,CAAoB,QAAA;AAAA,EAApB;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAU,sEAAA;AAAA,IACV;AAAA,GAAA;AAAA,EAEC;AACH,CAAA,kBACA,KAAA,CAAA,aAAA,CAAC,eAAU,CAAA,kBACX,KAAA,CAAA,aAAA,CAAC,oBAAoB,MAAA,EAApB,IAA2B,CAC9B,CACD;AACD,UAAA,CAAW,WAAA,GAAc,oBAAoB,IAAA,CAAK,WAAA;AAElD,MAAM,SAAA,GAAY,KAAA,CAAM,UAAA,CAGtB,CAAC,EAAE,SAAA,EAAW,WAAA,GAAc,UAAA,EAAY,GAAG,KAAA,EAAM,EAAG,GAAA,qBACpD,KAAA,CAAA,aAAA;AAAA,EAAC,mBAAA,CAAoB,mBAAA;AAAA,EAApB;AAAA,IACC,GAAA;AAAA,IACA,WAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACT,+CAAA;AAAA,MACA,gBAAgB,UAAA,IAAc,oDAAA;AAAA,MAC9B,gBAAgB,YAAA,IAAgB,sDAAA;AAAA,MAChC;AAAA,KACF;AAAA,IACC,GAAG;AAAA,GAAA;AAAA,kBAEJ,KAAA,CAAA,aAAA,CAAC,mBAAA,CAAoB,eAAA,EAApB,EAAoC,WAAU,0CAAA,EAA2C;AAC5F,CACD;AACD,SAAA,CAAU,WAAA,GAAc,oBAAoB,mBAAA,CAAoB,WAAA;;;;"}
|