@tooee/view 0.1.22 → 0.2.0

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.
Files changed (83) hide show
  1. package/README.md +67 -12
  2. package/dist/View.d.ts.map +1 -1
  3. package/dist/View.js +5 -1
  4. package/dist/View.js.map +1 -1
  5. package/dist/components/ViewScreen.d.ts +28 -0
  6. package/dist/components/ViewScreen.d.ts.map +1 -0
  7. package/dist/components/ViewScreen.js +29 -0
  8. package/dist/components/ViewScreen.js.map +1 -0
  9. package/dist/components/subviews/CodeSubview.d.ts +1 -1
  10. package/dist/components/subviews/CodeSubview.d.ts.map +1 -1
  11. package/dist/components/subviews/CodeSubview.js +20 -89
  12. package/dist/components/subviews/CodeSubview.js.map +1 -1
  13. package/dist/components/subviews/CustomSubview.d.ts +1 -1
  14. package/dist/components/subviews/CustomSubview.d.ts.map +1 -1
  15. package/dist/components/subviews/CustomSubview.js +19 -94
  16. package/dist/components/subviews/CustomSubview.js.map +1 -1
  17. package/dist/components/subviews/MarkdownSubview.d.ts +1 -1
  18. package/dist/components/subviews/MarkdownSubview.d.ts.map +1 -1
  19. package/dist/components/subviews/MarkdownSubview.js +32 -106
  20. package/dist/components/subviews/MarkdownSubview.js.map +1 -1
  21. package/dist/components/subviews/TableSubview.d.ts +1 -1
  22. package/dist/components/subviews/TableSubview.d.ts.map +1 -1
  23. package/dist/components/subviews/TableSubview.js +22 -123
  24. package/dist/components/subviews/TableSubview.js.map +1 -1
  25. package/dist/components/subviews/index.d.ts +0 -1
  26. package/dist/components/subviews/index.d.ts.map +1 -1
  27. package/dist/components/subviews/index.js +0 -1
  28. package/dist/components/subviews/index.js.map +1 -1
  29. package/dist/components/subviews/types.d.ts +6 -0
  30. package/dist/components/subviews/types.d.ts.map +1 -1
  31. package/dist/default-provider.d.ts +6 -3
  32. package/dist/default-provider.d.ts.map +1 -1
  33. package/dist/default-provider.js +24 -34
  34. package/dist/default-provider.js.map +1 -1
  35. package/dist/hooks/index.d.ts +2 -3
  36. package/dist/hooks/index.d.ts.map +1 -1
  37. package/dist/hooks/index.js +2 -3
  38. package/dist/hooks/index.js.map +1 -1
  39. package/dist/hooks/useContentCommands.d.ts +15 -0
  40. package/dist/hooks/useContentCommands.d.ts.map +1 -0
  41. package/dist/hooks/useContentCommands.js +21 -0
  42. package/dist/hooks/useContentCommands.js.map +1 -0
  43. package/dist/hooks/useViewCommandContext.d.ts +10 -42
  44. package/dist/hooks/useViewCommandContext.d.ts.map +1 -1
  45. package/dist/hooks/useViewCommandContext.js +3 -30
  46. package/dist/hooks/useViewCommandContext.js.map +1 -1
  47. package/dist/index.d.ts +2 -1
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +1 -1
  50. package/dist/index.js.map +1 -1
  51. package/dist/types.d.ts +15 -16
  52. package/dist/types.d.ts.map +1 -1
  53. package/dist/types.js.map +1 -1
  54. package/package.json +14 -14
  55. package/src/View.tsx +6 -1
  56. package/src/components/ViewScreen.tsx +76 -0
  57. package/src/components/subviews/CodeSubview.tsx +30 -120
  58. package/src/components/subviews/CustomSubview.tsx +32 -123
  59. package/src/components/subviews/MarkdownSubview.tsx +49 -130
  60. package/src/components/subviews/TableSubview.tsx +36 -164
  61. package/src/components/subviews/index.ts +0 -1
  62. package/src/components/subviews/types.ts +6 -0
  63. package/src/default-provider.ts +37 -34
  64. package/src/hooks/index.ts +2 -7
  65. package/src/hooks/useContentCommands.ts +29 -0
  66. package/src/hooks/useViewCommandContext.ts +13 -81
  67. package/src/index.ts +1 -1
  68. package/src/types.ts +15 -16
  69. package/dist/components/SubviewLayout.d.ts +0 -16
  70. package/dist/components/SubviewLayout.d.ts.map +0 -1
  71. package/dist/components/SubviewLayout.js +0 -18
  72. package/dist/components/SubviewLayout.js.map +0 -1
  73. package/dist/hooks/useMarkState.d.ts +0 -14
  74. package/dist/hooks/useMarkState.d.ts.map +0 -1
  75. package/dist/hooks/useMarkState.js +0 -71
  76. package/dist/hooks/useMarkState.js.map +0 -1
  77. package/dist/hooks/useViewCommands.d.ts +0 -13
  78. package/dist/hooks/useViewCommands.d.ts.map +0 -1
  79. package/dist/hooks/useViewCommands.js +0 -20
  80. package/dist/hooks/useViewCommands.js.map +0 -1
  81. package/src/components/SubviewLayout.tsx +0 -48
  82. package/src/hooks/useMarkState.ts +0 -100
  83. package/src/hooks/useViewCommands.ts +0 -36
