react-os-shell 0.6.4 → 0.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -298,6 +298,57 @@ declare function GlobalSearch({ providers, typeIcons, placeholder }?: GlobalSear
298
298
 
299
299
  declare function ShortcutHelp(): react_jsx_runtime.JSX.Element;
300
300
 
301
+ /**
302
+ * One help article. Generic shape — the consuming portal maps its own
303
+ * help-doc records onto this before passing them in.
304
+ */
305
+ interface HelpCenterDoc {
306
+ id: string;
307
+ slug: string;
308
+ title: string;
309
+ body: string;
310
+ /** Grouping key (e.g. `'getting_started'`). */
311
+ category: string;
312
+ /** Group header text (e.g. "Getting Started"). */
313
+ category_label: string;
314
+ /** When `false`, a "Draft" badge is shown. Omit for always-published docs. */
315
+ is_published?: boolean;
316
+ }
317
+ interface HelpCenterProps {
318
+ docs: HelpCenterDoc[];
319
+ loading?: boolean;
320
+ /**
321
+ * Category keys in display order. Categories not listed fall to the end in
322
+ * first-seen order. Without it, groups follow first-seen order.
323
+ */
324
+ categoryOrder?: string[];
325
+ /** Show the New/Edit affordances (consumer gates this on write permission). */
326
+ canEdit?: boolean;
327
+ onNew?: () => void;
328
+ onEdit?: (doc: HelpCenterDoc) => void;
329
+ /** Custom body renderer; defaults to preformatted text. */
330
+ renderBody?: (doc: HelpCenterDoc) => ReactNode;
331
+ emptyMessage?: string;
332
+ }
333
+ /**
334
+ * In-app help / documentation viewer. Two panes: a searchable, collapsible
335
+ * category tree on the left, the selected article's body on the right.
336
+ *
337
+ * Presentational only — it holds no API or permission knowledge. The consumer
338
+ * fetches its own help docs, maps them to `HelpCenterDoc`, and (for editors)
339
+ * wires `canEdit` + `onNew`/`onEdit` to its own create/edit UI.
340
+ *
341
+ * Search is client-side: a case-insensitive substring match over title, body
342
+ * and category label. While searching, matching groups auto-expand.
343
+ */
344
+ declare function HelpCenter({ docs, loading, categoryOrder, canEdit, onNew, onEdit, renderBody, emptyMessage, }: HelpCenterProps): react_jsx_runtime.JSX.Element;
345
+
346
+ interface MarkdownProps {
347
+ children: string;
348
+ className?: string;
349
+ }
350
+ declare function Markdown({ children, className }: MarkdownProps): react_jsx_runtime.JSX.Element;
351
+
301
352
  declare const isMac: boolean;
302
353
  /** Platform-aware modifier symbols */
303
354
  declare const MOD: string;
@@ -1217,4 +1268,4 @@ declare function useNewHotkey(callback: () => void): void;
1217
1268
  */
1218
1269
  declare function useEditHotkey(callback: (() => void) | null): void;
1219
1270
 
1220
- export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, BehaviorPanel, type BugReport, type BugReportConfig, BugReportConfigProvider, BugReportDetail, type BugReportExtraField, type BugReportExtraSelectField, BugReportProvider, type BugReportSubmission, type BugReportSubmitPayload, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, CancelButton, type CellStyle, type ChangelogEntry, type ColumnDef, ConfirmProvider, CopyButton, Customization, type CustomizationOmitSection, type CustomizationProps, Desktop, type DesktopHostConfig, DesktopHostProvider, DocFavStar, ENTER, EditableGrid, type EditableGridProps, type EntityFetcher, EntityList, type EntityListColumn, type EntityListProps, GLASS_DIVIDER, GLASS_INPUT_BG, GlobalSearch, type GridColumn, Layout, type LayoutProps, ListFooter, type LoginPayload, MOD, type MailCapabilities, MailConnectModal, type MailUser, Modal, ModalActions, NotificationBell, type NotificationsConfig, type PaginatedResponse, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, type ReportType, ResizableTable, SHIFT, type SearchConfig, type SearchProvider, type SearchResult, type SemanticGroup, type ShellAuth, ShellAuthProvider, ShellEntityFetcherProvider, type ShellNotification, type ShellPrefsAdapter, ShellPrefsProvider, ShortcutHelp, type SortState, SoundsPanel, StartMenu, StatusBadge, StatusBadgeProvider, type StickyEntityRef, type StickyResolver, SystemPreferences, type SystemPreferencesProps, type SystemPreferencesSection, VERSION, WindowManagerProvider, WindowRegistry, WindowTitle, commitExposeHighlight, confirm, confirmDestructive, createWindowRegistry, exitExposeMode, formatDate, getActiveWindowRoute, getExposeHighlight, glassStyle, isMac, openBugReportDialog, prompt, reportBug, setExposeHighlight, setShellApiClient, setShellAuthBridge, setShellMailServer, setShellNavIcons, setWindowDefaultPosition, subscribeExposeHighlight, toast, toggleExposeMode, useBugReport, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useInfiniteScroll, useLocalStoragePrefs, useMailAuth, useModalActive, useNewHotkey, useShellAuth, useShellEntityFetcher, useShellPrefs, useSort, useTableNav, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle };
1271
+ export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, BehaviorPanel, type BugReport, type BugReportConfig, BugReportConfigProvider, BugReportDetail, type BugReportExtraField, type BugReportExtraSelectField, BugReportProvider, type BugReportSubmission, type BugReportSubmitPayload, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, CancelButton, type CellStyle, type ChangelogEntry, type ColumnDef, ConfirmProvider, CopyButton, Customization, type CustomizationOmitSection, type CustomizationProps, Desktop, type DesktopHostConfig, DesktopHostProvider, DocFavStar, ENTER, EditableGrid, type EditableGridProps, type EntityFetcher, EntityList, type EntityListColumn, type EntityListProps, GLASS_DIVIDER, GLASS_INPUT_BG, GlobalSearch, type GridColumn, HelpCenter, type HelpCenterDoc, type HelpCenterProps, Layout, type LayoutProps, ListFooter, type LoginPayload, MOD, type MailCapabilities, MailConnectModal, type MailUser, Markdown, type MarkdownProps, Modal, ModalActions, NotificationBell, type NotificationsConfig, type PaginatedResponse, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, type ReportType, ResizableTable, SHIFT, type SearchConfig, type SearchProvider, type SearchResult, type SemanticGroup, type ShellAuth, ShellAuthProvider, ShellEntityFetcherProvider, type ShellNotification, type ShellPrefsAdapter, ShellPrefsProvider, ShortcutHelp, type SortState, SoundsPanel, StartMenu, StatusBadge, StatusBadgeProvider, type StickyEntityRef, type StickyResolver, SystemPreferences, type SystemPreferencesProps, type SystemPreferencesSection, VERSION, WindowManagerProvider, WindowRegistry, WindowTitle, commitExposeHighlight, confirm, confirmDestructive, createWindowRegistry, exitExposeMode, formatDate, getActiveWindowRoute, getExposeHighlight, glassStyle, isMac, openBugReportDialog, prompt, reportBug, setExposeHighlight, setShellApiClient, setShellAuthBridge, setShellMailServer, setShellNavIcons, setWindowDefaultPosition, subscribeExposeHighlight, toast, toggleExposeMode, useBugReport, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useInfiniteScroll, useLocalStoragePrefs, useMailAuth, useModalActive, useNewHotkey, useShellAuth, useShellEntityFetcher, useShellPrefs, useSort, useTableNav, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle };
package/dist/index.js CHANGED
@@ -21,7 +21,7 @@ import { useAuth, useShellAuth } from './chunk-ADJ3CERD.js';
21
21
  export { ShellAuthProvider, setShellAuthBridge, useShellAuth } from './chunk-ADJ3CERD.js';
