@orz/ui-content 0.0.0-stage → 0.1.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 (84) hide show
  1. package/LICENSE +29 -0
  2. package/README.md +410 -2
  3. package/dist/attachment/card-content.d.ts +26 -0
  4. package/dist/attachment/card-content.d.ts.map +1 -0
  5. package/dist/attachment/card-content.js +49 -0
  6. package/dist/attachment/card-content.js.map +1 -0
  7. package/dist/attachment/deleted.d.ts +9 -0
  8. package/dist/attachment/deleted.d.ts.map +1 -0
  9. package/dist/attachment/deleted.js +11 -0
  10. package/dist/attachment/deleted.js.map +1 -0
  11. package/dist/attachment/document-card.d.ts +32 -0
  12. package/dist/attachment/document-card.d.ts.map +1 -0
  13. package/dist/attachment/document-card.js +38 -0
  14. package/dist/attachment/document-card.js.map +1 -0
  15. package/dist/attachment/icon.d.ts +13 -0
  16. package/dist/attachment/icon.d.ts.map +1 -0
  17. package/dist/attachment/icon.js +34 -0
  18. package/dist/attachment/icon.js.map +1 -0
  19. package/dist/attachment/image-canvas.d.ts +25 -0
  20. package/dist/attachment/image-canvas.d.ts.map +1 -0
  21. package/dist/attachment/image-canvas.js +301 -0
  22. package/dist/attachment/image-canvas.js.map +1 -0
  23. package/dist/attachment/image-look.d.ts +18 -0
  24. package/dist/attachment/image-look.d.ts.map +1 -0
  25. package/dist/attachment/image-look.js +86 -0
  26. package/dist/attachment/image-look.js.map +1 -0
  27. package/dist/attachment/image-zoom.d.ts +67 -0
  28. package/dist/attachment/image-zoom.d.ts.map +1 -0
  29. package/dist/attachment/image-zoom.js +108 -0
  30. package/dist/attachment/image-zoom.js.map +1 -0
  31. package/dist/attachment/index.d.ts +12 -0
  32. package/dist/attachment/index.d.ts.map +1 -0
  33. package/dist/attachment/index.js +12 -0
  34. package/dist/attachment/index.js.map +1 -0
  35. package/dist/attachment/link.d.ts +18 -0
  36. package/dist/attachment/link.d.ts.map +1 -0
  37. package/dist/attachment/link.js +30 -0
  38. package/dist/attachment/link.js.map +1 -0
  39. package/dist/attachment/list.d.ts +26 -0
  40. package/dist/attachment/list.d.ts.map +1 -0
  41. package/dist/attachment/list.js +53 -0
  42. package/dist/attachment/list.js.map +1 -0
  43. package/dist/attachment/media-content.d.ts +21 -0
  44. package/dist/attachment/media-content.d.ts.map +1 -0
  45. package/dist/attachment/media-content.js +133 -0
  46. package/dist/attachment/media-content.js.map +1 -0
  47. package/dist/attachment/media-player.d.ts +23 -0
  48. package/dist/attachment/media-player.d.ts.map +1 -0
  49. package/dist/attachment/media-player.js +137 -0
  50. package/dist/attachment/media-player.js.map +1 -0
  51. package/dist/attachment/use-media.d.ts +27 -0
  52. package/dist/attachment/use-media.d.ts.map +1 -0
  53. package/dist/attachment/use-media.js +133 -0
  54. package/dist/attachment/use-media.js.map +1 -0
  55. package/dist/attachment/viewer.d.ts +85 -0
  56. package/dist/attachment/viewer.d.ts.map +1 -0
  57. package/dist/attachment/viewer.js +245 -0
  58. package/dist/attachment/viewer.js.map +1 -0
  59. package/dist/file-kind.d.ts +61 -0
  60. package/dist/file-kind.d.ts.map +1 -0
  61. package/dist/file-kind.js +166 -0
  62. package/dist/file-kind.js.map +1 -0
  63. package/dist/index.d.ts +6 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +5 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/registry.d.ts +44 -0
  68. package/dist/registry.d.ts.map +1 -0
  69. package/dist/registry.js +109 -0
  70. package/dist/registry.js.map +1 -0
  71. package/dist/source-text.d.ts +29 -0
  72. package/dist/source-text.d.ts.map +1 -0
  73. package/dist/source-text.js +101 -0
  74. package/dist/source-text.js.map +1 -0
  75. package/dist/title-bar.d.ts +23 -0
  76. package/dist/title-bar.d.ts.map +1 -0
  77. package/dist/title-bar.js +24 -0
  78. package/dist/title-bar.js.map +1 -0
  79. package/dist/types.d.ts +48 -0
  80. package/dist/types.d.ts.map +1 -0
  81. package/dist/types.js +2 -0
  82. package/dist/types.js.map +1 -0
  83. package/package.json +55 -3
  84. package/styles.css +4 -0