@@ -1,6 +1,10 @@
1
1
  import { parseAuto } from "@tooee/renderers"
2
2
  import type { Content, ContentFormat, ContentProvider } from "./types.js"
3
3
 
4
+ export interface CreateProviderOptions {
5
+ renderer?: ContentFormat
6
+ }
7
+
4
8
  function detectFormat(filePath: string): { format: ContentFormat; language?: string } {
5
9
  const ext = filePath.split(".").pop()?.toLowerCase()
6
10
  if (!ext) return { format: "text" }
@@ -45,59 +49,58 @@ function detectFormat(filePath: string): { format: ContentFormat; language?: str
45
49
  return { format: "text" }
46
50
  }
47
51
 
48
- export function createFileProvider(filePath: string): ContentProvider {
52
+ function contentFromText(
53
+ text: string,
54
+ format: ContentFormat,
55
+ title: string | undefined,
56
+ language?: string,
57
+ ): Content {
58
+ switch (format) {
59
+ case "markdown":
60
+ return { format: "markdown", markdown: text, title }
61
+ case "code":
62
+ return { format: "code", code: text, language, title }
63
+ case "table": {
64
+ const parsed = parseAuto(text)
65
+ return { format: "table", columns: parsed.columns, rows: parsed.rows, title }
66
+ }
67
+ case "text":
68
+ default:
69
+ return { format: "text", text, title }
70
+ }
71
+ }
72
+
73
+ export function createFileProvider(
74
+ filePath: string,
75
+ options: CreateProviderOptions = {},
76
+ ): ContentProvider {
49
77
  return {
50
78
  async load(): Promise<Content> {
51
- const { format, language } = detectFormat(filePath)
79
+ const detected = detectFormat(filePath)
80
+ const format = options.renderer ?? detected.format
52
81
  const title = filePath.split("/").pop()
53
82
 
54
83
  const file = Bun.file(filePath)
55
- if (format === "table") {
56
- const text = await file.text()
57
- const parsed = parseAuto(text)
58
- return { format: "table", columns: parsed.columns, rows: parsed.rows, title }
59
- }
60
84
  const text = await file.text()
61
- switch (format) {
62
- case "markdown":
63
- return { format: "markdown", markdown: text, title }
64
- case "code":
65
- return { format: "code", code: text, language, title }
66
- case "text":
67
- default:
68
- return { format: "text", text, title }
69
- }
85
+ return contentFromText(text, format, title, detected.language)
70
86
  },
71
87
  }
72
88
  }
73
89
 
74
- export function createStdinProvider(): ContentProvider {
90
+ export function createStdinProvider(options: CreateProviderOptions = {}): ContentProvider {
75
91
  return {
76
92
  async load(): Promise<Content> {
77
93
  const text = await new Response(Bun.stdin.stream() as unknown as ReadableStream).text()
78
- return { format: "markdown", markdown: text, title: "stdin" }
94
+ const format = options.renderer ?? "markdown"
95
+ return contentFromText(text, format, "stdin")
79
96
  },
80
97
  }
81
98
  }
82
99
 
83
100
  export function createTableFileProvider(filePath: string): ContentProvider {
84
- return {
85
- async load(): Promise<Content> {
86
- const title = filePath.split("/").pop()
87
- const file = Bun.file(filePath)
88
- const text = await file.text()
89
- const parsed = parseAuto(text)
90
- return { format: "table", columns: parsed.columns, rows: parsed.rows, title }
91
- },
92
- }
101
+ return createFileProvider(filePath, { renderer: "table" })
93
102
  }
94
103
 
95
104
  export function createTableStdinProvider(): ContentProvider {
96
- return {
97
- async load(): Promise<Content> {
98
- const text = await new Response(Bun.stdin.stream() as unknown as ReadableStream).text()
99
- const parsed = parseAuto(text)
100
- return { format: "table", columns: parsed.columns, rows: parsed.rows, title: "stdin" }
101
- },
102
- }
105
+ return createStdinProvider({ renderer: "table" })
103
106
  }
@@ -1,11 +1,6 @@
1
1
  export { useContentLoader } from "./useContentLoader.js"
2
- export { useMarkState } from "./useMarkState.js"
3
- export { useViewCommands } from "./useViewCommands.js"
4
- export {
5
- createViewCommandContext,
6
- useProvideViewCommandContext,
7
- useViewCommandContext,
8
- } from "./useViewCommandContext.js"
2
+ export { useContentCommands } from "./useContentCommands.js"
3
+ export { createViewCommandContext, useProvideViewCommandContext } from "./useViewCommandContext.js"
9
4
  export type {
10
5
  CreateViewCommandContextOptions,
11
6
  ProvideViewCommandContextOptions,
@@ -0,0 +1,29 @@
1
+ import { useState } from "react"
2
+ import { useCopyCommand, useToggleLineNumbersCommand } from "@tooee/shell"
3
+ import { useConfig } from "@tooee/config"
4
+ import type { AnyContent } from "../types.js"
5
+
6
+ interface UseContentCommandsParams {
7
+ content: AnyContent | null
8
+ textContent: string
9
+ }
10
+
11
+ /**
12
+ * The commands a content viewer owns on top of `DocumentScreen`: copying the
13
+ * whole document and toggling the line-number gutter. Theme, quit, actions and
14
+ * every row-level command belong to the document controller and its screen.
15
+ */
16
+ export function useContentCommands({ content, textContent }: UseContentCommandsParams) {
17
+ const config = useConfig()
18
+ const [showLineNumbers, setShowLineNumbers] = useState(config.view?.gutter ?? true)
19
+
20
+ useCopyCommand({
21
+ getText: () => (content ? textContent : undefined),
22
+ })
23
+ useToggleLineNumbersCommand({
24
+ showLineNumbers,
25
+ onToggle: () => setShowLineNumbers((v) => !v),
26
+ })
27
+
28
+ return { showLineNumbers }
29
+ }
@@ -1,19 +1,20 @@
1
- import { useProvideCommandContextKey, useMode } from "@tooee/commands"
2
- import type { Mode } from "@tooee/commands"
3
- import type { NavigationState } from "@tooee/shell"
1
+ import { useProvideCommandContextKey } from "@tooee/commands"
4
2
  import type { MarkSet } from "@tooee/marks"
5
3
  import type { AnyContent } from "../types.js"
6
4
 
7
- /** The `view` field contributed to the command context (see augmentation below). */
5
+ /**
6
+ * The `view` field contributed to the command context (see augmentation below).
7
+ *
8
+ * This slice is content-only. Row state — cursor, selection, active and
9
+ * selected rows — is generic to every row document and lives on `ctx.document`,
10
+ * which `DocumentScreen` provides alongside this.
11
+ */
8
12
  export interface ViewCommandContext {
9
13
  content: AnyContent
10
14
  format: string
11
15
  title?: string
12
16
  data?: unknown
13
- cursor: number | null
14
- selection: { start: number; end: number } | null
15
- mode: Mode
16
- toggledIndices: Set<number>
17
+ /** Reload the content from its provider. */
17
18
  reload: () => void
18
19
  marks: {
19
20
  setMarkSet: (set: MarkSet) => void
@@ -22,8 +23,6 @@ export interface ViewCommandContext {
22
23
  userMarks: MarkSet[]
23
24
  providerMarks: MarkSet[]
24
25
  }
25
- /** Subview extras (e.g. activeRow/selectedRows for tables). */
26
- [key: string]: unknown
27
26
  }
28
27
 
29
28
  declare module "@tooee/commands" {
@@ -34,8 +33,6 @@ declare module "@tooee/commands" {
34
33
 
35
34
  const noop = () => {}
36
35
 
37
- type ViewNavigationContext = Pick<NavigationState, "cursor" | "selection" | "toggledIndices">
38
-
39
36
  export interface CreateViewCommandContextOptions {
40
37
  /**
41
38
  * Content represented by this command context. Custom/headless surfaces may
@@ -45,35 +42,19 @@ export interface CreateViewCommandContextOptions {
45
42
  format?: string
46
43
  title?: string
47
44
  data?: unknown
48
- nav?: ViewNavigationContext
49
- cursor?: number | null
50
- selection?: { start: number; end: number } | null
51
- /** Caller-owned mode value. Prefer `useProvideViewCommandContext` in React so this is live. */
52
- mode: Mode
53
- toggledIndices?: Set<number>
54
45
  reload?: () => void
55
46
  marks?: Partial<ViewCommandContext["marks"]>
56
- extras?: Record<string, unknown>
57
47
  }
58
48
 
59
- export type ProvideViewCommandContextOptions = Omit<CreateViewCommandContextOptions, "mode"> & {
60
- /** Advanced override; normally omitted so the hook injects the live command mode. */
61
- mode?: Mode
62
- }
49
+ export type ProvideViewCommandContextOptions = CreateViewCommandContextOptions
63
50
 
64
51
  export function createViewCommandContext({
65
52
  content,
66
53
  format,
67
54
  title,
68
55
  data,
69
- nav,
70
- cursor,
71
- selection,
72
- mode,
73
- toggledIndices,
74
56
  reload,
75
57
  marks,
76
- extras,
77
58
  }: CreateViewCommandContextOptions): ViewCommandContext {
78
59
  const resolvedFormat = format ?? content?.format ?? "custom"
79
60
  const resolvedContent: AnyContent =
@@ -85,15 +66,10 @@ export function createViewCommandContext({
85
66
  } satisfies AnyContent)
86
67
 
87
68
  return {
88
- ...extras,
89
69
  content: resolvedContent,
90
70
  format: resolvedFormat,
91
71
  title: title ?? content?.title,
92
72
  data: data ?? ("data" in resolvedContent ? resolvedContent.data : undefined),
93
- cursor: cursor ?? nav?.cursor ?? null,
94
- selection: selection ?? nav?.selection ?? null,
95
- mode,
96
- toggledIndices: toggledIndices ?? nav?.toggledIndices ?? new Set<number>(),
97
73
  reload: reload ?? noop,
98
74
  marks: {
99
75
  setMarkSet: marks?.setMarkSet ?? noop,
@@ -108,51 +84,7 @@ export function createViewCommandContext({
108
84
  export function useProvideViewCommandContext(
109
85
  options: ProvideViewCommandContextOptions | (() => ProvideViewCommandContextOptions),
110
86
  ) {
111
- const mode = useMode()
112
- useProvideCommandContextKey("view", () => {
113
- const resolvedOptions = typeof options === "function" ? options() : options
114
- return createViewCommandContext({
115
- ...resolvedOptions,
116
- mode: resolvedOptions.mode ?? mode,
117
- })
118
- })
119
- }
120
-
121
- interface UseViewCommandContextParams {
122
- content: AnyContent
123
- nav: NavigationState
124
- reload: () => void
125
- providerMarks: MarkSet[]
126
- userMarks: MarkSet[]
127
- setMarkSet: (set: MarkSet) => void
128
- clearMarkNamespace: (namespace: string) => void
129
- clearAllUserMarks: () => void
130
- /** Extra fields merged into the view context (e.g. activeRow, selectedRows for table) */
131
- extras?: Record<string, unknown>
132
- }
133
-
134
- export function useViewCommandContext({
135
- content,
136
- nav,
137
- reload,
138
- providerMarks,
139
- userMarks,
140
- setMarkSet,
141
- clearMarkNamespace,
142
- clearAllUserMarks,
143
- extras,
144
- }: UseViewCommandContextParams) {
145
- useProvideViewCommandContext({
146
- content,
147
- nav,
148
- reload,
149
- marks: {
150
- setMarkSet,
151
- clearNamespace: clearMarkNamespace,
152
- clearAll: clearAllUserMarks,
153
- userMarks,
154
- providerMarks,
155
- },
156
- extras,
157
- })
87
+ useProvideCommandContextKey("view", () =>
88
+ createViewCommandContext(typeof options === "function" ? options() : options),
89
+ )
158
90
  }
package/src/index.ts CHANGED
@@ -8,12 +8,12 @@ export {
8
8
  createTableFileProvider,
9
9
  createTableStdinProvider,
10
10
  } from "./default-provider.js"
11
+ export type { CreateProviderOptions } from "./default-provider.js"
11
12
  export { listDirectoryFiles } from "./directory-provider.js"
12
13
  export type { DirectoryEntry } from "./directory-provider.js"
13
14
  export {
14
15
  createViewCommandContext,
15
16
  useProvideViewCommandContext,
16
- useViewCommandContext,
17
17
  } from "./hooks/useViewCommandContext.js"
18
18
  export type {
19
19
  CreateViewCommandContextOptions,
package/src/types.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { ReactNode } from "react"
2
- import type { ColumnDef, TableRow } from "@tooee/renderers"
3
- import type { MarkSet, MarkState } from "@tooee/marks"
2
+ import type { ColumnDef, SourceLineRow, TableRow } from "@tooee/renderers"
3
+ import type { DocumentController } from "@tooee/shell"
4
+ import type { MarkSet } from "@tooee/marks"
4
5
 
5
6
  // === Built-in content types ===
6
7
 
@@ -51,22 +52,20 @@ export type AnyContent = Content | CustomContent
51
52
 
52
53
  export interface ContentRendererProps {
53
54
  content: CustomContent
54
- lineCount: number
55
- cursor?: number
56
- selectionStart?: number
57
- selectionEnd?: number
58
- /** Combined mark state (nav + provider + user marks) */
59
- marks?: MarkState
60
55
  /**
61
- * Select a row by index — the mouse equivalent of the keyboard cursor move.
62
- * A custom renderer that has a notion of rows should call this from its own
63
- * `onMouseDown`/`onRowClick` handlers to make left-click select a row, the
64
- * same way the built-in code/markdown/table views do. Selection is a no-op
65
- * while a modal overlay is open (the host guards it), so renderers can wire
66
- * it unconditionally. Renderers that own a `RowDocumentRenderable` can map a
67
- * click's screen-Y to a row via its `getRowAtScreenY(event.y)` helper.
56
+ * The host's document controller. Its rows are the content's source lines
57
+ * (`SourceLineRow`), which is also the unit navigation, search and copy work
58
+ * in; `row.text` is the plain-text line and `row.source` its provenance.
59
+ *
60
+ * A renderer that owns a `<row-document>` binds the controller directly — it
61
+ * satisfies `DocumentBindings`, so `ref`, `decorations` and `onMouseDown`
62
+ * spread onto the element the way the built-in views wire them. A renderer
63
+ * with its own markup reads `activeIndex` and `navigation.selection` for
64
+ * cursor state and calls `selectRow(index)` from its mouse handlers;
65
+ * `selectRow` stands down while a modal overlay is open, so it can be wired
66
+ * unconditionally.
68
67
  */
69
- onSelectRow?: (index: number) => void
68
+ document: DocumentController<SourceLineRow>
70
69
  }
71
70
 
72
71
  export type ContentRenderer = (props: ContentRendererProps) => ReactNode
@@ -1,16 +0,0 @@
1
- import type { ReactNode } from "react";
2
- import { type StatusBarItem } from "@tooee/layout";
3
- import type { NavigationState } from "@tooee/shell";
4
- import type { SearchState } from "@tooee/search";
5
- import type { AnyContent } from "../types.js";
6
- interface SubviewLayoutProps {
7
- content: AnyContent;
8
- nav: NavigationState & SearchState;
9
- streaming: boolean;
10
- themeName: string;
11
- extraStatusItems?: StatusBarItem[];
12
- children: ReactNode;
13
- }
14
- export declare function SubviewLayout({ content, nav, streaming, themeName, extraStatusItems, children, }: SubviewLayoutProps): ReactNode;
15
- export {};
16
- //# sourceMappingURL=SubviewLayout.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SubviewLayout.d.ts","sourceRoot":"","sources":["../../src/components/SubviewLayout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,EAAa,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAE7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE7C,UAAU,kBAAkB;IAC1B,OAAO,EAAE,UAAU,CAAA;IACnB,GAAG,EAAE,eAAe,GAAG,WAAW,CAAA;IAClC,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,gBAAgB,CAAC,EAAE,aAAa,EAAE,CAAA;IAClC,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,GAAG,EACH,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,QAAQ,GACT,EAAE,kBAAkB,aAwBpB"}
@@ -1,18 +0,0 @@
1
- import { jsx as _jsx } from "@opentui/react/jsx-runtime";
2
- import { AppLayout } from "@tooee/layout";
3
- import { useMode } from "@tooee/commands";
4
- export function SubviewLayout({ content, nav, streaming, themeName, extraStatusItems, children, }) {
5
- const mode = useMode();
6
- const statusItems = [
7
- { label: "Theme:", value: themeName },
8
- ...(extraStatusItems ?? []),
9
- { label: "Mode:", value: mode },
10
- { label: "Cursor:", value: nav.cursor !== null ? String(nav.cursor) : "-" },
11
- ...(streaming ? [{ label: "Status:", value: "streaming" }] : []),
12
- ...(nav.searchActive ? [{ label: "Search:", value: nav.searchQuery }] : []),
13
- ];
14
- return (_jsx(AppLayout, { titleBar: content.title
15
- ? { title: content.title, subtitle: content.format }
16
- : { title: content.format }, statusBar: { items: statusItems }, searchBar: nav, children: children }));
17
- }
18
- //# sourceMappingURL=SubviewLayout.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SubviewLayout.js","sourceRoot":"","sources":["../../src/components/SubviewLayout.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAsB,MAAM,eAAe,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAczC,MAAM,UAAU,aAAa,CAAC,EAC5B,OAAO,EACP,GAAG,EACH,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,QAAQ,GACW;IACnB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;IACtB,MAAM,WAAW,GAAG;QAClB,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE;QACrC,GAAG,CAAC,gBAAgB,IAAI,EAAE,CAAC;QAC3B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE;QAC/B,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE;QAC3E,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5E,CAAA;IAED,OAAO,CACL,KAAC,SAAS,IACR,QAAQ,EACN,OAAO,CAAC,KAAK;YACX,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE;YACpD,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,EAE/B,SAAS,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,EACjC,SAAS,EAAE,GAAG,YAEb,QAAQ,GACC,CACb,CAAA;AACH,CAAC"}
@@ -1,14 +0,0 @@
1
- import type { MarkSet, MarkState } from "@tooee/marks";
2
- import type { NavigationState } from "@tooee/shell";
3
- import type { SearchState } from "@tooee/search";
4
- import type { ResolvedTheme } from "@tooee/themes";
5
- interface UseMarkStateParams {
6
- nav: Pick<NavigationState, "cursor" | "selection" | "toggledIndices">;
7
- search: Pick<SearchState, "matchingLines" | "currentMatchIndex">;
8
- theme: ResolvedTheme;
9
- providerMarks: MarkSet[];
10
- userMarks: MarkSet[];
11
- }
12
- export declare function useMarkState({ nav, search, theme, providerMarks, userMarks, }: UseMarkStateParams): MarkState | undefined;
13
- export {};
14
- //# sourceMappingURL=useMarkState.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useMarkState.d.ts","sourceRoot":"","sources":["../../src/hooks/useMarkState.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAElD,UAAU,kBAAkB;IAC1B,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,WAAW,GAAG,gBAAgB,CAAC,CAAA;IACrE,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,eAAe,GAAG,mBAAmB,CAAC,CAAA;IAChE,KAAK,EAAE,aAAa,CAAA;IACpB,aAAa,EAAE,OAAO,EAAE,CAAA;IACxB,SAAS,EAAE,OAAO,EAAE,CAAA;CACrB;AAED,wBAAgB,YAAY,CAAC,EAC3B,GAAG,EACH,MAAM,EACN,KAAK,EACL,aAAa,EACb,SAAS,GACV,EAAE,kBAAkB,GAAG,SAAS,GAAG,SAAS,CA8E5C"}
@@ -1,71 +0,0 @@
1
- import { useMemo } from "react";
2
- import { MarkSetBuilder, createMarkState, MarkPriorities } from "@tooee/marks";
3
- export function useMarkState({ nav, search, theme, providerMarks, userMarks, }) {
4
- return useMemo(() => {
5
- const sets = [];
6
- // Search matches
7
- if (search.matchingLines.length > 0) {
8
- const mapped = new Set(search.matchingLines);
9
- const builder = new MarkSetBuilder();
10
- for (const idx of mapped) {
11
- builder.addLine(idx, {
12
- background: theme.warning,
13
- signBefore: "\u25CF",
14
- foreground: theme.warning,
15
- });
16
- }
17
- sets.push(builder.build("search", MarkPriorities.SEARCH_MATCH));
18
- }
19
- // Toggled lines
20
- if (nav.toggledIndices.size > 0) {
21
- const mapped = new Set(nav.toggledIndices);
22
- const builder = new MarkSetBuilder();
23
- for (const idx of mapped) {
24
- builder.addLine(idx, { background: theme.backgroundPanel });
25
- }
26
- sets.push(builder.build("toggled", MarkPriorities.TOGGLED));
27
- }
28
- // Selection range
29
- if (nav.selection) {
30
- const builder = new MarkSetBuilder();
31
- builder.addRange({ line: nav.selection.start }, { line: nav.selection.end }, { background: theme.selection });
32
- sets.push(builder.build("selection", MarkPriorities.SELECTION));
33
- }
34
- // Current match highlight
35
- if (search.matchingLines.length > 0) {
36
- const currentLine = search.matchingLines[search.currentMatchIndex];
37
- if (currentLine != null) {
38
- const builder = new MarkSetBuilder();
39
- builder.addLine(currentLine, {
40
- background: theme.primary,
41
- signBefore: "\u25CF",
42
- foreground: theme.primary,
43
- });
44
- sets.push(builder.build("currentMatch", MarkPriorities.CURRENT_MATCH));
45
- }
46
- }
47
- // Cursor
48
- if (nav.cursor !== null) {
49
- const builder = new MarkSetBuilder();
50
- builder.addLine(nav.cursor, {
51
- background: theme.cursorLine,
52
- signBefore: "\u25B8",
53
- foreground: theme.primary,
54
- });
55
- sets.push(builder.build("cursor", MarkPriorities.CURSOR));
56
- }
57
- // Provider and user marks
58
- sets.push(...providerMarks, ...userMarks);
59
- return sets.length > 0 ? createMarkState(sets) : undefined;
60
- }, [
61
- search.matchingLines,
62
- search.currentMatchIndex,
63
- nav.toggledIndices,
64
- nav.selection,
65
- nav.cursor,
66
- theme,
67
- providerMarks,
68
- userMarks,
69
- ]);
70
- }
71
- //# sourceMappingURL=useMarkState.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useMarkState.js","sourceRoot":"","sources":["../../src/hooks/useMarkState.ts"],"names":[],"mappings":"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"}
@@ -1,13 +0,0 @@
1
- import type { ActionDefinition } from "@tooee/commands";
2
- import type { AnyContent } from "../types.js";
3
- interface UseViewCommandsParams {
4
- content: AnyContent | null;
5
- textContent: string;
6
- actions?: ActionDefinition[];
7
- }
8
- export declare function useViewCommands({ content, textContent, actions }: UseViewCommandsParams): {
9
- themeName: string;
10
- showLineNumbers: boolean;
11
- };
12
- export {};
13
- //# sourceMappingURL=useViewCommands.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useViewCommands.d.ts","sourceRoot":"","sources":["../../src/hooks/useViewCommands.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAEvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE7C,UAAU,qBAAqB;IAC7B,OAAO,EAAE,UAAU,GAAG,IAAI,CAAA;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAA;CAC7B;AAED,wBAAgB,eAAe,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,qBAAqB;;;EAiBvF"}
@@ -1,20 +0,0 @@
1
- import { useState } from "react";
2
- import { useThemeCommands, useQuitCommand, useCopyCommand, useToggleLineNumbersCommand, } from "@tooee/shell";
3
- import { useActions } from "@tooee/commands";
4
- import { useConfig } from "@tooee/config";
5
- export function useViewCommands({ content, textContent, actions }) {
6
- const config = useConfig();
7
- const [showLineNumbers, setShowLineNumbers] = useState(config.view?.gutter ?? true);
8
- const { name: themeName } = useThemeCommands();
9
- useQuitCommand();
10
- useCopyCommand({
11
- getText: () => (content ? textContent : undefined),
12
- });
13
- useToggleLineNumbersCommand({
14
- showLineNumbers,
15
- onToggle: () => setShowLineNumbers((v) => !v),
16
- });
17
- useActions(actions);
18
- return { themeName, showLineNumbers };
19
- }
20
- //# sourceMappingURL=useViewCommands.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useViewCommands.js","sourceRoot":"","sources":["../../src/hooks/useViewCommands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,2BAA2B,GAC5B,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AASzC,MAAM,UAAU,eAAe,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAyB;IACtF,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,IAAI,IAAI,CAAC,CAAA;IAEnF,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,gBAAgB,EAAE,CAAA;IAC9C,cAAc,EAAE,CAAA;IAChB,cAAc,CAAC;QACb,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;KACnD,CAAC,CAAA;IACF,2BAA2B,CAAC;QAC1B,eAAe;QACf,QAAQ,EAAE,GAAG,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;KAC9C,CAAC,CAAA;IAEF,UAAU,CAAC,OAAO,CAAC,CAAA;IAEnB,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CAAA;AACvC,CAAC"}
@@ -1,48 +0,0 @@
1
- import type { ReactNode } from "react"
2
- import { AppLayout, type StatusBarItem } from "@tooee/layout"
3
- import { useMode } from "@tooee/commands"
4
- import type { NavigationState } from "@tooee/shell"
5
- import type { SearchState } from "@tooee/search"
6
- import type { AnyContent } from "../types.js"
7
-
8
- interface SubviewLayoutProps {
9
- content: AnyContent
10
- nav: NavigationState & SearchState
11
- streaming: boolean
12
- themeName: string
13
- extraStatusItems?: StatusBarItem[]
14
- children: ReactNode
15
- }
16
-
17
- export function SubviewLayout({
18
- content,
19
- nav,
20
- streaming,
21
- themeName,
22
- extraStatusItems,
23
- children,
24
- }: SubviewLayoutProps) {
25
- const mode = useMode()
26
- const statusItems = [
27
- { label: "Theme:", value: themeName },
28
- ...(extraStatusItems ?? []),
29
- { label: "Mode:", value: mode },
30
- { label: "Cursor:", value: nav.cursor !== null ? String(nav.cursor) : "-" },
31
- ...(streaming ? [{ label: "Status:", value: "streaming" }] : []),
32
- ...(nav.searchActive ? [{ label: "Search:", value: nav.searchQuery }] : []),
33
- ]
34
-
35
- return (
36
- <AppLayout
37
- titleBar={
38
- content.title
39
- ? { title: content.title, subtitle: content.format }
40
- : { title: content.format }
41
- }
42
- statusBar={{ items: statusItems }}
43
- searchBar={nav}
44
- >
45
- {children}
46
- </AppLayout>
47
- )
48
- }