22
22
  import { glassStyle, startMenuCategories, navSections, isSection, GLASS_INPUT_BG, navIcons, sectionIcons } from './chunk-ZF6AYO4G.js';
23
23
  export { GLASS_DIVIDER, GLASS_INPUT_BG, glassStyle, setShellNavIcons } from './chunk-ZF6AYO4G.js';
24
- import { createContext, lazy, useState, useRef, useEffect, useCallback, useLayoutEffect, useContext, Suspense, isValidElement, cloneElement, useMemo, useSyncExternalStore } from 'react';
24
+ import { createContext, lazy, useState, useRef, useEffect, useCallback, useMemo, useLayoutEffect, useContext, Suspense, isValidElement, cloneElement, useSyncExternalStore } from 'react';
25
25
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
26
26
  import { Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react';
27
27
  import { createPortal } from 'react-dom';
@@ -256,6 +256,312 @@ function ShortcutHelp() {
256
256
  ] }) })
257
257
  ] });
258
258
  }
259
+ var INLINE_RE = /!\[([^\]]*)\]\(([^)]+)\)|\[([^\]]+)\]\(([^)]+)\)|\*\*([^*]+)\*\*|`([^`]+)`|\*([^*]+)\*/g;
260
+ function renderInline(text) {
261
+ const out = [];
262
+ let last = 0;
263
+ let key = 0;
264
+ let m;
265
+ INLINE_RE.lastIndex = 0;
266
+ while ((m = INLINE_RE.exec(text)) !== null) {
267
+ if (m.index > last) out.push(text.slice(last, m.index));
268
+ if (m[1] !== void 0) {
269
+ out.push(
270
+ /* @__PURE__ */ jsxs("span", { className: "text-gray-400", children: [
271
+ "[",
272
+ m[1],
273
+ "]"
274
+ ] }, key++)
275
+ );
276
+ } else if (m[3] !== void 0) {
277
+ out.push(
278
+ /* @__PURE__ */ jsx(
279
+ "a",
280
+ {
281
+ href: m[4],
282
+ target: "_blank",
283
+ rel: "noreferrer",
284
+ className: "text-blue-600 hover:underline",
285
+ children: m[3]
286
+ },
287
+ key++
288
+ )
289
+ );
290
+ } else if (m[5] !== void 0) {
291
+ out.push(
292
+ /* @__PURE__ */ jsx("strong", { className: "font-semibold text-gray-900", children: m[5] }, key++)
293
+ );
294
+ } else if (m[6] !== void 0) {
295
+ out.push(
296
+ /* @__PURE__ */ jsx(
297
+ "code",
298
+ {
299
+ className: "rounded bg-gray-100 px-1 py-0.5 font-mono text-[0.85em] text-gray-800",
300
+ children: m[6]
301
+ },
302
+ key++
303
+ )
304
+ );
305
+ } else if (m[7] !== void 0) {
306
+ out.push(/* @__PURE__ */ jsx("em", { children: m[7] }, key++));
307
+ }
308
+ last = INLINE_RE.lastIndex;
309
+ }
310
+ if (last < text.length) out.push(text.slice(last));
311
+ return out;
312
+ }
313
+ function ScreenshotPlaceholder({ alt }) {
314
+ const label = alt.replace(/^screenshot:\s*/i, "");
315
+ return /* @__PURE__ */ jsxs("div", { className: "my-1 flex items-start gap-2 rounded-lg border border-dashed border-gray-300 bg-gray-50 px-3 py-2.5", children: [
316
+ /* @__PURE__ */ jsx(
317
+ "svg",
318
+ {
319
+ className: "mt-0.5 h-4 w-4 shrink-0 text-gray-400",
320
+ viewBox: "0 0 20 20",
321
+ fill: "currentColor",
322
+ "aria-hidden": "true",
323
+ children: /* @__PURE__ */ jsx("path", { d: "M3 6a1.5 1.5 0 0 1 1.5-1.5h1.1l.4-.9a1 1 0 0 1 .9-.6h6.2a1 1 0 0 1 .9.6l.4.9h1.1A1.5 1.5 0 0 1 18 6v8.5A1.5 1.5 0 0 1 16.5 16h-13A1.5 1.5 0 0 1 2 14.5V6Zm7.5 1.5a3.25 3.25 0 1 0 0 6.5 3.25 3.25 0 0 0 0-6.5Z" })
324
+ }
325
+ ),
326
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-gray-500", children: [
327
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-600", children: "Screenshot \u2014 " }),
328
+ label
329
+ ] })
330
+ ] });
331
+ }
332
+ function collectItems(lines, itemRe) {
333
+ const items = [];
334
+ for (const line of lines) {
335
+ const m = itemRe.exec(line);
336
+ if (m) {
337
+ items.push(m[1]);
338
+ } else if (items.length) {
339
+ items[items.length - 1] += " " + line.trim();
340
+ }
341
+ }
342
+ return items;
343
+ }
344
+ var splitCells = (line) => line.replace(/^\s*\|/, "").replace(/\|\s*$/, "").split("|").map((c) => c.trim());
345
+ function isTable(lines) {
346
+ return lines.length >= 2 && lines[0].includes("|") && /^\s*\|?[\s:|-]*-[\s:|-]*\|?\s*$/.test(lines[1]) && lines[1].includes("-");
347
+ }
348
+ function renderTable(lines, key) {
349
+ const header = splitCells(lines[0]);
350
+ const rows = lines.slice(2).map(splitCells);
351
+ return /* @__PURE__ */ jsx("div", { className: "my-1 overflow-x-auto rounded-lg border border-gray-200", children: /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse text-sm", children: [
352
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { className: "bg-gray-50", children: header.map((h, i) => /* @__PURE__ */ jsx(
353
+ "th",
354
+ {
355
+ className: "border-b border-gray-200 px-3 py-1.5 text-left font-semibold text-gray-700",
356
+ children: renderInline(h)
357
+ },
358
+ i
359
+ )) }) }),
360
+ /* @__PURE__ */ jsx("tbody", { children: rows.map((row, r) => /* @__PURE__ */ jsx("tr", { className: "even:bg-gray-50/50", children: row.map((c, i) => /* @__PURE__ */ jsx("td", { className: "border-t border-gray-100 px-3 py-1.5 align-top text-gray-700", children: renderInline(c) }, i)) }, r)) })
361
+ ] }) }, key);
362
+ }
363
+ function renderBlock(block, key) {
364
+ const lines = block.split("\n");
365
+ const first = lines[0];
366
+ const heading = /^(#{2,4})\s+(.*)$/.exec(first);
367
+ if (heading && lines.length === 1) {
368
+ const level = heading[1].length;
369
+ const Tag = `h${level}`;
370
+ const cls = level === 2 ? "mt-2 text-[13px] font-semibold uppercase tracking-wide text-gray-500" : level === 3 ? "mt-1 text-base font-semibold text-gray-900" : "mt-1 text-sm font-semibold text-gray-900";
371
+ return /* @__PURE__ */ jsx(Tag, { className: cls, children: renderInline(heading[2]) }, key);
372
+ }
373
+ if (lines.length === 1 && /^---+$/.test(first)) {
374
+ return /* @__PURE__ */ jsx("hr", { className: "border-gray-200" }, key);
375
+ }
376
+ if (isTable(lines)) {
377
+ return renderTable(lines, key);
378
+ }
379
+ if (/^>\s?/.test(first)) {
380
+ const text = lines.map((l) => l.replace(/^>\s?/, "")).join(" ");
381
+ return /* @__PURE__ */ jsx(
382
+ "div",
383
+ {
384
+ className: "my-1 rounded-r-lg border-l-4 border-blue-300 bg-blue-50/60 px-3 py-2 text-gray-700",
385
+ children: renderInline(text)
386
+ },
387
+ key
388
+ );
389
+ }
390
+ const img = /^!\[([^\]]*)\]\(([^)]+)\)$/.exec(first);
391
+ if (img && lines.length === 1) {
392
+ return /* @__PURE__ */ jsx(ScreenshotPlaceholder, { alt: img[1] }, key);
393
+ }
394
+ if (/^[-*]\s+/.test(first)) {
395
+ const items = collectItems(lines, /^[-*]\s+(.*)$/);
396
+ return /* @__PURE__ */ jsx("ul", { className: "list-disc space-y-1 pl-5 marker:text-gray-400", children: items.map((it, j) => /* @__PURE__ */ jsx("li", { children: renderInline(it) }, j)) }, key);
397
+ }
398
+ const ordered = /^(\d+)\.\s+/.exec(first);
399
+ if (ordered) {
400
+ const items = collectItems(lines, /^\d+\.\s+(.*)$/);
401
+ return /* @__PURE__ */ jsx(
402
+ "ol",
403
+ {
404
+ start: Number(ordered[1]),
405
+ className: "list-decimal space-y-1 pl-5 marker:text-gray-400",
406
+ children: items.map((it, j) => /* @__PURE__ */ jsx("li", { className: "pl-1", children: renderInline(it) }, j))
407
+ },
408
+ key
409
+ );
410
+ }
411
+ return /* @__PURE__ */ jsx("p", { children: renderInline(lines.join(" ")) }, key);
412
+ }
413
+ function Markdown({ children, className }) {
414
+ const blocks = (children ?? "").replace(/\r\n/g, "\n").split(/\n{2,}/).map((b) => b.replace(/\s+$/, "")).filter((b) => b.trim() !== "");
415
+ return /* @__PURE__ */ jsx("div", { className: `space-y-3 text-sm leading-relaxed text-gray-700 ${className ?? ""}`.trim(), children: blocks.map((block, i) => renderBlock(block, i)) });
416
+ }
417
+ var Chevron = ({ open }) => /* @__PURE__ */ jsx(
418
+ "svg",
419
+ {
420
+ className: `h-3.5 w-3.5 shrink-0 text-gray-400 transition-transform ${open ? "rotate-90" : ""}`,
421
+ viewBox: "0 0 20 20",
422
+ fill: "currentColor",
423
+ "aria-hidden": "true",
424
+ children: /* @__PURE__ */ jsx(
425
+ "path",
426
+ {
427
+ fillRule: "evenodd",
428
+ d: "M7.21 14.77a.75.75 0 0 1 .02-1.06L11.168 10 7.23 6.29a.75.75 0 1 1 1.04-1.08l4.5 4.25a.75.75 0 0 1 0 1.08l-4.5 4.25a.75.75 0 0 1-1.06-.02Z",
429
+ clipRule: "evenodd"
430
+ }
431
+ )
432
+ }
433
+ );
434
+ function HelpCenter({
435
+ docs,
436
+ loading = false,
437
+ categoryOrder,
438
+ canEdit = false,
439
+ onNew,
440
+ onEdit,
441
+ renderBody,
442
+ emptyMessage = "No help articles yet."
443
+ }) {
444
+ const [query, setQuery] = useState("");
445
+ const [selectedSlug, setSelectedSlug] = useState(null);
446
+ const [expanded, setExpanded] = useState({});
447
+ const q = query.trim().toLowerCase();
448
+ const groups = useMemo(() => {
449
+ const map = /* @__PURE__ */ new Map();
450
+ for (const doc of docs) {
451
+ let g = map.get(doc.category);
452
+ if (!g) {
453
+ g = { key: doc.category, label: doc.category_label || doc.category, docs: [] };
454
+ map.set(doc.category, g);
455
+ }
456
+ g.docs.push(doc);
457
+ }
458
+ if (!categoryOrder?.length) return [...map.values()];
459
+ const rank = new Map(categoryOrder.map((k, i) => [k, i]));
460
+ return [...map.values()].sort(
461
+ (a, b) => (rank.get(a.key) ?? Infinity) - (rank.get(b.key) ?? Infinity)
462
+ );
463
+ }, [docs, categoryOrder]);
464
+ const matches = (doc) => !q || doc.title.toLowerCase().includes(q) || doc.body.toLowerCase().includes(q) || doc.category_label.toLowerCase().includes(q);
465
+ const visibleGroups = useMemo(
466
+ () => groups.map((g) => ({ ...g, docs: g.docs.filter(matches) })).filter((g) => g.docs.length > 0),
467
+ [groups, q]
468
+ );
469
+ const visibleDocs = useMemo(() => visibleGroups.flatMap((g) => g.docs), [visibleGroups]);
470
+ const selected = (selectedSlug ? visibleDocs.find((d) => d.slug === selectedSlug) : void 0) ?? visibleDocs[0] ?? null;
471
+ const isGroupOpen = (key) => q ? true : expanded[key] ?? key === selected?.category;
472
+ const toggleGroup = (key) => setExpanded((prev) => ({ ...prev, [key]: !isGroupOpen(key) }));
473
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-full gap-4 px-4 py-3 min-h-0", children: [
474
+ /* @__PURE__ */ jsxs("aside", { className: "w-64 shrink-0 flex flex-col bg-white rounded-lg shadow overflow-hidden", children: [
475
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 px-3 py-2 border-b border-gray-200 bg-gray-50 shrink-0", children: [
476
+ /* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold text-gray-900", children: "Help" }),
477
+ canEdit && onNew && /* @__PURE__ */ jsx("button", { type: "button", onClick: onNew, className: "text-xs text-blue-600 hover:underline", children: "+ New" })
478
+ ] }),
479
+ /* @__PURE__ */ jsx("div", { className: "px-2.5 py-2 border-b border-gray-100 shrink-0", children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
480
+ /* @__PURE__ */ jsx(
481
+ "svg",
482
+ {
483
+ className: "pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400",
484
+ viewBox: "0 0 20 20",
485
+ fill: "currentColor",
486
+ "aria-hidden": "true",
487
+ children: /* @__PURE__ */ jsx(
488
+ "path",
489
+ {
490
+ fillRule: "evenodd",
491
+ d: "M9 3.5a5.5 5.5 0 1 0 3.36 9.85l3.14 3.15a.75.75 0 1 0 1.06-1.06l-3.15-3.14A5.5 5.5 0 0 0 9 3.5ZM5 9a4 4 0 1 1 8 0 4 4 0 0 1-8 0Z",
492
+ clipRule: "evenodd"
493
+ }
494
+ )
495
+ }
496
+ ),
497
+ /* @__PURE__ */ jsx(
498
+ "input",
499
+ {
500
+ type: "text",
501
+ value: query,
502
+ onChange: (e) => setQuery(e.target.value),
503
+ placeholder: "Search help\u2026",
504
+ className: "w-full rounded-md border border-gray-300 bg-white py-1.5 pl-8 pr-2 text-sm shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
505
+ }
506
+ )
507
+ ] }) }),
508
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto py-1", children: loading ? /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-center text-xs text-gray-400", children: "Loading\u2026" }) : visibleGroups.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-center text-xs text-gray-500", children: q ? "No articles match your search." : emptyMessage }) : visibleGroups.map((group) => {
509
+ const open = isGroupOpen(group.key);
510
+ return /* @__PURE__ */ jsxs("div", { className: "py-0.5", children: [
511
+ /* @__PURE__ */ jsxs(
512
+ "button",
513
+ {
514
+ type: "button",
515
+ onClick: () => toggleGroup(group.key),
516
+ className: "w-full flex items-center gap-1.5 px-3 py-1.5 text-left text-[10px] font-semibold uppercase tracking-wide text-gray-400 hover:text-gray-600",
517
+ children: [
518
+ /* @__PURE__ */ jsx(Chevron, { open }),
519
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: group.label })
520
+ ]
521
+ }
522
+ ),
523
+ open && group.docs.map((doc) => {
524
+ const active = selected?.slug === doc.slug;
525
+ return /* @__PURE__ */ jsxs(
526
+ "button",
527
+ {
528
+ type: "button",
529
+ onClick: () => setSelectedSlug(doc.slug),
530
+ className: `w-full text-left pl-8 pr-3 py-1.5 text-sm flex items-center gap-1.5 transition-colors ${active ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-700 hover:bg-gray-50"}`,
531
+ children: [
532
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: doc.title }),
533
+ doc.is_published === false && /* @__PURE__ */ jsx("span", { className: "ml-auto shrink-0 text-[10px] text-amber-600", children: "Draft" })
534
+ ]
535
+ },
536
+ doc.slug
537
+ );
538
+ })
539
+ ] }, group.key);
540
+ }) })
541
+ ] }),
542
+ /* @__PURE__ */ jsx("main", { className: "flex-1 min-w-0 bg-white rounded-lg shadow overflow-hidden flex flex-col", children: selected ? /* @__PURE__ */ jsxs(Fragment, { children: [
543
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4 px-5 py-3 border-b border-gray-200 bg-gray-50 shrink-0", children: [
544
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
545
+ /* @__PURE__ */ jsx("h1", { className: "text-lg font-semibold text-gray-900 truncate", children: selected.title }),
546
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-500 mt-0.5", children: [
547
+ selected.category_label,
548
+ selected.is_published === false && /* @__PURE__ */ jsx("span", { className: "ml-2 text-amber-600", children: "\xB7 Draft" })
549
+ ] })
550
+ ] }),
551
+ canEdit && onEdit && /* @__PURE__ */ jsx(
552
+ "button",
553
+ {
554
+ type: "button",
555
+ onClick: () => onEdit(selected),
556
+ className: "shrink-0 text-sm text-blue-600 hover:underline",
557
+ children: "Edit"
558
+ }
559
+ )
560
+ ] }),
561
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-auto px-5 py-4", children: renderBody ? renderBody(selected) : selected.body ? /* @__PURE__ */ jsx(Markdown, { children: selected.body }) : /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 italic", children: "This article has no body yet." }) })
562
+ ] }) : /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-center px-6 text-center", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: loading ? "Loading\u2026" : "Pick a help article from the left." }) }) })
563
+ ] });
564
+ }
259
565
  function timeAgo(dateStr) {
260
566
  const diff = Date.now() - new Date(dateStr).getTime();
261
567
  const mins = Math.floor(diff / 6e4);
@@ -915,7 +1221,7 @@ function StatusBadge({ status }) {
915
1221
  }
916
1222
 
917
1223
  // src/version.ts
918
- var VERSION = "0.6.4" ;
1224
+ var VERSION = "0.6.7" ;
919
1225
  var APP_VERSION = VERSION;
920
1226
 
921
1227
  // src/changelog.ts
@@ -6123,6 +6429,6 @@ function useEditHotkey(callback) {
6123
6429
  }, [callback, isActive]);