@@ -0,0 +1,108 @@
1
+ /** Deepest zoom, in natural pixels: far enough to read a single pixel. */
2
+ export const MAX_NATURAL_SCALE = 8;
3
+ export function fitScale(f) {
4
+ const contain = Math.min(f.width / f.naturalWidth, f.height / f.naturalHeight);
5
+ return f.upscale ? contain : Math.min(1, contain);
6
+ }
7
+ /**
8
+ * An upscaled fit can already sit past the natural-pixel cap (a 48px icon
9
+ * maximized), so the ceiling always leaves room to double whatever fit is.
10
+ */
11
+ export function maxScale(f) {
12
+ return Math.max(MAX_NATURAL_SCALE, fitScale(f) * 2);
13
+ }
14
+ /**
15
+ * Never smaller than fit, except that actual pixels stay reachable when an
16
+ * upscaled fit (maximized) is already larger than them.
17
+ */
18
+ export function minScale(f) {
19
+ return Math.min(fitScale(f), 1);
20
+ }
21
+ export function fitView(f) {
22
+ const z = fitScale(f);
23
+ return {
24
+ z,
25
+ x: (f.width - f.naturalWidth * z) / 2,
26
+ y: (f.height - f.naturalHeight * z) / 2,
27
+ };
28
+ }
29
+ /** Within a hair of fit counts as fit, so float drift cannot strand a view. */
30
+ export function isFitted(f, v) {
31
+ return Math.abs(v.z / fitScale(f) - 1) < 0.001;
32
+ }
33
+ export function isAtMin(f, v) {
34
+ return v.z <= minScale(f) * 1.001;
35
+ }
36
+ export function isAtMax(f, v) {
37
+ return v.z >= maxScale(f) * 0.999;
38
+ }
39
+ function clampAxis(pos, size, room) {
40
+ // A side smaller than the canvas centres; a larger one may not pull an
41
+ // edge inside the canvas, so nothing past the image is ever exposed.
42
+ if (size <= room)
43
+ return (room - size) / 2;
44
+ return Math.min(0, Math.max(room - size, pos));
45
+ }
46
+ export function clampView(f, v) {
47
+ const z = Math.min(Math.max(v.z, minScale(f)), maxScale(f));
48
+ return {
49
+ z,
50
+ x: clampAxis(v.x, f.naturalWidth * z, f.width),
51
+ y: clampAxis(v.y, f.naturalHeight * z, f.height),
52
+ };
53
+ }
54
+ /**
55
+ * The height a restored (not maximized) canvas asks for at zoom `z`: the
56
+ * image's own, so zooming in grows the dialog until its CSS cap takes over
57
+ * and only then starts panning. Never shorter than at fit, so the request
58
+ * does not depend on the measured height it produces. Whole pixels, because
59
+ * the canvas is measured back with clientHeight.
60
+ */
61
+ export function canvasHeight(f, z) {
62
+ const restingScale = Math.min(1, f.width / f.naturalWidth);
63
+ return Math.round(f.naturalHeight * Math.max(z, restingScale));
64
+ }
65
+ /**
66
+ * Carry a view across a canvas resize. A fitted view refits; any other keeps
67
+ * whatever sat at the canvas centre there — the dialog is centred, so that
68
+ * is also what keeps the image still on screen while the canvas grows.
69
+ */
70
+ export function reframe(prev, next, v) {
71
+ if (isFitted(prev, v))
72
+ return fitView(next);
73
+ return clampView(next, {
74
+ z: v.z,
75
+ x: v.x + (next.width - prev.width) / 2,
76
+ y: v.y + (next.height - prev.height) / 2,
77
+ });
78
+ }
79
+ /** Scale by `factor` keeping canvas point (px, py) over the same image pixel. */
80
+ export function zoomAt(f, v, factor, px, py) {
81
+ const z = Math.min(maxScale(f), Math.max(minScale(f), v.z * factor));
82
+ const k = z / v.z;
83
+ return clampView(f, { z, x: px - (px - v.x) * k, y: py - (py - v.y) * k });
84
+ }
85
+ /** Actual pixels (100%), keeping canvas point (px, py) over the same image pixel. */
86
+ export function actualAt(f, v, px, py) {
87
+ return zoomAt(f, v, 1 / v.z, px, py);
88
+ }
89
+ export function panBy(f, v, dx, dy) {
90
+ return clampView(f, { z: v.z, x: v.x + dx, y: v.y + dy });
91
+ }
92
+ /**
93
+ * Click / tap: from fit, zoom at the pointer to actual pixels or twice the
94
+ * fit, whichever is deeper — a fit of 0.8 jumping to 1.0 would look like
95
+ * nothing happened. From anything else, back to fit.
96
+ */
97
+ export function toggleAt(f, v, px, py) {
98
+ if (!isFitted(f, v))
99
+ return fitView(f);
100
+ const target = Math.max(1, fitScale(f) * 2);
101
+ return zoomAt(f, v, target / v.z, px, py);
102
+ }
103
+ /** Wheel delta → multiplicative factor. Pinch arrives as ctrl+wheel with small deltas. */
104
+ export function wheelFactor(deltaY, deltaMode, ctrlKey) {
105
+ const px = deltaMode === 1 ? deltaY * 16 : deltaMode === 2 ? deltaY * 400 : deltaY;
106
+ return Math.exp(-px * (ctrlKey ? 0.01 : 0.002));
107
+ }
108
+ //# sourceMappingURL=image-zoom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-zoom.js","sourceRoot":"","sources":["../../src/attachment/image-zoom.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export { TEXT_PREVIEW_HARD_MAX_BYTES, TEXT_PREVIEW_MAX_BYTES, } from "../file-kind.ts";
2
+ export { type AttachmentCardOptions, attachmentCard, } from "./card-content.tsx";
3
+ export { DeletedAttachmentMark } from "./deleted.tsx";
4
+ export { DocumentCard, type DocumentCardProps } from "./document-card.tsx";
5
+ export { fileIcon } from "./icon.ts";
6
+ export { DEFAULT_IMAGE_LOOK, type ImageLook, parseImageLook, useStoredImageLook, } from "./image-look.ts";
7
+ export { AttachmentLink, type AttachmentLinkProps } from "./link.tsx";
8
+ export { type AttachmentItem, AttachmentList, type AttachmentListProps, } from "./list.tsx";
9
+ export { audioContent, type FrameContentOptions, htmlContent, imageContent, pdfContent, videoContent, } from "./media-content.tsx";
10
+ export { AudioPlayer, type AudioPlayerProps, VideoPlayer, type VideoPlayerProps, } from "./media-player.tsx";
11
+ export { AttachmentViewer, type AttachmentViewerControls, type AttachmentViewerProps, AttachmentViewerProvider, type AttachmentViewerProviderProps, type AttachmentViewerState, type FileSource, useAttachmentViewer, useCanPreview, useViewHref, } from "./viewer.tsx";
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/attachment/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,KAAK,qBAAqB,EAC1B,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EACL,kBAAkB,EAClB,KAAK,SAAS,EACd,cAAc,EACd,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EACL,KAAK,cAAc,EACnB,cAAc,EACd,KAAK,mBAAmB,GACzB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,YAAY,EACZ,KAAK,mBAAmB,EACxB,WAAW,EACX,YAAY,EACZ,UAAU,EACV,YAAY,GACb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,WAAW,EACX,KAAK,gBAAgB,EACrB,WAAW,EACX,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,gBAAgB,EAChB,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,wBAAwB,EACxB,KAAK,6BAA6B,EAClC,KAAK,qBAAqB,EAC1B,KAAK,UAAU,EACf,mBAAmB,EACnB,aAAa,EACb,WAAW,GACZ,MAAM,cAAc,CAAC"}
@@ -0,0 +1,12 @@
1
+ export { TEXT_PREVIEW_HARD_MAX_BYTES, TEXT_PREVIEW_MAX_BYTES, } from "../file-kind.js";
2
+ export { attachmentCard, } from "./card-content.js";
3
+ export { DeletedAttachmentMark } from "./deleted.js";
4
+ export { DocumentCard } from "./document-card.js";
5
+ export { fileIcon } from "./icon.js";
6
+ export { DEFAULT_IMAGE_LOOK, parseImageLook, useStoredImageLook, } from "./image-look.js";
7
+ export { AttachmentLink } from "./link.js";
8
+ export { AttachmentList, } from "./list.js";
9
+ export { audioContent, htmlContent, imageContent, pdfContent, videoContent, } from "./media-content.js";
10
+ export { AudioPlayer, VideoPlayer, } from "./media-player.js";
11
+ export { AttachmentViewer, AttachmentViewerProvider, useAttachmentViewer, useCanPreview, useViewHref, } from "./viewer.js";
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/attachment/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAEL,cAAc,GACf,MAAM,mBAAoB,CAAC;AAC5B,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAe,CAAC;AACtD,OAAO,EAAE,YAAY,EAA0B,MAAM,oBAAqB,CAAC;AAC3E,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EACL,kBAAkB,EAElB,cAAc,EACd,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAA4B,MAAM,WAAY,CAAC;AACtE,OAAO,EAEL,cAAc,GAEf,MAAM,WAAY,CAAC;AACpB,OAAO,EACL,YAAY,EAEZ,WAAW,EACX,YAAY,EACZ,UAAU,EACV,YAAY,GACb,MAAM,oBAAqB,CAAC;AAC7B,OAAO,EACL,WAAW,EAEX,WAAW,GAEZ,MAAM,mBAAoB,CAAC;AAC5B,OAAO,EACL,gBAAgB,EAGhB,wBAAwB,EAIxB,mBAAmB,EACnB,aAAa,EACb,WAAW,GACZ,MAAM,aAAc,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { ReactNode } from "react";
2
+ import { type FileSource } from "./viewer.tsx";
3
+ export type AttachmentLinkProps = {
4
+ file: FileSource;
5
+ /** A bordered chip; default false, underlined on hover. */
6
+ boxed?: boolean;
7
+ className?: string;
8
+ /** Default: the file's name. */
9
+ children?: ReactNode;
10
+ };
11
+ /**
12
+ * An inline link to a file, wearing its type icon. A real anchor, so
13
+ * copy-link and middle-click keep working; a plain click on a file the viewer
14
+ * can draw opens the viewer instead. A deleted file is its name struck
15
+ * through, and no link.
16
+ */
17
+ export declare function AttachmentLink({ file, boxed, className, children, }: AttachmentLinkProps): import("react").JSX.Element;
18
+ //# sourceMappingURL=link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../src/attachment/link.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EACL,KAAK,UAAU,EAIhB,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,UAAU,CAAC;IACjB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,KAAa,EACb,SAAS,EACT,QAAQ,GACT,EAAE,mBAAmB,+BAwCrB"}
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { isPlainLeftClick, LinkChip } from "@orz/ui/components/link-chip";
3
+ import { cn } from "@orz/ui/lib/utils";
4
+ import { fileIcon } from "./icon.js";
5
+ import { useAttachmentViewer, useCanPreview, useViewHref, } from "./viewer.js";
6
+ /**
7
+ * An inline link to a file, wearing its type icon. A real anchor, so
8
+ * copy-link and middle-click keep working; a plain click on a file the viewer
9
+ * can draw opens the viewer instead. A deleted file is its name struck
10
+ * through, and no link.
11
+ */
12
+ export function AttachmentLink({ file, boxed = false, className, children, }) {
13
+ const viewer = useAttachmentViewer();
14
+ const canPreview = useCanPreview(file);
15
+ const href = useViewHref(file);
16
+ if (file.deleted) {
17
+ const Icon = fileIcon(file);
18
+ return (_jsxs("span", { className: cn("font-medium text-muted-foreground line-through", className), title: `${file.name} (deleted)`, "data-attachment-deleted": "", children: [_jsx(Icon, { "aria-hidden": true, className: "mr-0.5 inline size-3.5 align-middle" }), children ?? file.name] }));
19
+ }
20
+ return (_jsx(LinkChip, { href: href === "" ? undefined : href,
21
+ // The label is the chip's truncating child, so a long filename is cut
22
+ // where it used to wrap and stay whole.
23
+ title: file.name, icon: fileIcon(file), boxed: boxed, className: className, onClick: (e) => {
24
+ if (viewer !== null && canPreview && isPlainLeftClick(e)) {
25
+ e.preventDefault();
26
+ viewer.show(file);
27
+ }
28
+ }, children: children ?? file.name }));
29
+ }
30
+ //# sourceMappingURL=link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.js","sourceRoot":"","sources":["../../src/attachment/link.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAEL,mBAAmB,EACnB,aAAa,EACb,WAAW,GACZ,MAAM,aAAc,CAAC;AAWtB;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,EAC7B,IAAI,EACJ,KAAK,GAAG,KAAK,EACb,SAAS,EACT,QAAQ,GACY;IACpB,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC;IACrC,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAE/B,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5B,OAAO,CACL,gBACE,SAAS,EAAE,EAAE,CACX,gDAAgD,EAChD,SAAS,CACV,EACD,KAAK,EAAE,GAAG,IAAI,CAAC,IAAI,YAAY,6BACP,EAAE,aAE1B,KAAC,IAAI,yBAAa,SAAS,EAAC,qCAAqC,GAAG,EACnE,QAAQ,IAAI,IAAI,CAAC,IAAI,IACjB,CACR,CAAC;IACJ,CAAC;IACD,OAAO,CACL,KAAC,QAAQ,IACP,IAAI,EAAE,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;QACpC,sEAAsE;QACtE,wCAAwC;QACxC,KAAK,EAAE,IAAI,CAAC,IAAI,EAChB,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,EACpB,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;YACb,IAAI,MAAM,KAAK,IAAI,IAAI,UAAU,IAAI,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzD,CAAC,CAAC,cAAc,EAAE,CAAC;gBACnB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpB,CAAC;QACH,CAAC,YAEA,QAAQ,IAAI,IAAI,CAAC,IAAI,GACb,CACZ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { type ReactNode } from "react";
2
+ import { type FileSource } from "./viewer.tsx";
3
+ export type AttachmentItem = FileSource & {
4
+ key: string | number;
5
+ /** Upload time, as an ISO string; the row prints it when given. */
6
+ createdAt?: string;
7
+ };
8
+ export type AttachmentListProps = {
9
+ items: AttachmentItem[];
10
+ /** Controls at the end of a row, after its download link: a delete button, say. */
11
+ actions?: (item: AttachmentItem) => ReactNode;
12
+ /** Default "Attachments". */
13
+ title?: ReactNode;
14
+ /** The section's id, for links that jump to it. */
15
+ id?: string;
16
+ className?: string;
17
+ };
18
+ /**
19
+ * A list of files. Every row is a real link (so copy-link and middle-click
20
+ * keep working), pointing at the provider's `viewHref` — hence the separate
21
+ * download icon, which is the only way left to save a viewable file. A plain
22
+ * click on anything previewable is hijacked into the viewer, anything else
23
+ * falls through to the browser. The viewer pages across the whole list.
24
+ */
25
+ export declare function AttachmentList({ items, actions, title, id, className, }: AttachmentListProps): import("react").JSX.Element | null;
26
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/attachment/list.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,SAAS,EAAY,MAAM,OAAO,CAAC;AAGjD,OAAO,EACL,KAAK,UAAU,EAIhB,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG;IACxC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,mFAAmF;IACnF,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,SAAS,CAAC;IAC9C,6BAA6B;IAC7B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,mDAAmD;IACnD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AA6EF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,OAAO,EACP,KAAqB,EACrB,EAAE,EACF,SAAS,GACV,EAAE,mBAAmB,sCAwDrB"}
@@ -0,0 +1,53 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { isPlainLeftClick } from "@orz/ui/components/link-chip";
3
+ import { cn } from "@orz/ui/lib/utils";
4
+ import { ChevronDownIcon, ChevronUpIcon, DownloadIcon, PaperclipIcon, } from "lucide-react";
5
+ import { useState } from "react";
6
+ import { formatSize } from "../file-kind.js";
7
+ import { fileIcon } from "./icon.js";
8
+ import { useAttachmentViewer, useCanPreview, useViewHref, } from "./viewer.js";
9
+ /** Rows a folded list keeps on screen — its newest end. */
10
+ const CAP = 5;
11
+ /**
12
+ * Below this many hidden rows, folding is a worse deal than the scroll it
13
+ * saves: the toggle is a row of its own and as tall as one (37px), so hiding
14
+ * one row saves nothing at all and hiding two saves a single row's height,
15
+ * both at the price of a click and of the section changing shape the moment
16
+ * a sixth file arrives.
17
+ */
18
+ const MIN_HIDDEN = 3;
19
+ function AttachmentRow({ items, index, actions, }) {
20
+ const item = items[index];
21
+ const viewer = useAttachmentViewer();
22
+ const canPreview = useCanPreview(item);
23
+ const href = useViewHref(item);
24
+ const Icon = fileIcon(item);
25
+ return (_jsxs("li", { className: "flex items-center hover:bg-muted/40", children: [_jsxs("a", { href: href === "" ? undefined : href, className: "flex min-w-0 flex-1 items-center gap-2 py-2 pl-3 text-sm", onClick: (e) => {
26
+ if (viewer !== null && canPreview && isPlainLeftClick(e)) {
27
+ e.preventDefault();
28
+ viewer.open(items, index);
29
+ }
30
+ }, children: [_jsx(Icon, { className: "size-4 shrink-0 text-muted-foreground" }), _jsx("span", { className: "truncate font-medium hover:underline", children: item.name }), item.size !== undefined && (_jsx("span", { className: "ml-auto shrink-0 text-xs text-muted-foreground", children: formatSize(item.size) })), item.createdAt !== undefined && (_jsx("span", { className: "hidden shrink-0 text-xs text-muted-foreground sm:inline", title: item.createdAt, children: _jsx("time", { dateTime: item.createdAt, children: new Date(item.createdAt).toLocaleString() }) }))] }), item.url !== undefined && (_jsx("a", { href: item.url, download: item.name, "aria-label": `download ${item.name}`, className: "shrink-0 py-2 pr-3 pl-2 text-muted-foreground hover:text-foreground", children: _jsx(DownloadIcon, { className: "size-3.5" }) })), actions?.(item)] }));
31
+ }
32
+ /**
33
+ * A list of files. Every row is a real link (so copy-link and middle-click
34
+ * keep working), pointing at the provider's `viewHref` — hence the separate
35
+ * download icon, which is the only way left to save a viewable file. A plain
36
+ * click on anything previewable is hijacked into the viewer, anything else
37
+ * falls through to the browser. The viewer pages across the whole list.
38
+ */
39
+ export function AttachmentList({ items, actions, title = "Attachments", id, className, }) {
40
+ // Not persisted anywhere: expanding is "show me now", not a preference.
41
+ const [expanded, setExpanded] = useState(false);
42
+ if (items.length === 0)
43
+ return null;
44
+ const collapsible = items.length >= CAP + MIN_HIDDEN;
45
+ const folded = collapsible && !expanded;
46
+ // The fold takes the head off an unchanged ascending list rather than
47
+ // reversing it: the same array is what the viewer's previous/next page
48
+ // through, and a list that read newest-first here would contradict it.
49
+ const shown = folded ? items.slice(-CAP) : items;
50
+ const hiddenBefore = items.length - shown.length;
51
+ return (_jsxs("section", { className: cn("rounded-lg border", className), id: id, children: [_jsxs("div", { className: "flex items-center gap-2 border-b bg-muted/40 px-3 py-1.5 text-sm", children: [_jsx(PaperclipIcon, { className: "size-3.5 text-muted-foreground" }), _jsx("span", { className: "font-medium", children: title }), _jsx("span", { className: "text-muted-foreground", children: items.length })] }), collapsible && (_jsx("button", { type: "button", "aria-expanded": expanded, onClick: () => setExpanded((v) => !v), className: "flex w-full items-center gap-1 border-b px-3 py-2 text-xs text-muted-foreground hover:bg-muted/40 hover:text-foreground", "data-testid": "attachment-fold-toggle", children: folded ? (_jsxs(_Fragment, { children: [_jsx(ChevronDownIcon, { className: "size-3.5" }), "Show ", items.length - CAP, " more"] })) : (_jsxs(_Fragment, { children: [_jsx(ChevronUpIcon, { className: "size-3.5" }), "Show less"] })) })), _jsx("ul", { className: "divide-y", children: shown.map((item, shownIndex) => (_jsx(AttachmentRow, { items: items, index: shownIndex + hiddenBefore, actions: actions }, item.key))) })] }));
52
+ }
53
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/attachment/list.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { ContentRenderer } from "../types.ts";
2
+ import { type FileSource } from "./viewer.tsx";
3
+ export type FrameContentOptions = {
4
+ /** Where the frame loads the file from. Default: the provider's `viewHref`, else `url`. */
5
+ src?: (file: FileSource) => string;
6
+ };
7
+ /**
8
+ * Images, in either placement. In a document the image opens the nearest
9
+ * attachment viewer on click, and is a plain image outside one. In the viewer
10
+ * it zooms and pans, with its controls in the viewer's title bar.
11
+ */
12
+ export declare function imageContent(): ContentRenderer;
13
+ /** HTML files, sandboxed, in the viewer. In a document they are text, and `attachmentCard`'s. */
14
+ export declare function htmlContent(options?: FrameContentOptions): ContentRenderer;
15
+ /** PDFs, in the browser's own viewer. Not offered in documents. */
16
+ export declare function pdfContent(options?: FrameContentOptions): ContentRenderer;
17
+ /** Video under the shared control bar, in either placement. */
18
+ export declare function videoContent(): ContentRenderer;
19
+ /** Audio under the shared control bar, in either placement. */
20
+ export declare function audioContent(): ContentRenderer;
21
+ //# sourceMappingURL=media-content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-content.d.ts","sourceRoot":"","sources":["../../src/attachment/media-content.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAEV,eAAe,EAGhB,MAAM,aAAa,CAAC;AAIrB,OAAO,EACL,KAAK,UAAU,EAIhB,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,mBAAmB,GAAG;IAChC,2FAA2F;IAC3F,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,MAAM,CAAC;CACpC,CAAC;AAsBF;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,eAAe,CA0D9C;AAED,iGAAiG;AACjG,wBAAgB,WAAW,CACzB,OAAO,GAAE,mBAAwB,GAChC,eAAe,CA0BjB;AAED,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,OAAO,GAAE,mBAAwB,GAAG,eAAe,CAuB7E;AAqCD,+DAA+D;AAC/D,wBAAgB,YAAY,IAAI,eAAe,CA8B9C;AAED,+DAA+D;AAC/D,wBAAgB,YAAY,IAAI,eAAe,CA2B9C"}
@@ -0,0 +1,133 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button } from "@orz/ui/components/button";
3
+ import { cn } from "@orz/ui/lib/utils";
4
+ import { Download } from "lucide-react";
5
+ import { useState } from "react";
6
+ import { isAudioFile, isHtmlFile, isImageFile, isPdfFile, isVideoFile, } from "../file-kind.js";
7
+ import { useContentTitleBar } from "../title-bar.js";
8
+ import { fileIcon } from "./icon.js";
9
+ import { ImageCanvas } from "./image-canvas.js";
10
+ import { AudioPlayer, VideoPlayer } from "./media-player.js";
11
+ import { useAttachmentViewer, useViewerImage, useViewHref, } from "./viewer.js";
12
+ function acceptsFile(kind, placements) {
13
+ return (source, placement) => source.kind === "file" &&
14
+ source.url !== undefined &&
15
+ placements.includes(placement) &&
16
+ kind(source);
17
+ }
18
+ const BOTH = ["document", "viewer"];
19
+ const VIEWER = ["viewer"];
20
+ /** Every renderer here accepts only files, so `Component` only ever sees one. */
21
+ function fileOf(source) {
22
+ if (source.kind !== "file")
23
+ throw new Error("expected a file source");
24
+ return source;
25
+ }
26
+ /**
27
+ * Images, in either placement. In a document the image opens the nearest
28
+ * attachment viewer on click, and is a plain image outside one. In the viewer
29
+ * it zooms and pans, with its controls in the viewer's title bar.
30
+ */
31
+ export function imageContent() {
32
+ function ImageFile({ source, placement, className }) {
33
+ const file = fileOf(source);
34
+ const viewer = useAttachmentViewer();
35
+ const viewerImage = useViewerImage();
36
+ const titleBar = useContentTitleBar(source);
37
+ if (placement === "viewer" &&
38
+ viewerImage !== null &&
39
+ titleBar !== undefined &&
40
+ file.url !== undefined) {
41
+ return (_jsx(ImageCanvas, { src: file.url, alt: file.name, maximized: viewerImage.maximized, toolbar: titleBar, look: viewerImage.look, onLookChange: viewerImage.setLook, lastHeight: viewerImage.lastHeight, held: viewerImage.held, className: className }));
42
+ }
43
+ if (placement === "viewer") {
44
+ return (_jsx("img", { src: file.url, alt: file.name, className: cn("mx-auto max-h-(--attachment-pane-height) rounded-md object-contain", className) }));
45
+ }
46
+ if (viewer === null) {
47
+ return _jsx("img", { src: file.url, alt: file.name, className: className });
48
+ }
49
+ return (_jsx("img", { src: file.url, alt: file.name, className: cn("cursor-zoom-in", className), onClick: () => viewer.show(file) }));
50
+ }
51
+ return {
52
+ name: "image",
53
+ accepts: acceptsFile(isImageFile, BOTH),
54
+ display: "inline",
55
+ Component: ImageFile,
56
+ };
57
+ }
58
+ /** HTML files, sandboxed, in the viewer. In a document they are text, and `attachmentCard`'s. */
59
+ export function htmlContent(options = {}) {
60
+ function HtmlFile({ source, className }) {
61
+ const file = fileOf(source);
62
+ const viewHref = useViewHref(file);
63
+ return (_jsx("iframe", { src: options.src?.(file) ?? viewHref, sandbox: "allow-scripts", title: file.name, className: cn("h-(--attachment-pane-height) w-full rounded-md border bg-white", className) }));
64
+ }
65
+ return {
66
+ name: "html",
67
+ accepts: acceptsFile(isHtmlFile, VIEWER),
68
+ display: "block",
69
+ Component: HtmlFile,
70
+ };
71
+ }
72
+ /** PDFs, in the browser's own viewer. Not offered in documents. */
73
+ export function pdfContent(options = {}) {
74
+ function PdfFile({ source, className }) {
75
+ const file = fileOf(source);
76
+ const viewHref = useViewHref(file);
77
+ return (_jsx("iframe", { src: options.src?.(file) ?? viewHref, title: file.name, className: cn("h-(--attachment-pane-height) w-full rounded-md border", className) }));
78
+ }
79
+ return {
80
+ name: "pdf",
81
+ accepts: acceptsFile(isPdfFile, VIEWER),
82
+ display: "block",
83
+ Component: PdfFile,
84
+ };
85
+ }
86
+ const UNPLAYABLE = "This browser can't play this file.";
87
+ /** The name and Download over a player in a document; in the viewer the title bar has both. */
88
+ function MediaHeader({ file, icon }) {
89
+ const Icon = fileIcon(file);
90
+ return (_jsxs("div", { className: "flex items-center gap-2 border-b bg-card py-1 pr-1 pl-3 text-card-foreground text-xs", children: [icon && _jsx(Icon, { "aria-hidden": true, className: "size-4 shrink-0" }), _jsx("span", { className: "min-w-0 flex-1 truncate", title: file.name, children: file.name }), file.url !== undefined && (_jsx(Button, { asChild: true, size: "xs", variant: "ghost", children: _jsxs("a", { href: file.url, download: file.name, children: [_jsx(Download, {}), "Download"] }) }))] }));
91
+ }
92
+ /** A file the browser cannot play still gets what the renderers after this one make of it. */
93
+ function Unplayable({ source, placement, className, Next }) {
94
+ return (_jsxs("div", { className: className, children: [_jsx(Next, { source: source, placement: placement }), _jsx("p", { className: "text-muted-foreground text-xs", children: UNPLAYABLE })] }));
95
+ }
96
+ /** Video under the shared control bar, in either placement. */
97
+ export function videoContent() {
98
+ function VideoFile(props) {
99
+ const { source, placement, className } = props;
100
+ const file = fileOf(source);
101
+ const [failed, setFailed] = useState(false);
102
+ if (failed)
103
+ return _jsx(Unplayable, { ...props });
104
+ return (_jsx(VideoPlayer, { src: file.url ?? "", title: file.name, header: placement === "document" ? _jsx(MediaHeader, { file: file }) : undefined, onError: () => setFailed(true), className: cn(
105
+ // The bar is 2.25rem tall; the picture takes the rest of the pane.
106
+ placement === "viewer" &&
107
+ "[&_video]:max-h-[calc(var(--attachment-pane-height)-2.25rem)]", className) }));
108
+ }
109
+ return {
110
+ name: "video",
111
+ accepts: acceptsFile(isVideoFile, BOTH),
112
+ display: "block",
113
+ Component: VideoFile,
114
+ };
115
+ }
116
+ /** Audio under the shared control bar, in either placement. */
117
+ export function audioContent() {
118
+ function AudioFile(props) {
119
+ const { source, placement, className } = props;
120
+ const file = fileOf(source);
121
+ const [failed, setFailed] = useState(false);
122
+ if (failed)
123
+ return _jsx(Unplayable, { ...props });
124
+ return (_jsx(AudioPlayer, { src: file.url ?? "", title: file.name, header: placement === "document" ? (_jsx(MediaHeader, { file: file, icon: true })) : undefined, onError: () => setFailed(true), className: cn(placement === "viewer" && "w-full", className) }));
125
+ }
126
+ return {
127
+ name: "audio",
128
+ accepts: acceptsFile(isAudioFile, BOTH),
129
+ display: "block",
130
+ Component: AudioFile,
131
+ };
132
+ }
133
+ //# sourceMappingURL=media-content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-content.js","sourceRoot":"","sources":["../../src/attachment/media-content.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { type ReactElement, type ReactNode } from "react";
2
+ type MediaPlayerProps = {
3
+ src: string;
4
+ /** The accessible name of the picture or sound, and the frame's `title`. */
5
+ title: string;
6
+ /** Drawn above the media: the renderers put the name and Download here. */
7
+ header?: ReactNode;
8
+ autoPlay?: boolean;
9
+ loop?: boolean;
10
+ /** Initial speed. Default 1. */
11
+ speed?: number;
12
+ /** The element failed to load or decode `src`. When this is set, the player draws nothing itself. */
13
+ onError?: (error: MediaError | null) => void;
14
+ className?: string;
15
+ };
16
+ export type VideoPlayerProps = MediaPlayerProps;
17
+ export type AudioPlayerProps = MediaPlayerProps;
18
+ /** A video under the shared control bar, with picture-in-picture and fullscreen where the browser offers them. */
19
+ export declare function VideoPlayer(props: VideoPlayerProps): ReactElement;
20
+ /** An audio file as a header over the shared control bar; the element itself is not drawn. */
21
+ export declare function AudioPlayer(props: AudioPlayerProps): ReactElement;
22
+ export {};
23
+ //# sourceMappingURL=media-player.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-player.d.ts","sourceRoot":"","sources":["../../src/attachment/media-player.tsx"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,SAAS,EAKf,MAAM,OAAO,CAAC;AAGf,KAAK,gBAAgB,GAAG;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qGAAqG;IACrG,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAChD,MAAM,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAEhD,kHAAkH;AAClH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,YAAY,CAGjE;AAED,8FAA8F;AAC9F,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,YAAY,CAEjE"}