@tutti-os/workspace-file-preview 0.0.219 → 0.0.221
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/react/index.d.ts +14 -2
- package/dist/react/index.js +30 -10
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,6 +15,8 @@ This package ships:
|
|
|
15
15
|
- `createWorkspaceFilePreviewController` for shared frontend loading lifecycle
|
|
16
16
|
(readiness, cancellation, stale-request fencing, decoding, object-URL cleanup)
|
|
17
17
|
- Built-in React preview shells for `image` / `video` / `text`
|
|
18
|
+
- `WorkspaceImagePreviewSurface` for reusing the built-in image canvas while
|
|
19
|
+
keeping source loading, URL lifetime, and error policy in the host
|
|
18
20
|
- Host renderer registry (by `previewKind`) and a resolve chain:
|
|
19
21
|
host hook → text degradation → unsupported state
|
|
20
22
|
- `toSurfaceState(controllerState, copy)` to project controller state into the
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WorkspaceFilePreviewKind, WorkspaceFilePreviewReadonlyReason, WorkspaceFilePreviewUnsupportedReason, WorkspaceFilePreviewControllerState } from '../core/index.js';
|
|
2
|
-
import { ReactNode, ReactElement } from 'react';
|
|
2
|
+
import { ReactNode, ReactElement, ImgHTMLAttributes } from 'react';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Thin built-in preview surface (image / video / text) plus host renderer hooks.
|
|
@@ -57,6 +57,18 @@ type WorkspaceFilePreviewSurfaceState<TEntry> = {
|
|
|
57
57
|
status: "error";
|
|
58
58
|
};
|
|
59
59
|
type WorkspaceFilePreviewSurfaceVariant = "canvas" | "compact" | "detail";
|
|
60
|
+
/**
|
|
61
|
+
* Host-neutral image canvas shared by workspace previews and other file-backed
|
|
62
|
+
* surfaces. The caller owns the source URL lifecycle and error-state policy.
|
|
63
|
+
*/
|
|
64
|
+
interface WorkspaceImagePreviewSurfaceProps {
|
|
65
|
+
alt: string;
|
|
66
|
+
draggable?: boolean;
|
|
67
|
+
onError?: ImgHTMLAttributes<HTMLImageElement>["onError"];
|
|
68
|
+
src: string;
|
|
69
|
+
variant: WorkspaceFilePreviewSurfaceVariant;
|
|
70
|
+
}
|
|
71
|
+
declare function WorkspaceImagePreviewSurface({ alt, draggable, onError, src, variant }: WorkspaceImagePreviewSurfaceProps): ReactElement;
|
|
60
72
|
interface WorkspaceFilePreviewHostRendererProps<TEntry> {
|
|
61
73
|
entry: TEntry;
|
|
62
74
|
previewKind: WorkspaceFilePreviewKind;
|
|
@@ -109,4 +121,4 @@ interface WorkspaceFilePreviewSurfaceCopy {
|
|
|
109
121
|
*/
|
|
110
122
|
declare function toSurfaceState<TEntry>(state: WorkspaceFilePreviewControllerState<TEntry>, copy: WorkspaceFilePreviewSurfaceCopy): WorkspaceFilePreviewSurfaceState<TEntry>;
|
|
111
123
|
|
|
112
|
-
export { type WorkspaceFilePreviewHostRenderer, type WorkspaceFilePreviewHostRendererProps, type WorkspaceFilePreviewHostRenderers, WorkspaceFilePreviewSurface, type WorkspaceFilePreviewSurfaceCopy, type WorkspaceFilePreviewSurfaceProps, type WorkspaceFilePreviewSurfaceState, type WorkspaceFilePreviewSurfaceVariant, toSurfaceState };
|
|
124
|
+
export { type WorkspaceFilePreviewHostRenderer, type WorkspaceFilePreviewHostRendererProps, type WorkspaceFilePreviewHostRenderers, WorkspaceFilePreviewSurface, type WorkspaceFilePreviewSurfaceCopy, type WorkspaceFilePreviewSurfaceProps, type WorkspaceFilePreviewSurfaceState, type WorkspaceFilePreviewSurfaceVariant, WorkspaceImagePreviewSurface, type WorkspaceImagePreviewSurfaceProps, toSurfaceState };
|
package/dist/react/index.js
CHANGED
|
@@ -66,6 +66,31 @@ function toSurfaceState(state, copy) {
|
|
|
66
66
|
|
|
67
67
|
// src/react/workspaceFilePreviewSurface.tsx
|
|
68
68
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
69
|
+
function WorkspaceImagePreviewSurface({
|
|
70
|
+
alt,
|
|
71
|
+
draggable,
|
|
72
|
+
onError,
|
|
73
|
+
src,
|
|
74
|
+
variant
|
|
75
|
+
}) {
|
|
76
|
+
const styles = workspaceFilePreviewSurfaceStyles[variant];
|
|
77
|
+
return /* @__PURE__ */ jsx(
|
|
78
|
+
WorkspaceFilePreviewFrame,
|
|
79
|
+
{
|
|
80
|
+
className: joinClassNames(styles.frame, styles.imageFrame),
|
|
81
|
+
children: /* @__PURE__ */ jsx(
|
|
82
|
+
"img",
|
|
83
|
+
{
|
|
84
|
+
alt,
|
|
85
|
+
className: styles.image,
|
|
86
|
+
draggable,
|
|
87
|
+
onError,
|
|
88
|
+
src
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
}
|
|
69
94
|
function WorkspaceFilePreviewSurface({
|
|
70
95
|
directoryMessage,
|
|
71
96
|
emptyMessage,
|
|
@@ -99,17 +124,11 @@ function WorkspaceFilePreviewSurface({
|
|
|
99
124
|
] }) });
|
|
100
125
|
case "image":
|
|
101
126
|
return /* @__PURE__ */ jsx(
|
|
102
|
-
|
|
127
|
+
WorkspaceImagePreviewSurface,
|
|
103
128
|
{
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
{
|
|
108
|
-
alt: imageAlt(state.entry),
|
|
109
|
-
className: styles.image,
|
|
110
|
-
src: state.objectUrl
|
|
111
|
-
}
|
|
112
|
-
)
|
|
129
|
+
alt: imageAlt(state.entry),
|
|
130
|
+
src: state.objectUrl,
|
|
131
|
+
variant
|
|
113
132
|
}
|
|
114
133
|
);
|
|
115
134
|
case "text":
|
|
@@ -242,6 +261,7 @@ function joinClassNames(...classNames) {
|
|
|
242
261
|
}
|
|
243
262
|
export {
|
|
244
263
|
WorkspaceFilePreviewSurface,
|
|
264
|
+
WorkspaceImagePreviewSurface,
|
|
245
265
|
toSurfaceState
|
|
246
266
|
};
|
|
247
267
|
//# sourceMappingURL=index.js.map
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react/toSurfaceState.ts","../../src/react/workspaceFilePreviewSurface.tsx"],"sourcesContent":["/**\n * Projects controller state into surface state with host-provided copy.\n *\n * Ownership rules: packages/workspace/file-preview/CONTRACT.md\n */\n\nimport type {\n WorkspaceFilePreviewControllerState,\n WorkspaceFilePreviewUnsupportedReason\n} from \"../core/workspaceFilePreviewController.ts\";\nimport type { WorkspaceFilePreviewReadonlyReason } from \"../core/workspaceFilePreview.ts\";\nimport type { WorkspaceFilePreviewKind } from \"../core/workspaceFilePreviewKinds.ts\";\nimport type { WorkspaceFilePreviewSurfaceState } from \"./workspaceFilePreviewSurface.tsx\";\n\nexport interface WorkspaceFilePreviewSurfaceCopy {\n errorMessage: (error: unknown) => string;\n readonlyMessage: (\n reason: WorkspaceFilePreviewReadonlyReason,\n maxSizeBytes?: number\n ) => string;\n unsupportedMessage: (\n reason: WorkspaceFilePreviewUnsupportedReason,\n previewKind?: WorkspaceFilePreviewKind\n ) => string;\n}\n\n/**\n * Shared projection from machine-readable controller state to the React\n * surface state. Controllers remain the source of truth; hosts inject copy.\n */\nexport function toSurfaceState<TEntry>(\n state: WorkspaceFilePreviewControllerState<TEntry>,\n copy: WorkspaceFilePreviewSurfaceCopy\n): WorkspaceFilePreviewSurfaceState<TEntry> {\n switch (state.status) {\n case \"empty\":\n return { status: \"empty\" };\n case \"directory\":\n return { entry: state.entry, status: \"directory\" };\n case \"loading\":\n return {\n entry: state.entry,\n previewKind: state.previewKind,\n status: \"loading\"\n };\n case \"text\":\n return {\n content: state.content,\n entry: state.entry,\n previewKind: state.previewKind,\n status: \"text\"\n };\n case \"image\":\n return {\n entry: state.entry,\n objectUrl: state.objectUrl,\n previewKind: \"image\",\n status: \"image\"\n };\n case \"video\":\n return {\n entry: state.entry,\n objectUrl: state.objectUrl,\n previewKind: \"video\",\n status: \"video\"\n };\n case \"bytes\":\n return {\n bytes: state.bytes,\n contentType: state.contentType,\n entry: state.entry,\n previewKind: state.previewKind,\n status: \"bytes\"\n };\n case \"readonly\":\n return {\n entry: state.entry,\n message: copy.readonlyMessage(state.reason, state.maxSizeBytes),\n previewKind: state.previewKind,\n status: \"readonly\"\n };\n case \"unsupported\":\n return {\n entry: state.entry,\n message: copy.unsupportedMessage(state.reason, state.previewKind),\n previewKind: state.previewKind,\n status: \"unsupported\"\n };\n case \"error\":\n return {\n entry: state.entry,\n message: copy.errorMessage(state.error),\n previewKind: state.previewKind,\n status: \"error\"\n };\n }\n}\n","/**\n * Thin built-in preview surface (image / video / text) plus host renderer hooks.\n *\n * Resolve order: host renderer for previewKind → built-in text degradation →\n * unsupported/fallback messaging already present in state.\n *\n * Ownership rules: packages/workspace/file-preview/CONTRACT.md\n */\n\nimport type { ReactElement, ReactNode } from \"react\";\nimport type { WorkspaceFilePreviewKind } from \"../core/workspaceFilePreviewKinds.ts\";\n\nexport type WorkspaceFilePreviewSurfaceState<TEntry> =\n | { status: \"empty\" }\n | { entry: TEntry; status: \"directory\" }\n | {\n entry: TEntry;\n previewKind?: WorkspaceFilePreviewKind;\n status: \"loading\";\n }\n | {\n content: string;\n entry: TEntry;\n previewKind: WorkspaceFilePreviewKind;\n status: \"text\";\n }\n | {\n entry: TEntry;\n objectUrl: string;\n previewKind: \"image\";\n status: \"image\";\n }\n | {\n entry: TEntry;\n objectUrl: string;\n previewKind: \"video\";\n status: \"video\";\n }\n | {\n bytes: Uint8Array<ArrayBuffer>;\n contentType: string | null;\n entry: TEntry;\n previewKind: WorkspaceFilePreviewKind;\n status: \"bytes\";\n }\n | {\n entry: TEntry;\n message: string;\n previewKind?: WorkspaceFilePreviewKind;\n status: \"readonly\";\n }\n | {\n entry: TEntry;\n message: string;\n previewKind?: WorkspaceFilePreviewKind;\n status: \"unsupported\";\n }\n | {\n entry: TEntry;\n message: string;\n previewKind?: WorkspaceFilePreviewKind;\n status: \"error\";\n };\n\nexport type WorkspaceFilePreviewSurfaceVariant =\n | \"canvas\"\n | \"compact\"\n | \"detail\";\n\nexport interface WorkspaceFilePreviewHostRendererProps<TEntry> {\n entry: TEntry;\n previewKind: WorkspaceFilePreviewKind;\n variant: WorkspaceFilePreviewSurfaceVariant;\n /** Present when the controller decoded text (including text-degradable kinds). */\n content?: string;\n /** Present for hook-only kinds loaded as raw bytes. */\n bytes?: Uint8Array<ArrayBuffer>;\n contentType?: string | null;\n /** Present for built-in media kinds when a host still overrides rendering. */\n objectUrl?: string;\n}\n\nexport type WorkspaceFilePreviewHostRenderer<TEntry> = (\n props: WorkspaceFilePreviewHostRendererProps<TEntry>\n) => ReactNode;\n\n/**\n * Host renderer registry keyed by previewKind. `variant` is passed as props;\n * optional (kind, variant) specificity may be added later.\n */\nexport type WorkspaceFilePreviewHostRenderers<TEntry> = Partial<\n Record<WorkspaceFilePreviewKind, WorkspaceFilePreviewHostRenderer<TEntry>>\n>;\n\nexport interface WorkspaceFilePreviewSurfaceProps<TEntry> {\n directoryMessage: string;\n emptyMessage: string;\n imageAlt: (entry: TEntry) => string;\n loadingIndicator: ReactNode;\n loadingMessage: string;\n /**\n * Optional host renderers registered by previewKind. When present for the\n * current kind, they win over built-in image / video / text shells.\n */\n renderers?: WorkspaceFilePreviewHostRenderers<TEntry>;\n renderIcon: (entry: TEntry) => ReactNode;\n state: WorkspaceFilePreviewSurfaceState<TEntry>;\n variant: WorkspaceFilePreviewSurfaceVariant;\n}\n\nexport function WorkspaceFilePreviewSurface<TEntry>({\n directoryMessage,\n emptyMessage,\n imageAlt,\n loadingIndicator,\n loadingMessage,\n renderers,\n renderIcon,\n state,\n variant\n}: WorkspaceFilePreviewSurfaceProps<TEntry>): ReactElement {\n const styles = workspaceFilePreviewSurfaceStyles[variant];\n const hostRendered = renderHostPreview({\n renderers,\n state,\n variant\n });\n if (hostRendered !== null) {\n return (\n <WorkspaceFilePreviewFrame className={styles.frame}>\n {hostRendered}\n </WorkspaceFilePreviewFrame>\n );\n }\n\n switch (state.status) {\n case \"directory\":\n return (\n <WorkspaceFilePreviewFrame className={styles.frame}>\n <div className=\"flex flex-col items-center justify-center gap-2.5 text-center text-[13px] leading-5 text-[var(--text-tertiary)]\">\n {renderIcon(state.entry)}\n <span>{directoryMessage}</span>\n </div>\n </WorkspaceFilePreviewFrame>\n );\n case \"loading\":\n return (\n <WorkspaceFilePreviewFrame className={styles.frame}>\n <div className=\"space-y-3 px-4 text-center text-[13px] text-[var(--text-tertiary)]\">\n {loadingIndicator}\n <span>{loadingMessage}</span>\n </div>\n </WorkspaceFilePreviewFrame>\n );\n case \"image\":\n return (\n <WorkspaceFilePreviewFrame\n className={joinClassNames(styles.frame, styles.imageFrame)}\n >\n <img\n alt={imageAlt(state.entry)}\n className={styles.image}\n src={state.objectUrl}\n />\n </WorkspaceFilePreviewFrame>\n );\n case \"text\":\n return (\n <WorkspaceFilePreviewFrame\n className={joinClassNames(styles.frame, styles.textFrame)}\n >\n <pre className={styles.text}>{state.content}</pre>\n </WorkspaceFilePreviewFrame>\n );\n case \"video\":\n return (\n <WorkspaceFilePreviewFrame\n className={joinClassNames(styles.frame, styles.videoFrame)}\n >\n <video\n aria-label={imageAlt(state.entry)}\n className={styles.video}\n muted\n playsInline\n preload=\"metadata\"\n src={state.objectUrl}\n onLoadedMetadata={(event) => {\n const video = event.currentTarget;\n if (video.duration > 0 && video.currentTime === 0) {\n video.currentTime = Math.min(0.1, video.duration / 2);\n }\n }}\n />\n </WorkspaceFilePreviewFrame>\n );\n case \"bytes\":\n // Hook-only kinds without a registered renderer fall through to the\n // unsupported messaging path via host-projected state; if bytes somehow\n // arrive without a hook, show the generic unsupported shell.\n return (\n <WorkspaceFilePreviewFrame className={styles.frame}>\n <div className=\"flex flex-col items-center justify-center gap-3 px-4 text-center text-[13px] text-[var(--text-tertiary)]\">\n {renderIcon(state.entry)}\n <span className={styles.message}>{emptyMessage}</span>\n </div>\n </WorkspaceFilePreviewFrame>\n );\n case \"readonly\":\n case \"unsupported\":\n case \"error\":\n return (\n <WorkspaceFilePreviewFrame className={styles.frame}>\n <div className=\"flex flex-col items-center justify-center gap-3 px-4 text-center text-[13px] text-[var(--text-tertiary)]\">\n {renderIcon(state.entry)}\n <span className={styles.message}>{state.message}</span>\n </div>\n </WorkspaceFilePreviewFrame>\n );\n case \"empty\":\n return (\n <WorkspaceFilePreviewFrame className={styles.frame}>\n <span className={styles.message}>{emptyMessage}</span>\n </WorkspaceFilePreviewFrame>\n );\n }\n}\n\nfunction renderHostPreview<TEntry>(input: {\n renderers: WorkspaceFilePreviewHostRenderers<TEntry> | undefined;\n state: WorkspaceFilePreviewSurfaceState<TEntry>;\n variant: WorkspaceFilePreviewSurfaceVariant;\n}): ReactNode | null {\n const { renderers, state, variant } = input;\n if (!renderers) {\n return null;\n }\n\n switch (state.status) {\n case \"text\": {\n const renderer = renderers[state.previewKind];\n return renderer\n ? renderer({\n content: state.content,\n entry: state.entry,\n previewKind: state.previewKind,\n variant\n })\n : null;\n }\n case \"image\":\n case \"video\": {\n const renderer = renderers[state.previewKind];\n return renderer\n ? renderer({\n entry: state.entry,\n objectUrl: state.objectUrl,\n previewKind: state.previewKind,\n variant\n })\n : null;\n }\n case \"bytes\": {\n const renderer = renderers[state.previewKind];\n return renderer\n ? renderer({\n bytes: state.bytes,\n contentType: state.contentType,\n entry: state.entry,\n previewKind: state.previewKind,\n variant\n })\n : null;\n }\n default:\n return null;\n }\n}\n\nconst workspaceFilePreviewSurfaceStyles: Record<\n WorkspaceFilePreviewSurfaceVariant,\n {\n frame: string;\n image: string;\n imageFrame: string;\n message: string;\n text: string;\n textFrame: string;\n video: string;\n videoFrame: string;\n }\n> = {\n compact: {\n frame:\n \"flex aspect-[3/2] w-full flex-col items-center justify-center overflow-hidden rounded-[8px] border border-[var(--line-2,var(--border-2))] bg-[var(--transparency-block)] p-0 text-center\",\n image: \"max-h-full max-w-full rounded-[6px] object-contain\",\n imageFrame: \"p-3\",\n message:\n \"mx-auto max-w-[24ch] text-center text-[13px] leading-5 text-[var(--text-secondary)] [overflow-wrap:anywhere]\",\n text: \"h-full w-full overflow-auto p-3 text-left text-[11px] leading-5 whitespace-pre-wrap break-words text-[var(--text-primary)]\",\n textFrame: \"items-stretch justify-stretch\",\n video: \"block max-h-full max-w-full rounded-[6px] object-contain\",\n videoFrame: \"p-3\"\n },\n detail: {\n frame:\n \"flex h-60 min-h-60 max-h-60 items-center justify-center overflow-hidden rounded-lg bg-[var(--transparency-block)]\",\n image: \"max-h-full max-w-full rounded-[6px] object-contain\",\n imageFrame: \"p-4\",\n message:\n \"max-w-[24ch] text-center text-[13px] leading-5 text-[var(--text-tertiary)] [overflow-wrap:anywhere]\",\n text: \"h-full overflow-auto p-4 text-[11px] leading-5 whitespace-pre-wrap break-words text-[var(--text-primary)]\",\n textFrame: \"items-stretch justify-stretch\",\n video: \"block max-h-full max-w-full rounded-[6px] object-contain\",\n videoFrame: \"p-4\"\n },\n canvas: {\n frame:\n \"flex h-full min-h-0 min-w-0 w-full items-center justify-center overflow-hidden bg-[var(--background-fronted)] text-[var(--text-tertiary)]\",\n image: \"block max-h-full max-w-full object-contain\",\n imageFrame: \"overflow-auto p-3\",\n message:\n \"max-w-[24ch] text-center text-[13px] leading-5 text-[var(--text-tertiary)] [overflow-wrap:anywhere]\",\n text: \"m-0 h-full min-h-0 min-w-0 w-full overflow-auto whitespace-pre-wrap break-words p-3 font-[var(--tsh-font-mono)] text-[11px] leading-[18px] text-[var(--text-secondary)]\",\n textFrame: \"items-stretch justify-stretch\",\n video: \"block max-h-full max-w-full object-contain\",\n videoFrame: \"overflow-auto p-3\"\n }\n};\n\nfunction WorkspaceFilePreviewFrame({\n children,\n className\n}: {\n children: ReactNode;\n className: string;\n}): ReactElement {\n return <div className={className}>{children}</div>;\n}\n\nfunction joinClassNames(\n ...classNames: Array<string | false | null | undefined>\n): string {\n return classNames.filter(Boolean).join(\" \");\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/react/toSurfaceState.ts","../../src/react/workspaceFilePreviewSurface.tsx"],"sourcesContent":["/**\n * Projects controller state into surface state with host-provided copy.\n *\n * Ownership rules: packages/workspace/file-preview/CONTRACT.md\n */\n\nimport type {\n WorkspaceFilePreviewControllerState,\n WorkspaceFilePreviewUnsupportedReason\n} from \"../core/workspaceFilePreviewController.ts\";\nimport type { WorkspaceFilePreviewReadonlyReason } from \"../core/workspaceFilePreview.ts\";\nimport type { WorkspaceFilePreviewKind } from \"../core/workspaceFilePreviewKinds.ts\";\nimport type { WorkspaceFilePreviewSurfaceState } from \"./workspaceFilePreviewSurface.tsx\";\n\nexport interface WorkspaceFilePreviewSurfaceCopy {\n errorMessage: (error: unknown) => string;\n readonlyMessage: (\n reason: WorkspaceFilePreviewReadonlyReason,\n maxSizeBytes?: number\n ) => string;\n unsupportedMessage: (\n reason: WorkspaceFilePreviewUnsupportedReason,\n previewKind?: WorkspaceFilePreviewKind\n ) => string;\n}\n\n/**\n * Shared projection from machine-readable controller state to the React\n * surface state. Controllers remain the source of truth; hosts inject copy.\n */\nexport function toSurfaceState<TEntry>(\n state: WorkspaceFilePreviewControllerState<TEntry>,\n copy: WorkspaceFilePreviewSurfaceCopy\n): WorkspaceFilePreviewSurfaceState<TEntry> {\n switch (state.status) {\n case \"empty\":\n return { status: \"empty\" };\n case \"directory\":\n return { entry: state.entry, status: \"directory\" };\n case \"loading\":\n return {\n entry: state.entry,\n previewKind: state.previewKind,\n status: \"loading\"\n };\n case \"text\":\n return {\n content: state.content,\n entry: state.entry,\n previewKind: state.previewKind,\n status: \"text\"\n };\n case \"image\":\n return {\n entry: state.entry,\n objectUrl: state.objectUrl,\n previewKind: \"image\",\n status: \"image\"\n };\n case \"video\":\n return {\n entry: state.entry,\n objectUrl: state.objectUrl,\n previewKind: \"video\",\n status: \"video\"\n };\n case \"bytes\":\n return {\n bytes: state.bytes,\n contentType: state.contentType,\n entry: state.entry,\n previewKind: state.previewKind,\n status: \"bytes\"\n };\n case \"readonly\":\n return {\n entry: state.entry,\n message: copy.readonlyMessage(state.reason, state.maxSizeBytes),\n previewKind: state.previewKind,\n status: \"readonly\"\n };\n case \"unsupported\":\n return {\n entry: state.entry,\n message: copy.unsupportedMessage(state.reason, state.previewKind),\n previewKind: state.previewKind,\n status: \"unsupported\"\n };\n case \"error\":\n return {\n entry: state.entry,\n message: copy.errorMessage(state.error),\n previewKind: state.previewKind,\n status: \"error\"\n };\n }\n}\n","/**\n * Thin built-in preview surface (image / video / text) plus host renderer hooks.\n *\n * Resolve order: host renderer for previewKind → built-in text degradation →\n * unsupported/fallback messaging already present in state.\n *\n * Ownership rules: packages/workspace/file-preview/CONTRACT.md\n */\n\nimport type { ImgHTMLAttributes, ReactElement, ReactNode } from \"react\";\nimport type { WorkspaceFilePreviewKind } from \"../core/workspaceFilePreviewKinds.ts\";\n\nexport type WorkspaceFilePreviewSurfaceState<TEntry> =\n | { status: \"empty\" }\n | { entry: TEntry; status: \"directory\" }\n | {\n entry: TEntry;\n previewKind?: WorkspaceFilePreviewKind;\n status: \"loading\";\n }\n | {\n content: string;\n entry: TEntry;\n previewKind: WorkspaceFilePreviewKind;\n status: \"text\";\n }\n | {\n entry: TEntry;\n objectUrl: string;\n previewKind: \"image\";\n status: \"image\";\n }\n | {\n entry: TEntry;\n objectUrl: string;\n previewKind: \"video\";\n status: \"video\";\n }\n | {\n bytes: Uint8Array<ArrayBuffer>;\n contentType: string | null;\n entry: TEntry;\n previewKind: WorkspaceFilePreviewKind;\n status: \"bytes\";\n }\n | {\n entry: TEntry;\n message: string;\n previewKind?: WorkspaceFilePreviewKind;\n status: \"readonly\";\n }\n | {\n entry: TEntry;\n message: string;\n previewKind?: WorkspaceFilePreviewKind;\n status: \"unsupported\";\n }\n | {\n entry: TEntry;\n message: string;\n previewKind?: WorkspaceFilePreviewKind;\n status: \"error\";\n };\n\nexport type WorkspaceFilePreviewSurfaceVariant =\n | \"canvas\"\n | \"compact\"\n | \"detail\";\n\n/**\n * Host-neutral image canvas shared by workspace previews and other file-backed\n * surfaces. The caller owns the source URL lifecycle and error-state policy.\n */\nexport interface WorkspaceImagePreviewSurfaceProps {\n alt: string;\n draggable?: boolean;\n onError?: ImgHTMLAttributes<HTMLImageElement>[\"onError\"];\n src: string;\n variant: WorkspaceFilePreviewSurfaceVariant;\n}\n\nexport function WorkspaceImagePreviewSurface({\n alt,\n draggable,\n onError,\n src,\n variant\n}: WorkspaceImagePreviewSurfaceProps): ReactElement {\n const styles = workspaceFilePreviewSurfaceStyles[variant];\n return (\n <WorkspaceFilePreviewFrame\n className={joinClassNames(styles.frame, styles.imageFrame)}\n >\n <img\n alt={alt}\n className={styles.image}\n draggable={draggable}\n onError={onError}\n src={src}\n />\n </WorkspaceFilePreviewFrame>\n );\n}\n\nexport interface WorkspaceFilePreviewHostRendererProps<TEntry> {\n entry: TEntry;\n previewKind: WorkspaceFilePreviewKind;\n variant: WorkspaceFilePreviewSurfaceVariant;\n /** Present when the controller decoded text (including text-degradable kinds). */\n content?: string;\n /** Present for hook-only kinds loaded as raw bytes. */\n bytes?: Uint8Array<ArrayBuffer>;\n contentType?: string | null;\n /** Present for built-in media kinds when a host still overrides rendering. */\n objectUrl?: string;\n}\n\nexport type WorkspaceFilePreviewHostRenderer<TEntry> = (\n props: WorkspaceFilePreviewHostRendererProps<TEntry>\n) => ReactNode;\n\n/**\n * Host renderer registry keyed by previewKind. `variant` is passed as props;\n * optional (kind, variant) specificity may be added later.\n */\nexport type WorkspaceFilePreviewHostRenderers<TEntry> = Partial<\n Record<WorkspaceFilePreviewKind, WorkspaceFilePreviewHostRenderer<TEntry>>\n>;\n\nexport interface WorkspaceFilePreviewSurfaceProps<TEntry> {\n directoryMessage: string;\n emptyMessage: string;\n imageAlt: (entry: TEntry) => string;\n loadingIndicator: ReactNode;\n loadingMessage: string;\n /**\n * Optional host renderers registered by previewKind. When present for the\n * current kind, they win over built-in image / video / text shells.\n */\n renderers?: WorkspaceFilePreviewHostRenderers<TEntry>;\n renderIcon: (entry: TEntry) => ReactNode;\n state: WorkspaceFilePreviewSurfaceState<TEntry>;\n variant: WorkspaceFilePreviewSurfaceVariant;\n}\n\nexport function WorkspaceFilePreviewSurface<TEntry>({\n directoryMessage,\n emptyMessage,\n imageAlt,\n loadingIndicator,\n loadingMessage,\n renderers,\n renderIcon,\n state,\n variant\n}: WorkspaceFilePreviewSurfaceProps<TEntry>): ReactElement {\n const styles = workspaceFilePreviewSurfaceStyles[variant];\n const hostRendered = renderHostPreview({\n renderers,\n state,\n variant\n });\n if (hostRendered !== null) {\n return (\n <WorkspaceFilePreviewFrame className={styles.frame}>\n {hostRendered}\n </WorkspaceFilePreviewFrame>\n );\n }\n\n switch (state.status) {\n case \"directory\":\n return (\n <WorkspaceFilePreviewFrame className={styles.frame}>\n <div className=\"flex flex-col items-center justify-center gap-2.5 text-center text-[13px] leading-5 text-[var(--text-tertiary)]\">\n {renderIcon(state.entry)}\n <span>{directoryMessage}</span>\n </div>\n </WorkspaceFilePreviewFrame>\n );\n case \"loading\":\n return (\n <WorkspaceFilePreviewFrame className={styles.frame}>\n <div className=\"space-y-3 px-4 text-center text-[13px] text-[var(--text-tertiary)]\">\n {loadingIndicator}\n <span>{loadingMessage}</span>\n </div>\n </WorkspaceFilePreviewFrame>\n );\n case \"image\":\n return (\n <WorkspaceImagePreviewSurface\n alt={imageAlt(state.entry)}\n src={state.objectUrl}\n variant={variant}\n />\n );\n case \"text\":\n return (\n <WorkspaceFilePreviewFrame\n className={joinClassNames(styles.frame, styles.textFrame)}\n >\n <pre className={styles.text}>{state.content}</pre>\n </WorkspaceFilePreviewFrame>\n );\n case \"video\":\n return (\n <WorkspaceFilePreviewFrame\n className={joinClassNames(styles.frame, styles.videoFrame)}\n >\n <video\n aria-label={imageAlt(state.entry)}\n className={styles.video}\n muted\n playsInline\n preload=\"metadata\"\n src={state.objectUrl}\n onLoadedMetadata={(event) => {\n const video = event.currentTarget;\n if (video.duration > 0 && video.currentTime === 0) {\n video.currentTime = Math.min(0.1, video.duration / 2);\n }\n }}\n />\n </WorkspaceFilePreviewFrame>\n );\n case \"bytes\":\n // Hook-only kinds without a registered renderer fall through to the\n // unsupported messaging path via host-projected state; if bytes somehow\n // arrive without a hook, show the generic unsupported shell.\n return (\n <WorkspaceFilePreviewFrame className={styles.frame}>\n <div className=\"flex flex-col items-center justify-center gap-3 px-4 text-center text-[13px] text-[var(--text-tertiary)]\">\n {renderIcon(state.entry)}\n <span className={styles.message}>{emptyMessage}</span>\n </div>\n </WorkspaceFilePreviewFrame>\n );\n case \"readonly\":\n case \"unsupported\":\n case \"error\":\n return (\n <WorkspaceFilePreviewFrame className={styles.frame}>\n <div className=\"flex flex-col items-center justify-center gap-3 px-4 text-center text-[13px] text-[var(--text-tertiary)]\">\n {renderIcon(state.entry)}\n <span className={styles.message}>{state.message}</span>\n </div>\n </WorkspaceFilePreviewFrame>\n );\n case \"empty\":\n return (\n <WorkspaceFilePreviewFrame className={styles.frame}>\n <span className={styles.message}>{emptyMessage}</span>\n </WorkspaceFilePreviewFrame>\n );\n }\n}\n\nfunction renderHostPreview<TEntry>(input: {\n renderers: WorkspaceFilePreviewHostRenderers<TEntry> | undefined;\n state: WorkspaceFilePreviewSurfaceState<TEntry>;\n variant: WorkspaceFilePreviewSurfaceVariant;\n}): ReactNode | null {\n const { renderers, state, variant } = input;\n if (!renderers) {\n return null;\n }\n\n switch (state.status) {\n case \"text\": {\n const renderer = renderers[state.previewKind];\n return renderer\n ? renderer({\n content: state.content,\n entry: state.entry,\n previewKind: state.previewKind,\n variant\n })\n : null;\n }\n case \"image\":\n case \"video\": {\n const renderer = renderers[state.previewKind];\n return renderer\n ? renderer({\n entry: state.entry,\n objectUrl: state.objectUrl,\n previewKind: state.previewKind,\n variant\n })\n : null;\n }\n case \"bytes\": {\n const renderer = renderers[state.previewKind];\n return renderer\n ? renderer({\n bytes: state.bytes,\n contentType: state.contentType,\n entry: state.entry,\n previewKind: state.previewKind,\n variant\n })\n : null;\n }\n default:\n return null;\n }\n}\n\nconst workspaceFilePreviewSurfaceStyles: Record<\n WorkspaceFilePreviewSurfaceVariant,\n {\n frame: string;\n image: string;\n imageFrame: string;\n message: string;\n text: string;\n textFrame: string;\n video: string;\n videoFrame: string;\n }\n> = {\n compact: {\n frame:\n \"flex aspect-[3/2] w-full flex-col items-center justify-center overflow-hidden rounded-[8px] border border-[var(--line-2,var(--border-2))] bg-[var(--transparency-block)] p-0 text-center\",\n image: \"max-h-full max-w-full rounded-[6px] object-contain\",\n imageFrame: \"p-3\",\n message:\n \"mx-auto max-w-[24ch] text-center text-[13px] leading-5 text-[var(--text-secondary)] [overflow-wrap:anywhere]\",\n text: \"h-full w-full overflow-auto p-3 text-left text-[11px] leading-5 whitespace-pre-wrap break-words text-[var(--text-primary)]\",\n textFrame: \"items-stretch justify-stretch\",\n video: \"block max-h-full max-w-full rounded-[6px] object-contain\",\n videoFrame: \"p-3\"\n },\n detail: {\n frame:\n \"flex h-60 min-h-60 max-h-60 items-center justify-center overflow-hidden rounded-lg bg-[var(--transparency-block)]\",\n image: \"max-h-full max-w-full rounded-[6px] object-contain\",\n imageFrame: \"p-4\",\n message:\n \"max-w-[24ch] text-center text-[13px] leading-5 text-[var(--text-tertiary)] [overflow-wrap:anywhere]\",\n text: \"h-full overflow-auto p-4 text-[11px] leading-5 whitespace-pre-wrap break-words text-[var(--text-primary)]\",\n textFrame: \"items-stretch justify-stretch\",\n video: \"block max-h-full max-w-full rounded-[6px] object-contain\",\n videoFrame: \"p-4\"\n },\n canvas: {\n frame:\n \"flex h-full min-h-0 min-w-0 w-full items-center justify-center overflow-hidden bg-[var(--background-fronted)] text-[var(--text-tertiary)]\",\n image: \"block max-h-full max-w-full object-contain\",\n imageFrame: \"overflow-auto p-3\",\n message:\n \"max-w-[24ch] text-center text-[13px] leading-5 text-[var(--text-tertiary)] [overflow-wrap:anywhere]\",\n text: \"m-0 h-full min-h-0 min-w-0 w-full overflow-auto whitespace-pre-wrap break-words p-3 font-[var(--tsh-font-mono)] text-[11px] leading-[18px] text-[var(--text-secondary)]\",\n textFrame: \"items-stretch justify-stretch\",\n video: \"block max-h-full max-w-full object-contain\",\n videoFrame: \"overflow-auto p-3\"\n }\n};\n\nfunction WorkspaceFilePreviewFrame({\n children,\n className\n}: {\n children: ReactNode;\n className: string;\n}): ReactElement {\n return <div className={className}>{children}</div>;\n}\n\nfunction joinClassNames(\n ...classNames: Array<string | false | null | undefined>\n): string {\n return classNames.filter(Boolean).join(\" \");\n}\n"],"mappings":"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","names":[]}
|