6124
6430
  }
6125
6431
 
6126
- export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, BehaviorPanel, BugReportConfigProvider, BugReportDetail, BugReportProvider, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, Customization, Desktop, DesktopHostProvider, ENTER, EntityList, GlobalSearch, Layout, ListFooter, MOD, MailConnectModal, NotificationBell, ResizableTable, SHIFT, ShellEntityFetcherProvider, ShortcutHelp, SoundsPanel, StartMenu, StatusBadge, StatusBadgeProvider, SystemPreferences, VERSION, createWindowRegistry, isMac, openBugReportDialog, reportBug, useBugReport, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useInfiniteScroll, useNewHotkey, useShellEntityFetcher, useSort, useTableNav };
6432
+ export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, BehaviorPanel, BugReportConfigProvider, BugReportDetail, BugReportProvider, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, Customization, Desktop, DesktopHostProvider, ENTER, EntityList, GlobalSearch, HelpCenter, Layout, ListFooter, MOD, MailConnectModal, Markdown, NotificationBell, ResizableTable, SHIFT, ShellEntityFetcherProvider, ShortcutHelp, SoundsPanel, StartMenu, StatusBadge, StatusBadgeProvider, SystemPreferences, VERSION, createWindowRegistry, isMac, openBugReportDialog, reportBug, useBugReport, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useInfiniteScroll, useNewHotkey, useShellEntityFetcher, useSort, useTableNav };
6127
6433
  //# sourceMappingURL=index.js.map
6128
6434
  //# sourceMappingURL=index.js.map